From 26f953dbb026675ca49790394e2adde7ba81b7ba Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 21 Dec 2022 03:57:08 -0500 Subject: [PATCH] Category displayed on App/Apps pages + category save bugfix --- lib/pages/app.dart | 60 ++++++++- lib/pages/apps.dart | 194 ++++++++++++++++------------- lib/providers/source_provider.dart | 4 +- 3 files changed, 168 insertions(+), 90 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 0434964..913a5ea 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -1,6 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; 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/custom_errors.dart'; import 'package:obtainium/main.dart'; @@ -33,6 +34,7 @@ class _AppPageState extends State { }); } + var categories = settingsProvider.categories; var sourceProvider = SourceProvider(); AppInMemory? app = appsProvider.apps[widget.appId]; var source = app != null ? sourceProvider.getSource(app.app.url) : null; @@ -148,7 +150,63 @@ class _AppPageState extends State { textAlign: TextAlign.center, style: const TextStyle( fontStyle: FontStyle.italic, fontSize: 12), - ) + ), + const SizedBox( + height: 32, + ), + app?.app.category != null + ? Chip( + label: Text(app!.app.category!), + backgroundColor: + Color(categories[app.app.category!] ?? 0x0), + onDeleted: () { + app.app.category = null; + appsProvider.saveApps([app.app]); + }, + visualDensity: VisualDensity.compact, + ) + : Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton( + onPressed: () { + showDialog?>( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: 'Pick a Category', + items: [ + [ + GeneratedFormItem( + 'category', // TODO + label: 'Category', + opts: [ + MapEntry('', + 'No Category'), + ...categories + .entries + .map((e) => + MapEntry( + e.key, + e.key)) + .toList() + ]) + ] + ]); + }).then((value) { + if (value != null && app != null) { + String? cat = (value['category'] + ?.isNotEmpty ?? + false) + ? value['category'] + : null; + app.app.category = cat; + appsProvider.saveApps([app.app]); + } + }); + }, + child: const Text('Categorize')) // TODO + ]) ], )), ], diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 71f3cb9..45fe128 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -225,96 +225,114 @@ class AppsPageState extends State { String? changesUrl = SourceProvider() .getSource(sortedApps[index].app.url) .changeLogPageFromStandardUrl(sortedApps[index].app.url); - return ListTile( - tileColor: sortedApps[index].app.pinned - ? Colors.grey.withOpacity(0.1) - : Colors.transparent, - selectedTileColor: Theme.of(context) - .colorScheme - .primary - .withOpacity(sortedApps[index].app.pinned ? 0.2 : 0.1), - selected: selectedApps.contains(sortedApps[index].app), - onLongPress: () { - toggleAppSelected(sortedApps[index].app); - }, - leading: sortedApps[index].installedInfo != null - ? Image.memory( - sortedApps[index].installedInfo!.icon!, - gaplessPlayback: true, - ) - : null, - title: Text( - sortedApps[index].installedInfo?.name ?? - sortedApps[index].app.name, - style: TextStyle( - fontWeight: sortedApps[index].app.pinned - ? FontWeight.bold - : FontWeight.normal), - ), - subtitle: Text(tr('byX', args: [sortedApps[index].app.author]), - style: TextStyle( + return Container( + decoration: BoxDecoration( + border: Border.symmetric( + vertical: BorderSide( + width: 3, + color: Color(settingsProvider.categories[ + sortedApps[index].app.category] ?? + const Color.fromARGB(0, 0, 0, 0).value)))), + child: ListTile( + tileColor: sortedApps[index].app.pinned + ? Colors.grey.withOpacity(0.1) + : Colors.transparent, + selectedTileColor: Theme.of(context) + .colorScheme + .primary + .withOpacity(sortedApps[index].app.pinned ? 0.2 : 0.1), + selected: selectedApps.contains(sortedApps[index].app), + onLongPress: () { + toggleAppSelected(sortedApps[index].app); + }, + leading: sortedApps[index].installedInfo != null + ? Image.memory( + sortedApps[index].installedInfo!.icon!, + gaplessPlayback: true, + ) + : null, + title: Text( + sortedApps[index].installedInfo?.name ?? + sortedApps[index].app.name, + style: TextStyle( fontWeight: sortedApps[index].app.pinned ? FontWeight.bold - : FontWeight.normal)), - trailing: SingleChildScrollView( - reverse: true, - child: sortedApps[index].downloadProgress != null - ? Text(tr('percentProgress', args: [ - sortedApps[index] - .downloadProgress - ?.toInt() - .toString() ?? - '100' - ])) - : (Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - SizedBox( - width: 100, - child: Text( - '${sortedApps[index].app.installedVersion ?? tr('notInstalled')}${sortedApps[index].app.additionalSettings['trackOnly'] == 'true' ? ' ${tr('estimateInBrackets')}' : ''}', - overflow: TextOverflow.fade, - textAlign: TextAlign.end, - )), - sortedApps[index].app.installedVersion != null && - sortedApps[index].app.installedVersion != - sortedApps[index].app.latestVersion - ? GestureDetector( - onTap: changesUrl == null - ? null - : () { - launchUrlString(changesUrl, - mode: LaunchMode - .externalApplication); - }, - child: appsProvider.areDownloadsRunning() - ? Text(tr('pleaseWait')) - : Text( - '${tr('updateAvailable')}${sortedApps[index].app.additionalSettings['trackOnly'] == 'true' ? ' ${tr('estimateInBracketsShort')}' : ''}', - style: TextStyle( - fontStyle: FontStyle.italic, - decoration: changesUrl == null - ? TextDecoration.none - : TextDecoration - .underline), - )) - : const SizedBox(), - ], - ))), - onTap: () { - if (selectedApps.isNotEmpty) { - toggleAppSelected(sortedApps[index].app); - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - AppPage(appId: sortedApps[index].app.id)), - ); - } - }, - ); + : FontWeight.normal, + ), + ), + subtitle: Text( + tr('byX', args: [sortedApps[index].app.author]), + style: TextStyle( + fontWeight: sortedApps[index].app.pinned + ? FontWeight.bold + : FontWeight.normal)), + trailing: SingleChildScrollView( + reverse: true, + child: sortedApps[index].downloadProgress != null + ? Text(tr('percentProgress', args: [ + sortedApps[index] + .downloadProgress + ?.toInt() + .toString() ?? + '100' + ])) + : (Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + SizedBox( + width: 100, + child: Text( + '${sortedApps[index].app.installedVersion ?? tr('notInstalled')}${sortedApps[index].app.additionalSettings['trackOnly'] == 'true' ? ' ${tr('estimateInBrackets')}' : ''}', + overflow: TextOverflow.fade, + textAlign: TextAlign.end, + )), + sortedApps[index].app.installedVersion != + null && + sortedApps[index] + .app + .installedVersion != + sortedApps[index] + .app + .latestVersion + ? GestureDetector( + onTap: changesUrl == null + ? null + : () { + launchUrlString(changesUrl, + mode: LaunchMode + .externalApplication); + }, + child: appsProvider + .areDownloadsRunning() + ? Text(tr('pleaseWait')) + : Text( + '${tr('updateAvailable')}${sortedApps[index].app.additionalSettings['trackOnly'] == 'true' ? ' ${tr('estimateInBracketsShort')}' : ''}', + style: TextStyle( + fontStyle: + FontStyle.italic, + decoration: changesUrl == + null + ? TextDecoration.none + : TextDecoration + .underline), + )) + : const SizedBox(), + ], + ))), + onTap: () { + if (selectedApps.isNotEmpty) { + toggleAppSelected(sortedApps[index].app); + } else { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + AppPage(appId: sortedApps[index].app.id)), + ); + } + }, + )); }, childCount: sortedApps.length)) ])), persistentFooterButtons: [ diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 0160004..7d2fc4a 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -19,6 +19,7 @@ import 'package:obtainium/app_sources/steammobile.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart'; +import 'package:obtainium/providers/settings_provider.dart'; class AppNames { late String author; @@ -354,7 +355,8 @@ class SourceProvider { apk.apkUrls.length - 1, additionalSettings, DateTime.now(), - currentApp?.pinned ?? false); + currentApp?.pinned ?? false, + category: currentApp?.category); } // Returns errors in [results, errors] instead of throwing them