From 81f66683d2ac721079a019d32988fed35eac3fb1 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 00:02:23 -0400 Subject: [PATCH 1/3] Less restrictive install permission requests (#488) --- lib/pages/add_app.dart | 3 --- lib/pages/app.dart | 3 --- lib/pages/apps.dart | 11 ++++++----- lib/providers/settings_provider.dart | 5 ++++- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 625e5dd..5f5400c 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -124,9 +124,6 @@ class _AddAppPageState extends State { pickedSource!, userInput, additionalSettings, trackOnlyOverride: trackOnly, overrideSource: pickedSourceOverride); - if (!trackOnly) { - await settingsProvider.getInstallPermission(); - } // Only download the APK here if you need to for the package ID if (sourceProvider.isTempId(app) && app.additionalSettings['trackOnly'] != true) { diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 3e4c3aa..8f851e5 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -327,9 +327,6 @@ class _AppPageState extends State { ? () async { try { HapticFeedback.heavyImpact(); - if (app?.app.additionalSettings['trackOnly'] != true) { - await settingsProvider.getInstallPermission(); - } var res = await appsProvider.downloadAndInstallLatestApps( [app!.app.id], globalNavigatorKey.currentContext); if (res.isNotEmpty && mounted) { diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index e00dae2..11c69da 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -624,11 +624,6 @@ class AppsPageState extends State { bool shouldInstallNew = values['installs'] == true; bool shouldMarkTrackOnlies = values['trackonlies'] == true; (() async { - if (shouldInstallNew || shouldInstallUpdates) { - await settingsProvider.getInstallPermission(); - } - })() - .then((_) { List toInstall = []; if (shouldInstallUpdates) { toInstall.addAll(existingUpdateIdsAllOrSelected); @@ -639,6 +634,12 @@ class AppsPageState extends State { if (shouldMarkTrackOnlies) { toInstall.addAll(trackOnlyUpdateIdsAllOrSelected); } + if (toInstall.length > 1) { + // Permission is requested automatically, but if there are more than 1 installs, + // We want to explicitly request it and wait for the result to avoid multiple requests + await settingsProvider.getInstallPermission( + enforce: false); + } appsProvider .downloadAndInstallLatestApps( toInstall, globalNavigatorKey.currentContext) diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 7fe5693..3be2151 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -120,7 +120,7 @@ class SettingsProvider with ChangeNotifier { return result; } - Future getInstallPermission() async { + Future getInstallPermission({bool enforce = false}) async { while (!(await Permission.requestInstallPackages.isGranted)) { // Explicit request as InstallPlugin request sometimes bugged Fluttertoast.showToast( @@ -129,6 +129,9 @@ class SettingsProvider with ChangeNotifier { PermissionStatus.granted) { break; } + if (!enforce) { + break; + } } } From 04b3c8ad7d1f0414cd25d5984d5d91be4575dcea Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 00:15:53 -0400 Subject: [PATCH 2/3] Bugfix for prev. commit --- lib/pages/apps.dart | 41 ++++++++++++---------------- lib/providers/apps_provider.dart | 8 +++++- lib/providers/settings_provider.dart | 7 +++-- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 11c69da..c240676 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -615,7 +615,7 @@ class AppsPageState extends State { items: formItems.map((e) => [e]).toList(), initValid: true, ); - }).then((values) { + }).then((values) async { if (values != null) { if (values.isEmpty) { values = getDefaultValuesFromFormItems([formItems]); @@ -623,29 +623,22 @@ class AppsPageState extends State { bool shouldInstallUpdates = values['updates'] == true; bool shouldInstallNew = values['installs'] == true; bool shouldMarkTrackOnlies = values['trackonlies'] == true; - (() async { - List toInstall = []; - if (shouldInstallUpdates) { - toInstall.addAll(existingUpdateIdsAllOrSelected); - } - if (shouldInstallNew) { - toInstall.addAll(newInstallIdsAllOrSelected); - } - if (shouldMarkTrackOnlies) { - toInstall.addAll(trackOnlyUpdateIdsAllOrSelected); - } - if (toInstall.length > 1) { - // Permission is requested automatically, but if there are more than 1 installs, - // We want to explicitly request it and wait for the result to avoid multiple requests - await settingsProvider.getInstallPermission( - enforce: false); - } - appsProvider - .downloadAndInstallLatestApps( - toInstall, globalNavigatorKey.currentContext) - .catchError((e) { - showError(e, context); - }); + List toInstall = []; + if (shouldInstallUpdates) { + toInstall.addAll(existingUpdateIdsAllOrSelected); + } + if (shouldInstallNew) { + toInstall.addAll(newInstallIdsAllOrSelected); + } + if (shouldMarkTrackOnlies) { + toInstall.addAll(trackOnlyUpdateIdsAllOrSelected); + } + appsProvider + .downloadAndInstallLatestApps( + toInstall, globalNavigatorKey.currentContext, + settingsProvider: settingsProvider) + .catchError((e) { + showError(e, context); }); } }); diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 46d57c4..6af3f10 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -351,7 +351,8 @@ class AppsProvider with ChangeNotifier { // If user input is needed and the App is in the background, a notification is sent to get the user's attention // Returns an array of Ids for Apps that were successfully downloaded, regardless of installation result Future> downloadAndInstallLatestApps( - List appIds, BuildContext? context) async { + List appIds, BuildContext? context, + {SettingsProvider? settingsProvider}) async { List appsToInstall = []; List trackOnlyAppsToUpdate = []; // For all specified Apps, filter out those for which: @@ -440,6 +441,11 @@ class AppsProvider with ChangeNotifier { silentUpdates = moveObtainiumToStart(silentUpdates); regularInstalls = moveObtainiumToStart(regularInstalls); + if (!(await settingsProvider?.getInstallPermission(enforce: false) ?? + true)) { + throw ObtainiumError(tr('cancelled')); + } + // // Install silent updates (uncomment when it works - TODO) // for (var u in silentUpdates) { // await installApk(u, silent: true); // Would need to add silent option diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 3be2151..2bc3005 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -120,19 +120,20 @@ class SettingsProvider with ChangeNotifier { return result; } - Future getInstallPermission({bool enforce = false}) async { + Future getInstallPermission({bool enforce = false}) async { while (!(await Permission.requestInstallPackages.isGranted)) { // Explicit request as InstallPlugin request sometimes bugged Fluttertoast.showToast( msg: tr('pleaseAllowInstallPerm'), toastLength: Toast.LENGTH_LONG); if ((await Permission.requestInstallPackages.request()) == PermissionStatus.granted) { - break; + return true; } if (!enforce) { - break; + return false; } } + return true; } bool get showAppWebpage { From dd19fcf6da1643f16ef6b84228558b622ee5996a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 00:58:32 -0400 Subject: [PATCH 3/3] Add warning popup toggles + fix breaking bug in add app --- assets/translations/de.json | 4 ++ assets/translations/en.json | 3 ++ assets/translations/fa.json | 4 ++ assets/translations/fr.json | 4 ++ assets/translations/hu.json | 4 ++ assets/translations/it.json | 4 ++ assets/translations/ja.json | 4 ++ assets/translations/zh.json | 4 ++ lib/pages/add_app.dart | 62 +++++++++++++++++++--------- lib/pages/settings.dart | 28 +++++++++++++ lib/providers/apps_provider.dart | 17 ++++---- lib/providers/settings_provider.dart | 18 ++++++++ lib/providers/source_provider.dart | 2 +- pubspec.yaml | 2 +- 14 files changed, 132 insertions(+), 28 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index c89f6db..f1d1f68 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -224,6 +224,10 @@ "standardVersionDetection": "Standardversionserkennung", "groupByCategory": "Nach Kategorie gruppieren", "autoApkFilterByArch": "Nach Möglichkeit versuchen, APKs nach CPU-Architektur zu filtern", + "overrideSource": "Override Source", + "dontShowAgain": "Don't show this again", + "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", + "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 8654d1d..58878ff 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -225,6 +225,9 @@ "groupByCategory": "Group by Category", "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", "overrideSource": "Override Source", + "dontShowAgain": "Don't show this again", + "dontShowTrackOnlyWarnings": "Don't Show 'Track-Only' Warnings", + "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 6aeee69..7b48c7d 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -224,6 +224,10 @@ "standardVersionDetection": "تشخیص نسخه استاندارد", "groupByCategory": "گروه بر اساس دسته", "autoApkFilterByArch": "در صورت امکان سعی کنید APKها را بر اساس معماری CPU فیلتر کنید", + "overrideSource": "Override Source", + "dontShowAgain": "Don't show this again", + "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", + "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 95a73ee..27dbd45 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -224,6 +224,10 @@ "standardVersionDetection": "Détection de version standard", "groupByCategory": "Group by Category", "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", + "overrideSource": "Override Source", + "dontShowAgain": "Don't show this again", + "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", + "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 30b3418..0355e37 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -223,6 +223,10 @@ "standardVersionDetection": "Alapért. verzió érzékelés", "groupByCategory": "Csoportosítás Kategória alapján", "autoApkFilterByArch": "Ha lehetséges, próbálja CPU architektúra szerint szűrni az APK-kat", + "overrideSource": "Override Source", + "dontShowAgain": "Don't show this again", + "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", + "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" diff --git a/assets/translations/it.json b/assets/translations/it.json index e212184..1b122d5 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -224,6 +224,10 @@ "standardVersionDetection": "Rilevamento di versione standard", "groupByCategory": "Raggruppa per categoria", "autoApkFilterByArch": "Tenta di filtrare gli APK in base all'architettura della CPU, se possibile", + "overrideSource": "Override Source", + "dontShowAgain": "Don't show this again", + "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", + "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 2de9a3c..262fffe 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -224,6 +224,10 @@ "standardVersionDetection": "標準のバージョン検出", "groupByCategory": "カテゴリ別にグループ化する", "autoApkFilterByArch": "可能であれば,CPUアーキテクチャによるAPKのフィルタリングを試みる", + "overrideSource": "Override Source", + "dontShowAgain": "Don't show this again", + "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", + "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 4a555a9..a430229 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -224,6 +224,10 @@ "standardVersionDetection": "常规版本检测", "groupByCategory": "按类别分组显示", "autoApkFilterByArch": "如果可能,尝试按 CPU 架构筛选 APK 文件", + "overrideSource": "Override Source", + "dontShowAgain": "Don't show this again", + "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", + "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 5f5400c..768f7e7 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -52,6 +52,18 @@ class _AddAppPageState extends State { searchnum++; } var prevHost = pickedSource?.host; + try { + var naturalSource = + valid ? sourceProvider.getSource(userInput) : null; + if (naturalSource != null && + naturalSource.runtimeType.toString() != + HTML().runtimeType.toString()) { + // If input has changed to match a regular source, reset the override + pickedSourceOverride = null; + } + } catch (e) { + // ignore + } var source = valid ? sourceProvider.getSource(userInput, overrideSource: pickedSourceOverride) @@ -71,24 +83,35 @@ class _AddAppPageState extends State { } } - getTrackOnlyConfirmationIfNeeded(bool userPickedTrackOnly) async { - return (!((userPickedTrackOnly || pickedSource!.enforceTrackOnly) && - // ignore: use_build_context_synchronously - await showDialog( - context: context, - builder: (BuildContext ctx) { - return GeneratedFormModal( - title: tr('xIsTrackOnly', args: [ - pickedSource!.enforceTrackOnly - ? tr('source') - : tr('app') - ]), - items: const [], - message: - '${pickedSource!.enforceTrackOnly ? tr('appsFromSourceAreTrackOnly') : tr('youPickedTrackOnly')}\n\n${tr('trackOnlyAppDescription')}', - ); - }) == - null)); + Future getTrackOnlyConfirmationIfNeeded( + bool userPickedTrackOnly, SettingsProvider settingsProvider, + {bool ignoreHideSetting = false}) async { + var useTrackOnly = userPickedTrackOnly || pickedSource!.enforceTrackOnly; + if (useTrackOnly && + (!settingsProvider.hideTrackOnlyWarning || ignoreHideSetting)) { + // ignore: use_build_context_synchronously + var values = await showDialog( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + initValid: true, + title: tr('xIsTrackOnly', args: [ + pickedSource!.enforceTrackOnly ? tr('source') : tr('app') + ]), + items: [ + [GeneratedFormSwitch('hide', label: tr('dontShowAgain'))] + ], + message: + '${pickedSource!.enforceTrackOnly ? tr('appsFromSourceAreTrackOnly') : tr('youPickedTrackOnly')}\n\n${tr('trackOnlyAppDescription')}', + ); + }); + if (values != null) { + settingsProvider.hideTrackOnlyWarning = values['hide'] == true; + } + return useTrackOnly && values != null; + } else { + return true; + } } getReleaseDateAsVersionConfirmationIfNeeded( @@ -116,7 +139,8 @@ class _AddAppPageState extends State { var settingsProvider = context.read(); var userPickedTrackOnly = additionalSettings['trackOnly'] == true; App? app; - if ((await getTrackOnlyConfirmationIfNeeded(userPickedTrackOnly)) && + if ((await getTrackOnlyConfirmationIfNeeded( + userPickedTrackOnly, settingsProvider)) && (await getReleaseDateAsVersionConfirmationIfNeeded( userPickedTrackOnly))) { var trackOnly = pickedSource!.enforceTrackOnly || userPickedTrackOnly; diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 2c4aeb0..a3808e8 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -286,6 +286,34 @@ class _SettingsPageState extends State { }) ], ), + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(tr('dontShowTrackOnlyWarnings')), + Switch( + value: + settingsProvider.hideTrackOnlyWarning, + onChanged: (value) { + settingsProvider.hideTrackOnlyWarning = + value; + }) + ], + ), + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(tr('dontShowAPKOriginWarnings')), + Switch( + value: + settingsProvider.hideAPKOriginWarning, + onChanged: (value) { + settingsProvider.hideAPKOriginWarning = + value; + }) + ], + ), const Divider( height: 16, ), diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 6af3f10..aff7412 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -332,13 +332,16 @@ class AppsProvider with ChangeNotifier { getHost(apkUrl.value) != getHost(app.url) && context != null) { // ignore: use_build_context_synchronously - if (await showDialog( - context: context, - builder: (BuildContext ctx) { - return APKOriginWarningDialog( - sourceUrl: app.url, apkUrl: apkUrl!.value); - }) != - true) { + var settingsProvider = context.read(); + if (!(settingsProvider.hideAPKOriginWarning) && + // ignore: use_build_context_synchronously + await showDialog( + context: context, + builder: (BuildContext ctx) { + return APKOriginWarningDialog( + sourceUrl: app.url, apkUrl: apkUrl!.value); + }) != + true) { apkUrl = null; } } diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 2bc3005..6c08d5f 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -163,6 +163,24 @@ class SettingsProvider with ChangeNotifier { notifyListeners(); } + bool get hideTrackOnlyWarning { + return prefs?.getBool('hideTrackOnlyWarning') ?? false; + } + + set hideTrackOnlyWarning(bool show) { + prefs?.setBool('hideTrackOnlyWarning', show); + notifyListeners(); + } + + bool get hideAPKOriginWarning { + return prefs?.getBool('hideAPKOriginWarning') ?? false; + } + + set hideAPKOriginWarning(bool show) { + prefs?.setBool('hideAPKOriginWarning', show); + notifyListeners(); + } + String? getSettingString(String settingId) { return prefs?.getString(settingId); } diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 367e559..2606a37 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -470,7 +470,7 @@ class SourceProvider { } AppSource? source; for (var s in sources.where((element) => element.host != null)) { - if (RegExp('://${s.host}').hasMatch(url)) { + if (RegExp('://${s.host}(/|\\z)?').hasMatch(url)) { source = s; break; } diff --git a/pubspec.yaml b/pubspec.yaml index e62f283..e817d41 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.12.0+159 # When changing this, update the tag in main() accordingly +version: 0.12.0+160 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0'