mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-10-31 13:33:28 +01:00 
			
		
		
		
	Merge pull request #504 from ImranR98/dev
Less restrictive install permission requests (#495) Add toggles to disable warnings (#495 Fix a breaking bug on Add App page from the previous PR
This commit is contained in:
		| @@ -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?" | ||||
|   | ||||
| @@ -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?" | ||||
|   | ||||
| @@ -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": "برنامه ها حذف شوند؟" | ||||
|   | ||||
| @@ -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 ?" | ||||
|   | ||||
| @@ -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?" | ||||
|   | ||||
| @@ -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?" | ||||
|   | ||||
| @@ -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": "アプリを削除しますか?" | ||||
|   | ||||
| @@ -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": "是否删除应用?" | ||||
|   | ||||
| @@ -52,6 +52,18 @@ class _AddAppPageState extends State<AddAppPage> { | ||||
|             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<AddAppPage> { | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     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<bool> 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<AddAppPage> { | ||||
|         var settingsProvider = context.read<SettingsProvider>(); | ||||
|         var userPickedTrackOnly = additionalSettings['trackOnly'] == true; | ||||
|         App? app; | ||||
|         if ((await getTrackOnlyConfirmationIfNeeded(userPickedTrackOnly)) && | ||||
|         if ((await getTrackOnlyConfirmationIfNeeded( | ||||
|                 userPickedTrackOnly, settingsProvider)) && | ||||
|             (await getReleaseDateAsVersionConfirmationIfNeeded( | ||||
|                 userPickedTrackOnly))) { | ||||
|           var trackOnly = pickedSource!.enforceTrackOnly || userPickedTrackOnly; | ||||
| @@ -124,9 +148,6 @@ class _AddAppPageState extends State<AddAppPage> { | ||||
|               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) { | ||||
|   | ||||
| @@ -327,9 +327,6 @@ class _AppPageState extends State<AppPage> { | ||||
|             ? () 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) { | ||||
|   | ||||
| @@ -615,7 +615,7 @@ class AppsPageState extends State<AppsPage> { | ||||
|                       items: formItems.map((e) => [e]).toList(), | ||||
|                       initValid: true, | ||||
|                     ); | ||||
|                   }).then((values) { | ||||
|                   }).then((values) async { | ||||
|                 if (values != null) { | ||||
|                   if (values.isEmpty) { | ||||
|                     values = getDefaultValuesFromFormItems([formItems]); | ||||
| @@ -623,28 +623,22 @@ class AppsPageState extends State<AppsPage> { | ||||
|                   bool shouldInstallUpdates = values['updates'] == true; | ||||
|                   bool shouldInstallNew = values['installs'] == true; | ||||
|                   bool shouldMarkTrackOnlies = values['trackonlies'] == true; | ||||
|                   (() async { | ||||
|                     if (shouldInstallNew || shouldInstallUpdates) { | ||||
|                       await settingsProvider.getInstallPermission(); | ||||
|                     } | ||||
|                   })() | ||||
|                       .then((_) { | ||||
|                     List<String> toInstall = []; | ||||
|                     if (shouldInstallUpdates) { | ||||
|                       toInstall.addAll(existingUpdateIdsAllOrSelected); | ||||
|                     } | ||||
|                     if (shouldInstallNew) { | ||||
|                       toInstall.addAll(newInstallIdsAllOrSelected); | ||||
|                     } | ||||
|                     if (shouldMarkTrackOnlies) { | ||||
|                       toInstall.addAll(trackOnlyUpdateIdsAllOrSelected); | ||||
|                     } | ||||
|                     appsProvider | ||||
|                         .downloadAndInstallLatestApps( | ||||
|                             toInstall, globalNavigatorKey.currentContext) | ||||
|                         .catchError((e) { | ||||
|                       showError(e, context); | ||||
|                     }); | ||||
|                   List<String> 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); | ||||
|                   }); | ||||
|                 } | ||||
|               }); | ||||
|   | ||||
| @@ -286,6 +286,34 @@ class _SettingsPageState extends State<SettingsPage> { | ||||
|                                     }) | ||||
|                               ], | ||||
|                             ), | ||||
|                             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, | ||||
|                             ), | ||||
|   | ||||
| @@ -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<SettingsProvider>(); | ||||
|       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; | ||||
|       } | ||||
|     } | ||||
| @@ -351,7 +354,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<List<String>> downloadAndInstallLatestApps( | ||||
|       List<String> appIds, BuildContext? context) async { | ||||
|       List<String> appIds, BuildContext? context, | ||||
|       {SettingsProvider? settingsProvider}) async { | ||||
|     List<String> appsToInstall = []; | ||||
|     List<String> trackOnlyAppsToUpdate = []; | ||||
|     // For all specified Apps, filter out those for which: | ||||
| @@ -440,6 +444,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 | ||||
|   | ||||
| @@ -120,16 +120,20 @@ class SettingsProvider with ChangeNotifier { | ||||
|     return result; | ||||
|   } | ||||
|  | ||||
|   Future<void> getInstallPermission() async { | ||||
|   Future<bool> 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) { | ||||
|         return false; | ||||
|       } | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   bool get showAppWebpage { | ||||
| @@ -159,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); | ||||
|   } | ||||
|   | ||||
| @@ -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; | ||||
|       } | ||||
|   | ||||
| @@ -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' | ||||
|   | ||||
		Reference in New Issue
	
	Block a user