diff --git a/lib/ui/views/app_selector/app_selector_view.dart b/lib/ui/views/app_selector/app_selector_view.dart index e0ead58f..93f9e06f 100644 --- a/lib/ui/views/app_selector/app_selector_view.dart +++ b/lib/ui/views/app_selector/app_selector_view.dart @@ -36,92 +36,59 @@ class _AppSelectorViewState extends State { child: Padding( padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 12.0), - child: model.apps.isNotEmpty - ? Column( - children: [ - SearchBar( - showSelectIcon: false, - fillColor: - isDark ? const Color(0xff1B222B) : Colors.grey[200], - hintText: FlutterI18n.translate( - context, - 'appSelectorView.searchBarHint', - ), - hintTextColor: Theme.of(context).colorScheme.tertiary, - onQueryChanged: (searchQuery) { - setState(() { - _query = searchQuery; - }); - }, - ), - const SizedBox(height: 12), - _query.isEmpty || _query.length < 2 - ? _getAllResults(model) - : _getFilteredResults(model) - ], + child: model.noApps + ? Center( + child: I18nText('appSelectorCard.noAppsLabel'), ) - : _query.isEmpty || _query.length < 2 + : model.apps.isEmpty ? Center( child: CircularProgressIndicator( color: Theme.of(context).colorScheme.secondary, ), ) - : Center( - child: I18nText('appSelectorCard.noAppsLabel'), + : Column( + children: [ + SearchBar( + showSelectIcon: false, + fillColor: isDark + ? const Color(0xff1B222B) + : Colors.grey[200], + hintText: FlutterI18n.translate( + context, + 'appSelectorView.searchBarHint', + ), + hintTextColor: + Theme.of(context).colorScheme.tertiary, + onQueryChanged: (searchQuery) { + setState(() { + _query = searchQuery; + }); + }, + ), + const SizedBox(height: 12), + Expanded( + child: ListView( + children: model + .getFilteredApps(_query) + .map((app) => InkWell( + onTap: () { + model.selectApp(app); + Navigator.of(context).pop(); + }, + child: InstalledAppItem( + name: app.appName, + pkgName: app.packageName, + icon: app.icon, + ), + )) + .toList(), + ), + ), + ], ), ), ), ), ); } - - Widget _getAllResults(AppSelectorViewModel model) { - return Expanded( - child: ListView.builder( - itemCount: model.apps.length, - itemBuilder: (context, index) { - model.apps.sort((a, b) => a.appName.compareTo(b.appName)); - return InkWell( - onTap: () { - model.selectApp(model.apps[index]); - Navigator.of(context).pop(); - }, - child: InstalledAppItem( - name: model.apps[index].appName, - pkgName: model.apps[index].packageName, - icon: model.apps[index].icon, - ), - ); - }, - ), - ); - } - - Widget _getFilteredResults(AppSelectorViewModel model) { - return Expanded( - child: ListView.builder( - itemCount: model.apps.length, - itemBuilder: (context, index) { - model.apps.sort((a, b) => a.appName.compareTo(b.appName)); - if (model.apps[index].appName.toLowerCase().contains( - _query.toLowerCase(), - )) { - return InkWell( - onTap: () { - model.selectApp(model.apps[index]); - Navigator.of(context).pop(); - }, - child: InstalledAppItem( - name: model.apps[index].appName, - pkgName: model.apps[index].packageName, - icon: model.apps[index].icon, - ), - ); - } else { - return const SizedBox(); - } - }, - ), - ); - } } diff --git a/lib/ui/views/app_selector/app_selector_viewmodel.dart b/lib/ui/views/app_selector/app_selector_viewmodel.dart index e622f6e7..3e689df2 100644 --- a/lib/ui/views/app_selector/app_selector_viewmodel.dart +++ b/lib/ui/views/app_selector/app_selector_viewmodel.dart @@ -14,17 +14,20 @@ import 'package:stacked/stacked.dart'; class AppSelectorViewModel extends BaseViewModel { final PatcherAPI _patcherAPI = locator(); final List apps = []; + bool noApps = false; bool _isRooted = false; Future initialize() async { apps.addAll(await _patcherAPI.getFilteredInstalledApps()); + apps.sort((a, b) => a.appName.compareTo(b.appName)); + noApps = apps.isEmpty; SharedPreferences prefs = await SharedPreferences.getInstance(); _isRooted = prefs.getBool('isRooted') ?? false; notifyListeners(); } void selectApp(ApplicationWithIcon application) async { - PatchedApplication app = PatchedApplication( + locator().selectedApp = PatchedApplication( name: application.appName, packageName: application.packageName, version: application.versionName!, @@ -35,7 +38,6 @@ class AppSelectorViewModel extends BaseViewModel { isFromStorage: false, appliedPatches: [], ); - locator().selectedApp = app; locator().selectedPatches.clear(); locator().notifyListeners(); } @@ -52,7 +54,7 @@ class AppSelectorViewModel extends BaseViewModel { await DeviceApps.getAppFromStorage(apkFile.path, true) as ApplicationWithIcon?; if (application != null) { - PatchedApplication app = PatchedApplication( + locator().selectedApp = PatchedApplication( name: application.appName, packageName: application.packageName, version: application.versionName!, @@ -63,7 +65,6 @@ class AppSelectorViewModel extends BaseViewModel { isFromStorage: true, appliedPatches: [], ); - locator().selectedApp = app; locator().selectedPatches.clear(); locator().notifyListeners(); } @@ -79,4 +80,13 @@ class AppSelectorViewModel extends BaseViewModel { ); } } + + List getFilteredApps(String query) { + return apps + .where((app) => + query.isEmpty || + query.length < 2 || + app.appName.toLowerCase().contains(query.toLowerCase())) + .toList(); + } } diff --git a/lib/ui/views/patches_selector/patches_selector_view.dart b/lib/ui/views/patches_selector/patches_selector_view.dart index e9597c88..4da19d1c 100644 --- a/lib/ui/views/patches_selector/patches_selector_view.dart +++ b/lib/ui/views/patches_selector/patches_selector_view.dart @@ -14,8 +14,7 @@ class PatchesSelectorView extends StatefulWidget { } class _PatchesSelectorViewState extends State { - final List _items = []; - String query = ''; + String _query = ''; @override Widget build(BuildContext context) { @@ -27,8 +26,13 @@ class _PatchesSelectorViewState extends State { child: Padding( padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 12.0), - child: model.patches.isNotEmpty - ? Column( + child: model.patches.isEmpty + ? Center( + child: CircularProgressIndicator( + color: Theme.of(context).colorScheme.secondary, + ), + ) + : Column( children: [ SearchBar( showSelectIcon: true, @@ -41,15 +45,28 @@ class _PatchesSelectorViewState extends State { hintTextColor: Theme.of(context).colorScheme.tertiary, onQueryChanged: (searchQuery) { setState(() { - query = searchQuery; + _query = searchQuery; }); }, onSelectAll: (value) => model.selectAllPatches(value), ), const SizedBox(height: 12), - query.isEmpty || query.length < 2 - ? _getAllResults(model) - : _getFilteredResults(model), + Expanded( + child: ListView( + children: model + .getFilteredPatches(_query) + .map((patch) => PatchItem( + name: patch.name, + simpleName: patch.simpleName, + version: patch.version, + description: patch.description, + isSelected: model.isSelected(patch), + onChanged: (value) => + model.selectPatch(patch, value), + )) + .toList(), + ), + ), MaterialButton( textColor: Colors.white, color: Theme.of(context).colorScheme.secondary, @@ -68,65 +85,10 @@ class _PatchesSelectorViewState extends State { child: I18nText('patchesSelectorView.doneButton'), ), ], - ) - : Center( - child: CircularProgressIndicator( - color: Theme.of(context).colorScheme.secondary, - ), ), ), ), ), ); } - - Widget _getAllResults(PatchesSelectorViewModel model) { - _items.clear(); - return Expanded( - child: ListView.builder( - itemCount: model.patches.length, - itemBuilder: (context, index) { - model.patches.sort((a, b) => a.simpleName.compareTo(b.simpleName)); - PatchItem item = PatchItem( - name: model.patches[index].name, - simpleName: model.patches[index].simpleName, - version: model.patches[index].version, - description: model.patches[index].description, - isSelected: model.isSelected(index), - onChanged: (value) => model.selectPatch(index, value), - ); - _items.add(item); - return item; - }, - ), - ); - } - - Widget _getFilteredResults(PatchesSelectorViewModel model) { - _items.clear(); - return Expanded( - child: ListView.builder( - itemCount: model.patches.length, - itemBuilder: (context, index) { - model.patches.sort((a, b) => a.simpleName.compareTo(b.simpleName)); - if (model.patches[index].simpleName.toLowerCase().contains( - query.toLowerCase(), - )) { - PatchItem item = PatchItem( - name: model.patches[index].name, - simpleName: model.patches[index].simpleName, - version: model.patches[index].version, - description: model.patches[index].description, - isSelected: model.isSelected(index), - onChanged: (value) => model.selectPatch(index, value), - ); - _items.add(item); - return item; - } else { - return const SizedBox(); - } - }, - ), - ); - } } diff --git a/lib/ui/views/patches_selector/patches_selector_viewmodel.dart b/lib/ui/views/patches_selector/patches_selector_viewmodel.dart index a0ee4195..79f53cb0 100644 --- a/lib/ui/views/patches_selector/patches_selector_viewmodel.dart +++ b/lib/ui/views/patches_selector/patches_selector_viewmodel.dart @@ -14,6 +14,7 @@ class PatchesSelectorViewModel extends BaseViewModel { patches.addAll(await _patcherAPI.getFilteredPatches( locator().selectedApp, )); + patches.sort((a, b) => a.simpleName.compareTo(b.simpleName)); for (Patch p in patches) { if (p.include) { selectedPatches.add(p); @@ -22,14 +23,13 @@ class PatchesSelectorViewModel extends BaseViewModel { notifyListeners(); } - bool isSelected(int index) { + bool isSelected(Patch patch) { return selectedPatches.any( - (element) => element.name == patches[index].name, + (element) => element.name == patch.name, ); } - void selectPatch(int index, bool isSelected) { - Patch patch = patches.firstWhere((p) => p.name == patches[index].name); + void selectPatch(Patch patch, bool isSelected) { if (isSelected && !selectedPatches.contains(patch)) { selectedPatches.add(patch); } else { @@ -50,4 +50,15 @@ class PatchesSelectorViewModel extends BaseViewModel { locator().selectedPatches = selectedPatches; locator().notifyListeners(); } + + List getFilteredPatches(String query) { + return patches + .where((patch) => + query.isEmpty || + query.length < 2 || + patch.simpleName.toLowerCase().contains( + query.toLowerCase(), + )) + .toList(); + } }