From 0362cdf8ac297ecb46a9f3e9dfad1986cdcfffea Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 25 Aug 2022 14:26:15 -0400 Subject: [PATCH] Added update all button + Obtainium added by default --- lib/main.dart | 13 ++++- lib/pages/apps.dart | 96 +++++++++++++++++++-------------- lib/services/apps_provider.dart | 17 ++++-- pubspec.yaml | 2 +- 4 files changed, 82 insertions(+), 46 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 53a0dd8..8b868fe 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -22,7 +22,7 @@ void backgroundUpdateCheck() { important: false); try { await appsProvider.loadApps(); - List updates = await appsProvider.getUpdates(); + List updates = await appsProvider.checkUpdates(); if (updates.isNotEmpty) { String message = updates.length == 1 ? '${updates[0].name} has an update.' @@ -87,13 +87,14 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return DynamicColorBuilder( builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) { + AppsProvider appsProvider = context.read(); + appsProvider.deleteSavedAPKs(); // Initialize the settings provider (if needed) and perform first-run actions if needed SettingsProvider settingsProvider = context.watch(); if (settingsProvider.prefs == null) { settingsProvider.initializeSettings().then((_) { bool isFirstRun = settingsProvider.checkAndFlipFirstRun(); if (isFirstRun) { - AppsProvider appsProvider = context.read(); appsProvider .notify( 3, @@ -106,6 +107,14 @@ class MyApp extends StatelessWidget { .whenComplete(() { appsProvider.downloaderNotifications.cancel(3); }); + appsProvider.saveApp(App( + 'imranr98_obtainium_github', + 'https://github.com/ImranR98/Obtainium', + 'ImranR98', + 'Obtainium', + 'v0.1.0-beta', // KEEP THIS IN SYNC WITH GITHUB RELEASES + 'v0.1.0-beta', + '')); } }); } diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 2884ed6..d382709 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -14,46 +14,62 @@ class _AppsPageState extends State { @override Widget build(BuildContext context) { var appsProvider = context.watch(); - appsProvider.getUpdates(); + appsProvider.checkUpdates(); + var existingUpdateAppIds = appsProvider.getExistingUpdates(); - return Center( - child: appsProvider.loadingApps - ? const CircularProgressIndicator() - : appsProvider.apps.isEmpty - ? Text( - 'No Apps', - style: Theme.of(context).textTheme.headline4, - ) - : RefreshIndicator( - onRefresh: appsProvider.getUpdates, - child: ListView( - children: appsProvider.apps.values - .map( - (e) => ListTile( - title: Text('${e.app.author}/${e.app.name}'), - subtitle: - Text(e.app.installedVersion ?? 'Not Installed'), - trailing: e.downloadProgress != null - ? Text( - 'Downloading - ${e.downloadProgress!.toInt()}%') - : (e.app.installedVersion != null && - e.app.installedVersion != - e.app.latestVersion - ? const Text('Update Available') - : null), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - AppPage(appId: e.app.id)), - ); - }, - ), - ) - .toList(), - ), - ), - ); + return Scaffold( + floatingActionButton: existingUpdateAppIds.isEmpty + ? null + : ElevatedButton.icon( + onPressed: appsProvider.apps.values + .where((element) => element.downloadProgress != null) + .isNotEmpty + ? null + : () { + for (var e in existingUpdateAppIds) { + appsProvider.downloadAndInstallLatestApp(e); + } + }, + icon: const Icon(Icons.update), + label: const Text('Update All')), + body: Center( + child: appsProvider.loadingApps + ? const CircularProgressIndicator() + : appsProvider.apps.isEmpty + ? Text( + 'No Apps', + style: Theme.of(context).textTheme.headline4, + ) + : RefreshIndicator( + onRefresh: appsProvider.checkUpdates, + child: ListView( + children: appsProvider.apps.values + .map( + (e) => ListTile( + title: Text('${e.app.author}/${e.app.name}'), + subtitle: Text( + e.app.installedVersion ?? 'Not Installed'), + trailing: e.downloadProgress != null + ? Text( + 'Downloading - ${e.downloadProgress!.toInt()}%') + : (e.app.installedVersion != null && + e.app.installedVersion != + e.app.latestVersion + ? const Text('Update Available') + : null), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + AppPage(appId: e.app.id)), + ); + }, + ), + ) + .toList(), + ), + ), + )); } } diff --git a/lib/services/apps_provider.dart b/lib/services/apps_provider.dart index 4320442..1631e62 100644 --- a/lib/services/apps_provider.dart +++ b/lib/services/apps_provider.dart @@ -132,6 +132,15 @@ class AppsProvider with ChangeNotifier { return appsDir; } + Future deleteSavedAPKs() async { + (await getExternalStorageDirectory()) + ?.listSync() + .where((element) => element.path.endsWith('.apk')) + .forEach((element) { + element.deleteSync(); + }); + } + Future loadApps() async { loadingApps = true; notifyListeners(); @@ -186,7 +195,7 @@ class AppsProvider with ChangeNotifier { return null; } - Future> getUpdates() async { + Future> checkUpdates() async { List updates = []; if (!gettingUpdates) { gettingUpdates = true; @@ -203,14 +212,16 @@ class AppsProvider with ChangeNotifier { return updates; } - Future installUpdates() async { + List getExistingUpdates() { + List updateAppIds = []; List appIds = apps.keys.toList(); for (int i = 0; i < appIds.length; i++) { App? app = apps[appIds[i]]!.app; if (app.installedVersion != app.latestVersion) { - await downloadAndInstallLatestApp(app.id); + updateAppIds.add(app.id); } } + return updateAppIds; } @override diff --git a/pubspec.yaml b/pubspec.yaml index 76a4f7f..1b784ca 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.1.0+1 +version: 0.1.0+1 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.19.0-79.0.dev <3.0.0'