Added Apps search

This commit is contained in:
Imran Remtulla
2022-09-24 01:57:45 -04:00
parent d03486fc5d
commit 2cfe62142a
7 changed files with 126 additions and 20 deletions

View File

@ -112,6 +112,7 @@ class GitHub implements AppSource {
} catch (e) {
return "Invalid regular expression";
}
return null;
}
])
]

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:obtainium/components/generated_form.dart';
import 'package:obtainium/components/generated_form_modal.dart';
import 'package:obtainium/providers/apps_provider.dart';
import 'package:obtainium/providers/settings_provider.dart';

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:obtainium/components/custom_app_bar.dart';
import 'package:obtainium/components/generated_form.dart';
import 'package:obtainium/components/generated_form_modal.dart';
import 'package:obtainium/pages/app.dart';
import 'package:obtainium/providers/apps_provider.dart';
import 'package:obtainium/providers/settings_provider.dart';
@ -14,12 +16,47 @@ class AppsPage extends StatefulWidget {
}
class _AppsPageState extends State<AppsPage> {
AppsFilter? filter;
@override
Widget build(BuildContext context) {
var appsProvider = context.watch<AppsProvider>();
var settingsProvider = context.watch<SettingsProvider>();
var existingUpdateAppIds = appsProvider.getExistingUpdates();
var sortedApps = appsProvider.apps.values.toList();
if (filter != null) {
sortedApps = sortedApps.where((app) {
if (app.app.installedVersion == app.app.latestVersion &&
filter!.onlyNonLatest) {
return false;
}
if (filter!.nameFilter.isEmpty && filter!.authorFilter.isEmpty) {
return true;
}
List<String> nameTokens = filter!.nameFilter
.split(' ')
.where((element) => element.trim().isNotEmpty)
.toList();
List<String> authorTokens = filter!.authorFilter
.split(' ')
.where((element) => element.trim().isNotEmpty)
.toList();
for (var t in nameTokens) {
if (!app.app.name.toLowerCase().contains(t.toLowerCase())) {
return false;
}
}
for (var t in authorTokens) {
if (!app.app.author.toLowerCase().contains(t.toLowerCase())) {
return false;
}
}
return true;
}).toList();
}
sortedApps.sort((a, b) {
int result = 0;
if (settingsProvider.sortColumn == SortColumnSettings.authorName) {
@ -31,14 +68,17 @@ class _AppsPageState extends State<AppsPage> {
}
return result;
});
if (settingsProvider.sortOrder == SortOrderSettings.ascending) {
sortedApps = sortedApps.reversed.toList();
}
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.surface,
floatingActionButton: existingUpdateAppIds.isEmpty
? null
floatingActionButton:
Row(mainAxisAlignment: MainAxisAlignment.end, children: [
existingUpdateAppIds.isEmpty || filter != null
? const SizedBox()
: ElevatedButton.icon(
onPressed: appsProvider.areDownloadsRunning()
? null
@ -51,6 +91,60 @@ class _AppsPageState extends State<AppsPage> {
},
icon: const Icon(Icons.install_mobile_outlined),
label: const Text('Install All')),
const SizedBox(
width: 16,
),
appsProvider.apps.isEmpty
? const SizedBox()
: ElevatedButton.icon(
onPressed: () {
showDialog<List<String>?>(
context: context,
builder: (BuildContext ctx) {
return GeneratedFormModal(
title: 'Filter Apps',
items: [
[
GeneratedFormItem(
label: "App Name", required: false),
GeneratedFormItem(
label: "Author", required: false)
],
[
GeneratedFormItem(
label: "Ignore Up-to-Date Apps",
type: FormItemType.bool)
]
],
defaultValues: filter == null
? []
: [
filter!.nameFilter,
filter!.authorFilter,
filter!.onlyNonLatest ? 'true' : ''
]);
}).then((values) {
if (values != null &&
values
.where((element) => element.isNotEmpty)
.isNotEmpty) {
setState(() {
filter = AppsFilter(
nameFilter: values[0],
authorFilter: values[1],
onlyNonLatest: values[2] == "true");
});
} else {
setState(() {
filter = null;
});
}
});
},
label: Text(filter == null ? 'Search' : 'Modify Search'),
icon: Icon(
filter == null ? Icons.search : Icons.manage_search)),
]),
body: RefreshIndicator(
onRefresh: () {
HapticFeedback.lightImpact();
@ -58,13 +152,15 @@ class _AppsPageState extends State<AppsPage> {
},
child: CustomScrollView(slivers: <Widget>[
const CustomAppBar(title: 'Apps'),
if (appsProvider.loadingApps || appsProvider.apps.isEmpty)
if (appsProvider.loadingApps || sortedApps.isEmpty)
SliverFillRemaining(
child: Center(
child: appsProvider.loadingApps
? const CircularProgressIndicator()
: Text(
'No Apps',
appsProvider.apps.isEmpty
? 'No Apps'
: 'No Search Results',
style:
Theme.of(context).textTheme.headlineMedium,
))),
@ -97,3 +193,14 @@ class _AppsPageState extends State<AppsPage> {
])));
}
}
class AppsFilter {
late String nameFilter;
late String authorFilter;
late bool onlyNonLatest;
AppsFilter(
{this.nameFilter = "",
this.authorFilter = "",
this.onlyNonLatest = false});
}

View File

@ -5,7 +5,6 @@ import 'package:obtainium/pages/add_app.dart';
import 'package:obtainium/pages/apps.dart';
import 'package:obtainium/pages/import_export.dart';
import 'package:obtainium/pages/settings.dart';
import 'package:obtainium/pages/test_page.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});

View File

@ -191,6 +191,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
}
}
}
return null;
}
])
]

View File

@ -27,7 +27,7 @@ class _SettingsPageState extends State<SettingsPage> {
child: Padding(
padding: const EdgeInsets.all(16),
child: settingsProvider.prefs == null
? Container()
? const SizedBox()
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

View File

@ -127,8 +127,7 @@ abstract class AppSource {
String standardUrl, List<String> additionalData);
AppNames getAppNames(String standardUrl);
late List<List<GeneratedFormItem>> additionalDataFormItems;
late List<String>
additionalDataDefaults; // TODO: Make these integrate into generated form
late List<String> additionalDataDefaults;
}
abstract class MassAppSource {