From fa2a80e34c3d86dab2a174e656b0299fdf6624eb Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 28 Jan 2023 00:04:57 -0500 Subject: [PATCH 001/600] APK RegEx Filter + Updated Packages --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/codeberg.dart | 10 +- lib/app_sources/github.dart | 10 +- lib/pages/add_app.dart | 2 + lib/pages/apps.dart | 1056 ++++++++++++++-------------- lib/pages/settings.dart | 2 - lib/providers/apps_provider.dart | 2 + lib/providers/source_provider.dart | 46 +- pubspec.lock | 372 ++++++---- 14 files changed, 830 insertions(+), 676 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 5a3bc13..ac7da30 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -211,6 +211,7 @@ "language": "Sprache", "storagePermissionDenied": "Storage permission denied", "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", + "filterAPKsByRegEx": "Filter APKs by Regular Expression", "tooManyRequestsTryAgainInMinutes": { "one": "Zu viele Anfragen (Rate begrenzt) - versuchen Sie es in {} Minute erneut", "other": "Zu viele Anfragen (Rate begrenzt) - versuchen Sie es in {} Minuten erneut" diff --git a/assets/translations/en.json b/assets/translations/en.json index 1fae8c8..274947e 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -211,6 +211,7 @@ "language": "Language", "storagePermissionDenied": "Storage permission denied", "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", + "filterAPKsByRegEx": "Filter APKs by Regular Expression", "tooManyRequestsTryAgainInMinutes": { "one": "Too many requests (rate limited) - try again in {} minute", "other": "Too many requests (rate limited) - try again in {} minutes" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 54e82e7..c6466fd 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -210,6 +210,7 @@ "language": "Nyelv", "storagePermissionDenied": "Tárhely engedély megtagadva", "selectedCategorizeWarning": "Ez felváltja a kiválasztott alkalmazások meglévő kategória-beállításait.", + "filterAPKsByRegEx": "Filter APKs by Regular Expression", "tooManyRequestsTryAgainInMinutes": { "one": "Túl sok kérés (korlátozott arány) – próbálja újra {} perc múlva", "other": "Túl sok kérés (korlátozott arány) – próbálja újra {} perc múlva" diff --git a/assets/translations/it.json b/assets/translations/it.json index a0f01f0..4a56c8a 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -211,6 +211,7 @@ "language": "Lingua", "storagePermissionDenied": "Storage permission denied", "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", + "filterAPKsByRegEx": "Filter APKs by Regular Expression", "tooManyRequestsTryAgainInMinutes": { "one": "Troppe richieste (traffico limitato) - riprova tra {} minuto", "other": "Troppe richieste (traffico limitato) - riprova tra {} minuti" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 7aadadb..ba1e5c1 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -211,6 +211,7 @@ "language": "言語", "storagePermissionDenied": "ストレージ権限が拒否されました", "selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。", + "filterAPKsByRegEx": "Filter APKs by Regular Expression", "tooManyRequestsTryAgainInMinutes": { "one": "リクエストが多すぎます(レート制限)- {}分後に再試行してください", "other": "リクエストが多すぎます(レート制限)- {}分後に再試行してください" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 0d271b1..8f103a8 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -211,6 +211,7 @@ "language": "语言", "storagePermissionDenied": "存储权限已被拒绝", "selectedCategorizeWarning": "这将取代所选应用程序的任何现有类别", + "filterAPKsByRegEx": "Filter APKs by Regular Expression", "tooManyRequestsTryAgainInMinutes": { "one": "请求过多 (API 限制) - 在 {} 分钟后重试", "other": "请求过多 (API 限制) - 在 {} 分钟后重试" diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index 1e38a4e..d00bcd8 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -26,15 +26,7 @@ class Codeberg extends AppSource { required: false, additionalValidators: [ (value) { - if (value == null || value.isEmpty) { - return null; - } - try { - RegExp(value); - } catch (e) { - return tr('invalidRegEx'); - } - return null; + return regExValidator(value); } ]) ] diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index f17adf9..1169d88 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -65,15 +65,7 @@ class GitHub extends AppSource { required: false, additionalValidators: [ (value) { - if (value == null || value.isEmpty) { - return null; - } - try { - RegExp(value); - } catch (e) { - return tr('invalidRegEx'); - } - return null; + return regExValidator(value); } ]) ] diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index ff3f75e..a216a7e 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -70,6 +70,7 @@ class _AddAppPageState extends State { additionalSettings['noVersionDetection'] == true; var cont = true; if ((userPickedTrackOnly || pickedSource!.enforceTrackOnly) && + // ignore: use_build_context_synchronously await showDialog( context: context, builder: (BuildContext ctx) { @@ -88,6 +89,7 @@ class _AddAppPageState extends State { cont = false; } if (userPickedNoVersionDetection && + // ignore: use_build_context_synchronously await showDialog( context: context, builder: (BuildContext ctx) { diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 1b422f8..56f569a 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -344,538 +344,564 @@ class AppsPageState extends State { )); }, childCount: sortedApps.length)) ])), - persistentFooterButtons: [ - Row( - children: [ - selectedApps.isEmpty - ? TextButton.icon( - style: - const ButtonStyle(visualDensity: VisualDensity.compact), - onPressed: () { - selectThese(sortedApps.map((e) => e.app).toList()); - }, - icon: Icon( - Icons.select_all_outlined, - color: Theme.of(context).colorScheme.primary, - ), - label: Text(sortedApps.length.toString())) - : TextButton.icon( - style: - const ButtonStyle(visualDensity: VisualDensity.compact), - onPressed: () { - selectedApps.isEmpty - ? selectThese(sortedApps.map((e) => e.app).toList()) - : clearSelected(); - }, - icon: Icon( - selectedApps.isEmpty - ? Icons.select_all_outlined - : Icons.deselect_outlined, - color: Theme.of(context).colorScheme.primary, - ), - label: Text(selectedApps.length.toString())), - const VerticalDivider(), - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - IconButton( - visualDensity: VisualDensity.compact, - onPressed: selectedApps.isEmpty - ? null - : () { - showDialog?>( - context: context, - builder: (BuildContext ctx) { - return GeneratedFormModal( - title: - tr('removeSelectedAppsQuestion'), - items: const [], - initValid: true, - message: tr( - 'xWillBeRemovedButRemainInstalled', - args: [ - plural( - 'apps', selectedApps.length) - ]), - ); - }).then((values) { - if (values != null) { - appsProvider.removeApps(selectedApps - .map((e) => e.id) - .toList()); - } - }); - }, - tooltip: tr('removeSelectedApps'), - icon: const Icon(Icons.delete_outline_outlined), - ), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: appsProvider.areDownloadsRunning() || - (existingUpdateIdsAllOrSelected.isEmpty && - newInstallIdsAllOrSelected.isEmpty && - trackOnlyUpdateIdsAllOrSelected.isEmpty) - ? null - : () { - HapticFeedback.heavyImpact(); - List formItems = []; - if (existingUpdateIdsAllOrSelected - .isNotEmpty) { - formItems.add(GeneratedFormSwitch( - 'updates', - label: tr('updateX', args: [ - plural( - 'apps', - existingUpdateIdsAllOrSelected - .length) - ]), - defaultValue: true)); - } - if (newInstallIdsAllOrSelected.isNotEmpty) { - formItems.add(GeneratedFormSwitch( - 'installs', - label: tr('installX', args: [ - plural( - 'apps', - newInstallIdsAllOrSelected - .length) - ]), - defaultValue: - existingUpdateIdsAllOrSelected - .isNotEmpty)); - } - if (trackOnlyUpdateIdsAllOrSelected - .isNotEmpty) { - formItems.add(GeneratedFormSwitch( - 'trackonlies', - label: tr('markXTrackOnlyAsUpdated', - args: [ - plural( - 'apps', - trackOnlyUpdateIdsAllOrSelected - .length) - ]), - defaultValue: - existingUpdateIdsAllOrSelected - .isNotEmpty || - newInstallIdsAllOrSelected - .isNotEmpty)); - } - showDialog?>( - context: context, - builder: (BuildContext ctx) { - var totalApps = - existingUpdateIdsAllOrSelected.length + - newInstallIdsAllOrSelected - .length + - trackOnlyUpdateIdsAllOrSelected - .length; - return GeneratedFormModal( - title: tr('changeX', args: [ - plural('apps', totalApps) - ]), - items: formItems - .map((e) => [e]) - .toList(), - initValid: true, - ); - }).then((values) { - if (values != null) { - if (values.isEmpty) { - values = - getDefaultValuesFromFormItems( - [formItems]); - } - bool shouldInstallUpdates = - values['updates'] == true; - bool shouldInstallNew = - values['installs'] == true; - bool shouldMarkTrackOnlies = - values['trackonlies'] == true; - (() async { - if (shouldInstallNew || - shouldInstallUpdates) { - await settingsProvider - .getInstallPermission(); + persistentFooterButtons: appsProvider.apps.isEmpty + ? null + : [ + Row( + children: [ + selectedApps.isEmpty + ? TextButton.icon( + style: const ButtonStyle( + visualDensity: VisualDensity.compact), + onPressed: () { + selectThese(sortedApps.map((e) => e.app).toList()); + }, + icon: Icon( + Icons.select_all_outlined, + color: Theme.of(context).colorScheme.primary, + ), + label: Text(sortedApps.length.toString())) + : TextButton.icon( + style: const ButtonStyle( + visualDensity: VisualDensity.compact), + onPressed: () { + selectedApps.isEmpty + ? selectThese( + sortedApps.map((e) => e.app).toList()) + : clearSelected(); + }, + icon: Icon( + selectedApps.isEmpty + ? Icons.select_all_outlined + : Icons.deselect_outlined, + color: Theme.of(context).colorScheme.primary, + ), + label: Text(selectedApps.length.toString())), + const VerticalDivider(), + Expanded( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + IconButton( + visualDensity: VisualDensity.compact, + onPressed: selectedApps.isEmpty + ? null + : () { + showDialog?>( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: tr( + 'removeSelectedAppsQuestion'), + items: const [], + initValid: true, + message: tr( + 'xWillBeRemovedButRemainInstalled', + args: [ + plural('apps', + selectedApps.length) + ]), + ); + }).then((values) { + if (values != null) { + appsProvider.removeApps(selectedApps + .map((e) => e.id) + .toList()); } - })() - .then((_) { - List 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); - }); }); - } - }); - }, - tooltip: selectedApps.isEmpty - ? tr('installUpdateApps') - : tr('installUpdateSelectedApps'), - icon: const Icon( - Icons.file_download_outlined, - )), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: selectedApps.isEmpty - ? null - : () async { - try { - Set? preselected; - var showPrompt = false; - for (var element in selectedApps) { - var currentCats = - element.categories.toSet(); - if (preselected == null) { - preselected = currentCats; - } else { - if (!settingsProvider.setEqual( - currentCats, preselected)) { - showPrompt = true; - break; - } - } - } - var cont = true; - if (showPrompt) { - cont = await showDialog< - Map?>( + }, + tooltip: tr('removeSelectedApps'), + icon: const Icon(Icons.delete_outline_outlined), + ), + IconButton( + visualDensity: VisualDensity.compact, + onPressed: appsProvider + .areDownloadsRunning() || + (existingUpdateIdsAllOrSelected + .isEmpty && + newInstallIdsAllOrSelected + .isEmpty && + trackOnlyUpdateIdsAllOrSelected + .isEmpty) + ? null + : () { + HapticFeedback.heavyImpact(); + List formItems = + []; + if (existingUpdateIdsAllOrSelected + .isNotEmpty) { + formItems.add(GeneratedFormSwitch( + 'updates', + label: tr('updateX', args: [ + plural( + 'apps', + existingUpdateIdsAllOrSelected + .length) + ]), + defaultValue: true)); + } + if (newInstallIdsAllOrSelected + .isNotEmpty) { + formItems.add(GeneratedFormSwitch( + 'installs', + label: tr('installX', args: [ + plural( + 'apps', + newInstallIdsAllOrSelected + .length) + ]), + defaultValue: + existingUpdateIdsAllOrSelected + .isNotEmpty)); + } + if (trackOnlyUpdateIdsAllOrSelected + .isNotEmpty) { + formItems.add(GeneratedFormSwitch( + 'trackonlies', + label: tr( + 'markXTrackOnlyAsUpdated', + args: [ + plural( + 'apps', + trackOnlyUpdateIdsAllOrSelected + .length) + ]), + defaultValue: + existingUpdateIdsAllOrSelected + .isNotEmpty || + newInstallIdsAllOrSelected + .isNotEmpty)); + } + showDialog?>( context: context, builder: (BuildContext ctx) { + var totalApps = existingUpdateIdsAllOrSelected + .length + + newInstallIdsAllOrSelected + .length + + trackOnlyUpdateIdsAllOrSelected + .length; return GeneratedFormModal( - title: tr('categorize'), - items: const [], + title: tr('changeX', args: [ + plural('apps', totalApps) + ]), + items: formItems + .map((e) => [e]) + .toList(), initValid: true, - message: tr( - 'selectedCategorizeWarning'), ); - }) != - null; - } - if (cont) { - await showDialog?>( - context: context, - builder: (BuildContext ctx) { - return GeneratedFormModal( - title: tr('categorize'), - items: const [], - initValid: true, - singleNullReturnButton: - tr('continue'), - additionalWidgets: [ - CategoryEditorSelector( - preselected: !showPrompt - ? preselected ?? {} - : {}, - showLabelWhenNotEmpty: false, - onSelected: (categories) { - appsProvider.saveApps( - selectedApps.map((e) { - e.categories = categories; - return e; - }).toList()); - }, - ) - ], - ); + }).then((values) { + if (values != null) { + if (values.isEmpty) { + values = + getDefaultValuesFromFormItems( + [formItems]); + } + bool shouldInstallUpdates = + values['updates'] == true; + 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); + } + if (shouldInstallNew) { + toInstall.addAll( + newInstallIdsAllOrSelected); + } + if (shouldMarkTrackOnlies) { + toInstall.addAll( + trackOnlyUpdateIdsAllOrSelected); + } + appsProvider + .downloadAndInstallLatestApps( + toInstall, + globalNavigatorKey + .currentContext) + .catchError((e) { + showError(e, context); + }); + }); + } }); - } - } catch (err) { - showError(err, context); - } - }, - tooltip: tr('categorize'), - icon: const Icon(Icons.category_outlined), - ), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: selectedApps.isEmpty - ? null - : () { - showDialog( - context: context, - builder: (BuildContext ctx) { - return AlertDialog( - scrollable: true, - content: Padding( - padding: - const EdgeInsets.only(top: 6), - child: Row( - mainAxisAlignment: - MainAxisAlignment - .spaceAround, - children: [ - IconButton( - onPressed: appsProvider - .areDownloadsRunning() - ? null - : () { - showDialog( - context: - context, - builder: - (BuildContext - ctx) { - return AlertDialog( - title: Text(tr( - 'markXSelectedAppsAsUpdated', - args: [ - selectedApps.length.toString() - ])), - content: - Text( - tr('onlyWorksWithNonEVDApps'), - style: const TextStyle( - fontWeight: - FontWeight.bold, - fontStyle: FontStyle.italic), - ), - actions: [ - TextButton( - onPressed: - () { - Navigator.of(context).pop(); - }, - child: - Text(tr('no'))), - TextButton( - onPressed: - () { - HapticFeedback.selectionClick(); - appsProvider.saveApps(selectedApps.map((a) { - if (a.installedVersion != null) { - a.installedVersion = a.latestVersion; - } - return a; - }).toList()); - - Navigator.of(context).pop(); - }, - child: - Text(tr('yes'))) - ], - ); - }).whenComplete(() { - Navigator.of( - context) - .pop(); - }); - }, - tooltip: tr( - 'markSelectedAppsUpdated'), - icon: const Icon( - Icons.done)), - IconButton( - onPressed: () { - var pinStatus = - selectedApps - .where((element) => - element - .pinned) - .isEmpty; - appsProvider.saveApps( - selectedApps.map((e) { - e.pinned = pinStatus; - return e; - }).toList()); - Navigator.of(context) - .pop(); - }, - tooltip: selectedApps - .where((element) => - element.pinned) - .isEmpty - ? tr('pinToTop') - : tr('unpinFromTop'), - icon: Icon(selectedApps - .where((element) => - element.pinned) - .isEmpty - ? Icons - .bookmark_outline_rounded - : Icons - .bookmark_remove_outlined), - ), - IconButton( - onPressed: () { - String urls = ''; - for (var a - in selectedApps) { - urls += '${a.url}\n'; - } - urls = urls.substring( - 0, urls.length - 1); - Share.share(urls, - subject: tr( - 'selectedAppURLsFromObtainium')); - Navigator.of(context) - .pop(); - }, - tooltip: tr( - 'shareSelectedAppURLs'), - icon: - const Icon(Icons.share), - ), - IconButton( - onPressed: () { - showDialog( - context: context, - builder: (BuildContext - ctx) { - return GeneratedFormModal( - title: tr( - 'resetInstallStatusForSelectedAppsQuestion'), - items: const [], - initValid: true, - message: tr( - 'installStatusOfXWillBeResetExplanation', - args: [ - plural( - 'app', - selectedApps - .length) - ]), - ); - }).then((values) { - if (values != null) { + }, + tooltip: selectedApps.isEmpty + ? tr('installUpdateApps') + : tr('installUpdateSelectedApps'), + icon: const Icon( + Icons.file_download_outlined, + )), + IconButton( + visualDensity: VisualDensity.compact, + onPressed: selectedApps.isEmpty + ? null + : () async { + try { + Set? preselected; + var showPrompt = false; + for (var element in selectedApps) { + var currentCats = + element.categories.toSet(); + if (preselected == null) { + preselected = currentCats; + } else { + if (!settingsProvider.setEqual( + currentCats, preselected)) { + showPrompt = true; + break; + } + } + } + var cont = true; + if (showPrompt) { + cont = await showDialog< + Map?>( + context: context, + builder: + (BuildContext ctx) { + return GeneratedFormModal( + title: tr('categorize'), + items: const [], + initValid: true, + message: tr( + 'selectedCategorizeWarning'), + ); + }) != + null; + } + if (cont) { + // ignore: use_build_context_synchronously + await showDialog< + Map?>( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: tr('categorize'), + items: const [], + initValid: true, + singleNullReturnButton: + tr('continue'), + additionalWidgets: [ + CategoryEditorSelector( + preselected: !showPrompt + ? preselected ?? {} + : {}, + showLabelWhenNotEmpty: + false, + onSelected: + (categories) { appsProvider.saveApps( selectedApps .map((e) { - e.installedVersion = - null; + e.categories = + categories; return e; }).toList()); - } - }).whenComplete(() { - Navigator.of(context) - .pop(); - }); - }, - tooltip: tr( - 'resetInstallStatus'), - icon: const Icon(Icons - .restore_page_outlined), - ), - ]), - ), - ); - }); - }, - tooltip: tr('more'), - icon: const Icon(Icons.more_horiz), - ), - ], - ))), - const VerticalDivider(), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: () { - setState(() { - if (currentFilterIsUpdatesOnly) { - filter = AppsFilter(); - } else { - filter = updatesOnlyFilter; - } - }); - }, - tooltip: currentFilterIsUpdatesOnly - ? tr('removeOutdatedFilter') - : tr('showOutdatedOnly'), - icon: Icon( - currentFilterIsUpdatesOnly - ? Icons.update_disabled_rounded - : Icons.update_rounded, - color: Theme.of(context).colorScheme.primary, - ), - ), - appsProvider.apps.isEmpty - ? const SizedBox() - : TextButton.icon( - style: - const ButtonStyle(visualDensity: VisualDensity.compact), - label: Text( - filter.isIdenticalTo(neutralFilter, settingsProvider) - ? tr('filter') - : tr('filterActive'), - style: TextStyle( - fontWeight: filter.isIdenticalTo( - neutralFilter, settingsProvider) - ? FontWeight.normal - : FontWeight.bold), - ), + }, + ) + ], + ); + }); + } + } catch (err) { + showError(err, context); + } + }, + tooltip: tr('categorize'), + icon: const Icon(Icons.category_outlined), + ), + IconButton( + visualDensity: VisualDensity.compact, + onPressed: selectedApps.isEmpty + ? null + : () { + showDialog( + context: context, + builder: (BuildContext ctx) { + return AlertDialog( + scrollable: true, + content: Padding( + padding: + const EdgeInsets.only( + top: 6), + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceAround, + children: [ + IconButton( + onPressed: appsProvider + .areDownloadsRunning() + ? null + : () { + showDialog( + context: + context, + builder: + (BuildContext + ctx) { + return AlertDialog( + title: + Text(tr('markXSelectedAppsAsUpdated', args: [ + selectedApps.length.toString() + ])), + content: + Text( + tr('onlyWorksWithNonEVDApps'), + style: const TextStyle(fontWeight: FontWeight.bold, fontStyle: FontStyle.italic), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(tr('no'))), + TextButton( + onPressed: () { + HapticFeedback.selectionClick(); + appsProvider.saveApps(selectedApps.map((a) { + if (a.installedVersion != null) { + a.installedVersion = a.latestVersion; + } + return a; + }).toList()); + + Navigator.of(context).pop(); + }, + child: Text(tr('yes'))) + ], + ); + }).whenComplete(() { + Navigator.of( + context) + .pop(); + }); + }, + tooltip: tr( + 'markSelectedAppsUpdated'), + icon: const Icon( + Icons.done)), + IconButton( + onPressed: () { + var pinStatus = selectedApps + .where((element) => + element + .pinned) + .isEmpty; + appsProvider + .saveApps( + selectedApps + .map( + (e) { + e.pinned = + pinStatus; + return e; + }).toList()); + Navigator.of( + context) + .pop(); + }, + tooltip: selectedApps + .where((element) => + element + .pinned) + .isEmpty + ? tr('pinToTop') + : tr( + 'unpinFromTop'), + icon: Icon(selectedApps + .where((element) => + element + .pinned) + .isEmpty + ? Icons + .bookmark_outline_rounded + : Icons + .bookmark_remove_outlined), + ), + IconButton( + onPressed: () { + String urls = ''; + for (var a + in selectedApps) { + urls += + '${a.url}\n'; + } + urls = + urls.substring( + 0, + urls.length - + 1); + Share.share(urls, + subject: tr( + 'selectedAppURLsFromObtainium')); + Navigator.of( + context) + .pop(); + }, + tooltip: tr( + 'shareSelectedAppURLs'), + icon: const Icon( + Icons.share), + ), + IconButton( + onPressed: () { + showDialog( + context: + context, + builder: + (BuildContext + ctx) { + return GeneratedFormModal( + title: tr( + 'resetInstallStatusForSelectedAppsQuestion'), + items: const [], + initValid: + true, + message: tr( + 'installStatusOfXWillBeResetExplanation', + args: [ + plural( + 'app', + selectedApps.length) + ]), + ); + }).then((values) { + if (values != + null) { + appsProvider.saveApps( + selectedApps + .map( + (e) { + e.installedVersion = + null; + return e; + }).toList()); + } + }).whenComplete(() { + Navigator.of( + context) + .pop(); + }); + }, + tooltip: tr( + 'resetInstallStatus'), + icon: const Icon(Icons + .restore_page_outlined), + ), + ]), + ), + ); + }); + }, + tooltip: tr('more'), + icon: const Icon(Icons.more_horiz), + ), + ], + ))), + const VerticalDivider(), + IconButton( + visualDensity: VisualDensity.compact, onPressed: () { - showDialog?>( - context: context, - builder: (BuildContext ctx) { - var vals = filter.toFormValuesMap(); - return GeneratedFormModal( - initValid: true, - title: tr('filterApps'), - items: [ - [ - GeneratedFormTextField('appName', - label: tr('appName'), - required: false, - defaultValue: vals['appName']), - GeneratedFormTextField('author', - label: tr('author'), - required: false, - defaultValue: vals['author']) - ], - [ - GeneratedFormSwitch('upToDateApps', - label: tr('upToDateApps'), - defaultValue: vals['upToDateApps']) - ], - [ - GeneratedFormSwitch('nonInstalledApps', - label: tr('nonInstalledApps'), - defaultValue: vals['nonInstalledApps']) - ] - ], - additionalWidgets: [ - const SizedBox( - height: 16, - ), - CategoryEditorSelector( - preselected: filter.categoryFilter, - onSelected: (categories) { - filter.categoryFilter = categories.toSet(); - }, - ) - ], - ); - }).then((values) { - if (values != null) { - setState(() { - filter.setFormValuesFromMap(values); - }); + setState(() { + if (currentFilterIsUpdatesOnly) { + filter = AppsFilter(); + } else { + filter = updatesOnlyFilter; } }); }, - icon: const Icon(Icons.filter_list_rounded)) - ], - ), - ], + tooltip: currentFilterIsUpdatesOnly + ? tr('removeOutdatedFilter') + : tr('showOutdatedOnly'), + icon: Icon( + currentFilterIsUpdatesOnly + ? Icons.update_disabled_rounded + : Icons.update_rounded, + color: Theme.of(context).colorScheme.primary, + ), + ), + TextButton.icon( + style: const ButtonStyle( + visualDensity: VisualDensity.compact), + label: Text( + filter.isIdenticalTo(neutralFilter, settingsProvider) + ? tr('filter') + : tr('filterActive'), + style: TextStyle( + fontWeight: filter.isIdenticalTo( + neutralFilter, settingsProvider) + ? FontWeight.normal + : FontWeight.bold), + ), + onPressed: () { + showDialog?>( + context: context, + builder: (BuildContext ctx) { + var vals = filter.toFormValuesMap(); + return GeneratedFormModal( + initValid: true, + title: tr('filterApps'), + items: [ + [ + GeneratedFormTextField('appName', + label: tr('appName'), + required: false, + defaultValue: vals['appName']), + GeneratedFormTextField('author', + label: tr('author'), + required: false, + defaultValue: vals['author']) + ], + [ + GeneratedFormSwitch('upToDateApps', + label: tr('upToDateApps'), + defaultValue: vals['upToDateApps']) + ], + [ + GeneratedFormSwitch('nonInstalledApps', + label: tr('nonInstalledApps'), + defaultValue: vals['nonInstalledApps']) + ] + ], + additionalWidgets: [ + const SizedBox( + height: 16, + ), + CategoryEditorSelector( + preselected: filter.categoryFilter, + onSelected: (categories) { + filter.categoryFilter = + categories.toSet(); + }, + ) + ], + ); + }).then((values) { + if (values != null) { + setState(() { + filter.setFormValuesFromMap(values); + }); + } + }); + }, + icon: const Icon(Icons.filter_list_rounded)) + ], + ), + ], ); } } diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 9698f95..e43aca4 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -4,10 +4,8 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:obtainium/components/custom_app_bar.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'; -import 'package:obtainium/providers/apps_provider.dart'; import 'package:obtainium/providers/logs_provider.dart'; import 'package:obtainium/providers/settings_provider.dart'; import 'package:obtainium/providers/source_provider.dart'; diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 92be206..a8380c6 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -262,6 +262,7 @@ class AppsProvider with ChangeNotifier { List archs = (await DeviceInfoPlugin().androidInfo).supportedAbis; if (app.apkUrls.length > 1 && context != null) { + // ignore: use_build_context_synchronously apkUrl = await showDialog( context: context, builder: (BuildContext ctx) { @@ -281,6 +282,7 @@ class AppsProvider with ChangeNotifier { if (apkUrl != null && getHost(apkUrl) != getHost(app.url) && context != null) { + // ignore: use_build_context_synchronously if (await showDialog( context: context, builder: (BuildContext ctx) { diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index d03f36b..0599c4e 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -225,7 +225,19 @@ class AppSource { label: tr('trackOnly'), ) ], - [GeneratedFormSwitch('noVersionDetection', label: tr('noVersionDetection'))] + [ + GeneratedFormSwitch('noVersionDetection', label: tr('noVersionDetection')) + ], + [ + GeneratedFormTextField('apkFilterRegEx', + label: tr('filterAPKsByRegEx'), + required: false, + additionalValidators: [ + (value) { + return regExValidator(value); + } + ]) + ] ]; // Previous 2 variables combined into one at runtime for convenient usage @@ -269,6 +281,18 @@ abstract class MassAppUrlSource { Future> getUrlsWithDescriptions(List args); } +regExValidator(String? value) { + if (value == null || value.isEmpty) { + return null; + } + try { + RegExp(value); + } catch (e) { + return tr('invalidRegEx'); + } + return null; +} + class SourceProvider { // Add more source classes here so they are available via the service List sources = [ @@ -344,20 +368,32 @@ class SourceProvider { } Future getApp( - AppSource source, String url, Map additionalSettings, - {App? currentApp, - bool trackOnlyOverride = false, - noVersionDetectionOverride = false}) async { + AppSource source, + String url, + Map additionalSettings, { + App? currentApp, + bool trackOnlyOverride = false, + noVersionDetectionOverride = false, + // String? apkFilterOverride + }) async { if (trackOnlyOverride || source.enforceTrackOnly) { additionalSettings['trackOnly'] = true; } if (noVersionDetectionOverride) { additionalSettings['noVersionDetection'] = true; } + // if (apkFilterOverride != null) { + // additionalSettings['apkFilterRegEx'] = apkFilterOverride; + // } var trackOnly = additionalSettings['trackOnly'] == true; String standardUrl = source.standardizeURL(preStandardizeUrl(url)); APKDetails apk = await source.getLatestAPKDetails(standardUrl, additionalSettings); + if (additionalSettings['apkFilterRegEx'] != null) { + var reg = RegExp(additionalSettings['apkFilterRegEx']); + apk.apkUrls = + apk.apkUrls.where((element) => reg.hasMatch(element)).toList(); + } if (apk.apkUrls.isEmpty && !trackOnly) { throw NoAPKError(); } diff --git a/pubspec.lock b/pubspec.lock index 3b629d8..4bd6b84 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,182 +5,208 @@ packages: dependency: "direct main" description: name: android_alarm_manager_plus - url: "https://pub.dartlang.org" + sha256: "71e796198588e0038dd125bf8c91683b3237b938ffad037413245c689b87ae28" + url: "https://pub.dev" source: hosted version: "2.1.0" animations: dependency: "direct main" description: name: animations - url: "https://pub.dartlang.org" + sha256: fe8a6bdca435f718bb1dc8a11661b2c22504c6da40ef934cee8327ed77934164 + url: "https://pub.dev" source: hosted version: "2.0.7" archive: dependency: transitive description: name: archive - url: "https://pub.dartlang.org" + sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d + url: "https://pub.dev" source: hosted - version: "3.3.5" + version: "3.3.6" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + url: "https://pub.dev" source: hosted version: "2.3.2" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.10.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" source: hosted version: "1.2.1" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" + sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + url: "https://pub.dev" source: hosted version: "2.0.2" cli_util: dependency: transitive description: name: cli_util - url: "https://pub.dartlang.org" + sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c" + url: "https://pub.dev" source: hosted version: "0.3.5" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted version: "3.1.1" cross_file: dependency: transitive description: name: cross_file - url: "https://pub.dartlang.org" + sha256: f71079978789bc2fe78d79227f1f8cfe195b31bbd8db2399b0d15a4b96fb843b + url: "https://pub.dev" source: hosted version: "0.3.3+2" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" csslib: dependency: transitive description: name: csslib - url: "https://pub.dartlang.org" + sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 + url: "https://pub.dev" source: hosted version: "0.17.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" source: hosted version: "1.0.5" dbus: dependency: transitive description: name: dbus - url: "https://pub.dartlang.org" + sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + url: "https://pub.dev" source: hosted version: "0.7.8" device_info_plus: dependency: "direct main" description: name: device_info_plus - url: "https://pub.dartlang.org" + sha256: "7ff671ed0a6356fa8f2e1ae7d3558d3fb7b6a41e24455e4f8df75b811fb8e4ab" + url: "https://pub.dev" source: hosted version: "8.0.0" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - url: "https://pub.dartlang.org" + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.dev" source: hosted version: "7.0.0" dynamic_color: dependency: "direct main" description: name: dynamic_color - url: "https://pub.dartlang.org" + sha256: "37a15576f5a0bfd5555b613cf20ea3bd379607cf88d457374a16032f4e942174" + url: "https://pub.dev" source: hosted version: "1.5.4" easy_localization: dependency: "direct main" description: name: easy_localization - url: "https://pub.dartlang.org" + sha256: "6a2e99fa0bfe5765bf4c6ca9b137d5de2c75593007178c5e4cd2ae985f870080" + url: "https://pub.dev" source: hosted version: "3.0.1" easy_logger: dependency: transitive description: name: easy_logger - url: "https://pub.dartlang.org" + sha256: c764a6e024846f33405a2342caf91c62e357c24b02c04dbc712ef232bf30ffb7 + url: "https://pub.dev" source: hosted version: "0.0.2" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" source: hosted version: "2.0.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted version: "6.1.4" file_picker: dependency: "direct main" description: name: file_picker - url: "https://pub.dartlang.org" + sha256: d090ae03df98b0247b82e5928f44d1b959867049d18d73635e2e0bc3f49542b9 + url: "https://pub.dev" source: hosted version: "5.2.5" flutter: @@ -192,42 +218,48 @@ packages: dependency: "direct main" description: name: flutter_fgbg - url: "https://pub.dartlang.org" + sha256: d37511eef6afb7e2e3f2278ec6498bb12c650ed517c81bcd09452d910e8b9174 + url: "https://pub.dev" source: hosted version: "0.2.2" flutter_launcher_icons: dependency: "direct dev" description: name: flutter_launcher_icons - url: "https://pub.dartlang.org" + sha256: ce0e501cfc258907842238e4ca605e74b7fd1cdf04b3b43e86c43f3e40a1592c + url: "https://pub.dev" source: hosted version: "0.11.0" flutter_lints: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" source: hosted version: "2.0.1" flutter_local_notifications: dependency: "direct main" description: name: flutter_local_notifications - url: "https://pub.dartlang.org" + sha256: "293995f94e120c8afce768981bd1fa9c5d6de67c547568e3b42ae2defdcbb4a0" + url: "https://pub.dev" source: hosted version: "13.0.0" flutter_local_notifications_linux: dependency: transitive description: name: flutter_local_notifications_linux - url: "https://pub.dartlang.org" + sha256: "8f6c1611e0c4a88a382691a97bb3c3feb24cc0c0b54152b8b5fb7ffb837f7fbf" + url: "https://pub.dev" source: hosted version: "3.0.0" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface - url: "https://pub.dartlang.org" + sha256: "5ec1feac5f7f7d9266759488bc5f76416152baba9aa1b26fe572246caa00d1ab" + url: "https://pub.dev" source: hosted version: "6.0.0" flutter_localizations: @@ -239,7 +271,8 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - url: "https://pub.dartlang.org" + sha256: "60fc7b78455b94e6de2333d2f95196d32cf5c22f4b0b0520a628804cb463503b" + url: "https://pub.dev" source: hosted version: "2.0.7" flutter_test: @@ -256,322 +289,360 @@ packages: dependency: "direct main" description: name: fluttertoast - url: "https://pub.dartlang.org" + sha256: "7cc92eabe01e3f1babe1571c5560b135dfc762a34e41e9056881e2196b178ec1" + url: "https://pub.dev" source: hosted version: "8.1.2" html: dependency: "direct main" description: name: html - url: "https://pub.dartlang.org" + sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269 + url: "https://pub.dev" source: hosted version: "0.15.1" http: dependency: "direct main" description: name: http - url: "https://pub.dartlang.org" + sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + url: "https://pub.dev" source: hosted version: "0.13.5" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted version: "4.0.2" image: dependency: transitive description: name: image - url: "https://pub.dartlang.org" + sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6" + url: "https://pub.dev" source: hosted version: "3.3.0" install_plugin_v2: dependency: "direct main" description: name: install_plugin_v2 - url: "https://pub.dartlang.org" + sha256: d6b014637e7a53839e9c5a254f9fd9bb8866392c6db1f16184ce17818cc2d979 + url: "https://pub.dev" source: hosted version: "1.0.0" installed_apps: dependency: "direct main" description: name: installed_apps - url: "https://pub.dartlang.org" + sha256: "145af8eb6e4e7c830e9888d6de0573ae5c139e8e0742a3e67316e1db21ab6fe0" + url: "https://pub.dev" source: hosted version: "1.3.1" intl: dependency: transitive description: name: intl - url: "https://pub.dartlang.org" + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" source: hosted version: "0.17.0" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.5" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + url: "https://pub.dev" source: hosted version: "4.8.0" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" source: hosted version: "2.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.13" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" source: hosted version: "1.8.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted version: "1.0.4" nested: dependency: transitive description: name: nested - url: "https://pub.dartlang.org" + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" source: hosted version: "1.0.0" package_archive_info: dependency: "direct main" description: name: package_archive_info - url: "https://pub.dartlang.org" + sha256: "8f671a29b79d15f192e5e2b0dab9d0bad66b9ee93fb58d4e0afdb62f91a259be" + url: "https://pub.dev" source: hosted version: "0.1.0" package_info: dependency: transitive description: name: package_info - url: "https://pub.dartlang.org" + sha256: "6c07d9d82c69e16afeeeeb6866fe43985a20b3b50df243091bfc4a4ad2b03b75" + url: "https://pub.dev" source: hosted version: "2.0.2" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" source: hosted version: "1.8.2" path_provider: dependency: "direct main" description: name: path_provider - url: "https://pub.dartlang.org" + sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.0.12" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + url: "https://pub.dev" source: hosted version: "2.0.22" - path_provider_ios: + path_provider_foundation: dependency: transitive description: - name: path_provider_ios - url: "https://pub.dartlang.org" + name: path_provider_foundation + sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.1.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + url: "https://pub.dev" source: hosted version: "2.1.7" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.7" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + url: "https://pub.dev" source: hosted version: "2.0.5" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + url: "https://pub.dev" source: hosted version: "2.1.3" permission_handler: dependency: "direct main" description: name: permission_handler - url: "https://pub.dartlang.org" + sha256: "33c6a1253d1f95fd06fa74b65b7ba907ae9811f9d5c1d3150e51417d04b8d6a8" + url: "https://pub.dev" source: hosted version: "10.2.0" permission_handler_android: dependency: transitive description: name: permission_handler_android - url: "https://pub.dartlang.org" + sha256: "8028362b40c4a45298f1cbfccd227c8dd6caf0e27088a69f2ba2ab15464159e2" + url: "https://pub.dev" source: hosted version: "10.2.0" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - url: "https://pub.dartlang.org" + sha256: "9c370ef6a18b1c4b2f7f35944d644a56aa23576f23abee654cf73968de93f163" + url: "https://pub.dev" source: hosted version: "9.0.7" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - url: "https://pub.dartlang.org" + sha256: "68abbc472002b5e6dfce47fe9898c6b7d8328d58b5d2524f75e277c07a97eb84" + url: "https://pub.dev" source: hosted version: "3.9.0" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - url: "https://pub.dartlang.org" + sha256: f67cab14b4328574938ecea2db3475dad7af7ead6afab6338772c5f88963e38b + url: "https://pub.dev" source: hosted version: "0.1.2" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" source: hosted version: "5.1.0" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + url: "https://pub.dev" source: hosted version: "2.1.3" pointycastle: dependency: transitive description: name: pointycastle - url: "https://pub.dartlang.org" + sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 + url: "https://pub.dev" source: hosted version: "3.6.2" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" provider: dependency: "direct main" description: name: provider - url: "https://pub.dartlang.org" + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + url: "https://pub.dev" source: hosted version: "6.0.5" share_plus: dependency: "direct main" description: name: share_plus - url: "https://pub.dartlang.org" + sha256: e387077716f80609bb979cd199331033326033ecd1c8f200a90c5f57b1c9f55e + url: "https://pub.dev" source: hosted version: "6.3.0" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface - url: "https://pub.dartlang.org" + sha256: "82ddd4ab9260c295e6e39612d4ff00390b9a7a21f1bb1da771e2f232d80ab8a1" + url: "https://pub.dev" source: hosted version: "3.2.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - url: "https://pub.dartlang.org" + sha256: "5949029e70abe87f75cfe59d17bf5c397619c4b74a099b10116baeb34786fad9" + url: "https://pub.dev" source: hosted version: "2.0.17" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - url: "https://pub.dartlang.org" + sha256: "955e9736a12ba776bdd261cf030232b30eadfcd9c79b32a3250dd4a494e8c8f7" + url: "https://pub.dev" source: hosted version: "2.0.15" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - url: "https://pub.dartlang.org" + sha256: "1ffa239043ab8baf881ec3094a3c767af9d10399b2839020b9e4d44c0bb23951" + url: "https://pub.dev" source: hosted version: "2.1.2" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - url: "https://pub.dartlang.org" + sha256: f8ea038aa6da37090093974ebdcf4397010605fd2ff65c37a66f9d28394cb874 + url: "https://pub.dev" source: hosted version: "2.1.3" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" + sha256: da9431745ede5ece47bc26d5d73a9d3c6936ef6945c101a5aca46f62e52c1cf3 + url: "https://pub.dev" source: hosted version: "2.1.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.dartlang.org" + sha256: a4b5bc37fe1b368bbc81f953197d55e12f49d0296e7e412dfe2d2d77d6929958 + url: "https://pub.dev" source: hosted version: "2.0.4" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.dartlang.org" + sha256: "5eaf05ae77658d3521d0e993ede1af962d4b326cd2153d312df716dc250f00c9" + url: "https://pub.dev" source: hosted version: "2.1.3" sky_engine: @@ -583,205 +654,234 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" sqflite: dependency: "direct main" description: name: sqflite - url: "https://pub.dartlang.org" + sha256: "78324387dc81df14f78df06019175a86a2ee0437624166c382e145d0a7fd9a4f" + url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.2.4+1" sqflite_common: dependency: transitive description: name: sqflite_common - url: "https://pub.dartlang.org" + sha256: bfd6973aaeeb93475bc0d875ac9aefddf7965ef22ce09790eb963992ffc5183f + url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2+2" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.dartlang.org" + sha256: "33b31b6beb98100bf9add464a36a8dd03eb10c7a8cf15aeec535e9b054aaf04b" + url: "https://pub.dev" source: hosted version: "3.0.1" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.4.16" timezone: dependency: transitive description: name: timezone - url: "https://pub.dartlang.org" + sha256: "24c8fcdd49a805d95777a39064862133ff816ebfffe0ceff110fb5960e557964" + url: "https://pub.dev" source: hosted version: "0.9.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted version: "1.3.1" url_launcher: dependency: "direct main" description: name: url_launcher - url: "https://pub.dartlang.org" + sha256: "698fa0b4392effdc73e9e184403b627362eb5fbf904483ac9defbb1c2191d809" + url: "https://pub.dev" source: hosted version: "6.1.8" url_launcher_android: dependency: transitive description: name: url_launcher_android - url: "https://pub.dartlang.org" + sha256: "3e2f6dfd2c7d9cd123296cab8ef66cfc2c1a13f5845f42c7a0f365690a8a7dd1" + url: "https://pub.dev" source: hosted version: "6.0.23" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - url: "https://pub.dartlang.org" + sha256: bb328b24d3bccc20bdf1024a0990ac4f869d57663660de9c936fb8c043edefe3 + url: "https://pub.dev" source: hosted version: "6.0.18" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.dartlang.org" + sha256: "318c42cba924e18180c029be69caf0a1a710191b9ec49bb42b5998fdcccee3cc" + url: "https://pub.dev" source: hosted version: "3.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.dartlang.org" + sha256: "41988b55570df53b3dd2a7fc90c76756a963de6a8c5f8e113330cb35992e2094" + url: "https://pub.dev" source: hosted version: "3.0.2" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.dartlang.org" + sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6" + url: "https://pub.dev" source: hosted version: "2.1.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.dartlang.org" + sha256: "44d79408ce9f07052095ef1f9a693c258d6373dc3944249374e30eff7219ccb0" + url: "https://pub.dev" source: hosted version: "2.0.14" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.dartlang.org" + sha256: b6217370f8eb1fd85c8890c539f5a639a01ab209a36db82c921ebeacefc7a615 + url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" uuid: dependency: transitive description: name: uuid - url: "https://pub.dartlang.org" + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" source: hosted version: "3.0.7" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" webview_flutter: dependency: "direct main" description: name: webview_flutter - url: "https://pub.dartlang.org" + sha256: f7ec234830f86d0ef2bd664e8460b0038b8c1a83ff076035cad74ac70273753c + url: "https://pub.dev" source: hosted version: "4.0.2" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - url: "https://pub.dartlang.org" + sha256: "9d97fa2bae0f1900553c48a2ef0aaa3864367fd7bb625d683c460754b691312c" + url: "https://pub.dev" source: hosted version: "3.2.1" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - url: "https://pub.dartlang.org" + sha256: "8b2262dda5d26eabc600a7282a8c16a9473a0c765526afb0ffc33eef912f7968" + url: "https://pub.dev" source: hosted version: "2.0.1" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - url: "https://pub.dartlang.org" + sha256: "523aff9168af9bb2170e4809e0499d7dee065c3919799fd3341d3e616c137960" + url: "https://pub.dev" source: hosted version: "3.0.2" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + url: "https://pub.dev" source: hosted version: "3.1.3" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + url: "https://pub.dev" source: hosted version: "0.2.0+3" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.2.2" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" source: hosted version: "3.1.1" sdks: - dart: ">=2.18.2 <3.0.0" + dart: ">=2.18.2 <4.0.0" flutter: ">=3.3.0" From 05f712603cf2557522abed70de5800c2813167b9 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 28 Jan 2023 00:08:17 -0500 Subject: [PATCH 002/600] GitHub & Codeberg - get first 100 releases (not 30) --- lib/app_sources/codeberg.dart | 2 +- lib/app_sources/github.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index d00bcd8..b4101ca 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -64,7 +64,7 @@ class Codeberg extends AppSource { ? additionalSettings['filterReleaseTitlesByRegEx'] : null; Response res = await get(Uri.parse( - 'https://$host/api/v1/repos${standardUrl.substring('https://$host'.length)}/releases')); + 'https://$host/api/v1/repos${standardUrl.substring('https://$host'.length)}/releases?per_page=100')); if (res.statusCode == 200) { var releases = jsonDecode(res.body) as List; diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 1169d88..7d92ed1 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -111,7 +111,7 @@ class GitHub extends AppSource { ? additionalSettings['filterReleaseTitlesByRegEx'] : null; Response res = await get(Uri.parse( - 'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/releases')); + 'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/releases?per_page=100')); if (res.statusCode == 200) { var releases = jsonDecode(res.body) as List; From a85d6d4f08483674666e2dccf841817f97dc714e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 28 Jan 2023 00:11:40 -0500 Subject: [PATCH 003/600] Increment version, remove comment --- lib/main.dart | 2 +- lib/providers/source_provider.dart | 4 ---- pubspec.yaml | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 939c938..fdef815 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.10.4'; +const String currentVersion = '0.10.5'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 0599c4e..e4c76e7 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -374,7 +374,6 @@ class SourceProvider { App? currentApp, bool trackOnlyOverride = false, noVersionDetectionOverride = false, - // String? apkFilterOverride }) async { if (trackOnlyOverride || source.enforceTrackOnly) { additionalSettings['trackOnly'] = true; @@ -382,9 +381,6 @@ class SourceProvider { if (noVersionDetectionOverride) { additionalSettings['noVersionDetection'] = true; } - // if (apkFilterOverride != null) { - // additionalSettings['apkFilterRegEx'] = apkFilterOverride; - // } var trackOnly = additionalSettings['trackOnly'] == true; String standardUrl = source.standardizeURL(preStandardizeUrl(url)); APKDetails apk = diff --git a/pubspec.yaml b/pubspec.yaml index cb72a09..6b4cccb 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.10.4+110 # When changing this, update the tag in main() accordingly +version: 0.10.5+111 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 427b0ed8d225a21714e0e0f17143c203f65987f8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 28 Jan 2023 00:13:03 -0500 Subject: [PATCH 004/600] Changed a string --- lib/custom_errors.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/custom_errors.dart b/lib/custom_errors.dart index 8ae0fa5..a049170 100644 --- a/lib/custom_errors.dart +++ b/lib/custom_errors.dart @@ -29,7 +29,7 @@ class NoReleasesError extends ObtainiumError { } class NoAPKError extends ObtainiumError { - NoAPKError() : super(tr('noReleaseFound')); + NoAPKError() : super(tr('noAPKFound')); } class NoVersionError extends ObtainiumError { From 52913b0450d74034bc6b7a1042785be5a9da972b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 28 Jan 2023 00:15:52 -0500 Subject: [PATCH 005/600] Slight UI tweak --- lib/pages/app.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 4a6a24c..94711ca 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -317,7 +317,7 @@ class _AppPageState extends State { tooltip: tr('more')), const SizedBox(width: 16.0), Expanded( - child: ElevatedButton( + child: TextButton( onPressed: (app?.app.installedVersion == null || app?.app.installedVersion != app?.app.latestVersion) && @@ -356,7 +356,8 @@ class _AppPageState extends State { ? tr('update') : tr('markUpdated')))), const SizedBox(width: 16.0), - ElevatedButton( + Expanded( + child: TextButton( onPressed: app?.downloadProgress != null ? null : () { @@ -401,7 +402,7 @@ class _AppPageState extends State { surfaceTintColor: Theme.of(context).colorScheme.error), child: Text(tr('remove')), - ), + )), ])), if (app?.downloadProgress != null) Padding( From a64bd67ef15418f64687a528b83af6c2fb9e830e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 28 Jan 2023 00:46:54 -0500 Subject: [PATCH 006/600] Updated screenshots --- README.md | 2 +- assets/screenshots/1.apps.png | Bin 233383 -> 239280 bytes assets/screenshots/2.dark_theme.png | Bin 165642 -> 244222 bytes assets/screenshots/3.material_you.png | Bin 173904 -> 143732 bytes assets/screenshots/4.app.png | Bin 149380 -> 142079 bytes assets/screenshots/5.apk_picker.png | Bin 192920 -> 0 bytes assets/screenshots/5.app_opts.png | Bin 0 -> 120691 bytes assets/screenshots/6.apk_install.png | Bin 196128 -> 0 bytes assets/screenshots/6.app_webview.png | Bin 0 -> 267760 bytes 9 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 assets/screenshots/5.apk_picker.png create mode 100644 assets/screenshots/5.app_opts.png delete mode 100644 assets/screenshots/6.apk_install.png create mode 100644 assets/screenshots/6.app_webview.png diff --git a/README.md b/README.md index 4337bde..185f69f 100644 --- a/README.md +++ b/README.md @@ -31,4 +31,4 @@ Currently supported App sources: | Apps Page | Dark Theme | Material You | | ------------------------------------------------------ | ----------------------------------------------------------------------- | -------------------------------------------------------------------- | -| App Page | Multiple APK Support | App Installation | +| App Page | App Options | App Web View | diff --git a/assets/screenshots/1.apps.png b/assets/screenshots/1.apps.png index d46fa405fb517da76cc33febaf5bf75e98136b69..ecd7aa823bfc949d1dff06adeae0b66c7234c711 100644 GIT binary patch literal 239280 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 S>(uO@D^*caSIm=t;QL<`ejlCy literal 233383 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.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 literal 165642 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
h! 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

m^h+N}>9yM<@VWbuWWjjwe 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 literal 173904 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

@ga{TkAX^ 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 Vs9vND&2I>ztnlD&o}B5+{{bmDf;a#G diff --git a/assets/screenshots/4.app.png b/assets/screenshots/4.app.png index a996051480d4c565c8263fafc01b460b7914cd30..55ae937f7afdd7295f4b9fcf5fb2d7900e1faed2 100644 GIT binary patch literal 142079 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%0A3)y0(TQ@u;d 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
ya38Upkxh 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 diff --git a/assets/screenshots/5.app_opts.png b/assets/screenshots/5.app_opts.png new file mode 100644 index 0000000000000000000000000000000000000000..5e5e7fe4cefcd7b13fd98bac7d02a961abf31ff9 GIT binary patch literal 120691 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%0Ab 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%0AKezS;}s9@ z;i6qBX5i)8GLThhZ0me{O9lKY?7xrvYRGvFnZ~Uw!``PA#n1eS&~26zJ1Ye%`JSNp zCaw}Y4?=7a04S(Utd4}`MS}a6kkdtX<@#o6Q^rv|*J@&!@|K-ES!^M$sj*p0o%aj~u78a%Z3CIU6rXwha$7cGTDRC6(!Slbh1gR=r3lRZu~K7zod^L#6kd{T_`TYiqAO zIo&l)ISoFBXGtxG2tyj%J#eJpOsGl9Zd+>UOE~=HZ|G zYp7+qCr@giwL$bqL}PMeM+ZIz#tYln^$I(y{k47#DXHqFvKE>ua3-C}$-~YmbAJ4& zA81T2@{Lu=4u-;Ek); z34PM0%^sJ5NtFi9& z2X$Y=O3i2J=ttwWCXO?x^eq-Zy2yF=-zW~hE46PLVY-!)oIF;14$-3MvU5&{<1)zp zdeZp#_{`jzIVC>^LE^4RPBUnc0BUbJ$Ag81%wea`<6~a~T->cMapMJ$xsf|=sy`1E zP1aGV3*Y^`;Zx6{n7A!B`m^r@?Ldia6Aq~hvIDbM$x05)`tB4o}j zvZoa<+{jMG##YpFl7`)f$4^grE{|ta8uzn9u4a+p)ZsV}k(EhH8t1I?`V?||!v`8% zYIdVDgaAreoqQ~Q8R1S9BomK3@L|?lB9y}CFO2NCYjaph6D^kR_qsPqw z1~7s{?p%ffLQdz1f-9Pg7n3+Ux62IE8zhWU=!k%MAP_1wnc^KVzKZe^6<2Z?51aG| zsIRX-^Rm4m1hLT7+1|XwOKQJS|M_UIczRM{ph6A>HcaMvca~X1-BX(x~0OFt$)lF|dbUc1#XUroK;};L~`GtkkLPL`m3tqs;J^j`4=C?c5X&NKz zQ*%gBc@U6DO*xIcq?0t}R4RvShgGX5KLJ`P2#f7QB>uyAVcN12qM2C{wJQwlhR|22 zgO(Ydy6%~h`AtH?sBQe6p3d8=!FTs2Ki|dNzh}6gOY9?Gy)|qjSO-uU>1x-NWBj4s zRAM4R;C4k{)Shor(m#HF|MBxbZC|1xWqNwA!@oR~p5q6tHV&J3`2G7-IH7hoRB2R< zhiT9gn645YI(EkFlLbDQ5*CBltl>QjcyIB~_Qzr1VqWFlb6VntwplfCS41mUAw&t! zIV~mS`rfvB(ad5qBDyQSat=sU7=wBRnT+au`UdZx+iYi-rq>o0Zl`G|czUAW5bEfp zXU`t5-)gcoGTJVkjIM8puiV@IlSYND0xeDo32{ckx1%{eP)zfBc5@WMi1)w4=XsHc zufwA)jjha&pMC^5?{uL9thgRf!syDMGxh%c`+?1s2~Hegp(~{u6EUHo(^d!UK22ja zx_L48YKxS89K?Wf!F{5;-{F98D|;s=S1>(@z7rOAIy*ADljb({vm#5FgM8e9X!9_< z)A%or;j_p{y2AFug8C`ZYIBa;IdTLlMCWWshhz9G{94G0Ky-%B*&0z_Z!}#+4ee!2 z+1YoHO<9X#eq_*j*eQ|7tJCf%rSC6L9Fmi+jdHp z-mB>T!y(vXq+S~QLWFm7a#n0czFt{f@!>C>4cv8n)CLBsfMatT&u57(F$EX3>X724 zTCFPtEZ0-L^1>tUY6FkX(8U|A?zFtJVm4mr6-%*CHm0U{AYNRF=R|&!gs2KsWyoqb zW|t-@si;^C>j(H{;`H%FN1Wd4&oT%+$VMF^y+)rj8UNlaa#J-LJ8K>oI2}pkmnP%q zHg4u|<^D9M$EZ>Ov0Oib!s$hgmhU9p-IX2yA`O|ScH-ef%IEn{WLfj{r_P+R#irWa zioFeCEQigWgHwdtYb&w&d0p7I^!TSrOi=ie3T)Cq-9dz&B0Oib+(rY&8(F-{L}_q* ze3@oDm(bU+u>IB~H@|yZxMJ!*dJPcLF}Cl!ZwO%p-?iC0rY4ssOSmK#mxeDp;gc1%wT3N46%{g&HH8`oN{_XP3cI=k z$>^y?YrCD(*+V5RwXz>SoKe%0Qgm+r9s7-K=)DLU=0ct4C**;>Jz|6GM)6w@1bHp&O#|77$H)(fT;nfnbq0T$0FAeA3KA7Kms=!vJ zciqaTbG59*HsB@)Yt$)-#_a9kma_pI%4M~W{}8|q9&>NNMZ)B2THLyFPq4T^57~r{!RvB^`~{X0tJ~1csAfX*vcC$m&Q`=dN?2~*gdOOx-jb=p>4506s7X)0R<8V=&VAL%4<==QJJ z+L`w%R~VopeQGlhT{_)AZNQQsk_P1?-$gNe-S)+4(CyWJw;aw+t|IgfxAnboq_X8Qe z_45nlpGpGS?=VuN!+1fQ7^x{r&9EAKnkQDIe0&QPCc=m9Ya<-9KQY`Hk{i z>H;55ehs$jTJKJ9v&=lNO=x1G1>}*jD1o?e-cXyv^ui>M=L<$PSI3;M9_;QeAj8?) zk%^2ab3qmY4D&Y^?Q7wR|o&_thi5eS(85xi`+H zw6@ld2hdmzTH;@S{OcU4kY9PPYuLF?P2>Ygy21<5OUVbCv<7m=mQF z7VS^5eD;!S*b^ajG--n?sXrD24yTtAhYyHI=L&iiGu-@$i(1ynLvu|3-Hd zlmBaOT6%iT1G^vnd&)7RLml4*(^d=2YR$j;_~_cvk!-O2Xu@*>%ZW>kgM)*HfiG-4 zrzkfkCOeEnagn@=)WZYgrVvo{v9VE+*x!X^!l!_Js&(E29UN8hjQKi@AH2^mqxPOL zF_BI4jxBDiLvq{fk)!`zHq+k;nrdYC2yfflEI{8;$KAP0lsW<^!7;ARS5JB)K%W`j z3UtFHBD~eQ)fXW*3w=Y?IAG%*uptzUI6y;q5upPsi5iGA56JQIXjDrfH1?drta>wXMtQCm`oY%<%UwlHE9ExQwq+C zu}vlCL&>gdA(hbNal*-ZaViJ;er;W|7`HQd7YL>C+Qg+)aHLoH>>(u zD&knOO=1KeP-y17g!^tsnN7VY7h}?!L_AK-JiY2;+p@2>kBH^woqR=eP}`btrwWp> zRZZoP_r>17BD^unLBhh!YU;{8|2aEe_FbdR@qJUOyH~0D`-ZNP;wvb04M(~E;Cfz< z+Jjyi|2wENXnIfzY(e!3csuv1UpXCY|8zcYhQ>nBaIT*GZL>PoSArR6`vxQq@nW2_ zsm6;`va~4WFxmD?;tKy`IMuuWsogcv>ww|#a^rE?8lP9H{Ns;J>hvko+ga=nIik$ZMe0{9^!}HV|o2nL;l1KegH0v;PdGu@AUIQ#qH=KsYEQ7L#l~>ja~$G&b9X@oxghyO~ebp zXAJtnzlma~@MGZb6tOfHIUH^n8gd0Y1ys#^{k#F^KVE8e2Rv;}^zFt(rOWQ0*5)ES zR_71AyvJK{QlBU!B-(B@%iQHRwY0RH$@;qaE8yct0XHEmryHSQHpFqdFz}BDh7-5Y zRQtXS87`gpnyLJ>MlGJ?BL)l*w&USN45x*7cPBsV<-SlAmM4L(;S*4CDy=!)LL^o| z^T;KxKy0Hi0rVmz5`&!`qgd9#;&0n`B;pmd@5XA`hE8Zj$V4tk>g{>h3E)9 zjlTX9p0u2Ah1keF{dDiTe0$RNj;=22)p^PwLvoT^t#vn!H1Or++3YxE>^Qo0B^5-g z@c5mkt!2#tPpXFt=!!2NdzSRkGc_zVRRL-SYPC}WrLUBeGh2dgNe>>EI%p*jcr`kBD`V0 z55paY8gDGh6TA(_8|1WedPka?n!1LDQdnC~OYPkvzx?A43-m*_jpm8_v_=9mGnIiR z^$3`lh?xs{IOQAsCTPURkX6@Evq^on8#S7Ae7w&QHPo=avxXOVxwE7x`X!$9_}N~- z|20o7ub>ci*8PO*5i>V;(V$J4h>8~J3DtPURWBVWrI=dA`12xYbzw|^U7 z)uN&(QhDd}KL$%?cIE?*o;gB$H?uQPgfGpSUfObp3CTlp>T>kd>31cd2lsZ0u{BV? zrxE!SYg4t=`3aGM$IfG=4t5Qheq3A?<7I1_dA~N>7fLQ?%l9cmX8TQTtRPlK`eTIE zdv2r+ClrO_-J24|l9QGFu&%r?GuoSgQfPi|vGUlzeF>)LY%Rs~ekPQEG+H2T3PH?f z*_U*UFtUre4&iwA11wkDe_J3Q^|i=fEtHeXD#tGBmU6$tYa&4a}U6`ju>_?f}q&g z@{?b-rivcmiq%me#*}ko6UFS^deNJDdmYx>_Wr(P@XOySly1gS;A5k3QS_kVkJ3hJ zCXMba9`n06Z`8+641IabKs!<6#8TPP1+gZFr_UePkpUedowj;Yh@5A4&&fPorRcJNi|8~^#iq+l8&cP*!_70EPj6agsB5Kh_gKzTt!Lqn9y za_{U3PmKtaEUk^RHLL0w8)V+9{zBcC@s!saA*cU#hthla>dpTi|49OQ(n5-CwOY8C z&{+ts^?|+2_>NiZW4jVxWJCnu0~GuYI%lba_c&NrR`{UW&~X2te`M?Zpg(^>UY3YD zs{W{b!tsF8W8$Ea+iF8+-ypadnrwzYjW5%i+}0>V)t@ZLXwSAto$Gbj3%zVy4Tn1< zJap24V(PWyE5HR$reje`4P&MC8gRQ#W~J#1U~yXOAlgbKqtrdV@Z!gDIcdq7qfs`3 zxs?&De@zyw05HUl+htTn{N0Xq=L5A*NL?*T0mNt!JIEQ&ZyOo0ZrtphC{0REuCiL? z1Ah$)fFKu8dD{IY6~~i^m{7gK(sgW294D+xN@7N}O11EX|2+=9f#*WM2Uo-4(hW-oQ=d%Z`vt_;K%jEHlH;t{wP}W80p05=>lx8~i0{n|$O(M~ zI5IYtwv!vH+gqdNgJQ%J z_ZC-S3|uzmXSpe=L}0m!Sfxz-#8@xvw7)bt z+T1nrI~g>ZsCF8P1W?7r-F7UrS(!j5E3?%F24IT)zKFPRI(dioO&8tC}3&=ZN(dR1@CmnMyJq&I8e;D(FF+7cYY!9;Xn-Ze3w& zVPVmCauucT4*_v3N^nEhxSf0SoTPO7IU8O5o2gzbn)mo^o>Gyuq z0y3NK!k6L0IR++u44bwo=#yW4mmmvK*p4&+_FP)>PO30)xepE^0Wh|*D#}x@Z0z;a zG%av!>Ym_ZgV=J5e+-}1#sEY-pbQN%8pphIRaVS8oB2xpi({jfQvu8W_t-e?-Mg-+ zOQbAgTWl8Mm*|$I0wFywPTa?3rarfG5t6|c(7y03e)P^k>r^J_?(O7i2Wc@V9s(01 zDmt=~3w-XS?zou@DR*p24|t+Br_PP5n=R+~uwMtgnF30TrQ@#4#L3=zf9)F@GNu7W zIy!F6)7yEJQvjURC0-I2_l7yOY^}!f#;Q!6oZK|-vsx3-v}TjVR#0mL#WEGXS>30u zpAPc+pTdHBOAJ+IJ1g<>-Fs)Dn3OLzFrKwrSZmq8RCq4=oG@38|`1j07$*oF)l1jSxH`3>w}iA;riM@LsJH((+C$EG?W3~*cAZyKRv(l z7weES2wk0IW4k_fW@ZaZ>y3@2wf6|Ah><59bvL&AL4;v2519ZVX$YHBse|8rEPCv< zdwR+PB_QYxeK0Qmd=hr(Hp2~kMQHXlm61{6<0LNCjzd&95m zx|O6Ua&Rb-QLV}n1S=TTJw-)ozPlW-v(O2vtJgJGut4>|5`h^x(u8PIR#enoL192W zt^3>cE>jJ`lXt|d;bxh+P!Kozffx+uzM0!dGC@E z2GK0jUQN!Wuieqo5LfKQJ}-NncTUujB*?)Ldu_+0Nx}bcvf7PmK`J>p3yrDnz2gNR z6Jw)D4>9|nGp8%&sHYcSOLV2r{?VT+gNcUukCTWoIgrkwcq~GB$*zxD?Q-o8Axpl8 zTTy3165mE_kq=89(Z)#r;s{uNsrQW$!j<#3Z$lfOe#34Jv?g?RaE`Tl@d0n2x7ZN- zj_Y+Y%zwYy)ayHCNrk;r83M^~WulGv&^vD$E2W(HZ=l`#$00ms_Zu6-khlN~o>)*r z!SPQeN~OKM#zobeNOm~D?zet8L?rO$A7PYDezr%g_F2~SEHEHm{>d`!&kBnbHT4(h zNcQ!!+i0v`{sK$&E4;r2L}MSpgHmkBth8LqNzO7*w>H?AH8!joPfzc6#Ahau;YHJe zdKh>*^+7>l+jsOHFVlK#FEq7q>)!%mKkf5GrjM73v@ChU^_1lCojGH)&VL~LjmYgMUXzS)@ia>1%qKa{2NhX!V8)i0k| zt2EPUn>{2g`r<~&c%xMrQ&+O{hm}oX0BC3i-_?42 zP2j=US^Q17!vs7jGEw9*(FFw4wf23ha$EiMq*I!195uU>9>C*D;v`enGhm3A{fuT0 z+&z3l&T?zOZk@o`ae^<_-cih2)X;Zi|L|0NVI!sc&5XpM;o6u6qN#}Lo<5qX4z(J5 z1I?N>NndGRFC?vb$EHq7H!n_)h8d@&tH^Y9NnW|J;z-PS#QhcDc(ihsZ=CL6D)pt8 z_cs30s7q3+BTB+zf_?H|1uR_mB4e3aI7E{h3CnsJ$Teg}S-HQWLVhGBJ+shUWT(aW z$n}q(7m-nu)ZCuw(%)}P0|>sjN4myzLy> zU`E%jY$qzM>&+wzA7cC_Tid?E9OG()2t1{#Er-SKI5+nk-~wO({H4Z_Ra<$i5`U+@ww52 z5*5PvxDztPNtp(J_+ zBffWpycQ1^zJ{Tf33Ih_{|6w2XcGU<=e<1UGgU&&%l?3Wf}f7BLbh-I<#!uJsp0eE zQt7cEhN~Zi{w+iGA7YD5VvBeFLsE{L#%W~sGQBOd>)jZW6l)Ps0!~mC@9(N6``Pc) z_OF7rD=ksFDPfPE;UH@1C8Qo_Tu^#y4<6Alni!=t=lACq4mV!*L*w~7H~?9W&RmJk zbaad+5Gs5vS=86Q!%T;5N$0~~*d}2NZvVSMs8?N~R@1{t)=f6p?!#`gq|LMhcUak4 zljEIXOv*{X+|rR?DueYuVAXKO=g)=7gbU)soCqI+jU$e+{p({-NlTWz(xyuWlgy zR}Tv$7kQUfk47jK<90aXcQ}d74_vxwE?!XUzfl};@9%W_|JaWC^K_TQTA4Gau)of+s&2>7@Zu~b}q zTc2hTkHJ(Jh!w4W-sih5tp^->9A;;~qN6ibA+4;bKEd7HHA2*A zv#8^sq5atskrj;IMI0#JRj|@h;*Q}M9uks`I6OI)GM1G1M%M=I^d@&}3jlB! z_A@oB*_TGt#7Whf+Be2RFAd~mS!Mc?>-J8iT?$`iD8vOFe6C zKb)^b%X}eVU?77|7vKmg#IL%dW)-7Lvx$W|V)z!TQLYmMP@sbrz*FIx*a_0IXWfTuj!TVGmImAlXLVC{=y+*pCJ@hwIOU2M(u7nPYHR0ChHt&@peCuOtQ z{(dP=U0Hc-JC@tlM5S~lWg=$Hi0&?nQH-Z&D!~I<+L>cty1jB!*YoOH{Ix(cnLFI& z-gfX3dLC_xpqr?GNG%7#&0=V=m_TbfxcgP)^J_Ty)&2E=>}EqUGZh+178ceq#3pW>e!fU=eAt?bHMMS_SPDe zit;scJ>8x~xhPo_TT-*6bx)PL6cK2l>Z*a}$lj?SW;lZW3D}eqs@yinsiNL>Of)nD zVf!DSOHGF3YVqzJtB8r&b>@+3XzZ8z_!x__KVxN%V>WEoaNAfOEb@2mZZqTe_w_Yx zn+I*Zon~V*iU}*{-W^Gh>r9UkhIHpbM--}oBWsQkpL~q?j(yRX#3SE$TEuh9wfB~m zTCv2FZsvK;+C$$RGBfv9XhG+?XXwV;p3)=r%^O0_=UZ*iui~xBFF+_N^IS{w^KS~> zCL%hmSV&7%?V6g}YNd%|Vr9p9(893d=R+|FrXG4|A6c=09#g6JkwXx)OsRbm6LfBhbrYg$wfGo#?QNcP5;Utxvz z9!H-3$We%I7`1mqG0D^vXdh@aHHnrC*lzDK9W{rD_rpku%8P`P1-*bFeNbP-s7QwW z<9+?lC;R(;+v`P((j^8?6}HO^2&m=Og?A`%jPDec5YnVCO-8gwHn z=fgLi`r^%N?{oOF+`80ypd6w7O`!3o7W^7)?ypu#v=VWxC8tQu0dg-bqEWs;Lix+?_DzT{%Av|kt03663qMMg&2B_(a|Ab~dVFMJkDNtxunCUWc;>;LJ~KGporCaZHe8Y{;duQT$Ur`{cA+1e*D($iz`z{1AEx^^vl#BFXw@TeK2pYFVX zx@>Y`XEdR4+r20a`YS_pl{Vb(YNi*)Ko%okP|@4FT;;8`2G;agZ;rNDnJ0T85u|9W z^m${_4*vvtSvfpd<@fq(C+`QlxHP_XGlm9l;TFn{ZnrLAR{xVxrH@|KoXbEK22 z1re?8nD{IFaq4eLJ{KZ?ksn>v;;YdIZR9Tm{iz+#nAr^tjA4BwzjT$b*unVxums8x z_nE!?$zQ(w8f@l-PcqgcX<*13)Bb$LR44X}OLx4tuWzo~JfMHKT4ZhrK`IZFYgHcw zuTR#hxEjQuF&Fr%j7mN~<0^!YI8 zj2b_Qj1I0gosIGw;x}n~b=2&qrgFvoblzRQ!g_ycEX7GU3*2#gRsvY3AUvgkwY7n1 zrdGM2Xz~e$H=!9LbU6&HRjoL*0dCn-y{W6KpvXz_Xg^Kk99id%IYf%bPpezkA*~@9Xqn8yUNQCIuucKy}3t72y{tbpWfg9Ii}zb)fhWuf9$4?|ERm3 zr?f9}d{C~`>{o_$%Zd90GL7k#ffogg)EY{~yBX-+9LGYuj=SomI!*qy&U79>9XpXL zZ2Y{uE_Mf9BSN4%S@#k!OUfwgnIC9QrIgZ-5wBPw&tR_QPwDz}Qp4A+;ty<}K z^1E)oG=KU2)dy>3$EfO9;TF8yDRtqK{jGuC-kfR-Sb#qoYnFtAXk7Gj*Oh>}22c;a zX~Xeg+f+nH#{&eal9KxGch_CPw3mN+^=MUQmBfNLmyA5Or>_Jwyw&dhonFRQ33<2x z35|E2i43dxR#Q{gv1}DxtsMEP)T&!!dp)vWk3*}GA1XSNJnD8oKD>H$;-~Ey$VAD= zxZU};mis4Meykxb-kN9Z7G%bMGJxah`J&AP=I+P7-aQ=I&!BUbz4lZ;ZJ(Al(+>IK z!{m9IvuX|Wtom+f6*9>Mi`+a_I+}#}_U;za^;AML4FoyUC|v7iZ^I$MVMc)`T^ieR zBidS8`+LOvc=!I~gzUqSm$))-dmhgkv`Kd&$ZfV?~N@ToGaNUR|Eb+d+3#L5zG>> z{O1Y&|NloZwNYHO6*^{G)ln%3adr0h4uSFnJd}?WVCm?sap#NuI{;{Q1dDM^p~|HJ z-~T)-8d?LEROz_HwMVd(EG!$WKCZkbPz@`Op0&A!yzND0caOx<-vG$}PoAj#T1Z$J z?ZsVgR$`;s$7Ik|UJ_`4MUT;5&-ARlJHGP$=}+-(lgL;5od+6I*D8ya%EOQMNM*}M z7IH}aW1sgWsdRHFo|bV&k1OMmkCnL$mm1+ilO58#cPpP)?k-Ob7oqOU59*ye&K&R2 zAyB6|1X`=9v7IVb(WNFQ3k_oU>`Nh{-L-4H_V1e7&oKATtKGUmt6;HHt>-I7)gEFP zgz0Hf=aN0gzQ!PmFj^*qn$OFXwN*KvZ_ne$#k-cd5Aar)cYz^InY25`^^JiHD>{yB z(GqXOU0rS{c;b#eYW|lrPj0pmv>txJ7)GBT1 zM{2_4l$E0b1LMF2n~y>yQehJFY=u-h5$keb+i<(CEV=h#(n!Zg@UC8CV=HO%8aqbn zL@R*YXh=*%NQ`~+qIE6b*ml}-(+^BZk&n=4ZEiq{-4K3;X zs+nZ^#q&EETg^GKgt+ABPlsv(tv?^@ZlYwqRj}O->7@V&a+rO!0emxfBB4b>=2yl}~wJ}iADGQ79a0@47f{OMpwpQx1=n>HZP(b4&H zj?d5R_#QA_7AVqw#=H5`+{(&L`^e4O+8PH*Yzm9KE(fMT!@$4*2JXGnJ{+Gf1afv% z-G?!+ZGE8avWV;@aw>%(c4!NFTj&sT;wdfdYg?<2r8#c3m!Msa&{wcQLMDmO?61PY z?H@jG_7wUbJ2}=BCB5*=Dca;l*4`y0R@vHaQjE(OQQuj`P*a=COar6lB!=5+c45yW z*`vPxvbJ_G-a5DAK1ENFm>F#QT+t7MTQ?@I?N$G|b&C|Fowtq)IY?c7Y?gXz+zCLh z>nS&Pe?=c!9Cl>nT`;#!ub8H$q=BAjbabSH^)kD`pZ7Fr`@S^>vn!y?Q0ua&Aduh& za;laRmLQ(tUhVE)EnLeNSJI7nKe+YsWz)FIKfw_Z0im&m`o?A;d{dXw@avL0_@~C4 zt7Cg~;AdXyrjrd`yvJ{)H1GE$Nbd!h4W+!ceU6*O|0 ztAq)oA|f6+>LFBG!1t)rvu`gOb!Hv>daco?4+MJ9<$?YNyOuf4rnQ+s2w z2YlLHiS5=WnLhmfnh~7F!H^5#l=X?TVOY*+_jPm$^>uZpc55yE^wa>fH!?OR&tPVt z!vkfG$S+nP21v%OCnQxHwzXAoLk_AJj@%oGD1+hdaeo1`?gVvO&T9d$9%YRLhli8i zxO;x^sTyaIU#rC9+h7we#YFBje<#=Iw_~zY%u`pd-WZ;l(K>4Xc5oHV2(oKNyZfZb(9rNN zUnb9w$|$}N(D9=b#1^MHhPb%6u)oN}a~4c@^Xo82mPa0WSOk-;kzL32?dy93(k*!8 zeC9N3`!w-xo2_0N3MZq=SX+PU+(Qx03nGu0gln z6t$h`GLL2s@~iDvKK59eTj0|gc}Z$K4qhlVH4QojdJM1K@!aw()a3bSs4Jk1*;1q> zaoX3`p5j=w-)MMI0lgngOhBn8E+)o){Wz4W1wVd^Gbc0ixZ};>E8l$A*@_-Q;8u3Pcf8K`&)uoqX*_|8L(8o#)d;MGs)61Hd+sC@co22bbXI z;ZN8%ll7C`YPS3Fr_M%NGcIZHmjz&)Ne?CW9;`Z@XY-_dCt=b{ScE<)v+#|Ofsj>> zJoQ?O^_4w3h)bDvsI}_2nU0#TbX)^B11_1H>p2MCG`F;%Up|J%Ez8- z?*1;QA@0)E)5XA;S{uwVDMMpAh^V_`X18mnf)&GO3s`ixTKgti+4bY1vP=c<$E zL|~OnoN92~Ujm7$H?LpA-e})-@L?%dWtIJu!Q;b7kI~J6#D){pSh+k_VoC~hdY{{0 zS9{v=l(~pyc4iijg42BWaQgfA-NNlcqKc%8=0wDVlXh0?bL(u4Q(bj!ZK<#dXuYm4 zm=(M1eudp^Tt~-XZkaPZwLcH>^LREBIXEx?wNcAc8ATvZHkk1UErAxC(oA@Ezud_A z29mYKhQIk+_`ZK{@Yth=<5@s0D>HLOhOrd%=8jk4XwxYyNNVYh-1G2kZtx;hP#Buz zakO{BJ=_03$a~AEsNV2x6!oVfh@g~GiiLoHNH>CjNVk>~fjTg9;V`BHbNQBhsyi zbT>ncbTc#zF>`MGzwcV-(^>0$e9vLc2T^cl@BPI6T=y04Bft}!MVTq#p{G{~AA`92 zJpqCF083i3T{tUe(dWDL#K^&dmnpeeV{WKxdV$R5W6P5*~S@)%72tiw&SyF7Pvbz5BFwwW1*y&0U6NdydGNf||J!Pucr^a4|$ zs)`EoUAiB>(`Z=S97hXr34|k5qQJzN8^1!a>`&a=0@_4PjheE4N3 zt*#NawFTa*WOU9NzslZ#J`ZSeB95I$pA0R5ubG(m_F!j6zvN)P{xE=^ppWW~Y8e^% zQhbW$zNTC&!pb+=m`^6;xy0iA>KeB!Fq2hN15+8+yAw{Dr@eA#W| zI1|L)U1X}<=#tLeR$%2)mFJG1T9mXB*`}&z~*PyBlTv1C8WCm(IA(*jC{P;~q#z21e zmoIdYY>s-c4Lk%@7@$_E=unx+$U%~nLOeV*eUVBI@6DJTQ&T`Xw;JMcQXl+o5OU58 zHU%+p`4eBd0I8FCx~n_%I#6?gEg9?QDJz=U*;!v-TIBIDEwg`qP=XXo0lh#$LftE6 zh%4F2aMbpBkO7F9#rFQAGu6Or3TBc>cXFMclK>j##ceX0y5i!S8JgWaJwEsm8Ay=n z@R4={LC3dvb++uBoX%)|JtZX$kiR@+OGUf1wYIwMY)94|oMSyJDScVfFSF9;P+Jo& z#AL1Alh4Q5))70LQ)LBv{deTret0UiA{Qs$fl#{K@7Fe&0L z-!rz?>9qsf^ArOl?jZ^EmYs=Xg)Yl_*lPTiqXdMWEiW$CZG(Pk2kE9F=(_DkVIoO* z%_v+xsEJFzpy5ve;2h*OejAR7i=*^9j6AYZ>KN?qhI-X-dM*3T)oa)Ep6ik_f3;0i z`}=WZi~eANoajG;x^DLYm$?FMCwAUv#Ky2U<)?+k#c601?kcaM^lQ9flWe%4k;Al# zuCVRX0~gWa%_=S%RwyXTw=_rwV&p`KLe7%n88ns$d=&TZ|C_R0D zrGlqSN_uK~8gNI5D}=96kt)}hE<;vB%EX~xV^f_zrKI%0(F4?~PLsVj*o-{M!2CH^ zg+*X5HnZ^42V!8HQA!niI2g5cDdQjEl=oKw-Hk-d43NaWs@t;YBJ4IrKs|w~sVG)K z)dHyI<+@scLSY)Tt!-=uA0CH;W&02(6NF}`lsQI3Md{!1(m2Ah@jKepjCGI`lpig-`iz{WESRy|iYH<-y+ zu1ulJus1NzH>|R2iWE48>|3e4LGqs9Hq~EP)uZOT;S6D=nRhKR?`9ShI3(zggSQ%- zS#3PujQ`4L{CSS31bY2S5s5M2N2;vsWxg2bMiY$Mq>uziEj1=?$I+o6p)n+3xFbz& zAkkXtL-DpIbHlZyK1*+^y5a&h){0mM{tiP+Ri~d=TV%(#Z6Pk9JK)WS)3$o@Cr<;W zsa9?*&+-L5`q6}{GRt|hBw-gwJfozeiv=`jgHEsn5Z@At41Ra=i1-+mHGnf=!&UG@%>YC-?)>~14rT~9T1sQ|#xj12NMOdZ5k zF(y$U@%7-_{?{f~T}x|+N!0Ey5ei^q$9qOR?ZegnZ(DMN!~6XF2k!_w>^jF+!mdb3y_J@F>#;V1pDNLmnj5Mp-L-pahZ8O9BER|a=nU{yM2n(U6t1Bxz z+uJ}KKDofeL>jQgUth;>f8LH|w|a*hBN9y{W|PzaL(mJ%`tb(h`0u3-I!{w_bE^R3 zsoOv3`;h(NmK?cqtY8V+B$9@v(77;-MLB^dcVy7g>S;n9>M$SPT&^s!Evi5I=H3{$KJjg@VR5)Jo^YhP5&2F)%FovjnIGhP2uiH1vc>U`) z)&mxd01D{B<|3bGWexRnD)tWD-^)!+oto*NX!&;h*}4e&1SrET5w9r-qnX>2KyG#F zVLg`mD^jQ-J+j&Chwc>_6ZJO~QqZSEJ6}qZ{VYE1!p6-ysr)S4d%ahQundC(>Wnj@ zHFW4`bVa#qys+m1=5P<1Dan?5h69~`mS)>dcVf!4kIG=Wkmb~w{Pda`|Dda$`;n=@=l0c^i)}S7dHA&X$}Qzz%++_z9+gTSGmKt4iFnqR~)RQ zadB|u!|uz8Gq8Jn2YPdbg*|+X99&%F71a0r7p5jk&@F5X4DrHMkd_iJ>LXP-|>3f^l!sPVy zSBIVUd;>2`>~7jH4jFpNpbv;i>mbY-p1zRpSbA)0cpKd=#Ra0JkIAQbwIHx_Q{EAe zE|iIF<2b3QBQo3|&dJeMTkO?(vdt;%FKMXOA zNJ?g}g0Q5;#s6txB@nJD>*#m@n84fsO-A;;pPrf}-N$rSukJ1m=p1b=q+OnAqtHSu z)HRthD%KYPtG|Z_~Uc^u3mdIeYHX)v=b2V_4|1$OBiqoim1`~m6rpOD37#H*@MjRxQg1*`gdMve21o&N!t?kC<`4K&Sle3bi0Kgb zOpM6XwyrjEEK}n-zP6aX4`Bej#lzi!%O80B!pL7)OFdA68~Gl7!xQfFcGe*Fj*cD2 zsyt98DxRL6AXGG&s>3sW`1rAwn(lswV;~XlB~wj5VUS0*SzaEmwx5Q!ASWy9CDJ+` z_jdnQb5YSsiK6uiG9>;4J;@y^_9CXzoM7IoaLiz z4#~Ky<5<|hNut79%;*JBA;A^&Uh~>eWBK}s+2`Bm-_M6s0tiIjy*{R=tGo09JKVBr z^!DE8&z~_~$E#d*IMI88>m_B8%CQedGJMV}kmep8A>>;=78Y{X()w&|VH1R1Hmf2e z04m^HuyYR4&e+NdzhRw)<2j@sPWf?nvR?RCo|`RW=zvw9)%Q~wiW}r2Grli#-hu6rUe{F zT{qh=c$WQCyVb~>dS^!f9s(4P0Rb4C&p67+2cKWh^)4r8X;VkXdv~@8J_mG-d;dnui>$8y?9>aJ%oS*u4dX4@>oWWY=>!17z^!Pf4T%a zJp(cP=I@X{JBG`n2W)kGb~m0Xbs&}Qf^qY~W~vTiXQjxx?cnd1^SWjcyws8s11N;i!YEEd2V2{r52KJ&_{x4U5LUICmmQAd@AydMAY&(z%hLdF zTuk$}=H1Hhu?`SlD5T`%%8W4hAS?M}aJ8u2uAd@QAIiEb?aXwHv%XC%>W`(yr`S#jb;fx4j@8|_16CY5C?WA zcvJI-F-O+&CF6zX$hJG1n}@5A9^hgEJ$M~lcX12PIfSRcJ}+bQSGB7lx{NgfJ!K9KM>InK|kqh}XF;9+lARn3|+*ZEjw? zc+t+zuF7q70)@)z9m0Is%SZ0LEdz0~#~QlyZ;NG4)MQ;4cr(^1M?Z;BguJTmdaKardbwcKV7^CT~EtU31clI6i;rY96o<+ys80 zi(K7yfZKyx)Uen$*do1j>9fj*wvG-yZoZO|!d1+Wi(i(G((wuzSrAQKwO#h!IzUdC z3w2;44Lk;WYlohUKsgjsje))}|5T%%rWlgNw)exKmWBqsfcq2-5WiS%KD>F0$3RYQsO48n5ytP-nQ9xl ze9f4Gf(cdZB#Sa5r4*!TrS=3?_9q1d%+}*nP^0UI0Sfbn+iOE*Att;wLj~jgtUL#M zTiZe&clWhby}T+Z>H*#97^p#%F^yO4s{G_d_xp~ zA8xIm4aE>i;s`e3IR`0|YN#8k^yXpl5fTy_;+3tVfioDvb88%SJ(u~eySMMAXJ*jR zU3FdfEBu}CGg0i2x2=Dvq7g|m#AZ#O8T2+p_(4kAF!P@+d)(T%SM%P*Z3fqk zua1U>6T>~zdc|Tyx?!zx>`R8bq#@@*IK}RMPAFK>CXx&+_nlq>9^x(k{kb-*?Q{Q` z%T6;3zw$=~Y^|*DyIZ=j2A{OjwBCoTlGRctuV^PnJcwo@TE8dgvI~HbEp13?qB;O9 z1x9u1eaY)UTLU8tN~!i};jr-2f1%poB9e@wy?mMGD#H!`Xw|Kk*X^YsGX=ZstDyLF z;cu_=%sM1;@<&E$L!k{RZQrcFK|9H)%2$TC2YR*_rdiml3W>UZ01?5DpH=io+4oUx zK!v%t)YxDho=OUq2JBpq^vJ5s6*sq?7RoHUiAvUg&5%@^Q_yL3HoXf0u4x(P-vbNd zG9(+=_u}6o&;JK_5U&7_(NVAZozkp|S7da(Fbgmd3IgDBLPExR-@BYQD<;M>#6gVZ zbDZWpgB8)b)d}|=eH#u|E-rzfLFLidg2xD4(Uzaxsv|)*Oz_wy-oE!FXS(Zu58{E? zDpC3QX(=fwEAFQxb8nvfa(aM@c+vOD=cU)VK?J8oOE~4%bgIY~m{dgnXY!Z-Pvl(x zzx&J`Y4i{OHy7YUq4Iwi!TkT-#r{8D;0ae9s4)(3Uf5fkrG`@tH3qr<_YuT&Q9Lvk z$f02aFOF4oNndY2gfI;Z33PXNYr2Q|@&5~oNx#R%#lp-jeuqy;Obk3&bCbVIj&Rsq zF<>;Hq@;9lAq63)h#un1nOo*%#9xF@KKB=3s7HgCK6-eey+Zv=V`KX8D}2xbg|CTnPsk(b9`C5J zjaq}SpjHQ}8yqLTvml zF9ko!(9&{2r@$ci^C!FR=dfDAwQ6WY9JFVc&(4xFiQWTr)e`r8{X4uaaWWq4F+wwM zDAoQ9`oEK_v9gzu34o5+xwGd7p7+9L-&@}c=N<_7gHQ(*9UZOB%Nai)KjrAn8z56c zvkMr{5df(QKP{!6kGscOa93B!F1>z6iPP*GYSWX z2N8!50~JBp+uM7r=qqhg-61k?w>)z4V-KcftRE zUG&uhuoTYVy=digGHSZjIs3n;1G+z0q7XIcs1ny*U{D2B39z{nc7$@B7Fx9=sF|yq z*L*@b6ou`e@JeW|6f(c+-kdd^~w^Hs$)pSNkraX+$}9C(s+ts;&yj;mp+GJ zU)iqttD&o#0|ZHqpv8};h$Oeloi_67zb-ix6pUB8*)}T700chXR)r+^T3g5DeEI|^ zWMTo(w|Y!}IGL3>jDw?1ef@9tT{!e(>;DueQ4?TQnR+N6=vP3T-Fe<4@}R!?sTP-bcrWd+fXVb)MsC zw&WTbf1ZDST^juFY5W4u5USma3=fh&o>`#0Liy(H+goX=OZR~%4`0`=Qkhx37|u|b zUmLH?&6S9~{<65F1j=itgZ7wK5tM!vukQ+#Io|~<=8!qe16Xd9u3h_iyeAxPuzw7t0I2XQ?Dj1Ql@Hxbb4yXp}Bgoo%cRiP@{h)}A>$$p$p| z7_Q}m$i)-;{jbYPhkm=$6Q@}*NSE1l-wn!Lomtd?Y$dB;_mBJg`;1lY6G6cak?7lh z01atr`L>z(_sieZ)I+|A^XQxZ#>CezdaobG!()$`0CT13HIo+ASZ$5V(>oZurYRxBh zPziC+%F&yP@7eVTOBF&R0;da%D!f=Z#W}^93)0hvdw#W`TQiNWcZt^=0^nGz%#)gy zme~PK&sVm8s#MwyhJ|U*s$Tb~chK>*Ha4F8+a3L_>=L6813m4KV$ea9MwSX7fEDg5 z!&f5M1K+-V8xSA^bL>x|h;iBBw!;kJ&Z!Gf4`!>$dZ9}b;s|3u42}5;i;JOw^I957 z$_%l8n`3=}@d*aueUFJ+BV%GBzs9P2ssK|lC>zjM9-yXn^k>^JNH~v48ev*nb7nbv z4umV*au^_SS_1~Bq7p~=@a^Plz+H{Z{+6o}_pk^po#G+&yIv}Q;`h7Y2M>7*bbpqZ zn&O*qf+Ap>6J>;qO(Hn0@-s4yGmRsj>pjoS&CSZpfXUd|{Df8te9;Nrp~rzny5J5T z2xpyev>DM;ifhy<-?J{0bH0&&BP}hx%sIqs>D?*L?O~{3l)(o#U;!~vwwc(RP5g$0 z=^BuZ?|69~@VQ}hiyR_Ev#XD$)E~-IMnp#9tCvQV^ak6EF0F6tt~Y3iRqhP}xBDJY zK(2U+nC)Rk$r&fO{GXK^G=0ck-y<9r!j|@uj!aVC#Du`7Io{J#m|~j+GdiKJTQqIn zHVR7j$*HrbM~3-M`GYC>`5+W~hLhI>3OT{|?Y}$29nJK!4q5iIy z0|UKoON1>1wzkHi)JitUiJx>maZIo+xfCEED$ZOxFrk>70cVe+w%RjQz|&{<|6Wo! zTJFC5VbT=*8f{oHX>wSyI>*J4GywN!zM19@;m4kmoxO4D9LJU-vEB2s&Y40RxV3VpBAcXDF~WM}Rx=(|Ac=YAqBtw9VtRQIKo3xuEa&}Iyz z<=CO)eLNZ7+uI9mDTjTdz@QM2V+2>yo7zw;TfIOapyf*1t9r@J zFU~I})&X;&ByBYL)I{R(dA{Pd#{uj*TpW5EPt|&SNJ(=CBv7`PTJEq>v-B(r|s<=;)MM;OIi+SU+UL6cVthR0#d>jj$3Quf*}trf}Z(zaOei5Nr7RN z_fq=?wAlR{UWw=(!n_N*&ePM8|7-af>S(vmepG;z+1IEf1zGpHgtoI?@j8z)K-k|b z39oaJBi-G$r&Pbh$7TP_Yn2H*Z$UAU0 z;0Q1^O_SK4NdS@pH3AHl9Rkid9^3Y{1xAVsVS!7Ke_-U*+OW8p{KJD#ApEv9rif)0 zdjxu+W#k1SK6w>_jsP2J;5)KuP7aP5%1nQ1W$-{h+*=+x7_w)kp`q!CpefPZPa(3W zeRLMgiSJzZ*_~+7X!56kPj4WC5EK$V0U-5dwY1!}N`s*NB=rH#yB@2(9V0z|`ul-` zDsW?AuJ#N9nw63HuVz;TFi9eZEwP-C(~3{p(|#=bj`U<2y(gz1`7wjV-5d^{IP z!36ZArUbg01ct7 zE3F7o1lY>MO|k3$j@KkPv!SO1r5#}9uYcWosE|@WTCfgF66d+TGgI?g7_tqfTKm4W z&|8gzKdv-qhfV{zN1r*P*==h9*K?Re$_&~+`!RhbR2H-@2zacL=TlF&jb#jS%XT*W zroc~^^++-ifxMBak-AzQg>(OnJu97x09rMy)k$@F;}xyVU(Qvy9U7}_`1;USe0Rns z`dsI~zhI$c{_r7>@4;>vYnX+mGTc@25T+#G^$hRBWo(^QcT^s%WF;OD1+X$)lb?K} zF4F|are7RCUjtHo#F=b)5Jke*tQgtxLekf->K-YPz(mQ(QxFgdD61(iFHcV|&#afE zhjrsI!ZL~+b6osr`ex2jPt6brRi!@A&H$HdD~d&P10W zck|RKfynC8dlH01fF!#xs5Nv6!gLg`>UHpYHi)C0gI?z?PJ#u@&;~UvaJi1IOZ^#W z>9sWj%Z_Mve=q{BKnVQ6g9%r`IHe0M2{SYTy}ea*^zO2=PybBuk@~=$*4Q$yajyF@ zEMFuDS68^NiohaIumH4%f7Wa zry73;{gHqz2V`vnf;aA(p+a06>aEkZ4bK+H5AAT zY_5TR8>H*k>3zvTn@O^X?Md^PO#}Pgsyzo$mX<9dt}WKqVhl<7>p{LRTYvki zGAXSk-0=q?sQxDUChm4U&^wiqCXQ{nB)sY=aKq6#+V_!&Uq_Z~hPuy0SIQ$|BXw83 ziQHP7Uk!VTl20xW^S0d(1#yhuL4DRN)5@QJNNG0xPKH(VKTA8Lcjfp zM3SSm&5Q)0sYTzdAzeY59VIT+R;J@Knv1vcEB%msx__CF2c!-2j!L5d3V6;MEL{sz zYsRo(g?&We_FxwO`O^e-A_>W*yxpi6UH+w`LuIraJ7fB&=@fuVe8ohY)$5`rkn z3|uqr8sM)5B6rZUOyl%@Q7i8Vd^lN;ki?GO^mERxu1q{$M;nxK_=!41&sN}ULiY@a zi~&uOyL7$pfb0yD7F*6I!ame(2ZX@>WX-;naKz5soiNtMum5{UyNS3RM2lu@FE5|0 zGDF+N#)q98M!v`L1IN@VcCo|EA~$c^wQSP5xVQk{8+I0HsndIFqqA#+o`dZyHbS=b zuC&NG{5DpE9dehPf$kjp+GJJJIP~W z=aq)ZEZW)|n3#x<G$ReX!QBh>eM1&oKUZOWwf1xxoMeB#*D_0u5u(Ap6g~Js9Sj zB=s+~ki3$5ph#H))yAOXNp)D}adZ%Pos7&@|4woy_A>i9JGi~E-1f?8dN;AvW_EU) zZF_Zb(b3{NN7co}{XlEWGd(X5kfe3wmj6=mjnW8Xks-qHLXdMgNB4X*KIO2 z#QQQeY%zQsslB~G>FmoWYJz8EFH+i`aGYMvGjT0RW7BvW1iETZbN%EZGT%*I1s(a+ z!Fg&iv6@QKlB+%$hBcmA$NV`N z3b3Ja66W9}(b#zX>FSytV-PL2k=s_fE?PjXGxDB2fZ{}+%3jPnUXSZ)!ER(}VaD;6 z&m#^%f)BnBT{ELlK@Hvyvi?s?tHjeKkxB|sC;jRfcBTT^IuHw$*m{H%>?H7=lJr?v zxYzkfPxaX|LLVP5@Agg{nz^*+bC6QF+oFZejy>ui?bOLpQuY0L@~1QOB}gSuPP|-b z#)IH2JG(upN|jjc*|YDPRb8!Z^g?g?8X8uHt`E5`t}r7<%24xhD1r`gXng$sFBUA7 zK$BTG5NA+a2!)A$0gUIWgKG^9PfNQZ0ei>}b&x+rm&Bp^anu{@3*a97bq|ZKMdT{p z1wJ4#DJeA=U~psAmcCwk@;WjyxbmQ`(qgP?=(`Y-gM+TZMxzfDFZY&vJCrBwb%2K4 zdo%m5+D}61YvHTcVwx@cYn&Fnm5e3th8>qocR`Ug)PQnb3lt+&VP z80i)J%tv~aDrsr0N;p=tAm0>PZ(VN+zMezy8JL=tX-m{ykEggPAYeK23F<(6Z$xes z)gS}JC6HdYaI{e5k>qXRZf6JP9qrl91jIZgt0G>+c#Kf!fpOLvKr%GdT~vD{InsLW z)MaW-DvJL2^1TAP=g&cSwcGY?^@nw7k-fQ)x{JS{+6Y_g*E<^KZ4{3s_m7=}3TVqO zPEMSuO$@;c?jgFw=6{R509zW5_AfqdhsP?I6?6^UP2^hYoT3z2a>i$eRmp+g*$MC% z6i%*ieEr;^*vded; z*t?K~0j_sq2tLAWPz=9YWIzYl zWprlrs5nWwoq?Ke!7YHT!LO>&bk)r-Z2bOaP20)Ru(-Gb_hXNq+bbPwrO`JRe4cM* zWH}}xm$p;ywy_L) zH_VM&AteJZb4vJL5FAkq$N3~>&Q*FUCh*FQYZ2u@;Luignn%({VS5XUjlE#M0)yx3 zL{?l9_7mYzdqzXIXlbK9PO}s*5W~CR(G^Ac%Qn$(-~R4z(a?0^91wJR@PL^)Wi92~ zw?&`5`x>TVtM*t4kyO*PeuJ}`AiO6MPWjN>&7+nTKtVds#hgL3+S=Kuj5mf&RUrfd zJ!U5hKA8st@7`PPv+A#pn(~umI^_(K?`2g_b&qIjX&tX`l}QmB7}UgQSmstSB!{_x zTMH6sTQTAB{k?BLZ*MJ+SB=YQf3C1qRLNN0br+Oxkq6)0O%9T%GYj3&3=n=hJnRA% zGw_$R>S063ZEdS(-zlb2&NK0GuZr4Mp6WHTH_!d<)Z|%__@qO?`N-ehAlo;3{=ty% zF&evXld`T&fA#7!y^);UtH~VzLrK2ZdHx)?uR%^ri}^7VgZ&WtBjWn0;xgaP5+5aO2#$a~dovI0QBk##bq)>c!pl_1#UIt=~C1!0bimQ)ceCtl7z5 z^biC$#D(>*8ds>*TkCNO6Q0x32IDmCp(M!zV+Z8wRzkFleLi@rUY2^CD9qR=SZckIpzaLVRXr3WUYK>+UT#adgB^t~r>Gv}!0A!P)2t_Xt?oi6|Us}EW zi}I|flMnOX`*-)F1?mRQ!zQ-Pu(T-D&%@2iIxF>5R`y-JW;F@u7Jx7vpAZjMuItl# ziCK{Maf*4lrDYr&(Z3w??z;dn#2*N^aHW0)j|>{7H9qfsd!~_*mX?tgdE(Hhs3;>< zh|hQl{luju8#1M!0%2jXZLjT>fwuO3O&y&*ewBVeCf?7_%rut??zm04lL+7W2aVJF z-jZd{+r7$kd7`Q;01ScR7%=cL`?rIcxDrESE;C&&=w1*oDc1dT3QgZfd4|ZZ6yoNV zmeT|;uTS2RLz`NMi>Ly^4S%Mh^YJ-~ULj4O{@1d*b{!i^k~R#K(KF=da&i+pZ?C_2 z0f?J-U_?el$lepTfiuMd|2~7lbkhMe8(YfEEX)~+MUxA>gx{Zeeg0w5j~Tsx`j;IY z9Wg(Wf88KGAil*ta7dLhl`@%{y!C!SU4_MIzj@N%i~R+}$n-QcD01u&<@~cowYT$& zYg#w{L^%gsZAMX7RgN83tMlZHpMwH5tQf@GZT;fj>n@$r{MTJZPu#03JT^FF=WR@q zsI$aQfX#MEc>g5K_|=gr0sN6?z%IVvSPmDYr6BLec0vS^tcreUZDG_@OA_?W`kP*v zBao5c9~qxGIIIn>j;i;mQ=<=scM~33XX-vZt@#<6G)rEcp8uN*K!k3~ySBy1z(7q0 z)g6BLz|vLmv+mO+id0jRlkXlqdM#D;_U$zM(17}tWUqgHqu{xA{l8Ny>UGBpg=vR` z5hH!|yo0aldFAP^2oi^|_vjK>VTcRy&}P@(mNa-418ykADCn0gES-!0D4gG&82|O_ z%gHxoQBm`%DkW5R`9ia9O8>5heS2AgZ`icCoLf=$vk2+GM_A=-dW4{(V-m_N|L$dP zZ~w%~%Fb>Dj=AT_7}6ur>3{XND|jqB!^bKUO%u4&nl3U<7NFvL83kuF19N2tQ-Ff;{p{uE>so@V4OMK;T)wt3& zOpopDRy6gm-Z=ZOX?_zdfA+?!R=Pv|TzV{*CG@nlX=pAp(Od?q-txj<5T0kj*TGG# zWYE8Jh;hu;2W)S<-l-y^TM&2nTn82ntt4k||MRuglv7Z!o!V#hVT@P)@BHi>pQt>* z;*~3u)iE*8lO}4Q#!&jKNGzCGH~xJs^fdH1h=^39QlzWTBQAyrQeSb~RkXe}-8>6aa9#o> z@_iZ#g`E_CHLQAl(ei;L-@iAv=jG$8d57~N+Y0(9Mo&+h5EJoj?Nk3xbSpZa@bi?z z+7jn~UugdQ&vo$KnXxfa(k;p>(;A$&L9>%vmFjM3>@c~|J@jW}ptE&NefIy5Ap>LKHo zeljooW)_y|%Xd6HmXSpQnvWhCs;L>vTg!WTKL4|`3`BLf155ee<$-@;P`Ti`jMmc8 z>4NM}OO;!urW$UvXI*cfJog)Jus?XWo?qitWIv%d{eQ&w1g_-&f8IF%+Y6|8;KZ6) zvX6}&6%`o?)&N@ib=q25K*7BAIKMJbT}oO*qX>3v$P)wv0$d)udlqxnzWQDI9|BNz zdiuR(6ASmwS>VV*E8@rILpL2)y=~VW*f|xII-sQ1d#+1=bz2jLV*kIP=x=6`aVP6` zMn)ENZL+H(OEt9(wY3c+VZo z7nt+xsXS49@oezazdw`I{kJa3z(YRIguadxuPtQE%g;AB+;MS# z34&2obK{);d_94zT4iOQgvOy@pmBbdK#KG56yY6)*b2`6hYt&l5jP$)8+`FA;UCdN zlX=<1>*woZolgb4`+0#yTgi{sXy)eF3Z4c*dk7?C@cQBMvNJ&>?o0GDWYYfD#>mJB zo{~lHIXb6SO0wqU6D5z!G(A51-x4rCnnB$s6SSFVeH_*ZJc^|WA8(AbAPdB zfF+8`U}SUN5voRVhQBG1n?!E^s4KhFbiPv!Ez>)rJ3Bja`=6cMU#k1aUomrV5Vv1~ zT(NZ;_x0|B)nfw#xgdst3k z5O7X4_uL{;2?%&^Lp&*`{VU=1$pAykJZos__F~PD3t@uKzq{Bc$8pE)28`IxUOObj zqE0(YTDaZr^=?jKVZ-0v16o&;A2M3E+y+95T0>)knD5OeDLwrSuAM6*>ERYjeNgU> z6e%ewQlmqXh(861&# zDj!QFUSKlXp4+fqP`&m)Ri1#u7%{P?BJ16|cl)xG!H=&BikeFRqh*0S)crAyBnYHe za1c^g5KH(R5izh3nnp$UR+%Bcpg>yz&K9O#CU9@~p$nM$J-zbZzC?)3Zy1s&hL~U`mAgd8dryQ#gqgdrAOq4(8d`371Zh`~oOV6^uY!YM zlFgeca;;^q*a@F>O!KJ3=0L8F2B&^=dwaPz?j`JzWNW6dG(jAgrKP2*z009x_>WNE zTRabWPzF`nLsvY7U;ZT`H#I$>{sjM{{-7nFJ^n7$MtnVKltD7djhh|(NrdiXw1~ki zg0Id*5y&rIm>b0Se5opRpFjH22XZ7h2ED&@J<{=FATe0IW>!8ujh3H3q6cr*obaS1 zO4{oz7>KhNz?2|!$w4}Bm5wIzWy<1*)a3GXLBZQIikkfox{TNC(aVa$2UWW&PoA__ z?qh`6fG_Y{tVT(ZDoXE^FfVlSi2O#~gxSk7#e}((1ZudrV zLX`(pLnQ|{)U^q#`N#`?|8q?a3Nn967NV_iG$JA*pzauC=0goFfd1y@B^_?^bx^TGhu`jygByV*=kEry`FOqWA~_xklc)yY)YQANGbH zh0++XdT%A@a2eI^&zE9ussw!dAzGZjbzx(ZyraF{&Q6zSXE4zR(Z}-;ot>@6AnN*n zoAsMmaGosaT%nl?I0NnJg#}`^g`b@=az51?J^`qW8)tnE#`MQJ+QUN=>=#?K+AQ05 zkkbh|0|rm}>g(UacS+ns5_oSr(?i#xfz|O*^-_C~_~i6nHzab>Ep&U>Y1`V?-jFgPD zv_spzW%KJjw-jhN9I!>%U*Vs+H*Vk}Ap+0TwCLn9Ls=_aT{hvTh&+(Ydab%w|zo?gHKj;pO@ z!z06`+c%6aPr}M&Rh1epL`fYHm6R3h^6gzceInH2KLjYP9RH(sec{2SE9_iv#@rCl zA6|w*CLm)^N&ew9)MPkxFdzT%{39r8(C)FQy9wehvJqLfjyst31KP6-$qNSomlXA? z+Ry_iFfGZ<%>0jGcz#aUX;F;4v?Ub8R4_yW{1ZNW4C-uF#7-CtHKHwsRk^Nn8PP@! zauqYU?QS2p(U3A9u_%JtUL_o>@0#H>Ra^yE1gUf@`=+Si;Nbd8(2V@W+@$i3Nkvhy zxiZ??#KZ=|Y^G*e=7KoBNl3SLDDoIbjeU6DlFzISkVkmxfULrP{ zZP&50wRN}%snZ%T1LJiFWmLA(XW9Mpm-Kn^t&QE~-VB9fjiVBmWn0IZ+y47oWd^NH zO!}4KZVzW(Sq-;<6H#@wJ~U+InjpS6t@>TaLXWgj3#kNpeXT1FNdeknucs;~IjEFg zJ#PN>`xIC%Jg4OWZK2rvOG#4_tL_C+Z~Pnffhhb==3RPLmdEm7$FB)vsKN;QEi^Pf zx~}nKV=I)u9x)rUX!LQ;%*_G$cXU)}Kltk6vRLnTOVl}|A7+bV<@?c<@8M>My{qUK z^LAT}E3)ixTygyJjNf>z8+s-{>?54~0Z3_76U9 z?rv%=%uu=>HMeTD&FV3MZ7S})+T{zIUR@IgJEO~ifgu+zh+Okz6Xjt~OPz{M z$Ui13dn9gHn*e5HieAAmtu=Gm2BHSXM*n3jupyWZx#aX$zdx$#E zFg!GT2`1G3RIZ9I`UvKon*q4p?Z#yHNgQt`6os`ND?|m+^Ay55qLi46|AyQ*@0-K; zhD&T#EM&X%sDbl_g>jE1?l(Im#pi$fw!)LG2rzc8WA#;-4#@LdoS%XM@jH7-ObFLm zu|TY?j3-Hk130MLi{QUFwl_Z!@mg7Lq8|hx++}ZKJkQ_z7*e(3>IiF1jx)68f$Xfo zfgvMR$g-FiTq|`h$mgL7a26RDY-y=D!s*bvV{r<#h2I|#6#Ex3gkjMaeuuGIT$dOY zQjTss)!6Ep_`R2{vrFO?|9Yw%Dj~OnIc#;(!<)I+J7BKQMP7{nr#2=Bd$KSqv z+l%aa!NFE3CDhfL6*3&u|I^ERX4zKXMR4<5Pe|L$zv@xh_^1P4$-#Fdfx z#WUykFm>CLjk{3lkJsAfQb_6PjUwx*a9KG(HpaUiqv{B^5rSsxs%7}Mc6oN66h4Ki zUx7Xqpb>Q=+cGboPQ@(`0=tg&8w<<)=Cq0!09CjBuRi!WUV$pg&#x(%;NZgT9&*(l zZqPIPfBd-E-@=o3@JvfvE7Lq3Oa~eoWq|cky}!AI%F73X)klF7pTff%__)O4;^V<- zt7lQzz5SKI&}#rjsi@|XE?y9(bQ2ai?5z|Sluf)uz-*xw7I#!%W)~NehDhur%Blg|ky|N;=ZtxLv#hLs~@oR72hRN0z$z`z9AB({HN_w^nzFJ6{H+=P!m>a;v zpQqLaBl$hgdRnF`%RGJu)GyI0i;PW#hL!4M#A)37yBzTr2U0dUx?Zc9`cD=WAN^?< zek`7SPoFAz`et@APqdJagPs2N;Hut_BCdSIRtDL1-;pD6j?LPmxjrQf@(#$<2N1pk z1PkS)TLd?JSO^Ne|3?m>*ov1K>n)Z{$Gd?^=g4>M7FlIO=xj|)Vv~}}+zun}1g_cU zb(WVeL`N4%eR$3@7duf&)e?pAW>a8=lnPPYKF@E_n%N`{SdRuWyL<_zTcF>S;31gp z6xq_}rdJ*`zNeo6fA393?w7b9EObW}Vt40ObTHm`{nwKo;0B^5)IW$77S5Nh4S!8= z@oX#>>Nv&)P)M0sWJ;878jqyzq#dn!P2#{9l#>IoUikM*vcSZ158UP-;73AsUhNM0 zkj(u-m?y4;w$gp|0L|{GvYV8d)>l$+Jn?4_g;>rA4^OZAzu0^8a47r#Z`gHp6{XOE zO89D_2p2+#DJrFqY}vE#`))85B0`dotq9roeXEphtl5{D$-ay+_Q7oT+jT$RQNwj<#b?=bUq%pU?aKdcPLZa`JVj^?OZq`dXhKTF!38n;>t!e+=eb z!wr-n==Jfb4XDLtP)HlYj242{rT_l>ky~oOy8r&r$*kk^Vzh{XsXg*R>uYAt zw^;fP=1uQOlfVYB7JxpgeZ41&OG2Y^4HJ!gq<+DG7tXQB!mC;orC3nPk1`opx?4TT$tY(+Kn)y!00U zvGC%%O>)9m-m(m?!u9eMP;Q@wJu`Pc?TsVOyC*36ssUe`J}+uB2T?`cZf{|=kk$fv z#!3VEc?(M%xO1*_#qTeXC6t`WX8)xlP@rQ-JuBWrO|DyZi>+KZ(%QD8tx2Ptp{r{N zrP)~CU?@$+^k0n~AUuOWgv<0Y!p&1yuaJm8Jq(X#DO-R1^l7cLV-RitCO$<)b^nIN zGM#fXy^{=jD!?lmTSrHM&$y6>toYx58AJL#Lfk zq*TsY?_wVvc@f1c!&Xgy)tX9Mj&C{*M^ zY4DQ|F#6T+F4dJ1NQl5}Pu$qbNR8x;^IHF$U35}ly!sXKm7tfD@6?Z4G`%<5`cOIaqu6c=xA#794>R9b{Y0tIC;DgoN65Y6dRzZ>067lk7 z3v35zf$K7Sx4~E>y2-&VIxVv-H@`lRy63t3{(a!4?(~t@qcSq8#DQCv>j_Ys#&4ZF zBnvV@*~2i*l{O9-{`&P1(;AG!c@@r%q{B=tK45(`w3JX`Z|u0rY?XNbWVQmZD-^?E zAx@JLA~RqTAQiYx%8NMK_nQR*z~KSoRP?E4J#+nc6Vv{cKs!qv;RAsZ&QDdZs*t=A zU{l=62Epf;@poF{P(m@TAaCDyPW+XZSsJ+#$?C1)R+MoIxlMS7xms(#Il}l}#NOew zhv=pNAZW4tC6-6EDwDH?)?uhpb6 z))BEWvr%fcBmsA8g6sZr+GMt>A`=3qA;g2sDv>rcFd+XNEZSc9l$Ms}Ju~v{ zy^g{B&Z~@4m#v))q1MPPX9sDR#&f2k^q5?)E)?gx$Jfu9WJx6#-uyP4qyY4elZrQL z%;Jb)8j*y#nVI#erFhG6E(JOm?d6upn*^E~nfJ4ICP*p2=K)j<9o_QWt(5tqx~_WF zu4oYyw^y$^^oQ$zEH2*IjLxN34mVx9sSL3}^QQLp^f9zEx^lRoM2b2j+4he4uzXBn zqDXKxYOxfUBv)|0qX*DnxEjLNL@%jf$N7^M%_Sklf$#Rs-?RturAtIMkEyVHWg3KI z&msnZ4x1bibpk}?QU<%%_ZKaRtZv}%PBa+Z4^h90(%<#C&q6Q!LE0VWDx`7gJ1GMc zP-GCup}4TLRA5}8vwPDQyl=GC3pfUpf=Rbg3ib9bHBxDF~X}kv8$Hn4;!!V9W}tv$|RP*JFvE z9$UEWz4${5VW%HPch5nA_Ty*kq0n;(PVTL>Y`lqKS)t5EB!A|`!+ahdwPSQ7>#Z6Z zeOt1lcI2yY4F9n+%cD5Yn}+@mseD_|NnTJ7f%d4|AieiO(@N^s23D!P*?@pEiMBi| zN=sGJ)<24&C*!RrF9MH>`4}^7F!XhNRLA0y)3w!3%?J*8#e z;rogbpPh9-{p&IZE(YW08sXtS)U$AXv4zv8-$ph5?>6igNhWtD4TR%F1}45}+i0X7V*lbDhh0)Dzw1J+YM^EQA$xx1%g3_5zCJzDucT7- zNvO(3w@BM_^-EJfAMyp))ZCFk)|_6zovV4GHSxjtJWLZKI43TgJ^R>XxYZU4lOsif zj@r_%T8u#~oR2_pan*?`P@S4XO?Gy%=PtfUOl({v7pB^jEWeK{In{UnD1mLM{>#A8LD;90*mQ|lKQ!0vWDPv3d-(f=AqtGA3lHaLg~+^{zns((*Q65Q(&jqK+3v}`GOM@U=qqBtg}fB|uL@rG4QwnWTXj86 z$Jp45GE)MqW#E8b`j<-+Xjzu5P3*dl?@`FE2>$JfiBVPWr*(c6n}(Zue78}9_aS zi!XSm_%|MnGAAS24-GQ$eHcZabWG2Snvy;RC4_U}qeZX|(Jv&ZniRlQI1+n1;-$#3 z-s7IB1t30RTfg`ooS)96nH zg)U<=Ne4*ymjgr!vJT2CYzgg8(4O>sk`6Tsm2P|zYzKSMu6jc0B04Rt}tsX0aM!z^{QvH8eES>LQ>wVyE=p@CRRfVp>Vctm0S z7FKpNx|lM_uF7)UmK9Uy-9*QRT8#4s)Haro_U&`0BZ)#XQO}=G0u%R?B5?g3c9suZ zN+a9bIsL_r$hTlrI-t}y(0d#ZzW%K4Q;H7bYppmW{c-91U|#0&Gl++bB|R+FkUfOI$ry|^-N41iV;A1^`KRCN;! zTsayhI#iCK#uS<4<>gPtZWBUtRQ7q_zz!9G(p-i!o@PH>FE|d!vqtGWh|hQf7sU8( z!_i>TCoN<2fI83wp4Dq|coXDGNOmxrtgI2j$GVviEq!`!QP|+iOb?;SnT%KG`;n}- zfuzd4uKvb5A6Mbb#5Xl%zG6_hW8w0MTGR>S7X`qXVI9|P+Sw#n#8K)e=nb0_4Xh&j z)0nAg^HZq>|1_9Rqi_BDv%7x{4%*Lw@tFrUkQy+W5)QEF>hcGHC2x@<$K-rT2be8L z@c_9uBG(9qzUw5(y93Dws~FaAeV%AiSxpOwTUhu)ju%!4;9p<)NxCA_4QWx95%Uh1 z#@ScdysGy#>iKjG47dQUEVEBFtXV2K#>I6^f@)|O!UpwIR;JOLiZ=cWI;)g^dTb=# zXSRY~Kwm9L7YdI+>FO9GJg)!#q)hbPStFl?_!gP?E9cK|Vi`FUb~`hUVb{KJS)8~S zZ*exiQVjUt#QL@8`<<-c?nzcB3PmY|UCn8tdTqYaBz{6#eW;yKV{N>8ZfTG*ouPUf zGxj_;6WuUAI$C8b(>43FC>1b9U|@eaxnC0qHH%q6iab z9me_XKIt{pL%+^ZJ^CyaFugl>egbP?$`as3$R9sE7v!_GznS(#`#nsP!iUToJ1yD? zJAMHK+PQvjMWP3BoRim`PjWVuk>fS*JOYTQ&l^o$@AoZ!X=_$y0gF}DL|=LXDk>_dJT zoJw&YcLuuF0mkYy^{^(ND;xdMjYGfeR{U>YpswugPvzGGFF2m6*YC;l;w%)G_4e%qWBeQ^y28I4P z;|&o0U;s%($jRmv?uUU5P?uA+A!Bjdja7K&=Bo`kSDIXMZk z2)+;4gSf5D@G9;*zyyvwrmA(Q4(jDfNLZw{yE-L0nk=uTjge2xUFeI9~ciZC0U8~wCHC;wzD|FjbfrqxV9f)Y{0t7jd7mxbi zW6X_LU{2C`O-!n!wDioBm`8DI@ACr_Nk^@E@(rga6|TV~Y}8$YV~!)}P;F0I**y?6 z!{EVZs>FJ(%h>1q^~)DGZ`+N9!0Esu0p{waN)3mQM?H&)0a-_SG5%Tx0b9pmUK zr_7&w=a$Jd+D0YZz5aU-EubJUp#K5BM-XGE5-U)EN@g8Kad2^RpYS^mS`I6#mWuEr zat7niomN1J0uXl+D&ml1p*pX9$ou>VJ&|saF2sv}Yc_I|OuCyhG`p(b{2v7y46<=) zQqCP{auGfzA_Dzm?WDd(FdPgl92Xfx-`R)ZFxm*Uzsu4G>(B0HVISqFmkKB zs)4>77NsqPW|lqq4^w2QtgIv!1;o;^Ul(9D>su{dl4X|!sg(ek1q=`Ca)WZgJ7H&$dq<~9*Ng|$0y;DCLeR1*H+Be{LvQnfHO z+4(Sot*!0BgTe-n?l74?eF{SScN|@(hx~)&Z`3!)jt{ti%eQTnT0)i!-@n-_5eD>I zM}+6oGYnkM0fA0W!s;xSbnSv8-sc$a$~=C!vi04IJ!dy6^Z#>dE(V}C1VC%Xz|71% zJp4l{3*3emGIrhPD+XV@1{?3KwCk=r#gmS1*Y5wniy(k!BMG~X;)9tS%>p?sz&)V+ zIEV0>aP&Ih?&_siYEx3CnXMn(s79@-qFrK;mF4jNi-DmEjl}{1QdUB!tnd=e-ygxr z3EpZ$-0)lu{`@(+nb;2>0*p!YpS*4et*eW(6jB!s(9_ccam1`aenCEgkVs@sIrh&N z@_aJYc>UHLrsL<%mOjN&ba+9`)9?Nzd;U=m5aix5Ujfd`5zRHhza_;g%F2KaC@wB; zw{>4G_;)W`$ot9E6vteKoBvS1l0d@hwuHaf6bAm|YEOKshgZkB&rdDS%q-7b3~qxY zZ_&$Om$pwK^7O2DnRQo}JB7zj-fw%!(#j4R1!R)I5*xTL0dIT80HhPHatBjR{Bw@S znvQ3%>j1x+iHI5h-ZGY@8s!YyA3HzgXwIItPB0_Wwb|qn(-;29K!^mn5W`2u(_Be= zdzaPz^51ETdCww#D+q2m2ntH?UBFMbT9_>4|3feA+VP3jI{g!3!q58r{m5v`ga0|> z0ceikDqSt`uUF2^_kOa^p`Z}B$S-*9{{xDL|EL`PqjLC<%HcmM zhyVYI9`-kf|B;#xWdqDXh7*sCjX6&EO*w2PE+mw}fE92}aG_ZyoP*K)X=rEC6m*tE z*ccdotAQvlm<_^s!wbeybf9^KM?}nwgJK#oivYbuQ5MNSk*u}(Cf|TG$j!S4EOR+V zqb7!!wD>y8D@KK#9ixzU=Zm2E&F;dfr%AZ>U{iAQkHL|F|SG@XL(q6aSsiwYxw)JgAN%djZfTkG4 zd2>H2G^x&rdv}UXYqc8PHp*yKpw8IszI&{!q|`i)CJ}~l@$&URNcs8+rKNib-jNde z@rB$NP}SDg#YeX#)C<9@PNTF8=BN>z*bCzd{@02z5pYt~LC3XRl+j)27{@11Ho>#c z-VJ4vrcoOCdFBT&h`jQT?tgj!9hDzzx|>hRmjPqZ=cxPWCN;jxe-KNpvk*NakHs$y zKHkj+QlSNxQ=t=>w5jrReEs?x$0^>(4CM_sSp3D<*x3nxXu4h5Kqx{KnH1S{=Xuc@ zj4Jo72YBQ+XVXe6OJf`@j5-~A?EWzn;25W& z?b~(dY_Ftahd0L}7+DDMj<472(BB%1zLzz;e$DHguU;pNVAu0`63A`xUc5EbX8;=5c(+&=)GrXU=&JUMn?YgXN^m^TcO71Tn z^09CeP$)O}f-QN4c%7RLkpTXugYCpNx7cGQ*S*dh8Ro3UEo^OASTEp*aNOYFYPjjH zRwLhE%>=}yX`_V^+;1GFc@M+sR+-J6_qew)clD^Os}@rUT>AK{wM8JoIkr-X>@g{g z4A~$K^(~H#^g$oGx7rX1+<>vo=Hb!N_(~^o0KO83CrX)8K8LO#KSK;><<9;=KOXhg z>gDrA?&=wgAK?R{4on&)t9vpZ=!Hg27{2d=+2JhXG7KHSYysbrcg>^axO#!l`*$E8 z`FIw1%J)D!;JI;%I9iqWE#Oa9#x^Odt^|80tU-I9oxMFIZAg0eZ2~e^Q`q8mNuMLN`Oc- zAsICoEVCkfy$M2j5)%C(Yyi$VH?7fVn9%4$FDYB|jUSaJoBZjm^)k$sa?Y4W%h74l zB>{m-Y7aab3^H)8TKrj7p6-7Qd#>fW&poubd-ns|_d(BRp=7p8t-kbWZz=kA#y&z$ zj?~3bx3USE{9Ow${?gn}xqtffy35Db2XrKr$o&Vj!oh67No5soA_2vMu%-l(!<#QZ zzF=`^8Az&9frv7<>6T-=+1m#x!sAb_JC|H_yLS27@@I#MdSIv^ol!Re#+F-JW`Xn= zu)30+suar12kV={=uRLAXOk$W;EcaS?;r0g18{0WkMN0n&Psk2o^LM-lU*cHjqi3e z&z?E)!^asW6X(5$m1{7Siw5e|?&8s7$VPHYXldLsa46CgPP!&-!RP-dw$CYthnaZ} zd+u=)F|7$d1{s+^02K~SkVAs*)YM#5RH)96f2rI7h?wu@lKXxPIIMrpDJ8V^PZkJq z!5OIn$$!LdEDL(Qy zBU~2)K6qRI;9zW*rXdhccNT8(-8MAza4;-q``$V}JergCcG%92D(wYsS@$J+d@{eR z&gInMD+;aPXI_I`au(-OIt*X7Qw;3w>}ZE41d!LAw-skauf^6yoZvYAE7@IJ%TUf` zb#DFY`+%zkhC=YZ53pvk^uVI`mafHj+uy&l{rATvF9-@qNYn!YcP1r79(hLfG~#|` z11-Z_!fKGH%cp41RJA^~%9d zWOl{4TB}myNdkS-T?hz~03LVprz#u4moh%Y>^+ zao!Tb`LAUFIe0vu1K!%*bRZ}V&e>N>6PfC71D9Qd-6F`#zpYrk@T_n1-gyn6N&xn2F3_9bL;u1*7LU)B}oc{?7QP_ix$aSHhOwXojb14_&u2-zamoY zovar}1X=#F=qa@p@F2?n!em`={D9;Ara#VabW?p1zxzAd#jSfX_SzL3Ne1^v`@Zb# zzbAKLo1@_QzqtVajfefeJCv_8Cxgcjp2STcoM2#B*zkYhz~g6W;jH_I$7{L&V=)WN z7=`Iix_39dU?db?mR%Bx?m21puueS@Fwt?DzYZQ! zO}#F8*(R(|qJFc(y~bCDnRCKr_$|_dpb7gNwh5=!a}P4OdK7lQCx}hUY8sII%S;K7 z726ugP4A5DF{wdia?wUgwz5qEZAe#Y3_L6K*8>Y~0fGFyJT$te3p}7sdHrp%yd%enlm9xJ z$u$p`bI1Q@>*5(mB4s2ZcfzyYDda-QTm3}CF#o#y%4U=iYQlXu0L*>~g!E@ZQ)bKi z7&+f9lZGfZZd5M80V3i|R^d-}6`0=GW)n)9_HB7{;Wp zF7HZ|ta0K{^GcxF7SYb^vl+@aV0Y)!XL2Q{%UN|L_h&X2$pf&heq(z8CuMsrPCM>S zcshuYAiAqF|22wACV&dgcJoU~gO)jBiYUF1#pSfwaH4+gM~=B-Sg)SDbFHh!JZrs9`|Mpmh4xpk z*6f?~;!NH&xoyQ0o5;K%yU5csKv-B?tN*LM0~jX8)OoJ`yZTD4*Pi?Vo5kfCP54-f zVfZ;=!@r$D4|HC<{$Gfqd26X_*OG78E}1__V^f5rp>s#%dUwse2{iNh6+|!_pLy#( zn_GT4e2Dk2Lo9)liKq`r1_J{_4wSVztOz5+vpnzzFii3yj9v*|-B{Zou_lQ7)|QmK zVw?IpNsY%-rj_{je8^0Epku|fE2*W*RxV}}L)esFyc9uhw%gl2+hL!bT9QIqePKHf zvCd%CQ-%J6;kV!?Jm+4#wegd}N2f5To*;L{dGG3tJUYqDO2=x$gx8nye6H2LQQz6r zv~Qa&E>~f>?bB-5hK#R_q@;?R91_A2PPV9@W502C7!&mVlI^t*P|atwHiJ2Aa`K@Y zq|FE;6a*Z`B%Dr5jN=P_@;BXY-~RV!=VIA@)Ys+Zufo!pA*Wdk+v&fr%U_T$a`(0s zF??-Yu`R?GoE+4ff$9fLo^rEWDnH3FW z`u%4`=2A)Vm$rQeZZwioefXrnL$Pbu94fN!X7~~!2g-NhfQ6Fx$|(rcT&$?V z2}Os!ZEGXzz@<@35Jsm^3MHYi3s(<|43FyUZtoCn1Gewl=IZ9=>d`ZDw}w6by!10X zI~AqKv__MoudT0Z$xNAeN|N$@!2>`{G57grm3kp z|3`O5Q0v2#8(rPlTRry6EhO;Y4!}K^Pt-fJdvKR!I|?WP#yrNF{OV<8WzH4Wd1+7U ztReF1I#6MJe$*@{=ZA+MF_4opamKwVnO0KdU#gw?q$OCK8lNJ{@`|E~5Z3tT0Y<#Fc2WD>&2gp z2%r*4Nmcr>fF4P|X6^x@-a?Uyiz~@V7o5DE2xnR%8?IfK^cb1|asY&tq+R#*SV=yJ zQP{xQTuYe{lb7F$?V)Gu+h+i%lBWTRAcTjjXowWhw7y9GT(eKt|ttYok0m$kKHbCF;y1FyR6 zm1GGdR^A(jlM1r6wD??LTqQ0VrKvNJD-B|x`xPnJgBRqb20lOwJ`wQ;EhAL-z7^Vcu$je z`g@XSBQ*uPMX*=HYyW1oM9+aOBhG(1z0&ngGzfVlO^Q0Y(6-q0N2lNuS$C(fTrZxF z3FX1N6c#s|GD`c?JvYwlpGjPVSLk<^?zFPs-IwTZ(BxlNuiR_`A88N2-H_oy)ukUl zc0_do`Ga>>snMNXq7}v9Xku>IFX{o%Yk?{5drL~)I z_|+P*kv>=FOf}Gz$ouqZvYFnH_91m?Ziz?MJ_=ZONbl^$t0Fqd@+gRi7WKHbf%*y_ zR~JGVl}*CND!i>1mVM(h$FU|jI5 zn8Qqc4Kw(403+^51caPVH%IY=hrg;{+e@m`EWEpcY1snoXXEsO7;?@~R9%#rIRb1R zza+Go3q;M$%{FeW;2o9oqInUn)6qC>p*+?Q?s{@Ja$Me3%i}f#B(VVA1G~>H>@A~fg_K9ggcIyPnrRcF9^+##; zc&fyeE0ZZC+{4eJ3UAck$Ye7cd$$Nq9KSqYLdJIC zldYPXnxDebBI|40o^Bq3mpj!}?vGULBa$UA zc)0Ykaqj=LqW5x_<2pbwFE5JF<&W)3kaE{rJ*~?r4Z9!YxwQ2)yB;pV4;67JO1R&( z$&-K^*k^OZ)KMi7p3BdNW5EwgP_Tpf2y?e`vOI6#3e-ha!uk`7RXPqB+BgU%hHS2Z zbIit^$m-UbyPF4OPd-pn#g;jHKX#i!7d7py9*9;;5jPq>qn4`Ry1E*u%Q<{-qmZ<@ z3h-oS7aCJxt!(!Adn&aKwE78y2i{zTN;5ZqIe!7+tgs+%^XR5~`NAQ4E>M8RRa9&j z0rpbsbZ}Ncv@2SvM^KE3YBq#ID3x$fK6% zq>t8B;oYl1q5*XjqkqX6kaQBDtB~{IwrD6Yu#~FPi<8n911I)rjVdULoA7njS zQXAx?sha`l@gUvjK^gswMB4D+V8JZ9yc7(FnZT&pxW?+|b0so_Crr*uf59}vS`-O4 zU_?)2zP02pmbmyhubqgWU0nr)P5TSVQMI#K1}NP2xObA&&fd=M-X1fbmf#@t8itw~ zo2M7{8E|-6Q>7rgt=c%K-xO#I>vJMcL<*h0eKY4*Pu?4i=bfLM&8K@|-t4EJj@R_% z>PQDR1a`q+;}urF6lO*?;>!6%5yLGlbD8tTTiY~zVN^7z6Yp!nS4_oZ9YZ)^Pl-F3 z<>A~gI|@7sZugj6sV}%zDDLgUe;i0=Ja!~m*3!?^G!S?Lad8!eRq1gTlv$|j<5qk> zcHX=q;WnObpuIgkdFA~kppw%qA`9|~1#Z~et`;r71LB68_|l_(A7o$?hWMoG0@(xzjcjE z!QpdR8I%IwQUmJzPH2G`pgUE*Vh^va$i(Z6tBik|G&nRwAx*QE%lkf5Rh1hZy&x~I z$}~xs?UyRnd-CK^^f^pJDJ;Ez9y*96M>CGGaGaI5TQ>5ZpmtT^)6LHJq{?xxlNKcH z?=FDq7R)5oQxrxkogbE@Ul!zl%ye89=|noxFM8>cEqsA0nU6){MQf;q@73c@2{mG> zjhS3~j7X}f*D44l&z}bo8^|1Ryu@uE4kUNhw`F6qIiuC zICEh9kt%lUArWGba}gPwa5l9B;dyYApKRIB!-&t~T3OEfR4){*$g zoAewVFHc?K5`}#O1)Wh}rh2)&VS$dp6Mcn^8Rpu;&%vQ-au5bT8HLXier_}K_vMc^|=r3WD zZI5x2f&+)HH?1xsOaiGtr_6p1;|i%gNZtxL?Y)G)X%1YVZk}i(Tm+0a7P(DH+}qn5 zsgC%I{pN=RPsW9uot=?^O~`Y4JH9e7nAy?XY`>iF1|rZdD6>}81ws2@skgTZepIl4 zD2B-h%cj{t$iUSEWD47q*+fV_N9)71+?E|O*4#ih0tt&QF0 zF~i0xeIH~l3}75TvMI`qeZGW5hJwG+VLoVhFqOEb$}7&+_R?-YzN}~uj*Rp!6-0$c zUH782y)S60r>A*iDP?ut2S^G7OJ=*18KJNhE;|r5U+bhPIA&#rSUz?$Q&D-0CO{er zr{Z7H=OiuK{x)hA(ew8v8TZA3x&0x=W9*7EGgkO90Vr;HvflB47T1RoBS0W>byg;)F zEU9)J;^we|^ws+NOeOB5sJW8M`bJcR4h!-5KSUJ65MEB2mygJ~hlwahhX60CV|Kmu zy}~EFE{IZhFR;o3ynFR(*y|(C-f8zw@>h|6R+W}+Z>(`DmY>Tyc=K^}#*4<>yt2ba z`(Q*c8)#>&=H}ShXKTGSwzlQnx3v__C|k_VcI4&1F@&GpupQNr2&eY%qY9*qd&i6| zm|iGBWkCx<^7{QgE}#7?>giBf^N85=iXnwnIs1=Vuj~FZAN32M5%=HD;S|gh)GaWI z`H;G|wI>-ZUusBSzrs9c?7cp)){)ymLii8&45K0{b?Hckr^*h4JlEx_-pe0d>VC$A! z(%sm0-sm*@jao2^=$U-}$F0ejdCkYMN%PMDT5jt?vnw9`g>hh41ltP;-MkXcp5n_M zAEBa++G+a)cRj@R&a%(4Y{M_$y#?NS9uyh*I+*QX$idpEV@IlwN?ecRlA|RGq!G6# zhoq#`5o^n!CO8woC%C8hj?L^_eFz`lNx2(;KXP6R3VOLBSFBs0V{K_!DVK}Isn170 z&d~zv96R;&c}_4LtOyASd7RVP-u`Rbpns`_wATI88?`wa3Y}d~p+M zkZzGniM}oXpu`sM-#2ka2{5=x+=nhMgKve>82*)A9+KlE7!_3qk4)u}`51eB|6>1` zed^NBe?-EqX}^XyhdYK`K6f@88|ib5hYp*T(_f+37#Dx!>{J@Vl|RZ9ufC zYO3RbF9I&W^Pm@54?pDE7mirjRp|4_%F`BNVQW31Xkn2BV>$dzySZ^HcF+2?r^ne< z2z{bb#?_$?xTgvcm=AV!@<~uT^I80Y&C9`oP^;xGA*$|7{loSn`6l0ONQ8PkTFXj> zo;Oe-FlRA`%u297qh)564ssd`@x;{U_43D0vw2`Bc;%z4PNYihnDj?Xu9ug8e<~jG zem>TL?r{t>G|%8?@*28ZID{CSll&u;9YooU6s=63oWHLGRw-+MYNNyL4Zc%0+E zyTz&U;K7H1C5><99+*6hyt>tId9Zi{I&9A;dkXhIsFR(T6z^!eN1oZB=V%E+1;E9D zJ@uRSsk!~|$jBp@{ump-Pl*j!-ie8D-Sgu$iX!$}e(baPAU6hWCJbt#qSWLS<}(>( z{q&cRvqpOdF9kmmj4P=0m?ob-b!~aFo%o=bs5>~NBAiI6s&JvkXW^@R$ySEmzKA=`LsY9y{MT=S{|1~ zVHImAD%2ARvc7(3*KMe})kTnVbZlT|_2-=k_OwRw5F>Y#G2GaH3wY3ydv{eb#bx>T zrNeNm0{gzqP^9S-UgDIsm8DJg)L=!BSKJ{WS$L86qPgU-AQVeapK2>9PI9i*X3}_^ zAND$&P0=Pkvg!5Jt5qG7Gp1|hVZ+C%<=mciM zeZ#Hd3dU1BE*?FuSN}U8gRn-aznj+pxsfEE%z-#h;%e3J95}sJ}LfJdhXT z7WPOQ{IR}BvLBL+^+Q9h+0Rk;Y;WSYw!Z#)J0~5vl}X2g?OUOU)0Ld|b`-Di;QPB7 z_f_tLf}^#Cq53^!sW0T1?$4Va_iF;123hi&%1H9GrI)Uku75<)v>EJE#Qe}|K9fk5y)|iwpKNsL7QtL-GxerOkS?tDLBd{Wd?yEieV;| z4&Vf46vr&y9@Fv;Z@=XV`@4_;KIHyw=J*E}Sv|_IQqoRqQw&l3g|O1_jj97CI5v zoF0a;otG5O+#%XOt9<*0Et_g7UfWt$c;L<17e^q*=nyM#rr8xK)xPHAdY=kepvN<+ zd+M}MuZpAP(|cNuCBcRq%vMKQuI})J@9xI>DxmBW^%L6mIvzQTwg3cLu3zK3?OKv9 zQ5IT}X@t+hWV3{F4`4MCKOyfoCiYvMIeS(|ODkA88TiMt9y`z2%vO?j0Y@=5@SX^a z2SiZ60J^U`5Q{m^ou!&$YGVU7j4rE>hQ)K)rfPSG?RA$XRx!h`9IaG=zB5*1PhN{{ z^=P;TW$qYb$yy0v#YKVQ5Z}mLifH~+Xy9*GvA5I{H=zxcM_R$o?To(HJd$%SL!|5K zSO?VZRd~}^`ne^$P*f_X(FIIdnM6fA-(2_NT=Fq!UJvs{ojZnZ>rEW2%Y}<-Z=Y0> z(fSHOH1@I?dv^v6Lm#K1IHy)1bFr^Hx+3|=cF4y`php@Hh zwCCis>wdXt#IKrM>+F7a%b>3PWH!@&;TkZh=yBinRm{Y_x>*%) zQqtRQJ1L%cRY=YqzYW$Xzo(}Bpxp~$!#NqEbXp^01_ow$QG1Orn;P^oH;+~3fjzn% zYA&2Fy=x0sc#IXH`z9?uHPvtV$%q`WVXb*C5}>l^GxC*~eu#5oJ$zO$cxN%5cML1@ zDmt2K)m$sm@WkGpi*T(PNg~=NxoG9?IZNdeEbx_8Uj~-|xB{mQcek^vBfkX7&p3m| zXY5Te^n5inviSIR3p>y0cp-#6*=lZnejgsXo8ju=Qg3P+kGx^0`T>T8E-p&u&9DYn zVRG6f&vw0vZ5`vs!k!9wCD;IZ7wFuor~?4}gEadH-=DPPXKDz0t|TO}R-Ng1JX@XH z7N?{AWf2{J%4q13J24Nz8>}&td%NgB@BH6)4=y~5h{*FAf?4N?3-o?@T3~K)c!RD` zFa-Gkyw#*n06aDTkX$z3Z75Cmi+;`n8NT5s?id?8xvBhW?-v-b^SotBLyI;BjtXhz z4MOF6LhSkNJlI-m4x4B2k@-yyxiqrwXBLq2+F#f|;(dQ;7N5#2r zD=R}?Z^%?)-_s2^TtIyQ#t?J0Q~1=SaP!vab21$K!3ol&S|>^dRF-%=p0tePj%SmW z_DIbRjSs20qobzd@z7$VuUU}^45-P(fP3`&Q05~1DEFq)Fi3v&4|cYrv-fr7dT@x} zFt{774M0~Spb2#I7{Bv3?C^Ez)eBIT!DD5y6B7ielZ(5jw1kB4<;zg}zN$GLFlqK0 zPe0yyg|<`TY< zc>|#q5E2qH2EpCWDvV4U>P<|HM&K4vD2pY^7_fH2Zjv4&){KA6P zqlC2Nx8>%;UU4dyV%vGDiKZa_SZTO?;6RXdsz0p()fAf&y9Ld6SLzvAH=p8&2m_e2 z7#pjp8Fw#A2vkVuuzHYeWQvTW8>3On6Im$}{^&}am0HrQSa0*-penybjc*MU%)KHg z8OvYgYB~x5d-?0(>#*4<`0m|?vh0N~GkoQXj80b5sASg0lvkDz?bsC}Qw z*qaS8IxKCocS%_4*A7V&5jSm*W{ai5|>Y2ru;*N(RU#Mb_O7Mz2V5TW#snXV31#uk?nk@bo7o zc7!9koVs9KOwa^u%h-QAEh%s;AwI3noy1$f@~+*YO0+fuqdg)Akz3Sd&FK9xeWH8z zaDhqxlAf+^)qZo1syPJJaW+b8bLgU+&#qEgP-T0~#g^ zOBAg!2tMJblt6tXvKX^+7w{}~QIr#5I1g4dgMiKd~1=R!h6pKzL+$Nua=x56FcwU~_QO^jO%VS~Q1VTU5rg^CQjUKP-)!}lYIB~s?}gL!r5-?9ZW4V9`HKX9rBNdT|$h*gg5@f)bRhtyvFKAx)0j+U?VaFxlYF%OUc2Cgh}f<2KZOf&ne=>eoJQWB@@9e&#~E!`UZbWA*Jhb&4kV91@-#vIW&wY5%l$DdAiR> zf&yG(7A{$e%g8s#zNWmO)Yj_5c$-%=?RayLQcEN(RKqBm%%_dH;BI@;=s@`?zTlLo z3VX23Bd3uNV`bjDcKRxQRv&U+9#mv;U|ziC9= z{`^YwPsW2Ux#iBCVTUBWr%#{$URv5;r(Q3X>0{Fur9cS>HNB^QTX6A(P>~-kmrotx z3l0iWdiwQu%!L=qQKtu;&J&hMeZ9Rd-za#P^}0jl19KX1+Am#y4BF@CP6t9+&PXAL zCcLZ%`+Itvdyz!SzSq_Kg>EZLYi(^E;8O$1;N|P2zZERf3w`Gq3=dd{D$vcGho9wH z?DYN)+2GvrV!w&g(bFhd&dF2^Q|9q^s9lL64L^f|KpN|-%Cy#!=ge3c-`VH>Uq{kQ z$>zsyK9D0h)Ua_4j%)uGoRs~G!Q)%WN#*_VRMvDW{+t(108)Agn5qZE{;J?429Rb6 z+j*avFVCKR%riL4z@XR*Bsp329Icg!jZii-M<>P>CT-{iOU&>k3w7z&r0AL>!y}638@;7jU>f$Gmcd{i9Fx+I_f4@86m8!x+ zHu31$o*P>f$zFfb2G{1dCYtx8*=Ax{wrESsDSAyyJ+L8)`I_fncC#Ki`>T%qPli32 z{kNN&nl3I*YCn1cd0S^rUEhHs)Yr#n%S$6Z^dUc&*bSc_t55f_3Z=->mXROTMc%e} zgO<>T0~NXa4Ew6MJ&@p+VPvd}#N29PDk4>#b^C~?PoFL~9O7o^JyG^QfnWCD#Vq{4 zqX6zJUl|zw^WOh_3k+}0?ejqy7+iMaIESe_mj0H$)bvosV`t}jfeN@F4!4RS^C{ns z&k3aiBc-Kp_rl-$T`)gjz^JLr+5atroAPojQSbDY*Yn5k()22(B7rfOpCoUMnZk_E z8p`MTdHVV5DQfB6`d{t6cTiJX)CY=s6|P88DN4Nv0#cRUqbML`%KjVDogr584DY4GP&XI5;&Aam86XOg9&A-w< zT|v)3M(zKB-wZ85mB;|Rl#dE7AdX@;jCen=NO|6oPGop4TUjFOVJwY6t=;Lsnl z^`2e%Lacvz$;ql|m^!bwq!4c`bE+1Q?;KWS0l5;9->4vy%{}3HjlFp^w60Rj%WuAexVQJ0kWfQJ?)6W$@&FUUgRfV56 z^1V85h&du%_ttv7>AsTUK%WKFwXdh=$@cLpu~dMb;B6*eSZKok?S^Fa%sx6E6YCi$ z_vE)RE19HNZLV~@^7hx&2-{rj3R^Bcl^GZ#R7YQ`cA~=b40*z1!ZagqWhYHBDq8D1 zOJ)93D0C~Q{2xnmt4C&rkA)LEiq>@D)cE(QGlUuE{M82NFkd-G&-h55-dn+U3g*UN zER9TxOG~AR^xv<`_GeFEmDk!I7QBrW)Qc|66U=vY8yHde8gyhycYXE`kwcd(M9ylj23EmhQl(JHSCSNl!{CL`YiL#IQ zG315!-#Hb!oL^!iinCt2o@T5$iu zP1nW}K7Tr>tnP^NPEeC?-+6i-3<27c>BXx~`1KO!t$9V692U%rzlC^Q3fO5&6LR+# z59vzkmS5c?p8LH!9EysPGsq)P2c3VcZ~iCHyvy7=e{5e{y}9IU#-VGL|K#_BUwsph zobK8-pBbxt`i-Ab`AB-t4y9UA?EKH7xpr{vXj}v>`XjyMvTID3)~Jk>V)I&mKKW`& z0=yC_YnpFtVqZWQXb-b2Q+25Bf)e^G3b}f?H>;^%*7J!L*Vb0)(Oj16D_-2cXeV(Q zR{R+M5mSDL$YwWBcsl*ZEvEoLXykoRG5JdlfDl@_ zazndN*!aA8I~ww~dYbEGtIQI*0Kq^47ITcC&OiD4ew$9Ls z5rzUNbm|j%x0l#1%lpIMeImtlFIN81o9ZZ4(DG0RfY{H3wSmV$lFk8r#olJ6gmj|W z=lnRa1m?xTfkCNt${kVZ3Ieh9_3pSuuT%49zjp=#%&IgDp{{27wCvQgnd4u}526Yr zOf>JUjqPW02g2Bg)8BGx50*u*rDXLGK!mpKU*= zt2dWv45v_?goRnkRVN7-veA|y%<~a+d%BJc3#@jxHsBt4`GMT2ujrPzz}~cbvt&`L zoZ+X=hB0?4eP?}(Hh=R-QgPUu(d*@3?manER7K+pK}74*#rXX-Ow(Dxqli%T=( zzjo~x%lJIIL_cPJezE*u8)_YeQ57itd=nY|mIU&F+IXG#CD+5N&bN;23{0xqL-W>Z6@xA4Qwq?o<7C^h!|!J^ zE?W-gDpCBOcSs)4RVQ?V_LkqXAHOu5`a5GhKGvg~yakVv$(F17B3jiiAUIMoUp9y+ zNMSb;OTGmL<2c2-eWvvS^c@@3Ey<-9tW+=UzPT!Dw1rRgbV%+t4tA`pJH9#p!Pf}^ zeD3`9a`u&E2Yxl*r70mrmgn&6!UPyq-+o>BNwT>n6FAvmnqn7BjTZ}?Fxcy2SQ^THg_b^I-|i9dSoBtG5y3HE7H_e}XM z`|Y#)+2~ley{ng1FR{!1$=`3S3bee)1G=7g@-=_e&1AlS$ChIq{`5uR-&{I6^Rf`e zKac@a8iRza_i`2^JMDW*M2*VDXWhbGk<2ta7cP}QCNAWe-U6^N&hEjjK+x{;VO4ET zHvDEKQb&-cx}x#u%uAK~S(lk_`l-?gv)jfO_Bl>8w#(UlMl!0J52mkq4;A-VD*Mq1 zY_i!&`WA(OU%|1(U}9y|8j|DO8mMo%bVuaDqT1@K`k{&sIVc&f$a~pRrdkBM<&M!Fb8~fm&X#2Kn`CN5&1m<+=tp-NJ>F|7(qQaK( zcy2nW1a=x8y|oU}F0%?OvLt_cE%y8}TdTwdJ@;Bz_^-HBvto@(NR9Hqz_-zT?Kg~# zBLkbMj&HtxT|HLluIt42c3RPR1%*z|qt1K;!Mjwu*Y_|nW3M<^l-ci3-Sn_YEdI*M zIkIaq~?Crydud40!ZQYIH7v}0g;O(mnx8D0*oB<#-H$6IbF^Ih~N-+*af7xv0$Kv6xq4#=a#p|uy*2(D?qyw<&IrktG3U3I&amjBo9E7rQpxVrzF!$z5ynexOoEYUXe$msh>Y+( zezki&*ts5C`&;PbX<`N|cMotsqe}1o*cOh;a@M@(ZW2*YU%XYiONo*v;^zBsEfBR6wsn5g_+&Wy)ch7zee}GQt(%Sn0T@4qkQb0CiHmTz9M|- z2y}rD0eX@~n*u2itOQZDA*b0`;qUZ6>Vkghc?;wQ9$ST_?SYJF$LJ7>&^^+NbhOEn z?{#D)r+~*z$ zFr0Mh)fPJb+LmtX>h%Q#>scUfRPqa;N(CgDWO38dDeKWD6C4jp!8$l9pY-|G%9X5+zL^dUwVE(O=6- zv4kkU24^m+k4V$OLFr#>9O9g=U^`)42}u&h0)^H5*Lc&L;Uidi@{hzl)L4F6-A=Zw zl5lmYBxzWPJ<8kl-zC}1*M8q7*Tb!E=d7RK7vJagQV&{3C#<@I1MWhGNt}1jP^CBu z%07O+n608@Ids!x|A{f&Ukkz5`18kz;v?u-uNCDypV;3=K8@LBPtRMY$c;=4YbhEk z@f3W++BzOZ7{sSoD~X0PF8|FeK(q@WDXmWq4H18;zWw$^!djBPlF6&+ks^oz*&1FT zoX-jMe14vNL7^F64*Y0XjvXfr@S@`~O3%;a6YiEn3* zcuq&t9f_o>wcdZ$u0+ZM@2SZT?VA0=JRWJvh2y@hS`^jQ818j^<#R_jYVM44TKyKs3p@X4CKyinnUI;W^SOy9o7(&57|5yF zu6D;6Q~i6*U(N>{0^s9;ubskIcEvx&T{9VPTfN*MeVUUM9{VooxPCFRhV=Mvo^~cb z(CDK;``}ZmSI7ON>Fzj2)d%x>x9;cby6C$5*|xXfj*|Y;uOE=4ko0Gwye$J3z#)cX z?CTae*UN#$?737{JhBB9`xj8}svmC#9uMtlqQ-)Cb-(f|N(>(hyO1MUQ@Z&hkV%iKxW8bd!P*PmvdYAA4S3hfg55ufZ?)eVKM5)O)!^(let zgp68K@&#$OPe2#36FJarL)Wc|x}y3`z*q|HE*^ecLgu)&|9<(^D?nl?Ba*+w$+*7! z86m6^Iv?y|0VYGhciknFjoA{jJQmsx+4|JdxhE^*?aLaEd6)V4=a?&?h6ysqT%3_2d7vZw3Mm2E8byoFgvN?p9b6*3VrdZ z=yk|jfH~G9U_ScwREAxf%6Y&g4v=}1O~LiWvfWxqq=@jIo&76VyaSU4$Gpx0lci6S zCD+Ak3Pkj~#y1g{uK8pr9Xs7i%3R+uYdWVsQcbcjAGawM@P; zh+KYSy1nk>r(-6^-5&6}%1*!;y6(YsrmXzwLTa{}8$xqSq zSfuid#{v?k1#})Jp9?BNk)>oj6RSS0qK1)?4*+1VyMfEeoI_U%Iwg=%+UG2F)d_PB zTMdv%&m)nFQe#Al;o)fEH08cK^^tkf*EZn}leRnd5%P&wJi%^>=cbM8Ko8tLYIp+6 z;-+IW)>Xvmo6HS8#$OkB@Hz0n(mEhfOUEH@A**-BDeP-IJ^r~xWRTMjp4BaVxZ`PI9Cf0RM z)Zas=Q>VaqFh5Hl_zYOe-WCYhi3lJaF}ORPolk$#YVY}V?Lb9Zy4VVw8X3*UT#R4p z@V^#N?5=6)(AzLvBEQoAxK_sfK^Y^yztqJ6lwvdnAG1Y%xxghmTl$|(KHD%&`ksWX z9Gvxxoy5v3Z$Ee%Z_!V*wFUc2VEkfp_4dEq7&=X%$ zEabiWr~)<$2a;tgC4vYj152D95FXKm22dr-B5Pg~VbGtMk!Q;cEke01ll-D9vFO2K z?mn%HE|}2fW!%~m@DizRcc9Qow0~um?m2y*feMZs{s)7zn~oJ#=mF$ERfFZ#=?J&vH^9 zJ&tBsZG{?m*qCZVX}cbZ#L|juMx*ltQAV;Zpg9+gEa*5_8E-dEHav2K+6%}=Q&Z%D zGUz9S8D=9+;_Bcgm z*m5f31nu&y}RC7$|fMM4|@krd{j6MFyAG8DM_2L1PF z`t|-P@MvP+cHDmyC_4SzmHi7r$^Q1B_dg=3JHJrgr1#+jwW9tn4`pV)2KLLz;#1@x zR}hK<;$4HV7p+V{19H=EqyK9F8{2I%$AFTo_rC}JqqoedW>+83 zD=5mF{oe~kzKW5r-phux|Iz^#`{jSxp#YH7n>Z1acjv3vdi zI*m$|#%qOeho>s#?CI~S4<4k5iu_(ZW!l|Pv&Uapw@%h3mVK-i;Q~jCyBDN-M($l1 z&qu@+wUo{`mkPWSNV4X^V`pA^qwTYf0j<5} zfNB&U4I`;9#$(sJ3*O83*Xxmop9tq>c0Lu3pVdpFNSjP3P3^8XoRfx z$B<~>n!l)?;C${ivfYbVRUsYEPQi~uato=bh-mPM;+PgXzAW^R_Fe?Kc6&@4Wm?t` zctiqDp272&L;NpO*XjRC5deQTvP8!+U|?sd6$C{BK!e zH%`toQbUH(cw}i2ckGqbyX4DE)er*UJwhlQ+yONg4K*G;&5DSqP9x7~q<~>RA|67F z<^~M&`>*UOK+0Gj-4}UEPc`o2I0ah`W0+d=W&ZXly>TJrs1NrZS~svPMD>z-^k7gM z0$+xnl6W)kdv@qy8w5CipVs-}_MnR}z~ByD2M;EuH-27NbPPF|4JDk?61E%(p|lf% zhe0a=t6tafk;ofxT)*`9#9*)Kem5DPzg)3`5nx=>EZdFILMBt8gP9&6q)B7=0RQZy!vgE9^ z>skAe)R7t*^!_z0RR5@{$e&C@j(1MVzTX~RRvl^ji@6^7)mpAxD*=3ZzLqXaRLpdZTqkmE6fXwIf^S(N>m#WRhDhK)zVda46ea z!Qpn%ki)d-=$(|}2atBg-? ztm|_cfSk-6A9h1PfR@7Tf;KKHE)E>&fXq$CL+Vd{D8{JQ^)RNhZnObz5o zEEAKVBHZkB*r{U(0TJAu-CcTs8$>XjNvMzFN;|td-NCbmCHFNH0IA=@+FZ>b2b%=y z#jc^w?HP)LXMZ>ear;J zPAk5}E95)*Zk7Q;{51>EArCe;opN2zyo9@Zcr5JDE<(u1$JrfF(7!~*dl5|6xm2F7 zG~XBakfPwfYnMMTyzEW&1S*)Ah<+a$xZK_nohbIZ)A=5cs1Est+QLH4;zG_8SiKk< z|NPmUF5$JMj^((fET!Q69T%G3KX|6$+%soqF9&~@poOuyfx&leg|xIjDaAB0Jb51t z!AEd$!-I>-=!oE_PoBR>5B&}>I|eLQmY3Jo#r&CTb`FEZkRU=Q1;s*Tc=N-oL*b~C zl<6wQ0##FLc+0F^yF)u#n>L!(XKZHl>R-&nH$hn{%F6P}%A?Dw0A-7NJn{k+646`#W0FQlGp^aI@57B%3C(iK z%PtdurC4cDtgMgt5C353qyR zQQ3(^KVObWK4%QIr9{$hMN#gZyk;+s)_2c=Bo<&DXT>0@+2@h}Rx(M7|1;Bh1ZFFq zF_ZDeG$3j{-{0xoEMsdvyRD|$BWH|-SDam@P8{LYD1gu1Y^YYbQ`GC`kSU1l^sh

FuwK@Aq#4KeVb8<%EY(XX*MQhouQ)z085nN19nRV5jG1vLW4=;W zOGWj>)2S8VP&Vk&vcKcE(f?Kp)-uhQDX7&U0ov3chS{fgma*J-7oCMs*fis$kezhw zZ2$!o_9%fbW7KUj67^u+{ghLqZV?~v38eV9!PkO(?HfYcs74))78|8c4cv;U6Ca1W13!UNw&6bFQ%14wk15I)|)X&8um9Gba?dHE&T-eaETs_*9Oq;yh}cHWD&#fl6s)!B>iyFjV+Sv)8yw ziy?UZcm5~|ly_p6W#})P#C_KAa zbtAFrZUT;OJ8reN7@ zdb>Xl7&ukTk&F|A1>iBbSd`@!(cHcxJ&sS4qt$>P#?THPCt?KSV`k<4w$!7-i{}(Zw%b)M7fdPTEoFfDw2pDFS&`M`U0Y{TJ|$L}rNygu zIlX=1Udwa9)aTp}3>?hvWdpsY+$r(mnYxN5GJgwMieCnU{CVZgr;+K;O2h$YRPers z=$L!<(Jep;N41Wa`+N`ayJqU9=}mCsI*zE&vRc-zTf+AtUa(Ic;6;y{88EeMvG596 zu9XAYpK}+*@(qV+#qpJ_osvoaE>owr*qKt89`|J*yxI35lbU9*4;Y!v9)Qlfj%o%8 zLs@3fGk z<;KQFnbu2mbSlIV+kF%t71fJ>Krl2PpFEuq_6|gr)T@ERQ@*@=SIEoD+tk#wpL=@C zT{TUPN=p;pJi-$%=Rny=QSptH+h7j68e9=b;`=LQSFymj9V=gCRXo0`b-GfrsPQA~Es_{68lFR|gu+Kxr`n}{Kg085}|OgG$j6{9UtAQ#yLhq+i{ zyj=b89_Yk#;h8`SNbpZ(QQwTu5DV+l0idpb+U5Kpgeg~AY-IuMc8MnK; zyWm~DhtrLF?(RK9-k*YkV9mY19kEy}45rOadE|;26vrKJ6GqF@g16h2mYhl+*IIf4 zK66QFULiwI7N^umerF$FX$8_}y9HR-)igeE$Oq2MExqa$jQX6|;nUxLNC-L#j{)J;Dk@y6azVRJo}L@lkkG=>s995ByAdbM z=9g|Zd{x;Q>eJwMJ6siP_xD>2BGoX&>~TR1l%6lCe7-;$qi`A=9>mA8$EfGp)b%mK!6`iVoY-@U6qeT)k8R2-b7E4iKmJUzNB8?7!izVB1^RepY7a zeBwIa7l9Cl(&IKKezd05Zk%saxuW(oO^>V);IVpnlC(5l?IT`)@a$B#qe}Di06%r> z1K0SjnO7l3;!geM4_INDktRoX{hoS7A$DW#{(iOUh#7H~jGPe7?svnnn}T0N=F!z}yv6u{$3D z+Og!Tw%ITiaL@jkxA(li|5vD_oZJCHvYVcc0d?}U{^Q2RhGO9M-1zu7X#4CgYLdE)y(BJKI_; zIFT>I!Wv)(U@R~;o^#&S#i|*(m6ZdQWAI=4GcU3&P$q>j>b9UvhP~RV9*Zr^&8;*R zagwu1QcqG~ ztn~}32L@8RzkTMT(;^s6e~NoD8_xt~1s~3|BeeG-s)yROateiq@xwm5k2kjBBVPSL z>D51{WC0e_@NiK2aZB>PRR;MYp&=pm$KJNickqJ<_G>G!rQW`G@do^5l!(t_!8P88 z9Y1GO$K4i4)IqUn950UZb$D>d%Km~uAu}=5duV~UNV%y{()xNZG<56NR^L|qVdt2W z8NUF(&5;*PhMfQIuh65NHT}sVQ*mLR=jP@n_i-ddj^YHg?nh(k9EiyLEadZG+2*UtD_ZAtmFf-HGIHOwV*WdN<-{O^-8AE;jt%g@&*4EaQClr~`>ZH-6 z?Cfl0$cP)5>;UX!eSQ5LH9Zsg{3V!qy=OXHwAX5E?t*<>cy_l+Qs};p>t12Zzzo8{ zC)*I2nhe{}Ihoau3Eqj&35j(5zKziCKcRF~jn;;|QLi(wDgFSpxW*=b90uv!BfeoQ zFd8nd+ukuH7hZQNEb9kXM_LMGlME5!8mXOH2ueY{n4a~aU7U;=7JbcT*50XAtq|x( zAy~p=A=2A~og^fVJv#E|_PP5pEr%;}FW}D3q`~gb;=z;kGb<4C+?#|evPhqe6ziio zt5T2d8uh?@1Dk>m(66w?wTwmRwHE|US$|?RA$p2zlj~ZAj%ryymz6bKZ0(A%zy`Pf zxF1=+ld?g0F)I__#=)hiBnzn|T}FZ^M^dGy<`5Fetniq#XXS^8uMm2I=Ggbil|2r+`=8$4@^a@?@C2ipfxbQn|I&)9vflg= z775-Cz_-BsWr;pK{>lCsW8r?hf*{JEtF0=Gh4%LL61B2bdAQZU*;oeI36MV4*FErp z_kxOa-lMy8A{dXjlv6fFTPB+LM3P~$;U7hP>6Er&kRkn1xs$=})8kmp!t1KP80hyn z(Ge*$yJNBl@xP4oWG_t*V%`CL!cvN65`O!5lQRQQ>C>Tv-MXEAMo3-<3nmXnRCyKK$a9iW9 zSTL#a#G7BoF{%EVqgA%G)cadA&hDslc;?9EZDyD_<*ENfqK%Ke{mgutshBkotTOXR zf2LDy1z`G039B2inQnzOape|+TOBBevc*jUb9)FrfLDkoeEQQT$Wa#eF|pFKdm=b7 z!01qQI>Iv)mS`lMsk7TiD_*>}rP~OY~YsELeE8 z>~Efqrb?5Xi#$>*F@?L9~PE`M5_uR+IM%2>n6W^sS4U|ZmTUi3p26} zEKz>+5o@pX^yoLbgH?r&XO2XzQBQ`|X~d#W+{-Ld;ESm3h;A37tNot1z$H>>)u8ro zTmb)Yzv2;TYC}GF7XUsO7n4cCh5hlJT7g7z*XcT)Mcr? z7|I%Fw}66jAC}>&_VCgkQvA@v!xe%r4UZW?eshMK$RS@tc{vzSoj)83uyNc)#C20L_7KWg^ zJAvn?Mr>@zs$#?|WPOvXPnjex5boz6w4B9IbKwGsd+oTQ(YIY?ZCZ>4i#w^?NK^20 zY2{6mBR8XDbt?@7ne@_B>SmuZDDU>{uikOdem<}^=yO1l+U&-#cRXzEe0`q-00u4R)r}4A z>(}Xcj0=H7`F8QtxVq+*VqI%jRwWt#7j|}YL%3QP3>M3&oZ4YOE0^>&wSIQ^tb(9s z<8k%=SS;+rcse&87?xSWG#}hEPPpHmh_g~TF#vN<%A3%A5_DhdZ=SiRmitpDS+4}r z=y(#ugKH$@OXfQs^o}r4eBr0XFjy<)Ppo9M70uJ-cm~(uVtVEM#vUVmja7cQo%d+( zM(qgviAeY(WNML~n*=X>p%Ukun=mt-)q1k+Df2CXQFZvwX79U)nQo|2KE(q$P%tP#*s)47`v6d@u@#DbkmXDP>Uu5_F`@+ zjch;s>jz^aAqiUPf(Oek5)exO|TS1{_P(uXS!38q8kY9Ls_}^cAjH(z*?L>4hs=tY>WCKz9 z%wu?*>68|cL+M%(O0DzRUQ7pdUCr=4Q9ii$O)gu9{$K+ zY+NB2AI>bUhT=~~_F$#ji;&6P<*gN$`58x^@Z*L@TRmp0AEZ7fCPEHxhxbT(JMAip zd+bec*-KL6_9G4WugbD@$l|0(?IAc*6(Bdf>J>$Mt7~X@y2@pv9*wNGFE=c`x++b=pR=i%&v5lIMU@p z?ux%3czBfF)6mdB)BxCQ4rQZ^s`Ee9hwmQU^s>5+Q=;^Troi?q*V5ioCijPAn}-*2 z@RBK749YbjIsGV!YPTug*hog9MBKQGz~^;QV#*~RrZ?z-3;vwfT+u~UZT*pN@C;-9 zO+%KomqpdU~4>srcAZoSv)jVH2o%?)?AegQw`ZPqk*pKA;idzhN}kI(Xb+3Q+lAth3Z z*u&H~Y2Ggc_6h7`e8EURfRl=3G&OTw6}Vq4s?|GD*L0~(@aof?D~5fiDoB4_siaoU|KO->VKK-< z$wnNzH@A5l6CLkvI^OQyW2R2d{$`h? zX_T#oS+P|?clXa2^#!6Q#|{;vaRoLqsI}4=i>(NLMs^)9jlgdFj48%jmMDf3p(CTB z9t)T?hr8ZuUxs3C%Hi2!g0MBg9*glz7x5^OaTm%EncP5jc|>%>@|>5StxPhkexrk_L!$${-zXLC!?wg zbj0OZQ;tBj$rWIWy}Bli^{yt|J-J)|=-0gW799Z88FbnE03pam#RjM>4LP=GUJ<|s zhTUb`g;0#AvSK~`S~z6a=hW?jLp`CzbyohvX1uN%9$&Iq>@z6>^>;{kS-j|8_El&M zuPEHBE+*tpNlXVVX5HzJ0woCAOR#>eCCGwJOq5NsxvrX*AZz~4Nmd9UI!r(2#YH>r z7@?YBYH4kaTBBrEk2+PD(M^U_WsSP9lqz1*En62=&38d2NJ}dA z>)pb8iphKJxxm(kQradT-%hUtKq3AWS!WFAf2Ez6Y<*t%=!(XTt*6G8R=cmSqC2m% z2d(2R{qm*?T=9d08#Ox9M`{lX>+ucWE0A+2&w`T-jfL)d&dRS~F|(l+@~Sg9oatv& z^&&h3hRr4;@0LmRz+09}Y_;|kBQpM&YC48YGM90&RkegcsJ>+Qostw;Jy95m=9bd9*}S7%B;uy;DBF-0@`g$GJd`P5<#9C ztUc~7rRKN9Lv};DKV>OL%1+JPt{hU3xLpUm7HGdzW$j}XmU z)ZD?(7k($nO?r2!$MJ!tRZmDl>uV>BX5>_S7JdWs_RXyny~s$ci>TZ0t}Z_8Qr}z4 ztuc$sE$;YvSF97uRDpAdsKiOLr$pI@Ynl2YikB8xau^}Q?ISAPuZ=;CA^hLn!L&o$v6{K7rfl~ zp>^27ag0vLnwNTblSO8*Gq(=S#Rl z+69CKinxKsZMCpM2`}ba(}GKp?hC^Mt9$w?qrtjcd-Vs$JHt~iY@33LdM>v-(^vEa z#I>}vaK@&krMZR*9+8ebCfdB}st>EzU=Xm1R$I~YFhx%s9_u#oE6ZLua&&Z@F?B`8 zi-?JO>vqKfoWH_mFfh8btY{tPAND5=I)TtwOFZjYA0rcDtoPYC(gdPF) zJ4);~CQSF_>ePsDRgUkm9gJLjxZky+^i+d%C+~M>XWe#tA-48Q9=f=Gr%MrA-N~W) zaAxjzQh@(;HwQ;Y8~ENJXTZQ4m}pevSQiA0VZ7%$aPE*&lx0=@WtTafGW0|iwhM;G(%>qWs;U2TlF$2Zb(@$cnH7g?`tNp ziwfc|g|kGr5Wk@#03TaA@sndSrnNF3{vt5n*M|&G3fFlrH;yg+xX?63sbf^V(rSb| znm1+tR&MfBJiw)CZ~aqmy@p;Sqs87}zHBJQB*m*x+Gjx)=wiSb?^gy8&SaIr(tFY@ z+ZbcLlBjYb63%EZ0cTLISpG4(zW&1zz#KazB<6(d9LYcnG?PW3$Bn!3a52(M0B(4h zZM_fxe+=8e)+$)!K&B2L1x3MpA;fg?5-SN)#S#KZ*Hx;X@ZWNrf$^=Fk$0Pym@e$SLX#AjsuAPN)r z_tBnCZ4N$zD_UivMT0Kj-Gzm&O+8wu3I%!j>QckDMISE?M~Ng|VPGU%`;-RcG0eSh ze3~-JsK+A3MMdQnD6MRcR@8d&IwstQe9OyF%&gcNnVgm;4mQMCjWhe5?ac=(zl~`! zHhTLl_uMs-@<=_?+l!0wa>cqI67`gl>*jfrH zt1rqVe09L2MN+aLCj?P_h%J#(G~&c@s4l_gN{(5O)fiK=#I6&u@JC9%RaJX^Kcl%* zqLDFH`kp7E+Mdj)N8es0~G3f`8LSp zkR41*tcp`{(JqH_JvmQ~;X8a-2P&2rAg@$9Io|7es;{dEqGOFRIfJc4myVG&$GK~X?sII5GwTv;$UW`Tale-(_33M2;g zCNgq0Cg@cAw%k!~2n{It(q;z~V*u!Jj8VhWv-`(6Y8iNtN*Xu2qQsp$lP)du-qjY? z%d4xxOf|rG=OQhP@P<_mfwWNzJBNpd5tiMIYEKD0BiS8^pqhb!fyPEvC=?JMo7v+g zBZNQ@KS$fz+5&L%-VtvEF7=r{){HWSag9+|Ms}JAA)b}Mn!XsyAeDpWel^cMz*r#D zppPvq)|Z!;SA^`!4&^)sR|^3Rbru#tJ9O>|!>!%@*x*H2zb8e=Lk3;9RhSh@WHoS@ z{hg4Jo2qBg3Dy-Up#2Qliw>T;JG}I&@y{a~1E7jax#lS{aZn0WKE1#EXY}m((-e=n zPkgsA(4k^$_hREywIz_EQh7BbttY&)Y>@S);E{m!dD4ZSA)C2K|J_VHbu(Hm$gAzQM~>9U5=+HX2YAW8h<^k_xz{)>t1&D%3ud-Y){_V zt1PJ*C0MpmZ03v)IGJXMjbV;%Q5<0m3JF;sG=pAeR}7x}^$E-;Fb5b_-7zu{Na)_m zU>m#Zv+?58)YK;1$aO;X^8lc_@b~iriAXAjcdX6xC&#``nhDXxz9)DK{u7ni6v@!t z+11t6DJm*1F6yasw&{KoFf~B_Xt&z<%RTuO5C@}KzH2m~uqB&jZYnmv0TbBz-A;1nR3AZ@yau>KLZWc1gBqeLIgE9&{s)>WP2}14<@s0_+u)S@FF?B`rCU>(2 zfpYC^&S6e^9$!B{PUWCr`|Q$E!+g`zv7Xq$dNE>ha?;S#xe#t3Q=32A8Vlw%0Hj8P zq(ehHhgKOqU^aj{D&A?X0*&MR4%mt!i0&VNwwXeC)#wl!3f9k0y}bb8-aFgSI=^UW z6=f=!*3G&dvHlEbGreRt*dFEzUZf7$Xc=5?bMUjLkOQJ3W8H!bCVl2cws1$t_JetZ zaH6ZE5vtugq0=6w4bCM&^xVtx!R29>?R676FTrO=DH>ejP>Q$xv7znL40Dtnw#Ele zR@MM(Y;yZXkXfEvK)~`Rpp_0`QoRN=;xoE7%297pkAF7s#sUcvNU>Jn5MnAks%lm- z09BGQGoSOz5V|l{M6M!+%xr{qZi{|O`=YIzB={ML&n@tS(AHX$S2BQyt zpWa;-kSR(Gg3Rw6_UFoqvC@F#oNH6*0QqunE?(bbt8k_*ULauf85W_#@3TGEhGHQG zZnp_Y51gfHFeOeDKv$K0R|X%498|D0;Co=_; zRp2$J{^AWGPgelI(MN?-Yx@8G|9^`E)q1Q{-z_6lDTkiQp~nYX>+8k9$r+}Dst7vV zo-f--Mh&y46rX=$_80RL&lgJ>MxlGdq2?>Xel?6EgQ@vnR5N6zUSy~h5czBmH>X`e6%iYF>spH-3z zPJgKkGT9Sf0&nA@{+kV9P5*Pp!5$J zwqWLiuk9W4p&-ofYZ`RPmxoF*nzD`~!*gA!Mwk`*n>foPmA``s5#X<}^5xVe;@gLG i;K}j-q5oYc3~+6Cl2yW!({#dAnreCvidCPy{yzX?|HN7V literal 0 HcmV?d00001 diff --git a/assets/screenshots/6.apk_install.png b/assets/screenshots/6.apk_install.png deleted file mode 100644 index 756c6676c74df84c5cb9f895f8f7a94dd5f3d1cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 196128 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 z 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 diff --git a/assets/screenshots/6.app_webview.png b/assets/screenshots/6.app_webview.png new file mode 100644 index 0000000000000000000000000000000000000000..636eaf289ca1858b2bbcf48c050babfdd2a6ab72 GIT binary patch literal 267760 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%0D~9d!riN=Fy_eH1|6;q?R}kEwb1HwbMWgM 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%0Djof^l9fWD=LidMjT`jsJ&H8H{S)I1qU8eYJyPh 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 Date: Sat, 28 Jan 2023 20:59:17 -0500 Subject: [PATCH 007/600] Added delay after Obtainium install prompt --- lib/providers/apps_provider.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index a8380c6..5036ff2 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -247,7 +247,11 @@ class AppsProvider with ChangeNotifier { !(await canDowngradeApps())) { throw DowngradeError(); } - await InstallPlugin.installApk(file.file.path, 'dev.imranr.obtainium'); + await InstallPlugin.installApk(file.file.path, obtainiumId); + if (file.appId == obtainiumId) { + // Obtainium prompt should be lowest + await Future.delayed(const Duration(milliseconds: 500)); + } apps[file.appId]!.app.installedVersion = apps[file.appId]!.app.latestVersion; // Don't correct install status as installation may not be done yet From 0ecfbef0a05c686644e875aa1060c206bd0ea941 Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Sun, 29 Jan 2023 17:28:54 +0900 Subject: [PATCH 008/600] Update Japanese translation --- assets/translations/ja.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index ba1e5c1..eb078b8 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -7,7 +7,7 @@ "appIdMismatch": "ダウンロードしたパッケージのIDが既存のApp IDと一致しません", "functionNotImplemented": "このクラスはこの機能を実装していません", "placeholder": "プレースホルダー", - "someErrors": "いくつかのエラーが発生しました", + "someErrors": "何らかのエラーが発生しました", "unexpectedError": "予期せぬエラーが発生しました", "ok": "OK", "and": "と", @@ -82,7 +82,7 @@ "pinToTop": "トップに固定", "unpinFromTop": "トップから固定解除", "resetInstallStatusForSelectedAppsQuestion": "選択したアプリのインストール状態をリセットしますか?", - "installStatusOfXWillBeResetExplanation": "選択したアプリのインストール状態がリセットされます。\n\nアップデートに失敗するなどして、Obtainiumに表示されるアプリのバージョンが正しくない場合に役立ちます。", + "installStatusOfXWillBeResetExplanation": "選択したアプリのインストール状態がリセットされます。\n\nアップデートに失敗した場合など、Obtainiumに表示されるアプリのバージョンが正しくない場合に有効です。", "shareSelectedAppURLs": "選択したアプリのURLを共有する", "resetInstallStatus": "インストール状態をリセットする", "more": "もっと見る", @@ -109,7 +109,7 @@ "searchX": "{}で検索", "noResults": "結果は見つかりませんでした", "importX": "{}をインポートする", - "importedAppsIdDisclaimer": "インポートしたアプリが「未インストール」と表示されることがあります。\nこれを解決するには、Obtainiumから再インストールしてください。\nアプリのデータには影響しません。\n\nURLとサードパーティーのインポートメソッドにのみ影響します。", + "importedAppsIdDisclaimer": "インポートしたアプリが「未インストール」と表示されることがあります。\nこれを解決するには、Obtainiumから再インストールしてください。\nアプリのデータには影響しません。\n\nURLとサードパーティのインポートメソッドにのみ影響します。", "importErrors": "インポートエラー", "importedXOfYApps": "{} / {} アプリをインポートしました", "followingURLsHadErrors": "以下のURLでエラーが発生しました:", @@ -133,7 +133,7 @@ "bgUpdateCheckInterval": "バックグラウンドでのアップデート確認の間隔", "neverManualOnly": "手動", "appearance": "外観", - "showWebInAppView": "アプリビューにソースウェブページを表示する", + "showWebInAppView": "アプリページにソースのWebページを表示する", "pinUpdates": "アップデートがあるアプリをトップに固定する", "updates": "アップデート", "sourceSpecific": "Github アクセストークン", @@ -184,7 +184,7 @@ "appIdOrName": "アプリのIDまたは名前", "appWithIdOrNameNotFound": "そのIDや名前を持つアプリは見つかりませんでした", "reposHaveMultipleApps": "リポジトリには複数のアプリが含まれることがあります", - "fdroidThirdPartyRepo": "F-Droid Third-Party Repo", + "fdroidThirdPartyRepo": "F-Droid サードパーティリポジトリ", "steam": "Steam", "steamMobile": "Steam Mobile", "steamChat": "Steam Chat", @@ -211,7 +211,7 @@ "language": "言語", "storagePermissionDenied": "ストレージ権限が拒否されました", "selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。", - "filterAPKsByRegEx": "Filter APKs by Regular Expression", + "filterAPKsByRegEx": "正規表現でAPKを絞り込む", "tooManyRequestsTryAgainInMinutes": { "one": "リクエストが多すぎます(レート制限)- {}分後に再試行してください", "other": "リクエストが多すぎます(レート制限)- {}分後に再試行してください" From ee4d0f259f75ae6664c33d76ce562723b3859af0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 29 Jan 2023 17:07:11 -0500 Subject: [PATCH 009/600] Generated form bugfix (initState not running) - #245 --- lib/components/generated_form.dart | 17 ++++++++++++----- lib/pages/add_app.dart | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/components/generated_form.dart b/lib/components/generated_form.dart index 1a7e45e..c84b630 100644 --- a/lib/components/generated_form.dart +++ b/lib/components/generated_form.dart @@ -150,6 +150,7 @@ class _GeneratedFormState extends State { Map values = {}; late List> formInputs; List> rows = []; + String? initKey; // If any value changes, call this to update the parent with value and validity void someValueChanged({bool isBuilding = false}) { @@ -169,13 +170,10 @@ class _GeneratedFormState extends State { widget.onValueChanges(returnValues, valid, isBuilding); } - @override - void initState() { - super.initState(); - + initForm() { + initKey = widget.key.toString(); // Initialize form values as all empty values.clear(); - int j = 0; for (var row in widget.items) { for (var e in row) { values[e.key] = e.defaultValue; @@ -245,8 +243,17 @@ class _GeneratedFormState extends State { someValueChanged(isBuilding: true); } + @override + void initState() { + super.initState(); + initForm(); + } + @override Widget build(BuildContext context) { + if (widget.key.toString() != initKey) { + initForm(); + } for (var r = 0; r < formInputs.length; r++) { for (var e = 0; e < formInputs[r].length; e++) { if (widget.items[r][e] is GeneratedFormSwitch) { diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index a216a7e..4386d22 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -327,6 +327,7 @@ class _AddAppPageState extends State { height: 16, ), GeneratedForm( + key: Key(pickedSource.runtimeType.toString()), items: pickedSource! .combinedAppSpecificSettingFormItems, onValueChanges: (values, valid, isBuilding) { From 60e3b68ebd4772c7f20a26528e8c2bdfe30b3efb Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 29 Jan 2023 17:23:35 -0500 Subject: [PATCH 010/600] Search allows option changes (no direct add) --- lib/pages/add_app.dart | 59 +++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 4386d22..80720a1 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -32,6 +32,7 @@ class _AddAppPageState extends State { Map additionalSettings = {}; bool additionalSettingsValid = true; List pickedCategories = []; + int searchnum = 0; @override Widget build(BuildContext context) { @@ -40,10 +41,14 @@ class _AddAppPageState extends State { bool doingSomething = gettingAppInfo || searching; - changeUserInput(String input, bool valid, bool isBuilding) { + changeUserInput(String input, bool valid, bool isBuilding, + {bool isSearch = false}) { userInput = input; if (!isBuilding) { setState(() { + if (isSearch) { + searchnum++; + } var source = valid ? sourceProvider.getSource(userInput) : null; if (pickedSource.runtimeType != source.runtimeType) { pickedSource = source; @@ -169,30 +174,32 @@ class _AddAppPageState extends State { children: [ Expanded( child: GeneratedForm( + key: Key(searchnum.toString()), items: [ - [ - GeneratedFormTextField('appSourceURL', - label: tr('appSourceURL'), - additionalValidators: [ - (value) { - try { - sourceProvider - .getSource(value ?? '') - .standardizeURL( - preStandardizeUrl( - value ?? '')); - } catch (e) { - return e is String - ? e - : e is ObtainiumError - ? e.toString() - : tr('error'); - } - return null; - } - ]) - ] - ], + [ + GeneratedFormTextField('appSourceURL', + label: tr('appSourceURL'), + defaultValue: userInput, + additionalValidators: [ + (value) { + try { + sourceProvider + .getSource(value ?? '') + .standardizeURL( + preStandardizeUrl( + value ?? '')); + } catch (e) { + return e is String + ? e + : e is ObtainiumError + ? e.toString() + : tr('error'); + } + return null; + } + ]) + ] + ], onValueChanges: (values, valid, isBuilding) { changeUserInput(values['appSourceURL']!, valid, isBuilding); @@ -296,8 +303,8 @@ class _AddAppPageState extends State { if (selectedUrls != null && selectedUrls.isNotEmpty) { changeUserInput( - selectedUrls[0], true, false); - addApp(resetUserInputAfter: true); + selectedUrls[0], true, false, + isSearch: true); } }).catchError((e) { showError(e, context); From ffe29009ed28624706187c68967aaa70bfd76da5 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 29 Jan 2023 17:29:41 -0500 Subject: [PATCH 011/600] URL select modal now works when tapping text --- lib/pages/import_export.dart | 37 ++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index f6d1dcf..df29739 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -564,18 +564,22 @@ class _UrlSelectionModalState extends State { widget.onlyOneSelectionAllowed ? tr('selectURL') : tr('selectURLs')), content: Column(children: [ ...urlWithDescriptionSelections.keys.map((urlWithD) { + select(bool? value) { + setState(() { + value ??= false; + if (value! && widget.onlyOneSelectionAllowed) { + selectOnlyOne(urlWithD.key); + } else { + urlWithDescriptionSelections[urlWithD] = value!; + } + }); + } + return Row(children: [ Checkbox( value: urlWithDescriptionSelections[urlWithD], onChanged: (value) { - setState(() { - value ??= false; - if (value! && widget.onlyOneSelectionAllowed) { - selectOnlyOne(urlWithD.key); - } else { - urlWithDescriptionSelections[urlWithD] = value!; - } - }); + select(value); }), const SizedBox( width: 8, @@ -599,12 +603,17 @@ class _UrlSelectionModalState extends State { const TextStyle(decoration: TextDecoration.underline), textAlign: TextAlign.start, )), - Text( - urlWithD.value.length > 128 - ? '${urlWithD.value.substring(0, 128)}...' - : urlWithD.value, - style: const TextStyle( - fontStyle: FontStyle.italic, fontSize: 12), + GestureDetector( + onTap: () { + select(!(urlWithDescriptionSelections[urlWithD] ?? false)); + }, + child: Text( + urlWithD.value.length > 128 + ? '${urlWithD.value.substring(0, 128)}...' + : urlWithD.value, + style: const TextStyle( + fontStyle: FontStyle.italic, fontSize: 12), + ), ), const SizedBox( height: 8, From c72c0fdb5730584cc8494c5532a4551ec93959df Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 29 Jan 2023 17:31:19 -0500 Subject: [PATCH 012/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index fdef815..d098cbe 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.10.5'; +const String currentVersion = '0.10.6'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 6b4cccb..105ad20 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.10.5+111 # When changing this, update the tag in main() accordingly +version: 0.10.6+112 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 71c80f11f54f43bddc4781ea26bc0123c0196fb6 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 4 Feb 2023 12:30:34 -0500 Subject: [PATCH 013/600] 'Fix' for GlobalKey error #254 --- lib/pages/home.dart | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/pages/home.dart b/lib/pages/home.dart index d0a7061..8700889 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -63,21 +63,29 @@ class _HomePageState extends State { .map((e) => NavigationDestination(icon: Icon(e.icon), label: e.title)) .toList(), - onDestinationSelected: (int index) { + onDestinationSelected: (int index) async { HapticFeedback.selectionClick(); - setState(() { - if (index == 0) { + if (index == 0) { + while ((pages[0].widget.key as GlobalKey) + .currentState != + null) { + // Avoid duplicate GlobalKey error + await Future.delayed(const Duration(milliseconds: 200)); + } + setState(() { selectedIndexHistory.clear(); - } else if (selectedIndexHistory.isEmpty || - (selectedIndexHistory.isNotEmpty && - selectedIndexHistory.last != index)) { + }); + } else if (selectedIndexHistory.isEmpty || + (selectedIndexHistory.isNotEmpty && + selectedIndexHistory.last != index)) { + setState(() { int existingInd = selectedIndexHistory.indexOf(index); if (existingInd >= 0) { selectedIndexHistory.removeAt(existingInd); } selectedIndexHistory.add(index); - } - }); + }); + } }, selectedIndex: selectedIndexHistory.isEmpty ? 0 : selectedIndexHistory.last, From 31c491d7c5b672cfdfb5df73582ac10383b1d6d5 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 4 Feb 2023 16:50:33 -0500 Subject: [PATCH 014/600] Fix prev. commit. --- lib/pages/home.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 8700889..d233297 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -70,7 +70,7 @@ class _HomePageState extends State { .currentState != null) { // Avoid duplicate GlobalKey error - await Future.delayed(const Duration(milliseconds: 200)); + await Future.delayed(const Duration(microseconds: 1)); } setState(() { selectedIndexHistory.clear(); From b03d7fba1a50f8eae467de9c768f848aa919f4d9 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 4 Feb 2023 17:07:59 -0500 Subject: [PATCH 015/600] Fix permission error on Android 10 #252 --- android/app/src/main/AndroidManifest.xml | 5 +++-- lib/providers/apps_provider.dart | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 1e2f4d3..2bc8000 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -3,7 +3,8 @@ + android:icon="@mipmap/ic_launcher" + android:requestLegacyExternalStorage="true"> + android:maxSdkVersion="29"/> \ No newline at end of file diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 5036ff2..c9e51b0 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -710,7 +710,7 @@ class AppsProvider with ChangeNotifier { exportDir = await getExternalStorageDirectory(); path = exportDir!.path; } - if ((await DeviceInfoPlugin().androidInfo).version.sdkInt <= 28) { + if ((await DeviceInfoPlugin().androidInfo).version.sdkInt <= 29) { if (await Permission.storage.isDenied) { await Permission.storage.request(); } From 15ad3bb4397fbe25949e35ef2183ad2f7a2026de Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 4 Feb 2023 17:21:39 -0500 Subject: [PATCH 016/600] Removed unnecessary repetitive log --- lib/providers/apps_provider.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index c9e51b0..18e5124 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -444,9 +444,6 @@ class AppsProvider with ChangeNotifier { } catch (e) { // } - if (!res) { - logs.add(tr('versionCorrectionDisabled')); - } return res; } From a2c227931ed8dee2cae056669db6204dbc1d9cd8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 4 Feb 2023 18:58:14 -0500 Subject: [PATCH 017/600] Added uninstall option --- android/app/src/main/AndroidManifest.xml | 1 + assets/translations/de.json | 7 ++- assets/translations/en.json | 7 ++- assets/translations/hu.json | 7 ++- assets/translations/it.json | 7 ++- assets/translations/ja.json | 7 ++- assets/translations/zh.json | 7 ++- lib/pages/app.dart | 56 ++++++++++-------------- lib/pages/apps.dart | 46 +++++++++---------- lib/providers/apps_provider.dart | 56 ++++++++++++++++++++++++ pubspec.lock | 8 ++++ pubspec.yaml | 1 + 12 files changed, 148 insertions(+), 62 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 2bc8000..8b78ce2 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -52,6 +52,7 @@ + diff --git a/assets/translations/de.json b/assets/translations/de.json index ac7da30..9d72135 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -178,7 +178,6 @@ "installedVersionX": "Installierte Version: {}", "lastUpdateCheckX": "Letzte Aktualisierungsprüfung: {}", "remove": "Entfernen", - "removeAppQuestion": "App entfernen?", "yesMarkUpdated": "Ja, als aktualisiert markieren", "fdroid": "F-Droid", "appIdOrName": "App ID oder Name", @@ -212,6 +211,12 @@ "storagePermissionDenied": "Storage permission denied", "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", "filterAPKsByRegEx": "Filter APKs by Regular Expression", + "removeFromObtainium": "Remove from Obtainium", + "uninstallFromDevice": "Uninstall from Device", + "removeAppQuestion": { + "one": "App entfernen?", + "other": "App entfernen?" + }, "tooManyRequestsTryAgainInMinutes": { "one": "Zu viele Anfragen (Rate begrenzt) - versuchen Sie es in {} Minute erneut", "other": "Zu viele Anfragen (Rate begrenzt) - versuchen Sie es in {} Minuten erneut" diff --git a/assets/translations/en.json b/assets/translations/en.json index 274947e..6fcc87a 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -178,7 +178,6 @@ "installedVersionX": "Installed Version: {}", "lastUpdateCheckX": "Last Update Check: {}", "remove": "Remove", - "removeAppQuestion": "Remove App?", "yesMarkUpdated": "Yes, Mark as Updated", "fdroid": "F-Droid", "appIdOrName": "App ID or Name", @@ -212,6 +211,12 @@ "storagePermissionDenied": "Storage permission denied", "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", "filterAPKsByRegEx": "Filter APKs by Regular Expression", + "removeFromObtainium": "Remove from Obtainium", + "uninstallFromDevice": "Uninstall from Device", + "removeAppQuestion": { + "one": "Remove App?", + "other": "Remove Apps?" + }, "tooManyRequestsTryAgainInMinutes": { "one": "Too many requests (rate limited) - try again in {} minute", "other": "Too many requests (rate limited) - try again in {} minutes" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index c6466fd..0ba0763 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -178,7 +178,6 @@ "installedVersionX": "Telepített verzió: {}", "lastUpdateCheckX": "Frissítés ellenőrizve: {}", "remove": "Eltávolítás", - "removeAppQuestion": "Eltávolítja az alkalmazást?", "yesMarkUpdated": "Igen, megjelölés frissítettként", "fdroid": "F-Droid", "appIdOrName": "App ID vagy név", @@ -211,6 +210,12 @@ "storagePermissionDenied": "Tárhely engedély megtagadva", "selectedCategorizeWarning": "Ez felváltja a kiválasztott alkalmazások meglévő kategória-beállításait.", "filterAPKsByRegEx": "Filter APKs by Regular Expression", + "removeFromObtainium": "Remove from Obtainium", + "uninstallFromDevice": "Uninstall from Device", + "removeAppQuestion": { + "one": "Eltávolítja az alkalmazást?", + "other": "Eltávolítja az alkalmazást?" + }, "tooManyRequestsTryAgainInMinutes": { "one": "Túl sok kérés (korlátozott arány) – próbálja újra {} perc múlva", "other": "Túl sok kérés (korlátozott arány) – próbálja újra {} perc múlva" diff --git a/assets/translations/it.json b/assets/translations/it.json index 4a56c8a..a6eaaab 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -178,7 +178,6 @@ "installedVersionX": "Versione installata: {}", "lastUpdateCheckX": "Ultimo controllo degli aggiornamenti: {}", "remove": "Rimuovi", - "removeAppQuestion": "Rimuovere l'App?", "yesMarkUpdated": "Sì, contrassegna come aggiornato", "fdroid": "F-Droid", "appIdOrName": "ID o nome dell'App", @@ -212,6 +211,12 @@ "storagePermissionDenied": "Storage permission denied", "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", "filterAPKsByRegEx": "Filter APKs by Regular Expression", + "removeFromObtainium": "Remove from Obtainium", + "uninstallFromDevice": "Uninstall from Device", + "removeAppQuestion": { + "one": "Rimuovere l'App?", + "other": "Rimuovere l'App?" + }, "tooManyRequestsTryAgainInMinutes": { "one": "Troppe richieste (traffico limitato) - riprova tra {} minuto", "other": "Troppe richieste (traffico limitato) - riprova tra {} minuti" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index eb078b8..20ef37d 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -178,7 +178,6 @@ "installedVersionX": "インストールされたバージョン: {}", "lastUpdateCheckX": "最終アップデート確認: {}", "remove": "削除", - "removeAppQuestion": "アプリを削除しますか?", "yesMarkUpdated": "はい、アップデート済みとしてマークします", "fdroid": "F-Droid", "appIdOrName": "アプリのIDまたは名前", @@ -212,6 +211,12 @@ "storagePermissionDenied": "ストレージ権限が拒否されました", "selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。", "filterAPKsByRegEx": "正規表現でAPKを絞り込む", + "removeFromObtainium": "Remove from Obtainium", + "uninstallFromDevice": "Uninstall from Device", + "removeAppQuestion": { + "one": "アプリを削除しますか?", + "other": "アプリを削除しますか?" + }, "tooManyRequestsTryAgainInMinutes": { "one": "リクエストが多すぎます(レート制限)- {}分後に再試行してください", "other": "リクエストが多すぎます(レート制限)- {}分後に再試行してください" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 8f103a8..89b6ea6 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -178,7 +178,6 @@ "installedVersionX": "已安装: {}", "lastUpdateCheckX": "最后检查: {}", "remove": "删除", - "removeAppQuestion": "删除应用?", "yesMarkUpdated": "'是的,标为已更新", "fdroid": "F-Droid", "appIdOrName": "应用 ID 或名称", @@ -212,6 +211,12 @@ "storagePermissionDenied": "存储权限已被拒绝", "selectedCategorizeWarning": "这将取代所选应用程序的任何现有类别", "filterAPKsByRegEx": "Filter APKs by Regular Expression", + "removeFromObtainium": "Remove from Obtainium", + "uninstallFromDevice": "Uninstall from Device", + "removeAppQuestion": { + "one": "删除应用?", + "other": "删除应用?" + }, "tooManyRequestsTryAgainInMinutes": { "one": "请求过多 (API 限制) - 在 {} 分钟后重试", "other": "请求过多 (API 限制) - 在 {} 分钟后重试" diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 94711ca..02bf1bb 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'; @@ -361,40 +362,12 @@ class _AppPageState extends State { onPressed: app?.downloadProgress != null ? null : () { - showDialog( - context: context, - builder: (BuildContext ctx) { - return AlertDialog( - title: Text(tr('removeAppQuestion')), - content: Text(tr( - 'xWillBeRemovedButRemainInstalled', - args: [ - app?.installedInfo?.name ?? - app?.app.name ?? - tr('app') - ])), - actions: [ - TextButton( - onPressed: () { - HapticFeedback - .selectionClick(); - appsProvider.removeApps( - [app!.app.id]).then((_) { - int count = 0; - Navigator.of(context) - .popUntil((_) => - count++ >= 2); - }); - }, - child: Text(tr('remove'))), - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text(tr('cancel'))) - ], - ); - }); + appsProvider.removeAppsWithModal( + context, [app!.app]).then((value) { + if (value == true) { + Navigator.of(context).pop(); + } + }); }, style: TextButton.styleFrom( foregroundColor: @@ -414,3 +387,18 @@ class _AppPageState extends State { ); } } + +class RemoveAppsModal extends StatefulWidget { + const RemoveAppsModal({super.key, this.apps = const []}); + final List apps; + + @override + State createState() => _RemoveAppsModalState(); +} + +class _RemoveAppsModalState extends State { + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 56f569a..e81be28 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -389,28 +389,30 @@ class AppsPageState extends State { onPressed: selectedApps.isEmpty ? null : () { - showDialog?>( - context: context, - builder: (BuildContext ctx) { - return GeneratedFormModal( - title: tr( - 'removeSelectedAppsQuestion'), - items: const [], - initValid: true, - message: tr( - 'xWillBeRemovedButRemainInstalled', - args: [ - plural('apps', - selectedApps.length) - ]), - ); - }).then((values) { - if (values != null) { - appsProvider.removeApps(selectedApps - .map((e) => e.id) - .toList()); - } - }); + appsProvider.removeAppsWithModal( + context, selectedApps.toList()); + // showDialog?>( + // context: context, + // builder: (BuildContext ctx) { + // return GeneratedFormModal( + // title: tr( + // 'removeSelectedAppsQuestion'), + // items: const [], + // initValid: true, + // message: tr( + // 'xWillBeRemovedButRemainInstalled', + // args: [ + // plural('apps', + // selectedApps.length) + // ]), + // ); + // }).then((values) { + // if (values != null) { + // appsProvider.removeApps(selectedApps + // .map((e) => e.id) + // .toList()); + // } + // }); }, tooltip: tr('removeSelectedApps'), icon: const Icon(Icons.delete_outline_outlined), diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 18e5124..c4dbbaa 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:android_intent_plus/flag.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -12,6 +13,8 @@ import 'package:flutter/services.dart'; import 'package:install_plugin_v2/install_plugin_v2.dart'; import 'package:installed_apps/app_info.dart'; import 'package:installed_apps/installed_apps.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/providers/logs_provider.dart'; import 'package:obtainium/providers/notifications_provider.dart'; @@ -23,6 +26,7 @@ import 'package:path_provider/path_provider.dart'; import 'package:flutter_fgbg/flutter_fgbg.dart'; import 'package:obtainium/providers/source_provider.dart'; import 'package:http/http.dart'; +import 'package:android_intent_plus/android_intent.dart'; class AppInMemory { late App app; @@ -259,6 +263,15 @@ class AppsProvider with ChangeNotifier { attemptToCorrectInstallStatus: false); } + void uninstallApp(String appId) async { + var intent = AndroidIntent( + action: 'android.intent.action.DELETE', + data: 'package:$appId', + flags: [Flag.FLAG_ACTIVITY_NEW_TASK], + package: 'vnd.android.package-archive'); + await intent.launch(); + } + Future confirmApkUrl(App app, BuildContext? context) async { // If the App has more than one APK, the user should pick one (if context provided) String? apkUrl = app.apkUrls[app.preferredApkIndex]; @@ -622,6 +635,49 @@ class AppsProvider with ChangeNotifier { } } + Future removeAppsWithModal(BuildContext context, List apps) async { + var showUninstallOption = + apps.where((a) => a.installedVersion != null).isNotEmpty; + var values = await showDialog( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: plural('removeAppQuestion', apps.length), + items: !showUninstallOption + ? [] + : [ + [ + GeneratedFormSwitch('rmAppEntry', + label: tr('removeFromObtainium'), defaultValue: true) + ], + [ + GeneratedFormSwitch('uninstallApp', + label: tr('uninstallFromDevice')) + ] + ], + initValid: true, + ); + }); + if (values != null) { + bool uninstall = values['uninstallApp'] == true && showUninstallOption; + bool remove = values['rmAppEntry'] == true || !showUninstallOption; + if (uninstall) { + for (var i = 0; i < apps.length; i++) { + if (apps[i].installedVersion != null) { + uninstallApp(apps[i].id); + apps[i].installedVersion = null; + } + } + await saveApps(apps, attemptToCorrectInstallStatus: false); + } + if (remove) { + await removeApps(apps.map((e) => e.id).toList()); + } + return uninstall || remove; + } + return false; + } + Future checkUpdate(String appId) async { App? currentApp = apps[appId]!.app; SourceProvider sourceProvider = SourceProvider(); diff --git a/pubspec.lock b/pubspec.lock index 4bd6b84..5c0b82a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + android_intent_plus: + dependency: "direct main" + description: + name: android_intent_plus + sha256: ebd110b60723334bdc6eeb373116d6c52e9bed8feb9dcbd9f034531f56636e31 + url: "https://pub.dev" + source: hosted + version: "3.1.5" animations: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 105ad20..6e82baf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,6 +58,7 @@ dependencies: android_alarm_manager_plus: ^2.1.0 sqflite: ^2.2.0+3 easy_localization: ^3.0.1 + android_intent_plus: ^3.1.5 dev_dependencies: From 6e0f6b528e73023cd75696933ebea407b9feba05 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 4 Feb 2023 19:11:28 -0500 Subject: [PATCH 018/600] Added App settings button --- lib/pages/app.dart | 16 ++++++++++++---- lib/providers/apps_provider.dart | 8 ++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 02bf1bb..4a222f7 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -1,7 +1,6 @@ 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'; @@ -268,8 +267,9 @@ class _AppPageState extends State { return row; }).toList(); return GeneratedFormModal( - title: tr('additionalOptions'), - items: items); + title: tr('additionalOptions'), + items: items, + ); }).then((values) { if (app != null && values != null) { var changedApp = app.app; @@ -290,7 +290,15 @@ class _AppPageState extends State { }); }, tooltip: tr('additionalOptions'), - icon: const Icon(Icons.settings)), + icon: const Icon(Icons.edit)), + if (app != null && app.installedInfo != null) + IconButton( + onPressed: () { + appsProvider.openAppSettings(app.app.id); + }, + icon: const Icon(Icons.settings), + tooltip: tr('settings'), + ), if (app != null && settingsProvider.showAppWebpage) IconButton( onPressed: () { diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index c4dbbaa..2fc89a3 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -678,6 +678,14 @@ class AppsProvider with ChangeNotifier { return false; } + Future openAppSettings(String appId) async { + final AndroidIntent intent = AndroidIntent( + action: 'action_application_details_settings', + data: 'package:$appId', + ); + await intent.launch(); + } + Future checkUpdate(String appId) async { App? currentApp = apps[appId]!.app; SourceProvider sourceProvider = SourceProvider(); From ea68b97ff798426d97fa4ac8990aa8c7c49d3723 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 4 Feb 2023 19:30:41 -0500 Subject: [PATCH 019/600] Mark updated feature more clear --- assets/translations/de.json | 2 +- assets/translations/en.json | 2 +- assets/translations/hu.json | 2 +- assets/translations/it.json | 2 +- assets/translations/ja.json | 2 +- lib/pages/app.dart | 12 ++++-------- lib/pages/apps.dart | 4 ++-- 7 files changed, 11 insertions(+), 15 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 9d72135..69ce123 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -74,7 +74,6 @@ "changeX": "Ändern {}", "installUpdateApps": "Apps installieren/aktualisieren", "installUpdateSelectedApps": "Ausgewählte Apps installieren/aktualisieren", - "onlyWorksWithNonEVDApps": "Funktioniert nur bei Apps, deren Installationsstatus nicht automatisch erkannt werden kann (ungewöhnlich).", "markXSelectedAppsAsUpdated": "Markiere {} ausgewählte Apps als aktuell?", "no": "Nein", "yes": "Ja", @@ -213,6 +212,7 @@ "filterAPKsByRegEx": "Filter APKs by Regular Expression", "removeFromObtainium": "Remove from Obtainium", "uninstallFromDevice": "Uninstall from Device", + "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", "removeAppQuestion": { "one": "App entfernen?", "other": "App entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 6fcc87a..95a41ef 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -74,7 +74,6 @@ "changeX": "Change {}", "installUpdateApps": "Install/Update Apps", "installUpdateSelectedApps": "Install/Update Selected Apps", - "onlyWorksWithNonEVDApps": "Only works for Apps whose install status cannot be automatically detected (uncommon).", "markXSelectedAppsAsUpdated": "Mark {} Selected Apps as Updated?", "no": "No", "yes": "Yes", @@ -213,6 +212,7 @@ "filterAPKsByRegEx": "Filter APKs by Regular Expression", "removeFromObtainium": "Remove from Obtainium", "uninstallFromDevice": "Uninstall from Device", + "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 0ba0763..a92460d 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -74,7 +74,6 @@ "changeX": "Változás {}", "installUpdateApps": "Appok telepítése/frissítése", "installUpdateSelectedApps": "Telepítse/frissítse a kiválasztott appokat", - "onlyWorksWithNonEVDApps": "Csak azoknál az alkalmazásoknál működik, amelyek telepítési állapota nem észlelhető autom. (nem gyakori).", "markXSelectedAppsAsUpdated": "Megjelöl {} kiválasztott alkalmazást frissítettként?", "no": "Nem", "yes": "Igen", @@ -212,6 +211,7 @@ "filterAPKsByRegEx": "Filter APKs by Regular Expression", "removeFromObtainium": "Remove from Obtainium", "uninstallFromDevice": "Uninstall from Device", + "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", "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 a6eaaab..c172613 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -74,7 +74,6 @@ "changeX": "Modifica {}", "installUpdateApps": "Installa/Aggiorna App", "installUpdateSelectedApps": "Installa/Aggiorna le App selezionate", - "onlyWorksWithNonEVDApps": "Funziona solo per le App il cui stato d'installazione non può essere rilevato automaticamente (inconsueto).", "markXSelectedAppsAsUpdated": "Contrassegnare le {} App selezionate come aggiornate?", "no": "No", "yes": "Sì", @@ -213,6 +212,7 @@ "filterAPKsByRegEx": "Filter APKs by Regular Expression", "removeFromObtainium": "Remove from Obtainium", "uninstallFromDevice": "Uninstall from Device", + "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere l'App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 20ef37d..05abcf6 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -74,7 +74,6 @@ "changeX": "{} を変更する", "installUpdateApps": "アプリのインストール/アップデート", "installUpdateSelectedApps": "選択したアプリのインストール/アップデート", - "onlyWorksWithNonEVDApps": "インストール状況を自動検出できないアプリ(一般的でないもの)のみ動作します。", "markXSelectedAppsAsUpdated": "{}個の選択したアプリをアップデート済みとしてマークしますか?", "no": "いいえ", "yes": "はい", @@ -213,6 +212,7 @@ "filterAPKsByRegEx": "正規表現でAPKを絞り込む", "removeFromObtainium": "Remove from Obtainium", "uninstallFromDevice": "Uninstall from Device", + "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 4a222f7..0946b13 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -42,6 +42,8 @@ class _AppPageState extends State { getUpdate(app.app.id); } var trackOnly = app?.app.additionalSettings['trackOnly'] == true; + var noVersionDetection = + app?.app.additionalSettings['noVersionDetection'] == true; var infoColumn = Column( mainAxisAlignment: MainAxisAlignment.center, @@ -190,8 +192,9 @@ class _AppPageState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - if (app?.app.installedVersion != null && + if (noVersionDetection && !trackOnly && + app?.app.installedVersion != null && app?.app.installedVersion != app?.app.latestVersion) IconButton( onPressed: app?.downloadProgress != null @@ -203,13 +206,6 @@ class _AppPageState extends State { return AlertDialog( title: Text(tr( 'alreadyUpToDateQuestion')), - content: Text( - tr('onlyWorksWithNonEVDApps'), - style: const TextStyle( - fontWeight: - FontWeight.bold, - fontStyle: - FontStyle.italic)), actions: [ TextButton( onPressed: () { diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index e81be28..ce666e7 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -662,7 +662,7 @@ class AppsPageState extends State { ])), content: Text( - tr('onlyWorksWithNonEVDApps'), + tr('onlyWorksWithNonVersionDetectApps'), style: const TextStyle(fontWeight: FontWeight.bold, fontStyle: FontStyle.italic), ), actions: [ @@ -675,7 +675,7 @@ class AppsPageState extends State { onPressed: () { HapticFeedback.selectionClick(); appsProvider.saveApps(selectedApps.map((a) { - if (a.installedVersion != null) { + if (a.installedVersion != null && a.additionalSettings['noVersionDetection'] == true) { a.installedVersion = a.latestVersion; } return a; From 4fe311bc03d904ec7805f9e857dc5ca6c9d4f03d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 4 Feb 2023 19:44:18 -0500 Subject: [PATCH 020/600] Update packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 24 ++++++++++++------------ pubspec.yaml | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index d098cbe..bc8840b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.10.6'; +const String currentVersion = '0.10.7'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 5c0b82a..62ea289 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -109,10 +109,10 @@ packages: dependency: transitive description: name: cross_file - sha256: f71079978789bc2fe78d79227f1f8cfe195b31bbd8db2399b0d15a4b96fb843b + sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" url: "https://pub.dev" source: hosted - version: "0.3.3+2" + version: "0.3.3+4" crypto: dependency: transitive description: @@ -165,10 +165,10 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: "37a15576f5a0bfd5555b613cf20ea3bd379607cf88d457374a16032f4e942174" + sha256: c4a508284b14ec4dda5adba2c28b2cdd34fbae1afead7e8c52cad87d51c5405b url: "https://pub.dev" source: hosted - version: "1.5.4" + version: "1.6.2" easy_localization: dependency: "direct main" description: @@ -617,10 +617,10 @@ packages: dependency: transitive description: name: shared_preferences_foundation - sha256: "1ffa239043ab8baf881ec3094a3c767af9d10399b2839020b9e4d44c0bb23951" + sha256: "2b55c18636a4edc529fa5cd44c03d3f3100c00513f518c5127c951978efcccd0" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" shared_preferences_linux: dependency: transitive description: @@ -838,10 +838,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "9d97fa2bae0f1900553c48a2ef0aaa3864367fd7bb625d683c460754b691312c" + sha256: "5f49a6e5fc59e21fcec5e1bbcd401afbee9792a24a4f3d9cef9b5bb0cd1e3767" url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.4" webview_flutter_platform_interface: dependency: transitive description: @@ -854,10 +854,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "523aff9168af9bb2170e4809e0499d7dee065c3919799fd3341d3e616c137960" + sha256: "92e7e7fa468f1df597fb9d37bcf1f303175cbe147c4dbdf06ecc323d950116eb" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.5" win32: dependency: transitive description: @@ -891,5 +891,5 @@ packages: source: hosted version: "3.1.1" sdks: - dart: ">=2.18.2 <4.0.0" - flutter: ">=3.3.0" + dart: ">=2.18.2 <3.0.0" + flutter: ">=3.4.0-17.0.pre" diff --git a/pubspec.yaml b/pubspec.yaml index 6e82baf..b439bb8 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.10.6+112 # When changing this, update the tag in main() accordingly +version: 0.10.7+113 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From a4c014a8bf8399c536059405414595270fabd230 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 4 Feb 2023 20:05:20 -0500 Subject: [PATCH 021/600] Remove unused class --- lib/pages/app.dart | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 0946b13..91f510b 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -391,18 +391,3 @@ class _AppPageState extends State { ); } } - -class RemoveAppsModal extends StatefulWidget { - const RemoveAppsModal({super.key, this.apps = const []}); - final List apps; - - @override - State createState() => _RemoveAppsModalState(); -} - -class _RemoveAppsModalState extends State { - @override - Widget build(BuildContext context) { - return const Placeholder(); - } -} From f89ac5965f661cc48b8e20df1f283459faaa00ff Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 4 Feb 2023 20:06:22 -0500 Subject: [PATCH 022/600] Removed unused commented code --- lib/pages/apps.dart | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index ce666e7..06a7ae7 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -391,28 +391,6 @@ class AppsPageState extends State { : () { appsProvider.removeAppsWithModal( context, selectedApps.toList()); - // showDialog?>( - // context: context, - // builder: (BuildContext ctx) { - // return GeneratedFormModal( - // title: tr( - // 'removeSelectedAppsQuestion'), - // items: const [], - // initValid: true, - // message: tr( - // 'xWillBeRemovedButRemainInstalled', - // args: [ - // plural('apps', - // selectedApps.length) - // ]), - // ); - // }).then((values) { - // if (values != null) { - // appsProvider.removeApps(selectedApps - // .map((e) => e.id) - // .toList()); - // } - // }); }, tooltip: tr('removeSelectedApps'), icon: const Icon(Icons.delete_outline_outlined), From db4517aa132b1d32a67744f78934b2ffa19bbabb Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Sun, 5 Feb 2023 12:23:30 +0900 Subject: [PATCH 023/600] Update Japanese translation --- assets/translations/ja.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 05abcf6..7804ded 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -210,9 +210,9 @@ "storagePermissionDenied": "ストレージ権限が拒否されました", "selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。", "filterAPKsByRegEx": "正規表現でAPKを絞り込む", - "removeFromObtainium": "Remove from Obtainium", - "uninstallFromDevice": "Uninstall from Device", - "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", + "removeFromObtainium": "Obtainiumから削除する", + "uninstallFromDevice": "デバイスからアンインストールする", + "onlyWorksWithNonVersionDetectApps": "バージョン検出を無効にしているアプリにのみ動作します。", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" From 4baf6bcd3b9b2cd47378f33daeac69e04da5b894 Mon Sep 17 00:00:00 2001 From: atilluF <110931720+atilluF@users.noreply.github.com> Date: Sun, 5 Feb 2023 12:10:59 +0100 Subject: [PATCH 024/600] Update it.json --- assets/translations/it.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/translations/it.json b/assets/translations/it.json index c172613..fab4c95 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -207,15 +207,15 @@ "addCategory": "Aggiungi categoria", "label": "Etichetta", "language": "Lingua", - "storagePermissionDenied": "Storage permission denied", - "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", - "filterAPKsByRegEx": "Filter APKs by Regular Expression", - "removeFromObtainium": "Remove from Obtainium", - "uninstallFromDevice": "Uninstall from Device", - "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", + "storagePermissionDenied": "Accesso ai file non autorizzato", + "selectedCategorizeWarning": "Ciò sostituirà le impostazioni di categoria esistenti per le App selezionate.", + "filterAPKsByRegEx": "Filtra file APK con espressioni regolari", + "removeFromObtainium": "Rimuovi da Obtainium", + "uninstallFromDevice": "Disinstalla dal dispositivo", + "onlyWorksWithNonVersionDetectApps": "Funziona solo per le App con il rilevamento della versione disattivato.", "removeAppQuestion": { "one": "Rimuovere l'App?", - "other": "Rimuovere l'App?" + "other": "Rimuovere le App?" }, "tooManyRequestsTryAgainInMinutes": { "one": "Troppe richieste (traffico limitato) - riprova tra {} minuto", From dab0f2bb726c6484cfd8241161cfe34c98a8a050 Mon Sep 17 00:00:00 2001 From: rollingmoai <75471378+rollingmoai@users.noreply.github.com> Date: Thu, 9 Feb 2023 22:13:16 +0800 Subject: [PATCH 025/600] Add installation badges --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 185f69f..2b4b120 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,15 @@ Currently supported App sources: - "HTML" (Fallback) - Any other URL that returns an HTML page with links to APK files (if multiple, the last file alphabetically is picked) +## Installation + +[Get it on GitHub](https://github.com/ImranR98/Obtainium/releases) +[Get it on IzzyOnDroid](https://apt.izzysoft.de/fdroid/index/apk/dev.imranr.obtainium) + ## Limitations - App installs happen asynchronously and the success/failure of an install cannot be determined directly. This results in install statuses and versions sometimes being out of sync with the OS until the next launch or until the problem is manually corrected. - Auto (unattended) updates are unsupported due to a lack of any capable Flutter plugin. From 78baee7265149d559c39dfc317ec2030d98033c4 Mon Sep 17 00:00:00 2001 From: gidano Date: Sat, 11 Feb 2023 11:41:52 +0100 Subject: [PATCH 026/600] Updated hu.json --- assets/translations/hu.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index a92460d..9126c61 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -208,10 +208,10 @@ "language": "Nyelv", "storagePermissionDenied": "Tárhely engedély megtagadva", "selectedCategorizeWarning": "Ez felváltja a kiválasztott alkalmazások meglévő kategória-beállításait.", - "filterAPKsByRegEx": "Filter APKs by Regular Expression", - "removeFromObtainium": "Remove from Obtainium", - "uninstallFromDevice": "Uninstall from Device", - "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", + "filterAPKsByRegEx": "Az APK-k szűrése reguláris kifejezéssel", + "removeFromObtainium": "Eltávolítás az Obtainiumból", + "uninstallFromDevice": "Eltávolítás a készülékről", + "onlyWorksWithNonVersionDetectApps": "Csak azoknál az alkalmazásoknál működik, amelyeknél a verzióérzékelés le van tiltva.", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From 32c40ae7b391a70cf080975dad645160eff1d3bc Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 12 Feb 2023 14:16:19 -0500 Subject: [PATCH 027/600] No longer blocking App ID changes in updates --- assets/translations/de.json | 1 - assets/translations/en.json | 1 - assets/translations/hu.json | 1 - assets/translations/it.json | 1 - assets/translations/ja.json | 1 - assets/translations/zh.json | 1 - lib/custom_errors.dart | 4 ---- lib/main.dart | 2 +- lib/pages/app.dart | 2 ++ lib/providers/apps_provider.dart | 5 +---- pubspec.yaml | 2 +- 11 files changed, 5 insertions(+), 16 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 69ce123..3dafa2b 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -4,7 +4,6 @@ "noVersionFound": "Release-Version nicht ermittelbar", "urlMatchesNoSource": "URL stimmt mit keiner bekannten Quelle überein", "cantInstallOlderVersion": "Installation einer älteren App-Version nicht möglich", - "appIdMismatch": "Die heruntergeladene Paket-ID stimmt nicht mit der vorhandenen App-ID überein", "functionNotImplemented": "Diese Klasse hat diese Funktion nicht implementiert", "placeholder": "Platzhalter", "someErrors": "Es traten einige Fehler auf", diff --git a/assets/translations/en.json b/assets/translations/en.json index 95a41ef..15c8498 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -4,7 +4,6 @@ "noVersionFound": "Could not determine release version", "urlMatchesNoSource": "URL does not match a known source", "cantInstallOlderVersion": "Cannot install an older version of an App", - "appIdMismatch": "Downloaded package ID does not match existing App ID", "functionNotImplemented": "This class has not implemented this function", "placeholder": "Placeholder", "someErrors": "Some Errors Occurred", diff --git a/assets/translations/hu.json b/assets/translations/hu.json index a92460d..96dbaaa 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -4,7 +4,6 @@ "noVersionFound": "Nem sikerült meghatározni a kiadás verzióját", "urlMatchesNoSource": "Az URL nem egyezik ismert forrással", "cantInstallOlderVersion": "Nem telepíthető egy app régebbi verziója", - "appIdMismatch": "A letöltött csomagazonosító nem egyezik a meglévő app azonosítóval", "functionNotImplemented": "Ez az osztály nem valósította meg ezt a függvényt", "placeholder": "Helykitöltő", "someErrors": "Néhány hiba történt", diff --git a/assets/translations/it.json b/assets/translations/it.json index c172613..72fc524 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -4,7 +4,6 @@ "noVersionFound": "Impossibile determinare la versione della release", "urlMatchesNoSource": "L'URL non corrisponde ad alcuna fonte conosciuta", "cantInstallOlderVersion": "Impossibile installare una versione precedente di un'App", - "appIdMismatch": "L'ID del pacchetto scaricato non corrisponde all'ID dell'App esistente", "functionNotImplemented": "Questa classe non ha implementato questa funzione", "placeholder": "Segnaposto", "someErrors": "Si sono verificati degli errori", diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 05abcf6..c63fe1c 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -4,7 +4,6 @@ "noVersionFound": "リリースバージョンを特定できませんでした", "urlMatchesNoSource": "URLが既知のソースと一致しません", "cantInstallOlderVersion": "旧バージョンのアプリをインストールできません", - "appIdMismatch": "ダウンロードしたパッケージのIDが既存のApp IDと一致しません", "functionNotImplemented": "このクラスはこの機能を実装していません", "placeholder": "プレースホルダー", "someErrors": "何らかのエラーが発生しました", diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 89b6ea6..82ae514 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -4,7 +4,6 @@ "noVersionFound": "无法确定更新版本", "urlMatchesNoSource": "URL 与已知来源不符", "cantInstallOlderVersion": "无法安装旧版应用程序", - "appIdMismatch": "下载的软件包名与现有的应用程序包名不一致", "functionNotImplemented": "该类没有实现此功能", "placeholder": "占位符", "someErrors": "出现了一些错误", diff --git a/lib/custom_errors.dart b/lib/custom_errors.dart index a049170..beef068 100644 --- a/lib/custom_errors.dart +++ b/lib/custom_errors.dart @@ -44,10 +44,6 @@ class DowngradeError extends ObtainiumError { DowngradeError() : super(tr('cantInstallOlderVersion')); } -class IDChangedError extends ObtainiumError { - IDChangedError() : super(tr('appIdMismatch')); -} - class NotImplementedError extends ObtainiumError { NotImplementedError() : super(tr('functionNotImplemented')); } diff --git a/lib/main.dart b/lib/main.dart index bc8840b..0938de6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.10.7'; +const String currentVersion = '0.10.8'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 91f510b..312dfdb 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -347,6 +347,8 @@ class _AppPageState extends State { if (res.isNotEmpty && mounted) { Navigator.of(context).pop(); } + }).catchError((e) { + showError(e, context); }); }).catchError((e) { showError(e, context); diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 2fc89a3..0673458 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -179,12 +179,9 @@ class AppsProvider with ChangeNotifier { } } // If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed - // The former case should be handled (give the App its real ID), the latter is a security issue + // In either case, the app should be given the new ID var newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); if (app.id != newInfo.packageName) { - if (apps[app.id] != null && !SourceProvider().isTempId(app.id)) { - throw IDChangedError(); - } var originalAppId = app.id; app.id = newInfo.packageName; downloadedFile = downloadedFile.renameSync( diff --git a/pubspec.yaml b/pubspec.yaml index b439bb8..ae50a6a 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.10.7+113 # When changing this, update the tag in main() accordingly +version: 0.10.8+114 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From fd9aebc5b2340856d6fd00e3589e5d01e49d5717 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 12 Feb 2023 14:36:54 -0500 Subject: [PATCH 028/600] Reverse changes related to App ID changes (#270) --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/zh.json | 1 + lib/custom_errors.dart | 4 ++++ lib/main.dart | 2 +- lib/providers/apps_provider.dart | 5 ++++- pubspec.yaml | 2 +- 10 files changed, 16 insertions(+), 3 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 3dafa2b..69ce123 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -4,6 +4,7 @@ "noVersionFound": "Release-Version nicht ermittelbar", "urlMatchesNoSource": "URL stimmt mit keiner bekannten Quelle überein", "cantInstallOlderVersion": "Installation einer älteren App-Version nicht möglich", + "appIdMismatch": "Die heruntergeladene Paket-ID stimmt nicht mit der vorhandenen App-ID überein", "functionNotImplemented": "Diese Klasse hat diese Funktion nicht implementiert", "placeholder": "Platzhalter", "someErrors": "Es traten einige Fehler auf", diff --git a/assets/translations/en.json b/assets/translations/en.json index 15c8498..95a41ef 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -4,6 +4,7 @@ "noVersionFound": "Could not determine release version", "urlMatchesNoSource": "URL does not match a known source", "cantInstallOlderVersion": "Cannot install an older version of an App", + "appIdMismatch": "Downloaded package ID does not match existing App ID", "functionNotImplemented": "This class has not implemented this function", "placeholder": "Placeholder", "someErrors": "Some Errors Occurred", diff --git a/assets/translations/hu.json b/assets/translations/hu.json index a7e3e1b..9126c61 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -4,6 +4,7 @@ "noVersionFound": "Nem sikerült meghatározni a kiadás verzióját", "urlMatchesNoSource": "Az URL nem egyezik ismert forrással", "cantInstallOlderVersion": "Nem telepíthető egy app régebbi verziója", + "appIdMismatch": "A letöltött csomagazonosító nem egyezik a meglévő app azonosítóval", "functionNotImplemented": "Ez az osztály nem valósította meg ezt a függvényt", "placeholder": "Helykitöltő", "someErrors": "Néhány hiba történt", diff --git a/assets/translations/it.json b/assets/translations/it.json index a8f4cb8..fab4c95 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -4,6 +4,7 @@ "noVersionFound": "Impossibile determinare la versione della release", "urlMatchesNoSource": "L'URL non corrisponde ad alcuna fonte conosciuta", "cantInstallOlderVersion": "Impossibile installare una versione precedente di un'App", + "appIdMismatch": "L'ID del pacchetto scaricato non corrisponde all'ID dell'App esistente", "functionNotImplemented": "Questa classe non ha implementato questa funzione", "placeholder": "Segnaposto", "someErrors": "Si sono verificati degli errori", diff --git a/assets/translations/ja.json b/assets/translations/ja.json index e7c8f34..7804ded 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -4,6 +4,7 @@ "noVersionFound": "リリースバージョンを特定できませんでした", "urlMatchesNoSource": "URLが既知のソースと一致しません", "cantInstallOlderVersion": "旧バージョンのアプリをインストールできません", + "appIdMismatch": "ダウンロードしたパッケージのIDが既存のApp IDと一致しません", "functionNotImplemented": "このクラスはこの機能を実装していません", "placeholder": "プレースホルダー", "someErrors": "何らかのエラーが発生しました", diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 82ae514..89b6ea6 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -4,6 +4,7 @@ "noVersionFound": "无法确定更新版本", "urlMatchesNoSource": "URL 与已知来源不符", "cantInstallOlderVersion": "无法安装旧版应用程序", + "appIdMismatch": "下载的软件包名与现有的应用程序包名不一致", "functionNotImplemented": "该类没有实现此功能", "placeholder": "占位符", "someErrors": "出现了一些错误", diff --git a/lib/custom_errors.dart b/lib/custom_errors.dart index beef068..a049170 100644 --- a/lib/custom_errors.dart +++ b/lib/custom_errors.dart @@ -44,6 +44,10 @@ class DowngradeError extends ObtainiumError { DowngradeError() : super(tr('cantInstallOlderVersion')); } +class IDChangedError extends ObtainiumError { + IDChangedError() : super(tr('appIdMismatch')); +} + class NotImplementedError extends ObtainiumError { NotImplementedError() : super(tr('functionNotImplemented')); } diff --git a/lib/main.dart b/lib/main.dart index 0938de6..06291e4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.10.8'; +const String currentVersion = '0.10.9'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 0673458..2fc89a3 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -179,9 +179,12 @@ class AppsProvider with ChangeNotifier { } } // If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed - // In either case, the app should be given the new ID + // The former case should be handled (give the App its real ID), the latter is a security issue var newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); if (app.id != newInfo.packageName) { + if (apps[app.id] != null && !SourceProvider().isTempId(app.id)) { + throw IDChangedError(); + } var originalAppId = app.id; app.id = newInfo.packageName; downloadedFile = downloadedFile.renameSync( diff --git a/pubspec.yaml b/pubspec.yaml index ae50a6a..94707b5 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.10.8+114 # When changing this, update the tag in main() accordingly +version: 0.10.9+115 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From b07cce8ecd4999d4652a10c6be1211935d37483e Mon Sep 17 00:00:00 2001 From: Mehdee <85278288+mehdijahann@users.noreply.github.com> Date: Mon, 13 Feb 2023 07:07:30 +0900 Subject: [PATCH 029/600] Create FA.json --- assets/translations/FA.json | 264 ++++++++++++++++++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 assets/translations/FA.json diff --git a/assets/translations/FA.json b/assets/translations/FA.json new file mode 100644 index 0000000..79b5223 --- /dev/null +++ b/assets/translations/FA.json @@ -0,0 +1,264 @@ +{ + "invalidURLForSource": "آدرس اینترنتی برنامه {} معتبر نیست", + "noReleaseFound": "نسخه مناسبی پیدا نشد", + "noVersionFound": "نمی توان نسخه منتشر شده را تعیین کرد", + "urlMatchesNoSource": "آدرس اینترنتی با منبع شناخته شده مطابقت ندارد", + "cantInstallOlderVersion": "نمی توان نسخه قدیمی یک برنامه را نصب کرد", + "appIdMismatch": "شناسه بسته دانلود شده با شناسه برنامه موجود مطابقت ندارد", + "functionNotImplemented": "این کلاس این تابع را پیاده سازی نکرده است", + "placeholder": "نگهدارنده مکان", + "someErrors": "برخی از خطاها رخ داده است", + "unexpectedError": "خطای غیرمنتظره", + "ok": "باشه", + "and": "و", + "startedBgUpdateTask": "شروع بررسی بروزرسانی BG", + "bgUpdateIgnoreAfterIs": "نادیده گرفتن بروزرسانی BG بعد از {} است", + "startedActualBGUpdateCheck": "بررسی به‌روزرسانی واقعی BG آغاز شد", + "bgUpdateTaskFinished": "کار بررسی به‌روزرسانی BG تمام شد", + "firstRun": "این اولین اجرای Obtainium است", + "settingUpdateCheckIntervalTo": "تنظیم فاصله به‌روزرسانی روی {}", + "githubPATLabel": "توکن دسترسی شخصی گیت هاب(محدودیت نرخ را افزایش میدهد)", + "githubPATHint": "PAT باید در این قالب باشد: username:token", + "githubPATFormat": "username:token", + "githubPATLinkText": "درباره گیتهاب PATs", + "includePrereleases": "شامل نسخه های اولیه", + "fallbackToOlderReleases": "بازگشت به نسخه های قدیمی تر", + "filterReleaseTitlesByRegEx": "عناوین انتشار را با بیان منظم فیلتر کنید", + "invalidRegEx": "عبارت منظم نامعتبر است", + "noDescription": "بدون توضیحات", + "cancel": "لغو", + "continue": "ادامه دهید", + "requiredInBrackets": "(ضروری)", + "dropdownNoOptsError": "خطا: کشویی باید حداقل یک گزینه داشته باشد", + "colour": "رنگ", + "githubStarredRepos": "مخازن ستاره دار گیتهاب", + "uname": "نام کاربری", + "wrongArgNum": "تعداد آرگومان های ارائه شده اشتباه است", + "xIsTrackOnly": "{} فقط ردیابی", + "source": "منبع", + "app": "برنامه", + "appsFromSourceAreTrackOnly": "برنامه‌های این منبع «فقط ردیابی» هستند", + "youPickedTrackOnly": "شما گزینه ی «فقط ردیابی» را انتخاب کرده اید", + "trackOnlyAppDescription": "برنامه برای به روز رسانی ها ردیابی می شود، اما Obtainium قادر به دانلود یا نصب آن نخواهد بود.", + "cancelled": "لغو شد", + "appAlreadyAdded": "برنامه قبلاً اضافه شده است", + "alreadyUpToDateQuestion": "برنامه از قبل به روز شده است؟", + "addApp": "افزودن برنامه", + "appSourceURL": "آدرس اینترنتی منبع برنامه", + "error": "خطا", + "add": "اضافه کردن", + "searchSomeSourcesLabel": "جستجو (فقط برخی منابع)", + "search": "جستجو کردن", + "additionalOptsFor": "گزینه های اضافی برای {}", + "supportedSourcesBelow": "منابع پشتیبانی شده:", + "trackOnlyInBrackets": "«فقط ردیابی»", + "searchableInBrackets": "(قابل جستجو)", + "appsString": "برنامه ها", + "noApps": "برنامه ای وجود ندارد", + "noAppsForFilter": "برنامه ای برای فیلتر کردن وجود ندارد", + "byX": "توسط {}", + "percentProgress": "پیش رفتن: {}%", + "pleaseWait": "لطفا صبر کنید", + "updateAvailable": "بروزرسانی در دسترس", + "estimateInBracketsShort": "(تخمین)", + "notInstalled": "نصب نشده", + "estimateInBrackets": "(تخمین زدن)", + "selectAll": "انتخاب همه", + "deselectN": "Deselect {}", + "xWillBeRemovedButRemainInstalled": "{} will be removed from Obtainium but remain installed on device.", + "removeSelectedAppsQuestion": "Remove Selected Apps?", + "removeSelectedApps": "Remove Selected Apps", + "updateX": "Update {}", + "installX": "Install {}", + "markXTrackOnlyAsUpdated": "Mark {}\n(Track-Only)\nas Updated", + "changeX": "Change {}", + "installUpdateApps": "Install/Update Apps", + "installUpdateSelectedApps": "Install/Update Selected Apps", + "markXSelectedAppsAsUpdated": "Mark {} Selected Apps as Updated?", + "no": "No", + "yes": "Yes", + "markSelectedAppsUpdated": "Mark Selected Apps as Updated", + "pinToTop": "Pin to top", + "unpinFromTop": "Unpin from top", + "resetInstallStatusForSelectedAppsQuestion": "Reset Install Status for Selected Apps?", + "installStatusOfXWillBeResetExplanation": "The install status of any selected Apps will be reset.\n\nThis can help when the App version shown in Obtainium is incorrect due to failed updates or other issues.", + "shareSelectedAppURLs": "Share Selected App URLs", + "resetInstallStatus": "Reset Install Status", + "more": "More", + "removeOutdatedFilter": "Remove Out-of-Date App Filter", + "showOutdatedOnly": "Show Out-of-Date Apps Only", + "filter": "Filter", + "filterActive": "Filter *", + "filterApps": "Filter Apps", + "appName": "App Name", + "author": "Author", + "upToDateApps": "Up to Date Apps", + "nonInstalledApps": "Non-Installed Apps", + "importExport": "Import/Export", + "settings": "Settings", + "exportedTo": "Exported to {}", + "obtainiumExport": "Obtainium Export", + "invalidInput": "Invalid input", + "importedX": "Imported {}", + "obtainiumImport": "Obtainium Import", + "importFromURLList": "Import from URL List", + "searchQuery": "Search Query", + "appURLList": "App URL List", + "line": "Line", + "searchX": "Search {}", + "noResults": "No results found", + "importX": "Import {}", + "importedAppsIdDisclaimer": "Imported Apps may incorrectly show as \"Not Installed\".\nTo fix this, re-install them through Obtainium.\nThis should not affect App data.\n\nOnly affects URL and third-party import methods.", + "importErrors": "Import Errors", + "importedXOfYApps": "{} of {} Apps imported.", + "followingURLsHadErrors": "The following URLs had errors:", + "okay": "Okay", + "selectURL": "Select URL", + "selectURLs": "Select URLs", + "pick": "Pick", + "theme": "Theme", + "dark": "Dark", + "light": "Light", + "followSystem": "Follow System", + "obtainium": "Obtainium", + "materialYou": "Material You", + "appSortBy": "App Sort By", + "authorName": "Author/Name", + "nameAuthor": "Name/Author", + "asAdded": "As Added", + "appSortOrder": "App Sort Order", + "ascending": "Ascending", + "descending": "Descending", + "bgUpdateCheckInterval": "Background Update Checking Interval", + "neverManualOnly": "Never - Manual Only", + "appearance": "Appearance", + "showWebInAppView": "Show Source Webpage in App View", + "pinUpdates": "Pin Updates to Top of Apps View", + "updates": "Updates", + "sourceSpecific": "Source-Specific", + "appSource": "App Source", + "noLogs": "No Logs", + "appLogs": "App Logs", + "close": "Close", + "share": "Share", + "appNotFound": "App not found", + "obtainiumExportHyphenatedLowercase": "obtainium-export", + "pickAnAPK": "Pick an APK", + "appHasMoreThanOnePackage": "{} has more than one package:", + "deviceSupportsXArch": "Your device supports the {} CPU architecture.", + "deviceSupportsFollowingArchs": "Your device supports the following CPU architectures:", + "warning": "Warning", + "sourceIsXButPackageFromYPrompt": "The App source is '{}' but the release package comes from '{}'. Continue?", + "updatesAvailable": "Updates Available", + "updatesAvailableNotifDescription": "Notifies the user that updates are available for one or more Apps tracked by Obtainium", + "noNewUpdates": "No new updates.", + "xHasAnUpdate": "{} has an update.", + "appsUpdated": "Apps Updated", + "appsUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were applied in the background", + "xWasUpdatedToY": "{} was updated to {}.", + "errorCheckingUpdates": "Error Checking for Updates", + "errorCheckingUpdatesNotifDescription": "A notification that shows when background update checking fails", + "appsRemoved": "Apps Removed", + "appsRemovedNotifDescription": "Notifies the user that one or more Apps were removed due to errors while loading them", + "xWasRemovedDueToErrorY": "{} was removed due to this error: {}", + "completeAppInstallation": "Complete App Installation", + "obtainiumMustBeOpenToInstallApps": "Obtainium must be open to install Apps", + "completeAppInstallationNotifDescription": "Asks the user to return to Obtainium to finish installing an App", + "checkingForUpdates": "Checking for Updates", + "checkingForUpdatesNotifDescription": "Transient notification that appears when checking for updates", + "pleaseAllowInstallPerm": "Please allow Obtainium to install Apps", + "trackOnly": "Track-Only", + "errorWithHttpStatusCode": "Error {}", + "versionCorrectionDisabled": "Version correction disabled (plugin doesn't seem to work)", + "unknown": "Unknown", + "none": "None", + "never": "Never", + "latestVersionX": "Latest Version: {}", + "installedVersionX": "Installed Version: {}", + "lastUpdateCheckX": "Last Update Check: {}", + "remove": "Remove", + "yesMarkUpdated": "Yes, Mark as Updated", + "fdroid": "F-Droid", + "appIdOrName": "App ID or Name", + "appWithIdOrNameNotFound": "No App was found with that ID or Name", + "reposHaveMultipleApps": "Repos may contain multiple Apps", + "fdroidThirdPartyRepo": "F-Droid Third-Party Repo", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Chat", + "install": "Install", + "markInstalled": "Mark Installed", + "update": "Update", + "markUpdated": "Mark Updated", + "additionalOptions": "Additional Options", + "disableVersionDetection": "Disable Version Detection", + "noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.", + "downloadingX": "Downloading {}", + "downloadNotifDescription": "Notifies the user of the progress in downloading an App", + "noAPKFound": "No APK found", + "noVersionDetection": "No version detection", + "categorize": "Categorize", + "categories": "Categories", + "category": "Category", + "noCategory": "No Category", + "noCategories": "No Categories", + "deleteCategoriesQuestion": "Delete Categories?", + "categoryDeleteWarning": "All Apps in deleted categories will be set to uncategorized.", + "addCategory": "Add Category", + "label": "Label", + "language": "Language", + "storagePermissionDenied": "Storage permission denied", + "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", + "filterAPKsByRegEx": "Filter APKs by Regular Expression", + "removeFromObtainium": "Remove from Obtainium", + "uninstallFromDevice": "Uninstall from Device", + "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", + "removeAppQuestion": { + "one": "Remove App?", + "other": "Remove Apps?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Too many requests (rate limited) - try again in {} minute", + "other": "Too many requests (rate limited) - try again in {} minutes" + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "BG update checking encountered a {}, will schedule a retry check in {} minute", + "other": "BG update checking encountered a {}, will schedule a retry check in {} minutes" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "BG update checking found {} update - will notify user if needed", + "other": "BG update checking found {} updates - will notify user if needed" + }, + "apps": { + "one": "{} App", + "other": "{} Apps" + }, + "url": { + "one": "{} URL", + "other": "{} URLs" + }, + "minute": { + "one": "{} Minute", + "other": "{} Minutes" + }, + "hour": { + "one": "{} Hour", + "other": "{} Hours" + }, + "day": { + "one": "{} Day", + "other": "{} Days" + }, + "clearedNLogsBeforeXAfterY": { + "one": "Cleared {n} log (before = {before}, after = {after})", + "other": "Cleared {n} logs (before = {before}, after = {after})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "{} and 1 more app have updates.", + "other": "{} and {} more apps have updates." + }, + "xAndNMoreUpdatesInstalled": { + "one": "{} and 1 more app were updated.", + "other": "{} and {} more apps were updated." + } +} From d762467a313d4d300178b85623756d6ff6a7b8e6 Mon Sep 17 00:00:00 2001 From: Mehdee <85278288+mehdijahann@users.noreply.github.com> Date: Mon, 13 Feb 2023 08:16:06 +0900 Subject: [PATCH 030/600] Update FA.json --- assets/translations/FA.json | 334 ++++++++++++++++++------------------ 1 file changed, 167 insertions(+), 167 deletions(-) diff --git a/assets/translations/FA.json b/assets/translations/FA.json index 79b5223..47845b3 100644 --- a/assets/translations/FA.json +++ b/assets/translations/FA.json @@ -64,201 +64,201 @@ "notInstalled": "نصب نشده", "estimateInBrackets": "(تخمین زدن)", "selectAll": "انتخاب همه", - "deselectN": "Deselect {}", - "xWillBeRemovedButRemainInstalled": "{} will be removed from Obtainium but remain installed on device.", - "removeSelectedAppsQuestion": "Remove Selected Apps?", - "removeSelectedApps": "Remove Selected Apps", - "updateX": "Update {}", - "installX": "Install {}", - "markXTrackOnlyAsUpdated": "Mark {}\n(Track-Only)\nas Updated", - "changeX": "Change {}", - "installUpdateApps": "Install/Update Apps", - "installUpdateSelectedApps": "Install/Update Selected Apps", - "markXSelectedAppsAsUpdated": "Mark {} Selected Apps as Updated?", - "no": "No", - "yes": "Yes", - "markSelectedAppsUpdated": "Mark Selected Apps as Updated", - "pinToTop": "Pin to top", - "unpinFromTop": "Unpin from top", - "resetInstallStatusForSelectedAppsQuestion": "Reset Install Status for Selected Apps?", - "installStatusOfXWillBeResetExplanation": "The install status of any selected Apps will be reset.\n\nThis can help when the App version shown in Obtainium is incorrect due to failed updates or other issues.", - "shareSelectedAppURLs": "Share Selected App URLs", - "resetInstallStatus": "Reset Install Status", - "more": "More", - "removeOutdatedFilter": "Remove Out-of-Date App Filter", - "showOutdatedOnly": "Show Out-of-Date Apps Only", - "filter": "Filter", - "filterActive": "Filter *", - "filterApps": "Filter Apps", - "appName": "App Name", - "author": "Author", - "upToDateApps": "Up to Date Apps", - "nonInstalledApps": "Non-Installed Apps", - "importExport": "Import/Export", - "settings": "Settings", - "exportedTo": "Exported to {}", - "obtainiumExport": "Obtainium Export", - "invalidInput": "Invalid input", - "importedX": "Imported {}", - "obtainiumImport": "Obtainium Import", - "importFromURLList": "Import from URL List", - "searchQuery": "Search Query", - "appURLList": "App URL List", - "line": "Line", - "searchX": "Search {}", - "noResults": "No results found", - "importX": "Import {}", - "importedAppsIdDisclaimer": "Imported Apps may incorrectly show as \"Not Installed\".\nTo fix this, re-install them through Obtainium.\nThis should not affect App data.\n\nOnly affects URL and third-party import methods.", - "importErrors": "Import Errors", - "importedXOfYApps": "{} of {} Apps imported.", - "followingURLsHadErrors": "The following URLs had errors:", - "okay": "Okay", - "selectURL": "Select URL", - "selectURLs": "Select URLs", - "pick": "Pick", - "theme": "Theme", - "dark": "Dark", - "light": "Light", - "followSystem": "Follow System", + "deselectN": "لغو انتخاب {}", + "xWillBeRemovedButRemainInstalled": "{} از Obtainium حذف می‌شود اما روی دستگاه نصب می‌ماند.", + "removeSelectedAppsQuestion": "برنامه های انتخابی حذف شود؟", + "removeSelectedApps": "حذف برنامه های انتخاب شده", + "updateX": "به روز رسانی {}", + "installX": "نصب {}", + "markXTrackOnlyAsUpdated": "علامت {}\n(فقط ردیابی)\nبروز شده", + "changeX": "تغییر دادن {}", + "installUpdateApps": "نصب/به‌روزرسانی برنامه‌ها", + "installUpdateSelectedApps": "برنامه‌های انتخابی را نصب/به‌روزرسانی کنید", + "markXSelectedAppsAsUpdated": "{} برنامه های انتخابی را به عنوان به روز علامت گذاری کنید؟", + "no": "خیر", + "yes": "بله", + "markSelectedAppsUpdated": "برنامه های انتخاب شده را به عنوان به روز علامت گذاری کنید", + "pinToTop": "پین به بالا", + "unpinFromTop": "برداشتن پین از بالا", + "resetInstallStatusForSelectedAppsQuestion": "وضعیت نصب برنامه‌های انتخابی بازنشانی شود؟", + "installStatusOfXWillBeResetExplanation": "وضعیت نصب برنامه‌های انتخاب‌شده بازنشانی می‌شود.\n\nاگر نسخه برنامه نشان‌داده‌شده در Obtainium به دلیل به‌روزرسانی‌های ناموفق یا مشکلات دیگر نادرست باشد، می‌تواند کمک کند.", + "shareSelectedAppURLs": "اشتراک گذاری آدرس اینترنتی برنامه های انتخاب شده", + "resetInstallStatus": "بازنشانی وضعیت نصب", + "more": "بیشتر", + "removeOutdatedFilter": "فیلتر برنامه قدیمی را حذف کنید", + "showOutdatedOnly": "فقط برنامه های قدیمی را نشان دهید", + "filter": "فیلتر", + "filterActive": "فیلتر *", + "filterApps": "فیلتر کردن برنامه ها", + "appName": "نام برنامه", + "author": "سازنده", + "upToDateApps": "برنامه های به روز", + "nonInstalledApps": "برنامه های نصب نشده", + "importExport": "وادر کردن/صادر کردن", + "settings": "تنظیمات", + "exportedTo": "صادر کردن به{}", + "obtainiumExport": "صادرکردن Obtainium", + "invalidInput": "ورودی نامعتبر", + "importedX": "وارد شده {}", + "obtainiumImport": "واردکردن Obtainium", + "importFromURLList": "وارد کردن از فهرست آدرس اینترنتی", + "searchQuery": "جستجوی سوال", + "appURLList": "فهرست آدرس اینترنتی برنامه", + "line": "خط", + "searchX": "جستجو {}", + "noResults": "نتیجه ای پیدا نشد", + "importX": "وارد کردن {}", + "importedAppsIdDisclaimer": "ممکن است برنامه‌های وارد شده به اشتباه به‌عنوان \"نصب نشده\" نشان داده شوند.\nبرای رفع این مشکل، آنها را دوباره از طریق Obtainium نصب کنید.\nاین نباید روی داده‌های برنامه تأثیر بگذارد.\n\nفقط بر روی آدرس اینترنتی و روش‌های وارد کردن شخص ثالث تأثیر می‌گذارد.", + "importErrors": "خطاهای وارد کردن", + "importedXOfYApps": "{} از {} برنامه وارد شد.", + "followingURLsHadErrors": "آدرس های اینترنتی زیر دارای خطا بودند:", + "okay": "باشه", + "selectURL": "آدرس اینترنتی انتخاب شده", + "selectURLs": "آدرس های اینترنتی انتخاب شده", + "pick": "انتخاب", + "theme": "تم", + "dark": "تاریک", + "light": "روشن", + "followSystem": "هماهنگ با سیستم", "obtainium": "Obtainium", "materialYou": "Material You", - "appSortBy": "App Sort By", - "authorName": "Author/Name", - "nameAuthor": "Name/Author", - "asAdded": "As Added", - "appSortOrder": "App Sort Order", - "ascending": "Ascending", - "descending": "Descending", - "bgUpdateCheckInterval": "Background Update Checking Interval", - "neverManualOnly": "Never - Manual Only", - "appearance": "Appearance", - "showWebInAppView": "Show Source Webpage in App View", - "pinUpdates": "Pin Updates to Top of Apps View", - "updates": "Updates", - "sourceSpecific": "Source-Specific", - "appSource": "App Source", - "noLogs": "No Logs", - "appLogs": "App Logs", - "close": "Close", - "share": "Share", - "appNotFound": "App not found", - "obtainiumExportHyphenatedLowercase": "obtainium-export", - "pickAnAPK": "Pick an APK", - "appHasMoreThanOnePackage": "{} has more than one package:", - "deviceSupportsXArch": "Your device supports the {} CPU architecture.", - "deviceSupportsFollowingArchs": "Your device supports the following CPU architectures:", - "warning": "Warning", - "sourceIsXButPackageFromYPrompt": "The App source is '{}' but the release package comes from '{}'. Continue?", - "updatesAvailable": "Updates Available", - "updatesAvailableNotifDescription": "Notifies the user that updates are available for one or more Apps tracked by Obtainium", - "noNewUpdates": "No new updates.", - "xHasAnUpdate": "{} has an update.", - "appsUpdated": "Apps Updated", - "appsUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were applied in the background", - "xWasUpdatedToY": "{} was updated to {}.", - "errorCheckingUpdates": "Error Checking for Updates", - "errorCheckingUpdatesNotifDescription": "A notification that shows when background update checking fails", - "appsRemoved": "Apps Removed", - "appsRemovedNotifDescription": "Notifies the user that one or more Apps were removed due to errors while loading them", - "xWasRemovedDueToErrorY": "{} was removed due to this error: {}", - "completeAppInstallation": "Complete App Installation", - "obtainiumMustBeOpenToInstallApps": "Obtainium must be open to install Apps", - "completeAppInstallationNotifDescription": "Asks the user to return to Obtainium to finish installing an App", - "checkingForUpdates": "Checking for Updates", - "checkingForUpdatesNotifDescription": "Transient notification that appears when checking for updates", - "pleaseAllowInstallPerm": "Please allow Obtainium to install Apps", - "trackOnly": "Track-Only", - "errorWithHttpStatusCode": "Error {}", - "versionCorrectionDisabled": "Version correction disabled (plugin doesn't seem to work)", - "unknown": "Unknown", - "none": "None", - "never": "Never", - "latestVersionX": "Latest Version: {}", - "installedVersionX": "Installed Version: {}", - "lastUpdateCheckX": "Last Update Check: {}", - "remove": "Remove", - "yesMarkUpdated": "Yes, Mark as Updated", + "appSortBy": "مرتب سازی برنامه بر اساس", + "authorName": "سازنده/اسم", + "nameAuthor": "اسم/سازنده", + "asAdded": "همانطور که اضافه شد", + "appSortOrder": "ترتیب مرتب سازی برنامه", + "ascending": "صعودی", + "descending": "نزولی", + "bgUpdateCheckInterval": "فاصله بررسی به‌روزرسانی در پس‌زمینه", + "neverManualOnly": "هرگز - فقط دستی", + "appearance": "ظاهر", + "showWebInAppView": "نمایش صفحه وب منبع در نمای برنامه", + "pinUpdates": "به‌روزرسانی‌ها را به نمای بالای برنامه‌ها پین کنید", + "updates": "به روز رسانی ها", + "sourceSpecific": "منبع خاص", + "appSource": "منبع برنامه", + "noLogs": "بدون گزارش", + "appLogs": "گزارش های برنامه", + "close": "بستن", + "share": "اشتراک گذاری", + "appNotFound": "برنامه پیدا نشد", + "obtainiumExportHyphenatedLowercase": "صادر کردن-obtainium", + "pickAnAPK": "یک APK انتخاب کنید", + "appHasMoreThanOnePackage": "{} بیش از یک بسته دارد:", + "deviceSupportsXArch": "دستگاه شما از معماری پردازنده {} پشتیبانی میکند", + "deviceSupportsFollowingArchs": "دستگاه شما از معماری های پردازنده زیر پشتیبانی می کند:", + "warning": "اخطار", + "sourceIsXButPackageFromYPrompt": "منبع برنامه "{}" است اما بسته انتشار از "{}" آمده است. ادامه هید؟", + "updatesAvailable": "بروزرسانی در دسترس ", + "updatesAvailableNotifDescription": "به کاربر اطلاع می دهد که به روز رسانی برای یک یا چند برنامه ردیابی شده توسط Obtainium در دسترس است", + "noNewUpdates": "به روز رسانی جدیدی وجود ندارد.", + "xHasAnUpdate": "{} یک به روز رسانی دارد.", + "appsUpdated": "برنامه ها به روز شدند", + "appsUpdatedNotifDescription": "به کاربر اطلاع می دهد که به روز رسانی یک یا چند برنامه در پس زمینه اعمال شده است", + "xWasUpdatedToY": "{} به {} به روز شد.", + "errorCheckingUpdates": "خطا در بررسی به‌روزرسانی‌ها", + "errorCheckingUpdatesNotifDescription": "اعلانی که وقتی بررسی به‌روزرسانی پس‌زمینه ناموفق است نشان می‌دهد", + "appsRemoved": "برنامه ها حذف شدند", + "appsRemovedNotifDescription": "به کاربر اطلاع می دهد که یک یا چند برنامه به دلیل خطا در هنگام بارگیری حذف شده است", + "xWasRemovedDueToErrorY": "{} به دلیل این خطا حذف شد: {}", + "completeAppInstallation": "نصب کامل برنامه", + "obtainiumMustBeOpenToInstallApps": "Obtainium باید برای نصب برنامه ها باز باشد", + "completeAppInstallationNotifDescription": "از کاربر می‌خواهد برای پایان نصب برنامه به Obtainium برگردد", + "checkingForUpdates": "بررسی به‌روزرسانی‌ها", + "checkingForUpdatesNotifDescription": "اعلان گذرا که هنگام بررسی به روز رسانی ظاهر می شود", + "pleaseAllowInstallPerm": "لطفاً به Obtainium اجازه دهید برنامه‌ها را نصب کند", + "trackOnly": "فقط ردیابی", + "errorWithHttpStatusCode": "خطا {}", + "versionCorrectionDisabled": "تصحیح نسخه غیرفعال شد (به نظر می رسد افزونه کار نمی کند)", + "unknown": "ناشناخته", + "none": "هیچ", + "never": "هرگز", + "latestVersionX": "آخرین نسخه: {}", + "installedVersionX": "نسخه نصب شده: {}", + "lastUpdateCheckX": "بررسی آخرین به‌روزرسانی: {}", + "remove": "حذف", + "yesMarkUpdated": "بله، علامت گذاری به عنوان به روز شده", "fdroid": "F-Droid", - "appIdOrName": "App ID or Name", - "appWithIdOrNameNotFound": "No App was found with that ID or Name", - "reposHaveMultipleApps": "Repos may contain multiple Apps", - "fdroidThirdPartyRepo": "F-Droid Third-Party Repo", + "appIdOrName": "شناسه یا نام برنامه", + "appWithIdOrNameNotFound": "هیچ برنامه ای با آن شناسه یا نام یافت نشد", + "reposHaveMultipleApps": "مخازن ممکن است شامل چندین برنامه باشد", + "fdroidThirdPartyRepo": "مخازن شخص ثالث F-Droid", "steam": "Steam", "steamMobile": "Steam Mobile", "steamChat": "Steam Chat", - "install": "Install", - "markInstalled": "Mark Installed", - "update": "Update", - "markUpdated": "Mark Updated", - "additionalOptions": "Additional Options", - "disableVersionDetection": "Disable Version Detection", - "noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.", - "downloadingX": "Downloading {}", - "downloadNotifDescription": "Notifies the user of the progress in downloading an App", - "noAPKFound": "No APK found", - "noVersionDetection": "No version detection", - "categorize": "Categorize", - "categories": "Categories", - "category": "Category", - "noCategory": "No Category", - "noCategories": "No Categories", - "deleteCategoriesQuestion": "Delete Categories?", - "categoryDeleteWarning": "All Apps in deleted categories will be set to uncategorized.", - "addCategory": "Add Category", - "label": "Label", - "language": "Language", - "storagePermissionDenied": "Storage permission denied", - "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", - "filterAPKsByRegEx": "Filter APKs by Regular Expression", - "removeFromObtainium": "Remove from Obtainium", - "uninstallFromDevice": "Uninstall from Device", - "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", + "install": "نصب", + "markInstalled": "علامت گذاری به عنوان نصب شده", + "update": "به روز رسانی", + "markUpdated": "علامت گذاری به روز شد", + "additionalOptions": "گزینه های اضافی", + "disableVersionDetection": "غیرفعال کردن تشخیص نسخه", + "noVersionDetectionExplanation": "این گزینه فقط باید برای برنامه هایی استفاده شود که تشخیص نسخه به درستی کار نمی کند.", + "downloadingX": "در حال دانلود {}", + "downloadNotifDescription": "کاربر را از پیشرفت دانلود یک برنامه مطلع می کند", + "noAPKFound": "APK پیدا نشد فایل", + "noVersionDetection": "بدون تشخیص نسخه", + "categorize": "دسته بندی کردن", + "categories": "دسته بندی ها", + "category": "دسته بندی", + "noCategory": "بدون دسته بندی", + "noCategories": "بدون دسته بندی ها", + "deleteCategoriesQuestion": "دسته بندی ها حذف شوند؟", + "categoryDeleteWarning": "همه برنامه‌ها در دسته‌های حذف شده روی دسته‌بندی نشده تنظیم می‌شوند.", + "addCategory": "اضافه کردن دسته", + "label": "برچسب", + "language": "زبان", + "storagePermissionDenied": "مجوز ذخیره سازی رد شد", + "selectedCategorizeWarning": "این جایگزین تنظیمات دسته بندی موجود برای برنامه های انتخابی می شود.", + "filterAPKsByRegEx": "فایل‌های APK را با نظم فیلتر کنید", + "removeFromObtainium": "از Obtainium حذف کنید", + "uninstallFromDevice": "حذف نصب از دستگاه", + "onlyWorksWithNonVersionDetectApps": "فقط برای برنامه‌هایی کار می‌کند که تشخیص نسخه غیرفعال است.", "removeAppQuestion": { - "one": "Remove App?", - "other": "Remove Apps?" + "one": "برنامه حذف شود؟", + "other": "برنامه ها حذف شوند؟" }, "tooManyRequestsTryAgainInMinutes": { - "one": "Too many requests (rate limited) - try again in {} minute", - "other": "Too many requests (rate limited) - try again in {} minutes" + "one": "درخواست‌های بسیار زیاد (نرخ محدود) - {} دقیقه دیگر دوباره امتحان کنید", + "other": "درخواست های بسیار زیاد (نرخ محدود) - بعد از {} دقیقه دوباره امتحان کنید" }, "bgUpdateGotErrorRetryInMinutes": { - "one": "BG update checking encountered a {}, will schedule a retry check in {} minute", - "other": "BG update checking encountered a {}, will schedule a retry check in {} minutes" + "one": "بررسی به‌روزرسانی BG با یک {} مواجه شد، یک بررسی مجدد را در {} دقیقه برنامه‌ریزی می‌کند", + "other": "بررسی به‌روزرسانی BG با {} مواجه شد، یک بررسی مجدد را در {} دقیقه برنامه‌ریزی می‌کند" }, "bgCheckFoundUpdatesWillNotifyIfNeeded": { - "one": "BG update checking found {} update - will notify user if needed", - "other": "BG update checking found {} updates - will notify user if needed" + "one": "بررسی به‌روزرسانی BG پیدا شد {} به‌روزرسانی - در صورت نیاز به کاربر اطلاع می‌دهد", + "other": "بررسی به‌روزرسانی BG {} به‌روزرسانی‌های یافت شده - در صورت نیاز به کاربر اطلاع می‌دهد" }, "apps": { - "one": "{} App", - "other": "{} Apps" + "one": "برنامه {}", + "other": "{} برنامه ها" }, "url": { - "one": "{} URL", - "other": "{} URLs" + "one": "{} آدرس اینترنتی", + "other": "{} آدرس های اینترنتی" }, "minute": { - "one": "{} Minute", - "other": "{} Minutes" + "one": "{} دقیقه", + "other": "{} دقیقه" }, "hour": { - "one": "{} Hour", - "other": "{} Hours" + "one": "{} ساعت", + "other": "{} ساعت" }, "day": { - "one": "{} Day", - "other": "{} Days" + "one": "{} روز", + "other": "{} روز" }, "clearedNLogsBeforeXAfterY": { - "one": "Cleared {n} log (before = {before}, after = {after})", - "other": "Cleared {n} logs (before = {before}, after = {after})" + "one": "گزارش {n} پاک شد (قبل از = {پیش از}، بعد = {بعد})", + "other": "{n} گزارش پاک شد (قبل از = {پیش از}، بعد = {بعد})" }, "xAndNMoreUpdatesAvailable": { - "one": "{} and 1 more app have updates.", - "other": "{} and {} more apps have updates." + "one": "{} و 1 برنامه دیگر به‌روزرسانی دارند.", + "other": "{} و {} برنامه دیگر به روز رسانی دارند." }, "xAndNMoreUpdatesInstalled": { - "one": "{} and 1 more app were updated.", - "other": "{} and {} more apps were updated." + "one": "{} و 1 برنامه دیگر به روز شدند.", + "other": "{} و {} برنامه دیگر به روز شدند." } } From e01ca704bc312f840f1d0d4afeffb004326edf4d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 12 Feb 2023 19:19:59 -0500 Subject: [PATCH 031/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 06291e4..7b42aba 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.10.9'; +const String currentVersion = '0.10.10'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 94707b5..c42c9c1 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.10.9+115 # When changing this, update the tag in main() accordingly +version: 0.10.10+116 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 9f03234ac14b9cf9a7e8b14775944e6e3d60a7fa Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 12 Feb 2023 19:25:44 -0500 Subject: [PATCH 032/600] Added FA to language menu (and renamed file for consistency) --- assets/translations/{FA.json => fa.json} | 0 lib/main.dart | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) rename assets/translations/{FA.json => fa.json} (100%) diff --git a/assets/translations/FA.json b/assets/translations/fa.json similarity index 100% rename from assets/translations/FA.json rename to assets/translations/fa.json diff --git a/lib/main.dart b/lib/main.dart index 7b42aba..10ff585 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -33,7 +33,8 @@ const supportedLocales = [ Locale('it'), Locale('ja'), Locale('hu'), - Locale('de') + Locale('de'), + Locale('fa') ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; From eda5c1bac648f49ec4926a30c17a26741b2de4fa Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 12 Feb 2023 19:32:05 -0500 Subject: [PATCH 033/600] Fixed breaking typo in fa.json --- assets/translations/fa.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 47845b3..57f1d4f 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -148,7 +148,7 @@ "deviceSupportsXArch": "دستگاه شما از معماری پردازنده {} پشتیبانی میکند", "deviceSupportsFollowingArchs": "دستگاه شما از معماری های پردازنده زیر پشتیبانی می کند:", "warning": "اخطار", - "sourceIsXButPackageFromYPrompt": "منبع برنامه "{}" است اما بسته انتشار از "{}" آمده است. ادامه هید؟", + "sourceIsXButPackageFromYPrompt": "منبع برنامه \"{}\" است اما بسته انتشار از \"{}\" آمده است. ادامه هید؟", "updatesAvailable": "بروزرسانی در دسترس ", "updatesAvailableNotifDescription": "به کاربر اطلاع می دهد که به روز رسانی برای یک یا چند برنامه ردیابی شده توسط Obtainium در دسترس است", "noNewUpdates": "به روز رسانی جدیدی وجود ندارد.", From e149f0b225693cac4a5fbbe83531d25fcf4de0bb Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 15 Feb 2023 21:05:14 -0500 Subject: [PATCH 034/600] HTML Source bugfix --- lib/app_sources/html.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 984c20e..865162c 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -37,7 +37,9 @@ class HTML extends AppSource { .map((e) => e.toLowerCase().startsWith('http://') || e.toLowerCase().startsWith('https://') ? e - : '${uri.origin}/$e') + : e.startsWith('/') + ? '${uri.origin}/$e' + : '${uri.origin}/${uri.path}/$e') .toList(); return APKDetails(version, apkUrls, AppNames(uri.host, tr('app'))); } else { From b60622e2cbeb133fc7dfda1c31ca6a86b8ae61b1 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 15 Feb 2023 21:26:05 -0500 Subject: [PATCH 035/600] Steam bugfix --- lib/app_sources/steammobile.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/app_sources/steammobile.dart b/lib/app_sources/steammobile.dart index dacc088..a5e07cf 100644 --- a/lib/app_sources/steammobile.dart +++ b/lib/app_sources/steammobile.dart @@ -10,7 +10,10 @@ class SteamMobile extends AppSource { host = 'store.steampowered.com'; name = tr('steam'); additionalSourceAppSpecificSettingFormItems = [ - [GeneratedFormDropdown('app', apks.entries.toList(), label: tr('app'))] + [ + GeneratedFormDropdown('app', apks.entries.toList(), + label: tr('app'), defaultValue: apks.entries.toList()[0].key) + ] ]; } @@ -35,7 +38,8 @@ class SteamMobile extends AppSource { if (apkNamePrefix == null) { throw NoReleasesError(); } - String apkInURLRegexPattern = '/$apkNamePrefix-[^/]+\\.apk\$'; + String apkInURLRegexPattern = + '/$apkNamePrefix-([0-9]+\\.)*[0-9]+\\.apk\$'; var links = parse(res.body) .querySelectorAll('a') .map((e) => e.attributes['href'] ?? '') From 56658abd60e435664b0d820756086a927c95a901 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 15 Feb 2023 21:26:55 -0500 Subject: [PATCH 036/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 10ff585..f7956d6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.10.10'; +const String currentVersion = '0.10.11'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index c42c9c1..bec8a1d 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.10.10+116 # When changing this, update the tag in main() accordingly +version: 0.10.11+117 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 890787f87f9318df4ad9036393f0b950fa64b2f1 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 16 Feb 2023 22:36:53 -0500 Subject: [PATCH 037/600] Fixed type errors and HTML APK filter --- lib/app_sources/codeberg.dart | 4 ++-- lib/app_sources/github.dart | 4 ++-- lib/app_sources/html.dart | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index b4101ca..e2fa5ab 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -54,9 +54,9 @@ class Codeberg extends AppSource { String standardUrl, Map additionalSettings, ) async { - bool includePrereleases = additionalSettings['includePrereleases']; + bool includePrereleases = additionalSettings['includePrereleases'] == true; bool fallbackToOlderReleases = - additionalSettings['fallbackToOlderReleases']; + additionalSettings['fallbackToOlderReleases'] == true; String? regexFilter = (additionalSettings['filterReleaseTitlesByRegEx'] as String?) ?.isNotEmpty == diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 7d92ed1..f4660a5 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -101,9 +101,9 @@ class GitHub extends AppSource { String standardUrl, Map additionalSettings, ) async { - bool includePrereleases = additionalSettings['includePrereleases']; + bool includePrereleases = additionalSettings['includePrereleases'] == true; bool fallbackToOlderReleases = - additionalSettings['fallbackToOlderReleases']; + additionalSettings['fallbackToOlderReleases'] == true; String? regexFilter = (additionalSettings['filterReleaseTitlesByRegEx'] as String?) ?.isNotEmpty == diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 865162c..003eef0 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -27,6 +27,10 @@ class HTML extends AppSource { .where((element) => element.toLowerCase().endsWith('.apk')) .toList(); links.sort((a, b) => a.split('/').last.compareTo(b.split('/').last)); + if (additionalSettings['apkFilterRegEx'] != null) { + var reg = RegExp(additionalSettings['apkFilterRegEx']); + links = links.where((element) => reg.hasMatch(element)).toList(); + } if (links.isEmpty) { throw NoReleasesError(); } From a11c2f1d37a2521b16bc5ddc2ca60eff1468a0ac Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 16 Feb 2023 22:37:17 -0500 Subject: [PATCH 038/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index f7956d6..c5da1bb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.10.11'; +const String currentVersion = '0.10.12'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index bec8a1d..a9d897e 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.10.11+117 # When changing this, update the tag in main() accordingly +version: 0.10.12+118 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 64ded1d720bcfb4186a336ddd3356f841628402e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 16 Feb 2023 22:39:35 -0500 Subject: [PATCH 039/600] Updated packages --- pubspec.lock | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 62ea289..15e4730 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: "direct main" description: name: android_alarm_manager_plus - sha256: "71e796198588e0038dd125bf8c91683b3237b938ffad037413245c689b87ae28" + sha256: "8647cc5f9339f3955a2bd9ec40e0f10c3a80049f31f80b3ffdd87e07bb73fce2" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" android_intent_plus: dependency: "direct main" description: name: android_intent_plus - sha256: ebd110b60723334bdc6eeb373116d6c52e9bed8feb9dcbd9f034531f56636e31 + sha256: "54810cb33945c2c10742cd746ea994822c115e9dbe189919bc63cb436e45a6af" url: "https://pub.dev" source: hosted - version: "3.1.5" + version: "3.1.6" animations: dependency: "direct main" description: @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: args - sha256: "139d809800a412ebb26a3892da228b2d0ba36f0ef5d9a82166e5e52ec8d61611" + sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.0" async: dependency: transitive description: @@ -149,10 +149,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "7ff671ed0a6356fa8f2e1ae7d3558d3fb7b6a41e24455e4f8df75b811fb8e4ab" + sha256: "1d6e5a61674ba3a68fb048a7c7b4ff4bebfed8d7379dbe8f2b718231be9a7c95" url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "8.1.0" device_info_plus_platform_interface: dependency: transitive description: @@ -297,10 +297,10 @@ packages: dependency: "direct main" description: name: fluttertoast - sha256: "7cc92eabe01e3f1babe1571c5560b135dfc762a34e41e9056881e2196b178ec1" + sha256: "774fa28b07f3a82c93596bc137be33189fec578ed3447a93a5a11c93435de394" url: "https://pub.dev" source: hosted - version: "8.1.2" + version: "8.1.3" html: dependency: "direct main" description: @@ -473,10 +473,10 @@ packages: dependency: transitive description: name: path_provider_linux - sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + sha256: "2e32f1640f07caef0d3cb993680f181c79e54a3827b997d5ee221490d131fbd9" url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.1.8" path_provider_platform_interface: dependency: transitive description: @@ -585,10 +585,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: e387077716f80609bb979cd199331033326033ecd1c8f200a90c5f57b1c9f55e + sha256: "8c6892037b1824e2d7e8f59d54b3105932899008642e6372e5079c6939b4b625" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" share_plus_platform_interface: dependency: transitive description: @@ -750,10 +750,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "698fa0b4392effdc73e9e184403b627362eb5fbf904483ac9defbb1c2191d809" + sha256: e8f2efc804810c0f2f5b485f49e7942179f56eabcfe81dce3387fec4bb55876b url: "https://pub.dev" source: hosted - version: "6.1.8" + version: "6.1.9" url_launcher_android: dependency: transitive description: @@ -766,10 +766,10 @@ packages: dependency: transitive description: name: url_launcher_ios - sha256: bb328b24d3bccc20bdf1024a0990ac4f869d57663660de9c936fb8c043edefe3 + sha256: "0a5af0aefdd8cf820dd739886efb1637f1f24489900204f50984634c07a54815" url: "https://pub.dev" source: hosted - version: "6.0.18" + version: "6.1.0" url_launcher_linux: dependency: transitive description: @@ -838,10 +838,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "5f49a6e5fc59e21fcec5e1bbcd401afbee9792a24a4f3d9cef9b5bb0cd1e3767" + sha256: da98c8cdaebea4cf89481853f37ca93ccc8d31fc386f5b3c928aea3b6e83268c url: "https://pub.dev" source: hosted - version: "3.2.4" + version: "3.3.0" webview_flutter_platform_interface: dependency: transitive description: @@ -854,10 +854,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "92e7e7fa468f1df597fb9d37bcf1f303175cbe147c4dbdf06ecc323d950116eb" + sha256: dcd9ad0ef0f608f399d7a54d0b289597385e59a89f04983a672b9348faddfd98 url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.1.0" win32: dependency: transitive description: From ea81b0e66eaa23f4213833a20b58465c6c2fb87e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Feb 2023 18:31:42 -0500 Subject: [PATCH 040/600] Bugfix for different ID same URL Apps (#299) --- lib/pages/add_app.dart | 2 +- lib/pages/app.dart | 10 +++++++++- lib/providers/apps_provider.dart | 2 +- lib/providers/source_provider.dart | 21 ++++++--------------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 80720a1..165910b 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -118,7 +118,7 @@ class _AddAppPageState extends State { await settingsProvider.getInstallPermission(); } // Only download the APK here if you need to for the package ID - if (sourceProvider.isTempId(app.id) && + if (sourceProvider.isTempId(app) && app.additionalSettings['trackOnly'] != true) { // ignore: use_build_context_synchronously var apkUrl = await appsProvider.confirmApkUrl(app, context); diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 312dfdb..46d9828 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -113,7 +113,7 @@ class _AppPageState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - const SizedBox(height: 150), + const SizedBox(height: 125), app?.installedInfo != null ? Row(mainAxisAlignment: MainAxisAlignment.center, children: [ Image.memory( @@ -136,6 +136,14 @@ class _AppPageState extends State { textAlign: TextAlign.center, style: Theme.of(context).textTheme.headlineMedium, ), + const SizedBox( + height: 8, + ), + Text( + app?.app.id ?? '', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.labelSmall, + ), const SizedBox( height: 32, ), diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 2fc89a3..f24cc98 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -182,7 +182,7 @@ class AppsProvider with ChangeNotifier { // The former case should be handled (give the App its real ID), the latter is a security issue var newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); if (app.id != newInfo.packageName) { - if (apps[app.id] != null && !SourceProvider().isTempId(app.id)) { + if (apps[app.id] != null && !SourceProvider().isTempId(app)) { throw IDChangedError(); } var originalAppId = app.id; diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index e4c76e7..955a82d 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -350,21 +350,12 @@ class SourceProvider { return false; } - String generateTempID(AppNames names, AppSource source) => - '${names.author.toLowerCase()}_${names.name.toLowerCase()}_${source.host}'; + String generateTempID( + String standardUrl, Map additionalSettings) => + (standardUrl + additionalSettings.toString()).hashCode.toString(); - bool isTempId(String id) { - List parts = id.split('_'); - if (parts.length < 3) { - return false; - } - for (int i = 0; i < parts.length - 1; i++) { - if (RegExp('.*[A-Z].*').hasMatch(parts[i])) { - // TODO: Look into RegEx for non-Latin characters - return false; - } - } - return true; + bool isTempId(App app) { + return app.id == generateTempID(app.url, app.additionalSettings); } Future getApp( @@ -400,7 +391,7 @@ class SourceProvider { currentApp?.id ?? source.tryInferringAppId(standardUrl, additionalSettings: additionalSettings) ?? - generateTempID(apk.names, source), + generateTempID(standardUrl, additionalSettings), standardUrl, apk.names.author[0].toUpperCase() + apk.names.author.substring(1), name.trim().isNotEmpty From 191776d0d5990cab00c2f0fe24e4df93dda5db03 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Feb 2023 20:37:30 -0500 Subject: [PATCH 041/600] Initial release date support --- assets/translations/de.json | 3 + assets/translations/en.json | 3 + assets/translations/fa.json | 3 + assets/translations/hu.json | 3 + assets/translations/it.json | 3 + assets/translations/ja.json | 3 + assets/translations/zh.json | 3 + lib/app_sources/github.dart | 6 +- lib/pages/add_app.dart | 22 ++++++- lib/pages/app.dart | 38 ++++++++++++ lib/pages/apps.dart | 98 +++++++++++++++++++++--------- lib/providers/source_provider.dart | 90 ++++++++++++++++----------- 12 files changed, 209 insertions(+), 66 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 69ce123..6cff611 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -213,6 +213,9 @@ "removeFromObtainium": "Remove from Obtainium", "uninstallFromDevice": "Uninstall from Device", "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", + "useReleaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", + "changes": "Changes", "removeAppQuestion": { "one": "App entfernen?", "other": "App entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 95a41ef..eeed384 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -213,6 +213,9 @@ "removeFromObtainium": "Remove from Obtainium", "uninstallFromDevice": "Uninstall from Device", "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", + "useReleaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", + "changes": "Changes", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 57f1d4f..fcafb95 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -213,6 +213,9 @@ "removeFromObtainium": "از Obtainium حذف کنید", "uninstallFromDevice": "حذف نصب از دستگاه", "onlyWorksWithNonVersionDetectApps": "فقط برای برنامه‌هایی کار می‌کند که تشخیص نسخه غیرفعال است.", + "useReleaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", + "changes": "Changes", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 9126c61..6982f24 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -212,6 +212,9 @@ "removeFromObtainium": "Eltávolítás az Obtainiumból", "uninstallFromDevice": "Eltávolítás a készülékről", "onlyWorksWithNonVersionDetectApps": "Csak azoknál az alkalmazásoknál működik, amelyeknél a verzióérzékelés le van tiltva.", + "useReleaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", + "changes": "Changes", "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 fab4c95..ad67d63 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -213,6 +213,9 @@ "removeFromObtainium": "Rimuovi da Obtainium", "uninstallFromDevice": "Disinstalla dal dispositivo", "onlyWorksWithNonVersionDetectApps": "Funziona solo per le App con il rilevamento della versione disattivato.", + "useReleaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", + "changes": "Changes", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 7804ded..ca15558 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -213,6 +213,9 @@ "removeFromObtainium": "Obtainiumから削除する", "uninstallFromDevice": "デバイスからアンインストールする", "onlyWorksWithNonVersionDetectApps": "バージョン検出を無効にしているアプリにのみ動作します。", + "useReleaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", + "changes": "Changes", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 89b6ea6..ba97af8 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -213,6 +213,9 @@ "filterAPKsByRegEx": "Filter APKs by Regular Expression", "removeFromObtainium": "Remove from Obtainium", "uninstallFromDevice": "Uninstall from Device", + "useReleaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", + "changes": "Changes", "removeAppQuestion": { "one": "删除应用?", "other": "删除应用?" diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index f4660a5..1ce8cfc 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -154,11 +154,15 @@ class GitHub extends AppSource { throw NoReleasesError(); } String? version = targetRelease['tag_name']; + DateTime? releaseDate = targetRelease['published_at'] != null + ? DateTime.parse(targetRelease['published_at']) + : null; if (version == null) { throw NoVersionError(); } return APKDetails(version, targetRelease['apkUrls'] as List, - getAppNames(standardUrl)); + getAppNames(standardUrl), + releaseDate: releaseDate); } else { rateLimitErrorCheck(res); throw getObtainiumHttpError(res); diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 165910b..0208c9e 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -73,6 +73,8 @@ class _AddAppPageState extends State { var userPickedTrackOnly = additionalSettings['trackOnly'] == true; var userPickedNoVersionDetection = additionalSettings['noVersionDetection'] == true; + var userPickedReleaseDateAsVersion = + additionalSettings['releaseDateAsVersion'] == true; var cont = true; if ((userPickedTrackOnly || pickedSource!.enforceTrackOnly) && // ignore: use_build_context_synchronously @@ -93,7 +95,22 @@ class _AddAppPageState extends State { null) { cont = false; } - if (userPickedNoVersionDetection && + if (userPickedReleaseDateAsVersion && // ignore: use_build_context_synchronously + // ignore: use_build_context_synchronously + await showDialog( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: tr('useReleaseDateAsVersion'), + items: const [], + message: tr('releaseDateAsVersionExplanation'), + ); + }) == + null) { + cont = false; + } + if (!userPickedReleaseDateAsVersion && + userPickedNoVersionDetection && // ignore: use_build_context_synchronously await showDialog( context: context, @@ -113,7 +130,8 @@ class _AddAppPageState extends State { App app = await sourceProvider.getApp( pickedSource!, userInput, additionalSettings, trackOnlyOverride: trackOnly, - noVersionDetectionOverride: userPickedNoVersionDetection); + noVersionDetectionOverride: userPickedNoVersionDetection, + releaseDateAsVersionOverride: userPickedReleaseDateAsVersion); if (!trackOnly) { await settingsProvider.getInstallPermission(); } diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 46d9828..4e0fa5a 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -144,6 +144,13 @@ class _AppPageState extends State { textAlign: TextAlign.center, style: Theme.of(context).textTheme.labelSmall, ), + app?.app.releaseDate == null + ? const SizedBox.shrink() + : Text( + app!.app.releaseDate.toString(), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.labelSmall, + ), const SizedBox( height: 32, ), @@ -286,6 +293,37 @@ class _AppPageState extends State { tr('appsFromSourceAreTrackOnly'), context); } + if (changedApp.additionalSettings[ + 'releaseDateAsVersion'] == + true) { + changedApp.additionalSettings[ + 'noVersionDetection'] = true; + if (app.app.additionalSettings[ + 'releaseDateAsVersion'] != + true) { + if (app.app.releaseDate != null) { + changedApp.latestVersion = app + .app + .releaseDate! + .microsecondsSinceEpoch + .toString(); + if (app.app.installedVersion == + app.app.latestVersion) { + changedApp.installedVersion = + changedApp.latestVersion; + } + } + } + } else if (app.app.additionalSettings[ + 'releaseDateAsVersion'] == + true) { + changedApp.additionalSettings[ + 'noVersionDetection'] = false; + changedApp.installedVersion = app + .installedInfo + ?.versionName ?? + changedApp.installedVersion; + } appsProvider.saveApps( [changedApp]).then((value) { getUpdate(changedApp.id); diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 06a7ae7..0b49c0d 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -264,6 +264,7 @@ class AppsPageState extends State { sortedApps[index].installedInfo?.name ?? sortedApps[index].app.name, style: TextStyle( + overflow: TextOverflow.ellipsis, fontWeight: sortedApps[index].app.pinned ? FontWeight.bold : FontWeight.normal, @@ -289,12 +290,35 @@ class AppsPageState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ - SizedBox( - width: 100, + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + '${sortedApps[index].app.installedVersion ?? tr('notInstalled')}${sortedApps[index].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}', + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.end, + ) + ]), + GestureDetector( + onTap: changesUrl == null + ? null + : () { + launchUrlString(changesUrl, + mode: LaunchMode + .externalApplication); + }, 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.releaseDate == + null + ? tr('changes') + : DateFormat('yyyy-MM-dd').format( + sortedApps[index] + .app + .releaseDate!), + style: const TextStyle( + fontStyle: FontStyle.italic, + decoration: + TextDecoration.underline), )), sortedApps[index].app.installedVersion != null && @@ -304,29 +328,47 @@ class AppsPageState extends State { 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(), + ? appsProvider.areDownloadsRunning() + ? Text(tr('pleaseWait')) + : Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: + MainAxisAlignment.end, + children: [ + GestureDetector( + onTap: () { + appsProvider + .downloadAndInstallLatestApps( + [ + sortedApps[index] + .app + .id + ], + globalNavigatorKey + .currentContext).catchError( + (e) { + showError(e, context); + }); + }, + child: Text( + sortedApps[index] + .app + .additionalSettings[ + 'trackOnly'] == + true + ? tr('markUpdated') + : tr('update'), + style: TextStyle( + color: + Theme.of(context) + .colorScheme + .primary, + fontWeight: + FontWeight.bold), + )), + ], + ) + : const SizedBox.shrink(), ], ))), onTap: () { diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 955a82d..357081a 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -33,8 +33,9 @@ class APKDetails { late String version; late List apkUrls; late AppNames names; + late DateTime? releaseDate; - APKDetails(this.version, this.apkUrls, this.names); + APKDetails(this.version, this.apkUrls, this.names, {this.releaseDate}); } class App { @@ -50,6 +51,7 @@ class App { late DateTime? lastUpdateCheck; bool pinned = false; List categories; + late DateTime? releaseDate; App( this.id, this.url, @@ -62,7 +64,8 @@ class App { this.additionalSettings, this.lastUpdateCheck, this.pinned, - {this.categories = const []}); + {this.categories = const [], + this.releaseDate}); @override String toString() { @@ -111,30 +114,34 @@ class App { preferredApkIndex = 0; } return App( - json['id'] as String, - json['url'] as String, - json['author'] as String, - json['name'] as String, - json['installedVersion'] == null - ? null - : json['installedVersion'] as String, - json['latestVersion'] as String, - json['apkUrls'] == null - ? [] - : List.from(jsonDecode(json['apkUrls'])), - preferredApkIndex, - additionalSettings, - json['lastUpdateCheck'] == null - ? null - : DateTime.fromMicrosecondsSinceEpoch(json['lastUpdateCheck']), - json['pinned'] ?? false, - categories: json['categories'] != null - ? (json['categories'] as List) - .map((e) => e.toString()) - .toList() - : json['category'] != null - ? [json['category'] as String] - : []); + json['id'] as String, + json['url'] as String, + json['author'] as String, + json['name'] as String, + json['installedVersion'] == null + ? null + : json['installedVersion'] as String, + json['latestVersion'] as String, + json['apkUrls'] == null + ? [] + : List.from(jsonDecode(json['apkUrls'])), + preferredApkIndex, + additionalSettings, + json['lastUpdateCheck'] == null + ? null + : DateTime.fromMicrosecondsSinceEpoch(json['lastUpdateCheck']), + json['pinned'] ?? false, + categories: json['categories'] != null + ? (json['categories'] as List) + .map((e) => e.toString()) + .toList() + : json['category'] != null + ? [json['category'] as String] + : [], + releaseDate: json['releaseDate'] == null + ? null + : DateTime.fromMicrosecondsSinceEpoch(json['releaseDate']), + ); } Map toJson() => { @@ -149,7 +156,8 @@ class App { 'additionalSettings': jsonEncode(additionalSettings), 'lastUpdateCheck': lastUpdateCheck?.microsecondsSinceEpoch, 'pinned': pinned, - 'categories': categories + 'categories': categories, + 'releaseDate': releaseDate?.microsecondsSinceEpoch }; } @@ -225,6 +233,10 @@ class AppSource { label: tr('trackOnly'), ) ], + [ + GeneratedFormSwitch('releaseDateAsVersion', + label: tr('useReleaseDateAsVersion')) + ], [ GeneratedFormSwitch('noVersionDetection', label: tr('noVersionDetection')) ], @@ -359,16 +371,19 @@ class SourceProvider { } Future getApp( - AppSource source, - String url, - Map additionalSettings, { - App? currentApp, - bool trackOnlyOverride = false, - noVersionDetectionOverride = false, - }) async { + AppSource source, String url, Map additionalSettings, + {App? currentApp, + bool trackOnlyOverride = false, + bool noVersionDetectionOverride = false, + bool releaseDateAsVersionOverride = false}) async { if (trackOnlyOverride || source.enforceTrackOnly) { additionalSettings['trackOnly'] = true; } + if (releaseDateAsVersionOverride) { + additionalSettings['releaseDateAsVersion'] = true; + noVersionDetectionOverride = + true; // Rel. date as version means no ver. det. + } if (noVersionDetectionOverride) { additionalSettings['noVersionDetection'] = true; } @@ -376,6 +391,10 @@ class SourceProvider { String standardUrl = source.standardizeURL(preStandardizeUrl(url)); APKDetails apk = await source.getLatestAPKDetails(standardUrl, additionalSettings); + if (additionalSettings['releaseDateAsVersion'] == true && + apk.releaseDate != null) { + apk.version = apk.releaseDate!.microsecondsSinceEpoch.toString(); + } if (additionalSettings['apkFilterRegEx'] != null) { var reg = RegExp(additionalSettings['apkFilterRegEx']); apk.apkUrls = @@ -404,7 +423,8 @@ class SourceProvider { additionalSettings, DateTime.now(), currentApp?.pinned ?? false, - categories: currentApp?.categories ?? const []); + categories: currentApp?.categories ?? const [], + releaseDate: apk.releaseDate); } // Returns errors in [results, errors] instead of throwing them From 5f7e342e6bc8b5a10eaf9842a4dde5e0edc4bb43 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Feb 2023 20:47:29 -0500 Subject: [PATCH 042/600] Added rel. date sort --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/fa.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/zh.json | 1 + lib/pages/apps.dart | 91 +++++++++++++++------------- lib/pages/settings.dart | 4 ++ lib/providers/settings_provider.dart | 3 +- 10 files changed, 60 insertions(+), 45 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 6cff611..3aa50e4 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -216,6 +216,7 @@ "useReleaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", + "releaseDate": "Release Date", "removeAppQuestion": { "one": "App entfernen?", "other": "App entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index eeed384..c6c91bd 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -216,6 +216,7 @@ "useReleaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", + "releaseDate": "Release Date", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index fcafb95..999162b 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -216,6 +216,7 @@ "useReleaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", + "releaseDate": "Release Date", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 6982f24..45ee74d 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -215,6 +215,7 @@ "useReleaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", + "releaseDate": "Release Date", "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 ad67d63..39d8054 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -216,6 +216,7 @@ "useReleaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", + "releaseDate": "Release Date", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index ca15558..fce19ec 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -216,6 +216,7 @@ "useReleaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", + "releaseDate": "Release Date", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index ba97af8..001a3ef 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -216,6 +216,7 @@ "useReleaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", + "releaseDate": "Release Date", "removeAppQuestion": { "one": "删除应用?", "other": "删除应用?" diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 0b49c0d..3cf8040 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -54,12 +54,12 @@ class AppsPageState extends State { Widget build(BuildContext context) { var appsProvider = context.watch(); var settingsProvider = context.watch(); - var sortedApps = appsProvider.apps.values.toList(); + var listedApps = appsProvider.apps.values.toList(); var currentFilterIsUpdatesOnly = filter.isIdenticalTo(updatesOnlyFilter, settingsProvider); selectedApps = selectedApps - .where((element) => sortedApps.map((e) => e.app).contains(element)) + .where((element) => listedApps.map((e) => e.app).contains(element)) .toSet(); toggleAppSelected(App app) { @@ -72,7 +72,7 @@ class AppsPageState extends State { }); } - sortedApps = sortedApps.where((app) { + listedApps = listedApps.where((app) { if (app.app.installedVersion == app.app.latestVersion && !(filter.includeUptodate)) { return false; @@ -111,7 +111,7 @@ class AppsPageState extends State { return true; }).toList(); - sortedApps.sort((a, b) { + listedApps.sort((a, b) { var nameA = a.installedInfo?.name ?? a.app.name; var nameB = b.installedInfo?.name ?? b.app.name; int result = 0; @@ -119,25 +119,30 @@ class AppsPageState extends State { result = (a.app.author + nameA).compareTo(b.app.author + nameB); } else if (settingsProvider.sortColumn == SortColumnSettings.nameAuthor) { result = (nameA + a.app.author).compareTo(nameB + b.app.author); + } else if (settingsProvider.sortColumn == + SortColumnSettings.releaseDate) { + result = (a.app.releaseDate) + ?.compareTo(b.app.releaseDate ?? DateTime.now()) ?? + 0; } return result; }); if (settingsProvider.sortOrder == SortOrderSettings.descending) { - sortedApps = sortedApps.reversed.toList(); + listedApps = listedApps.reversed.toList(); } var existingUpdates = appsProvider.findExistingUpdates(installedOnly: true); var existingUpdateIdsAllOrSelected = existingUpdates .where((element) => selectedApps.isEmpty - ? sortedApps.where((a) => a.app.id == element).isNotEmpty + ? listedApps.where((a) => a.app.id == element).isNotEmpty : selectedApps.map((e) => e.id).contains(element)) .toList(); var newInstallIdsAllOrSelected = appsProvider .findExistingUpdates(nonInstalledOnly: true) .where((element) => selectedApps.isEmpty - ? sortedApps.where((a) => a.app.id == element).isNotEmpty + ? listedApps.where((a) => a.app.id == element).isNotEmpty : selectedApps.map((e) => e.id).contains(element)) .toList(); @@ -159,26 +164,26 @@ class AppsPageState extends State { if (settingsProvider.pinUpdates) { var temp = []; - sortedApps = sortedApps.where((sa) { + listedApps = listedApps.where((sa) { if (existingUpdates.contains(sa.app.id)) { temp.add(sa); return false; } return true; }).toList(); - sortedApps = [...temp, ...sortedApps]; + listedApps = [...temp, ...listedApps]; } var tempPinned = []; var tempNotPinned = []; - for (var a in sortedApps) { + for (var a in listedApps) { if (a.app.pinned) { tempPinned.add(a); } else { tempNotPinned.add(a); } } - sortedApps = [...tempPinned, ...tempNotPinned]; + listedApps = [...tempPinned, ...tempNotPinned]; return Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, @@ -198,7 +203,7 @@ class AppsPageState extends State { }, child: CustomScrollView(slivers: [ CustomAppBar(title: tr('appsString')), - if (appsProvider.loadingApps || sortedApps.isEmpty) + if (appsProvider.loadingApps || listedApps.isEmpty) SliverFillRemaining( child: Center( child: appsProvider.loadingApps @@ -225,8 +230,8 @@ class AppsPageState extends State { delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { String? changesUrl = SourceProvider() - .getSource(sortedApps[index].app.url) - .changeLogPageFromStandardUrl(sortedApps[index].app.url); + .getSource(listedApps[index].app.url) + .changeLogPageFromStandardUrl(listedApps[index].app.url); var transparent = const Color.fromARGB(0, 0, 0, 0).value; return Container( decoration: BoxDecoration( @@ -234,53 +239,53 @@ class AppsPageState extends State { vertical: BorderSide( width: 4, color: Color( - sortedApps[index].app.categories.isNotEmpty + listedApps[index].app.categories.isNotEmpty ? settingsProvider.categories[ - sortedApps[index] + listedApps[index] .app .categories .first] ?? transparent : transparent)))), child: ListTile( - tileColor: sortedApps[index].app.pinned + tileColor: listedApps[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), + .withOpacity(listedApps[index].app.pinned ? 0.2 : 0.1), + selected: selectedApps.contains(listedApps[index].app), onLongPress: () { - toggleAppSelected(sortedApps[index].app); + toggleAppSelected(listedApps[index].app); }, - leading: sortedApps[index].installedInfo != null + leading: listedApps[index].installedInfo != null ? Image.memory( - sortedApps[index].installedInfo!.icon!, + listedApps[index].installedInfo!.icon!, gaplessPlayback: true, ) : null, title: Text( - sortedApps[index].installedInfo?.name ?? - sortedApps[index].app.name, + listedApps[index].installedInfo?.name ?? + listedApps[index].app.name, style: TextStyle( overflow: TextOverflow.ellipsis, - fontWeight: sortedApps[index].app.pinned + fontWeight: listedApps[index].app.pinned ? FontWeight.bold : FontWeight.normal, ), ), subtitle: Text( - tr('byX', args: [sortedApps[index].app.author]), + tr('byX', args: [listedApps[index].app.author]), style: TextStyle( - fontWeight: sortedApps[index].app.pinned + fontWeight: listedApps[index].app.pinned ? FontWeight.bold : FontWeight.normal)), trailing: SingleChildScrollView( reverse: true, - child: sortedApps[index].downloadProgress != null + child: listedApps[index].downloadProgress != null ? Text(tr('percentProgress', args: [ - sortedApps[index] + listedApps[index] .downloadProgress ?.toInt() .toString() ?? @@ -294,7 +299,7 @@ class AppsPageState extends State { mainAxisSize: MainAxisSize.min, children: [ Text( - '${sortedApps[index].app.installedVersion ?? tr('notInstalled')}${sortedApps[index].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}', + '${listedApps[index].app.installedVersion ?? tr('notInstalled')}${listedApps[index].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}', overflow: TextOverflow.ellipsis, textAlign: TextAlign.end, ) @@ -308,11 +313,11 @@ class AppsPageState extends State { .externalApplication); }, child: Text( - sortedApps[index].app.releaseDate == + listedApps[index].app.releaseDate == null ? tr('changes') : DateFormat('yyyy-MM-dd').format( - sortedApps[index] + listedApps[index] .app .releaseDate!), style: const TextStyle( @@ -320,12 +325,12 @@ class AppsPageState extends State { decoration: TextDecoration.underline), )), - sortedApps[index].app.installedVersion != + listedApps[index].app.installedVersion != null && - sortedApps[index] + listedApps[index] .app .installedVersion != - sortedApps[index] + listedApps[index] .app .latestVersion ? appsProvider.areDownloadsRunning() @@ -340,7 +345,7 @@ class AppsPageState extends State { appsProvider .downloadAndInstallLatestApps( [ - sortedApps[index] + listedApps[index] .app .id ], @@ -351,7 +356,7 @@ class AppsPageState extends State { }); }, child: Text( - sortedApps[index] + listedApps[index] .app .additionalSettings[ 'trackOnly'] == @@ -373,18 +378,18 @@ class AppsPageState extends State { ))), onTap: () { if (selectedApps.isNotEmpty) { - toggleAppSelected(sortedApps[index].app); + toggleAppSelected(listedApps[index].app); } else { Navigator.push( context, MaterialPageRoute( builder: (context) => - AppPage(appId: sortedApps[index].app.id)), + AppPage(appId: listedApps[index].app.id)), ); } }, )); - }, childCount: sortedApps.length)) + }, childCount: listedApps.length)) ])), persistentFooterButtons: appsProvider.apps.isEmpty ? null @@ -396,20 +401,20 @@ class AppsPageState extends State { style: const ButtonStyle( visualDensity: VisualDensity.compact), onPressed: () { - selectThese(sortedApps.map((e) => e.app).toList()); + selectThese(listedApps.map((e) => e.app).toList()); }, icon: Icon( Icons.select_all_outlined, color: Theme.of(context).colorScheme.primary, ), - label: Text(sortedApps.length.toString())) + label: Text(listedApps.length.toString())) : TextButton.icon( style: const ButtonStyle( visualDensity: VisualDensity.compact), onPressed: () { selectedApps.isEmpty ? selectThese( - sortedApps.map((e) => e.app).toList()) + listedApps.map((e) => e.app).toList()) : clearSelected(); }, icon: Icon( diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index e43aca4..e2ba218 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -101,6 +101,10 @@ class _SettingsPageState extends State { DropdownMenuItem( value: SortColumnSettings.added, child: Text(tr('asAdded')), + ), + DropdownMenuItem( + value: SortColumnSettings.releaseDate, + child: Text(tr('releaseDate')), ) ], onChanged: (value) { diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 068ebf8..ea6985a 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -6,7 +6,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:obtainium/app_sources/github.dart'; -import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/main.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -18,7 +17,7 @@ enum ThemeSettings { system, light, dark } enum ColourSettings { basic, materialYou } -enum SortColumnSettings { added, nameAuthor, authorName } +enum SortColumnSettings { added, nameAuthor, authorName, releaseDate } enum SortOrderSettings { ascending, descending } From 2b4f94b407fb1657a2cc51436eacd35c7942fa4a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Feb 2023 20:49:45 -0500 Subject: [PATCH 043/600] Date sort bugfix --- lib/pages/apps.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 3cf8040..3ee67c6 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -121,8 +121,8 @@ class AppsPageState extends State { result = (nameA + a.app.author).compareTo(nameB + b.app.author); } else if (settingsProvider.sortColumn == SortColumnSettings.releaseDate) { - result = (a.app.releaseDate) - ?.compareTo(b.app.releaseDate ?? DateTime.now()) ?? + result = (a.app.releaseDate)?.compareTo( + b.app.releaseDate ?? DateTime.fromMicrosecondsSinceEpoch(0)) ?? 0; } return result; From f06d245e205b875c58ef6157026af25f5ea40ecb Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Feb 2023 20:55:23 -0500 Subject: [PATCH 044/600] Added release date support to GitLab --- lib/app_sources/gitlab.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index b9bef9b..428568e 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -54,10 +54,14 @@ class GitLab extends AppSource { var entryId = entry?.querySelector('id')?.innerHtml; var version = entryId == null ? null : Uri.parse(entryId).pathSegments.last; + var releaseDateString = entry?.querySelector('updated')?.innerHtml; + DateTime? releaseDate = + releaseDateString != null ? DateTime.parse(releaseDateString) : null; if (version == null) { throw NoVersionError(); } - return APKDetails(version, apkUrls, GitHub().getAppNames(standardUrl)); + return APKDetails(version, apkUrls, GitHub().getAppNames(standardUrl), + releaseDate: releaseDate); } else { throw getObtainiumHttpError(res); } From d5fdf28a98d259788a59c2837533080150140745 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Feb 2023 20:58:08 -0500 Subject: [PATCH 045/600] Added release date support to Codeberg --- lib/app_sources/codeberg.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index e2fa5ab..aa21171 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -112,11 +112,15 @@ class Codeberg extends AppSource { throw NoReleasesError(); } String? version = targetRelease['tag_name']; + DateTime? releaseDate = targetRelease['published_at'] != null + ? DateTime.parse(targetRelease['published_at']) + : null; if (version == null) { throw NoVersionError(); } return APKDetails(version, targetRelease['apkUrls'] as List, - getAppNames(standardUrl)); + getAppNames(standardUrl), + releaseDate: releaseDate); } else { throw getObtainiumHttpError(res); } From fe0126095a2779a3c339dee6992d62356719f02d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Feb 2023 21:03:22 -0500 Subject: [PATCH 046/600] Added release date support to third part f-droid repos --- lib/app_sources/fdroidrepo.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index cffe307..11e8e01 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -69,6 +69,8 @@ class FDroidRepo extends AppSource { foundApps[0].querySelector('name')?.innerHtml ?? appIdOrName; var releases = foundApps[0].querySelectorAll('package'); String? latestVersion = releases[0].querySelector('version')?.innerHtml; + String? added = releases[0].querySelector('added')?.innerHtml; + DateTime? releaseDate = added != null ? DateTime.parse(added) : null; if (latestVersion == null) { throw NoVersionError(); } @@ -78,7 +80,8 @@ class FDroidRepo extends AppSource { element.querySelector('apkname') != null) .map((e) => '$standardUrl/${e.querySelector('apkname')!.innerHtml}') .toList(); - return APKDetails(latestVersion, apkUrls, AppNames(authorName, appName)); + return APKDetails(latestVersion, apkUrls, AppNames(authorName, appName), + releaseDate: releaseDate); } else { throw getObtainiumHttpError(res); } From 4be3478b9776d7682d42795e31d5b01c1de2be6f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Feb 2023 21:16:28 -0500 Subject: [PATCH 047/600] Added release date support to APKMirror --- lib/app_sources/apkmirror.dart | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/app_sources/apkmirror.dart b/lib/app_sources/apkmirror.dart index d583bbb..cf4721a 100644 --- a/lib/app_sources/apkmirror.dart +++ b/lib/app_sources/apkmirror.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:html/parser.dart'; import 'package:http/http.dart'; import 'package:obtainium/custom_errors.dart'; @@ -30,10 +32,16 @@ class APKMirror extends AppSource { ) async { Response res = await get(Uri.parse('$standardUrl/feed')); if (res.statusCode == 200) { - String? titleString = parse(res.body) - .querySelector('item') - ?.querySelector('title') - ?.innerHtml; + var item = parse(res.body).querySelector('item'); + String? titleString = item?.querySelector('title')?.innerHtml; + String? dateString = item + ?.querySelector('pubDate') + ?.innerHtml + .split(' ') + .sublist(0, 5) + .join(' '); + DateTime? releaseDate = + dateString != null ? HttpDate.parse('$dateString GMT') : null; String? version = titleString ?.substring(RegExp('[0-9]').firstMatch(titleString)?.start ?? 0, RegExp(' by ').firstMatch(titleString)?.start ?? 0) @@ -44,7 +52,8 @@ class APKMirror extends AppSource { if (version == null || version.isEmpty) { throw NoVersionError(); } - return APKDetails(version, [], getAppNames(standardUrl)); + return APKDetails(version, [], getAppNames(standardUrl), + releaseDate: releaseDate); } else { throw getObtainiumHttpError(res); } From a788d9d7cd5ecd6a5d2454dc400063b02f83aedb Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Feb 2023 21:22:36 -0500 Subject: [PATCH 048/600] Increment version --- lib/main.dart | 2 +- pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index c5da1bb..ff32826 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.10.12'; +const String currentVersion = '0.11.0'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 15e4730..cab96e0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -258,10 +258,10 @@ packages: dependency: transitive description: name: flutter_local_notifications_linux - sha256: "8f6c1611e0c4a88a382691a97bb3c3feb24cc0c0b54152b8b5fb7ffb837f7fbf" + sha256: ccb08b93703aeedb58856e5637450bf3ffec899adb66dc325630b68994734b89 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.0+1" flutter_local_notifications_platform_interface: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a9d897e..bdceeff 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.10.12+118 # When changing this, update the tag in main() accordingly +version: 0.11.0+119 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 859158e84a14604c820e045a7ebde5bd82ea5b5f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Feb 2023 21:39:26 -0500 Subject: [PATCH 049/600] App edit bugfixes --- lib/pages/app.dart | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 4e0fa5a..0cf9405 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -283,50 +283,53 @@ class _AppPageState extends State { ); }).then((values) { if (app != null && values != null) { - var changedApp = app.app; - changedApp.additionalSettings = - values; + Map + originalSettings = + app.app.additionalSettings; + app.app.additionalSettings = values; if (source.enforceTrackOnly) { - changedApp.additionalSettings[ + app.app.additionalSettings[ 'trackOnly'] = true; showError( tr('appsFromSourceAreTrackOnly'), context); } - if (changedApp.additionalSettings[ + if (app.app.additionalSettings[ 'releaseDateAsVersion'] == true) { - changedApp.additionalSettings[ + app.app.additionalSettings[ 'noVersionDetection'] = true; - if (app.app.additionalSettings[ + if (originalSettings[ 'releaseDateAsVersion'] != true) { if (app.app.releaseDate != null) { - changedApp.latestVersion = app + bool isUpdated = + app.app.installedVersion == + app.app.latestVersion; + app.app.latestVersion = app .app .releaseDate! .microsecondsSinceEpoch .toString(); - if (app.app.installedVersion == - app.app.latestVersion) { - changedApp.installedVersion = - changedApp.latestVersion; + if (isUpdated) { + app.app.installedVersion = + app.app.latestVersion; } } } - } else if (app.app.additionalSettings[ + } else if (originalSettings[ 'releaseDateAsVersion'] == true) { - changedApp.additionalSettings[ + app.app.additionalSettings[ 'noVersionDetection'] = false; - changedApp.installedVersion = app + app.app.installedVersion = app .installedInfo ?.versionName ?? - changedApp.installedVersion; + app.app.installedVersion; } - appsProvider.saveApps( - [changedApp]).then((value) { - getUpdate(changedApp.id); + appsProvider.saveApps([app.app]).then( + (value) { + getUpdate(app.app.id); }); } }); From ffb3516a4b0b4edd0d19013387135a68093d39ac Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Sun, 19 Feb 2023 15:41:14 +0900 Subject: [PATCH 050/600] Update Japanese translation --- assets/translations/ja.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index fce19ec..3eb133d 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -213,10 +213,10 @@ "removeFromObtainium": "Obtainiumから削除する", "uninstallFromDevice": "デバイスからアンインストールする", "onlyWorksWithNonVersionDetectApps": "バージョン検出を無効にしているアプリにのみ動作します。", - "useReleaseDateAsVersion": "Use Release Date as Version", - "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", - "changes": "Changes", - "releaseDate": "Release Date", + "useReleaseDateAsVersion": "リリース日をバージョンとして使用する", + "releaseDateAsVersionExplanation": "このオプションは、バージョン検出が正しく機能しないアプリで、リリース日が利用可能な場合にのみ使用する必要があります。", + "changes": "変更点", + "releaseDate": "リリース日", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" From bd29d7bc10de2315bd2dd2961aeb99041ddd806f Mon Sep 17 00:00:00 2001 From: atilluF <110931720+atilluF@users.noreply.github.com> Date: Sun, 19 Feb 2023 12:44:31 +0100 Subject: [PATCH 051/600] Update it.json --- assets/translations/it.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/translations/it.json b/assets/translations/it.json index 39d8054..7cc3307 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -56,9 +56,9 @@ "appsString": "App", "noApps": "Nessuna App", "noAppsForFilter": "Nessuna App per i filtri selezionati", - "byX": "Da {}", + "byX": "Di {}", "percentProgress": "Progresso: {}%", - "pleaseWait": "Attendere prego", + "pleaseWait": "In attesa", "updateAvailable": "Aggiornamento disponibile", "estimateInBracketsShort": "(prev.)", "notInstalled": "Non installato", @@ -94,7 +94,7 @@ "author": "Autore", "upToDateApps": "App aggiornate", "nonInstalledApps": "App non installate", - "importExport": "Importa - Esporta", + "importExport": "Importa/Esporta", "settings": "Impostazioni", "exportedTo": "Esportato in {}", "obtainiumExport": "Esporta da Obtainium", @@ -213,10 +213,10 @@ "removeFromObtainium": "Rimuovi da Obtainium", "uninstallFromDevice": "Disinstalla dal dispositivo", "onlyWorksWithNonVersionDetectApps": "Funziona solo per le App con il rilevamento della versione disattivato.", - "useReleaseDateAsVersion": "Use Release Date as Version", - "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", - "changes": "Changes", - "releaseDate": "Release Date", + "useReleaseDateAsVersion": "Usa data di rilascio come versione", + "releaseDateAsVersionExplanation": "Questa opzione dovrebbe essere usata solo per le App in cui il rilevamento della versione non funziona correttamente, ma è disponibile una data di rilascio.", + "changes": "Novità", + "releaseDate": "Data di rilascio", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" From f6af3a7998837f4fc1401e39f7ab013a97d5fab3 Mon Sep 17 00:00:00 2001 From: gidano Date: Sun, 19 Feb 2023 15:12:06 +0100 Subject: [PATCH 052/600] Update hu.json --- assets/translations/hu.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 45ee74d..c5745bf 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -34,7 +34,7 @@ "githubStarredRepos": "GitHub Csillagos Repo-k", "uname": "Felh.név", "wrongArgNum": "Rossz számú argumentumot adott meg", - "xIsTrackOnly": "A(z) {} csak nyomkövethető", + "xIsTrackOnly": "A(z) {} csak nyomonkövethető", "source": "Forrás", "app": "App", "appsFromSourceAreTrackOnly": "Az ebből a forrásból származó alkalmazások 'Csak nyomon követhetőek'.", @@ -78,7 +78,7 @@ "no": "Nem", "yes": "Igen", "markSelectedAppsUpdated": "Jelölje meg a kiválasztott appokat frissítettként", - "pinToTop": "Rögzítés a felülre", + "pinToTop": "Rögzítés felülre", "unpinFromTop": "Eltávolít felülről", "resetInstallStatusForSelectedAppsQuestion": "Visszaállítja a kiválasztott appok telepítési állapotát?", "installStatusOfXWillBeResetExplanation": "A kiválasztott appok telepítési állapota visszaáll.\n\nEz akkor segíthet, ha az Obtainiumban megjelenített app verzió hibás, frissítések vagy egyéb problémák miatt.", @@ -212,10 +212,10 @@ "removeFromObtainium": "Eltávolítás az Obtainiumból", "uninstallFromDevice": "Eltávolítás a készülékről", "onlyWorksWithNonVersionDetectApps": "Csak azoknál az alkalmazásoknál működik, amelyeknél a verzióérzékelés le van tiltva.", - "useReleaseDateAsVersion": "Use Release Date as Version", - "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", - "changes": "Changes", - "releaseDate": "Release Date", + "useReleaseDateAsVersion": "Használja a Kiadás dátumát, mint verziót", + "releaseDateAsVersionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzió érzékelése nem működik megfelelően, de elérhető a kiadás dátuma.", + "changes": "Változtatások", + "releaseDate": "Kiadás dátuma", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From c376a7abeca9108e1ff80350a5b4ce634db7acf7 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 19 Feb 2023 18:20:28 -0500 Subject: [PATCH 053/600] Longer version names bugfix for apps list UI --- lib/pages/apps.dart | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 3ee67c6..e733439 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -266,6 +266,7 @@ class AppsPageState extends State { ) : null, title: Text( + maxLines: 1, listedApps[index].installedInfo?.name ?? listedApps[index].app.name, style: TextStyle( @@ -298,11 +299,14 @@ class AppsPageState extends State { Row( mainAxisSize: MainAxisSize.min, children: [ - Text( - '${listedApps[index].app.installedVersion ?? tr('notInstalled')}${listedApps[index].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}', - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.end, - ) + Container( + constraints: const BoxConstraints( + maxWidth: 150), + child: Text( + '${listedApps[index].app.installedVersion ?? tr('notInstalled')}${listedApps[index].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}', + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.end, + )) ]), GestureDetector( onTap: changesUrl == null From b57f023739f6950d2cbf2e2b548b35ff9eaff64f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 19 Feb 2023 18:46:30 -0500 Subject: [PATCH 054/600] Added prev. rel. and regex title filter support to APKMirror --- lib/app_sources/apkmirror.dart | 45 +++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/app_sources/apkmirror.dart b/lib/app_sources/apkmirror.dart index cf4721a..6905023 100644 --- a/lib/app_sources/apkmirror.dart +++ b/lib/app_sources/apkmirror.dart @@ -1,7 +1,9 @@ import 'dart:io'; +import 'package:easy_localization/easy_localization.dart'; import 'package:html/parser.dart'; import 'package:http/http.dart'; +import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -9,6 +11,23 @@ class APKMirror extends AppSource { APKMirror() { host = 'apkmirror.com'; enforceTrackOnly = true; + + additionalSourceAppSpecificSettingFormItems = [ + [ + GeneratedFormSwitch('fallbackToOlderReleases', + label: tr('fallbackToOlderReleases'), defaultValue: true) + ], + [ + GeneratedFormTextField('filterReleaseTitlesByRegEx', + label: tr('filterReleaseTitlesByRegEx'), + required: false, + additionalValidators: [ + (value) { + return regExValidator(value); + } + ]) + ] + ]; } @override @@ -30,11 +49,31 @@ class APKMirror extends AppSource { String standardUrl, Map additionalSettings, ) async { + bool fallbackToOlderReleases = + additionalSettings['fallbackToOlderReleases'] == true; + String? regexFilter = + (additionalSettings['filterReleaseTitlesByRegEx'] as String?) + ?.isNotEmpty == + true + ? additionalSettings['filterReleaseTitlesByRegEx'] + : null; Response res = await get(Uri.parse('$standardUrl/feed')); if (res.statusCode == 200) { - var item = parse(res.body).querySelector('item'); - String? titleString = item?.querySelector('title')?.innerHtml; - String? dateString = item + var items = parse(res.body).querySelectorAll('item'); + dynamic targetRelease; + for (int i = 0; i < items.length; i++) { + if (!fallbackToOlderReleases && i > 0) break; + String? nameToFilter = items[i].querySelector('title')?.innerHtml; + if (regexFilter != null && + nameToFilter != null && + !RegExp(regexFilter).hasMatch(nameToFilter.trim())) { + continue; + } + targetRelease = items[i]; + break; + } + String? titleString = targetRelease?.querySelector('title')?.innerHtml; + String? dateString = targetRelease ?.querySelector('pubDate') ?.innerHtml .split(' ') From a2879f5bfa548b80510dcdfa2d3bf5673111dfe4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 19 Feb 2023 18:48:21 -0500 Subject: [PATCH 055/600] Increment version, update package --- lib/main.dart | 2 +- pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index ff32826..bd13b3e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.0'; +const String currentVersion = '0.11.1'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index cab96e0..5434aa0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -830,10 +830,10 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: f7ec234830f86d0ef2bd664e8460b0038b8c1a83ff076035cad74ac70273753c + sha256: dad1f2caa3272071275436984eb123276a6810dbe7cd6f4c60697640b56a4699 url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.0.4" webview_flutter_android: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index bdceeff..019ad6e 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.11.0+119 # When changing this, update the tag in main() accordingly +version: 0.11.1+120 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From b82d28f2a77bd0e9c6acd34b91914ef4ef6e5163 Mon Sep 17 00:00:00 2001 From: Markus <82206269+markus-gitdev@users.noreply.github.com> Date: Tue, 21 Feb 2023 16:02:32 +0100 Subject: [PATCH 056/600] Update de.json Update German translation. --- assets/translations/de.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 3aa50e4..88f9bb8 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -207,16 +207,16 @@ "addCategory": "Kategorie hinzufügen", "label": "Bezeichnung", "language": "Sprache", - "storagePermissionDenied": "Storage permission denied", - "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", - "filterAPKsByRegEx": "Filter APKs by Regular Expression", - "removeFromObtainium": "Remove from Obtainium", - "uninstallFromDevice": "Uninstall from Device", - "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", - "useReleaseDateAsVersion": "Use Release Date as Version", - "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", - "changes": "Changes", - "releaseDate": "Release Date", + "storagePermissionDenied": "Speicherberechtigung verweigert", + "selectedCategorizeWarning": "Dadurch werden alle bestehenden Kategorieeinstellungen für die ausgewählten Apps ersetzt.", + "filterAPKsByRegEx": "APKs mit regulärem Ausdruck (RegEx) filtern", + "removeFromObtainium": "Aus Obtainium entfernen", + "uninstallFromDevice": "Vom Gerät deinstallieren", + "onlyWorksWithNonVersionDetectApps": "Funktioniert nur bei Apps mit deaktivierter Versionserkennung.", + "useReleaseDateAsVersion": "Veröffentlichungsdatum als Version verwenden", + "releaseDateAsVersionExplanation": "Diese Option sollte nur für Apps verwendet werden, bei denen die Versionserkennung nicht korrekt funktioniert, aber ein Veröffentlichungsdatum verfügbar ist.", + "changes": "Änderungen", + "releaseDate": "Veröffentlichungsdatum", "removeAppQuestion": { "one": "App entfernen?", "other": "App entfernen?" From 2e159c9886cea0573e018eaf10820104fd6042da Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 23 Feb 2023 16:20:03 -0500 Subject: [PATCH 057/600] Bugfix --- lib/providers/source_provider.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 357081a..2076600 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -367,7 +367,8 @@ class SourceProvider { (standardUrl + additionalSettings.toString()).hashCode.toString(); bool isTempId(App app) { - return app.id == generateTempID(app.url, app.additionalSettings); + // return app.id == generateTempID(app.url, app.additionalSettings); + return RegExp('^[0-9]+\$').hasMatch(app.id); } Future getApp( From 508fcccec90b8e089dbc6fbb00356651c4a40e1e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 23 Feb 2023 18:31:08 -0500 Subject: [PATCH 058/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 112 +++++++++++++++++++++++++------------------------- pubspec.yaml | 2 +- 3 files changed, 58 insertions(+), 58 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index bd13b3e..8d398da 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.1'; +const String currentVersion = '0.11.2'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 5434aa0..863f011 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -279,10 +279,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "60fc7b78455b94e6de2333d2f95196d32cf5c22f4b0b0520a628804cb463503b" + sha256: "4bef634684b2c7f3468c77c766c831229af829a0cd2d4ee6c1b99558bd14e5d2" url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "2.0.8" flutter_test: dependency: "direct dev" description: flutter @@ -297,10 +297,10 @@ packages: dependency: "direct main" description: name: fluttertoast - sha256: "774fa28b07f3a82c93596bc137be33189fec578ed3447a93a5a11c93435de394" + sha256: "2f9c4d3f4836421f7067a28f8939814597b27614e021da9d63e5d3fb6e212d25" url: "https://pub.dev" source: hosted - version: "8.1.3" + version: "8.2.1" html: dependency: "direct main" description: @@ -449,50 +449,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + sha256: "04890b994ee89bfa80bf3080bfec40d5a92c5c7a785ebb02c13084a099d2b6f9" url: "https://pub.dev" source: hosted - version: "2.0.12" + version: "2.0.13" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + sha256: "7623b7d4be0f0f7d9a8b5ee6879fc13e4522d4c875ab86801dee4af32b54b83e" url: "https://pub.dev" source: hosted - version: "2.0.22" + version: "2.0.23" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + sha256: eec003594f19fe2456ea965ae36b3fc967bc5005f508890aafe31fa75e41d972 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: "2e32f1640f07caef0d3cb993680f181c79e54a3827b997d5ee221490d131fbd9" + sha256: "525ad5e07622d19447ad740b1ed5070031f7a5437f44355ae915ff56e986429a" url: "https://pub.dev" source: hosted - version: "2.1.8" + version: "2.1.9" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.0.6" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + sha256: "642ddf65fde5404f83267e8459ddb4556316d3ee6d511ed193357e25caa3632d" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" permission_handler: dependency: "direct main" description: @@ -553,10 +553,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" pointycastle: dependency: transitive description: @@ -601,58 +601,58 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "5949029e70abe87f75cfe59d17bf5c397619c4b74a099b10116baeb34786fad9" + sha256: ee6257848f822b8481691f20c3e6d2bfee2e9eccb2a3d249907fcfb198c55b41 url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.0.18" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "955e9736a12ba776bdd261cf030232b30eadfcd9c79b32a3250dd4a494e8c8f7" + sha256: a51a4f9375097f94df1c6e0a49c0374440d31ab026b59d58a7e7660675879db4 url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.0.16" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "2b55c18636a4edc529fa5cd44c03d3f3100c00513f518c5127c951978efcccd0" + sha256: "6b84fdf06b32bb336f972d373cd38b63734f3461ba56ac2ba01b56d052796259" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: f8ea038aa6da37090093974ebdcf4397010605fd2ff65c37a66f9d28394cb874 + sha256: d7fb71e6e20cd3dfffcc823a28da3539b392e53ed5fc5c2b90b55fdaa8a7e8fa url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: da9431745ede5ece47bc26d5d73a9d3c6936ef6945c101a5aca46f62e52c1cf3 + sha256: "824bfd02713e37603b2bdade0842e47d56e7db32b1dcdd1cae533fb88e2913fc" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: a4b5bc37fe1b368bbc81f953197d55e12f49d0296e7e412dfe2d2d77d6929958 + sha256: "6737b757e49ba93de2a233df229d0b6a87728cea1684da828cbc718b65dcf9d7" url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.0.5" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "5eaf05ae77658d3521d0e993ede1af962d4b326cd2153d312df716dc250f00c9" + sha256: bd014168e8484837c39ef21065b78f305810ceabc1d4f90be6e3b392ce81b46d url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" sky_engine: dependency: transitive description: flutter @@ -750,66 +750,66 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: e8f2efc804810c0f2f5b485f49e7942179f56eabcfe81dce3387fec4bb55876b + sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" url: "https://pub.dev" source: hosted - version: "6.1.9" + version: "6.1.10" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "3e2f6dfd2c7d9cd123296cab8ef66cfc2c1a13f5845f42c7a0f365690a8a7dd1" + sha256: "1f4d9ebe86f333c15d318f81dcdc08b01d45da44af74552608455ebdc08d9732" url: "https://pub.dev" source: hosted - version: "6.0.23" + version: "6.0.24" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "0a5af0aefdd8cf820dd739886efb1637f1f24489900204f50984634c07a54815" + sha256: c9cd648d2f7ab56968e049d4e9116f96a85517f1dd806b96a86ea1018a3a82e5 url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.1.1" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "318c42cba924e18180c029be69caf0a1a710191b9ec49bb42b5998fdcccee3cc" + sha256: e29039160ab3730e42f3d811dc2a6d5f2864b90a70fb765ea60144b03307f682 url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "41988b55570df53b3dd2a7fc90c76756a963de6a8c5f8e113330cb35992e2094" + sha256: "2dddb3291a57b074dade66b5e07e64401dd2487caefd4e9e2f467138d8c7eb06" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6" + sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "44d79408ce9f07052095ef1f9a693c258d6373dc3944249374e30eff7219ccb0" + sha256: "574cfbe2390666003c3a1d129bdc4574aaa6728f0c00a4829a81c316de69dd9b" url: "https://pub.dev" source: hosted - version: "2.0.14" + version: "2.0.15" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: b6217370f8eb1fd85c8890c539f5a639a01ab209a36db82c921ebeacefc7a615 + sha256: "97c9067950a0d09cbd93e2e3f0383d1403989362b97102fbf446473a48079a4b" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" uuid: dependency: transitive description: @@ -830,34 +830,34 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: dad1f2caa3272071275436984eb123276a6810dbe7cd6f4c60697640b56a4699 + sha256: "9ba213434f13e760ea0f175fbc4d6bb6aeafd7dfc6c7d973f15d3e47a5d6686e" url: "https://pub.dev" source: hosted - version: "4.0.4" + version: "4.0.5" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: da98c8cdaebea4cf89481853f37ca93ccc8d31fc386f5b3c928aea3b6e83268c + sha256: "48c8cfb023168473c0a3a4c21ffea6c23a32cc7156701c39f618b303c6a3c96e" url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "3.3.1" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "8b2262dda5d26eabc600a7282a8c16a9473a0c765526afb0ffc33eef912f7968" + sha256: df6472164b3f4eaf3280422227f361dc8424b106726b7f21d79a8656ba53f71f url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - sha256: dcd9ad0ef0f608f399d7a54d0b289597385e59a89f04983a672b9348faddfd98 + sha256: "283a38c2a2544768033864c698e0133aa9eee0f2c800f494b538a3d1044f7ecb" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 019ad6e..946f921 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.11.1+120 # When changing this, update the tag in main() accordingly +version: 0.11.2+121 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From d6dcac0f970f9e5e7ef3e1d45cd11f170a01adaa Mon Sep 17 00:00:00 2001 From: Markus <82206269+markus-gitdev@users.noreply.github.com> Date: Fri, 24 Feb 2023 10:00:15 +0100 Subject: [PATCH 059/600] Update de.json Improve readability. --- assets/translations/de.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 88f9bb8..be299b2 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -209,11 +209,11 @@ "language": "Sprache", "storagePermissionDenied": "Speicherberechtigung verweigert", "selectedCategorizeWarning": "Dadurch werden alle bestehenden Kategorieeinstellungen für die ausgewählten Apps ersetzt.", - "filterAPKsByRegEx": "APKs mit regulärem Ausdruck (RegEx) filtern", + "filterAPKsByRegEx": "APKs nach regulärem Ausdruck filtern", "removeFromObtainium": "Aus Obtainium entfernen", "uninstallFromDevice": "Vom Gerät deinstallieren", "onlyWorksWithNonVersionDetectApps": "Funktioniert nur bei Apps mit deaktivierter Versionserkennung.", - "useReleaseDateAsVersion": "Veröffentlichungsdatum als Version verwenden", + "useReleaseDateAsVersion": "Veröffentlichungsdatum als Version\n verwenden", "releaseDateAsVersionExplanation": "Diese Option sollte nur für Apps verwendet werden, bei denen die Versionserkennung nicht korrekt funktioniert, aber ein Veröffentlichungsdatum verfügbar ist.", "changes": "Änderungen", "releaseDate": "Veröffentlichungsdatum", From 728dafcc280dabc348b1d6208dba3e8b95cb90c2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 24 Feb 2023 21:54:27 -0500 Subject: [PATCH 060/600] Added "URLs in file (like OPML)" import --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/fa.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/zh.json | 1 + lib/pages/import_export.dart | 198 +++++++++++++++++++++-------------- 8 files changed, 124 insertions(+), 81 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 88f9bb8..c88c168 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -217,6 +217,7 @@ "releaseDateAsVersionExplanation": "Diese Option sollte nur für Apps verwendet werden, bei denen die Versionserkennung nicht korrekt funktioniert, aber ein Veröffentlichungsdatum verfügbar ist.", "changes": "Änderungen", "releaseDate": "Veröffentlichungsdatum", + "importFromURLsInFile": "Import from URLs in File (like OPML)", "removeAppQuestion": { "one": "App entfernen?", "other": "App entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index c6c91bd..c271c8f 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -217,6 +217,7 @@ "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", "releaseDate": "Release Date", + "importFromURLsInFile": "Import from URLs in File (like OPML)", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 999162b..452eedf 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -217,6 +217,7 @@ "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", "releaseDate": "Release Date", + "importFromURLsInFile": "Import from URLs in File (like OPML)", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index c5745bf..95dacf0 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -216,6 +216,7 @@ "releaseDateAsVersionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzió érzékelése nem működik megfelelően, de elérhető a kiadás dátuma.", "changes": "Változtatások", "releaseDate": "Kiadás dátuma", + "importFromURLsInFile": "Import from URLs in File (like OPML)", "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 7cc3307..ba3c839 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -217,6 +217,7 @@ "releaseDateAsVersionExplanation": "Questa opzione dovrebbe essere usata solo per le App in cui il rilevamento della versione non funziona correttamente, ma è disponibile una data di rilascio.", "changes": "Novità", "releaseDate": "Data di rilascio", + "importFromURLsInFile": "Import from URLs in File (like OPML)", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 3eb133d..807ea30 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -217,6 +217,7 @@ "releaseDateAsVersionExplanation": "このオプションは、バージョン検出が正しく機能しないアプリで、リリース日が利用可能な場合にのみ使用する必要があります。", "changes": "変更点", "releaseDate": "リリース日", + "importFromURLsInFile": "Import from URLs in File (like OPML)", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 001a3ef..f16798d 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -217,6 +217,7 @@ "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", "releaseDate": "Release Date", + "importFromURLsInFile": "Import from URLs in File (like OPML)", "removeAppQuestion": { "one": "删除应用?", "other": "删除应用?" diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index df29739..71ec42c 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -41,6 +41,66 @@ class _ImportExportPageState extends State { ), ); + urlListImport({String? initValue, bool overrideInitValid = false}) { + showDialog?>( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + initValid: overrideInitValid, + title: tr('importFromURLList'), + items: [ + [ + GeneratedFormTextField('appURLList', + defaultValue: initValue ?? '', + label: tr('appURLList'), + max: 7, + additionalValidators: [ + (dynamic value) { + if (value != null && value.isNotEmpty) { + var lines = value.trim().split('\n'); + for (int i = 0; i < lines.length; i++) { + try { + sourceProvider.getSource(lines[i]); + } catch (e) { + return '${tr('line')} ${i + 1}: $e'; + } + } + } + return null; + } + ]) + ] + ], + ); + }).then((values) { + if (values != null) { + var urls = (values['appURLList'] as String).split('\n'); + setState(() { + importInProgress = true; + }); + appsProvider.addAppsByURL(urls).then((errors) { + if (errors.isEmpty) { + showError(tr('importedX', args: [plural('apps', urls.length)]), + context); + } else { + showDialog( + context: context, + builder: (BuildContext ctx) { + return ImportErrorDialog( + urlsLength: urls.length, errors: errors); + }); + } + }).catchError((e) { + showError(e, context); + }).whenComplete(() { + setState(() { + importInProgress = false; + }); + }); + } + }); + } + return Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, body: CustomScrollView(slivers: [ @@ -150,88 +210,60 @@ class _ImportExportPageState extends State { ], ) else - const Divider( - height: 32, - ), - TextButton( - onPressed: importInProgress - ? null - : () { - showDialog?>( - context: context, - builder: (BuildContext ctx) { - return GeneratedFormModal( - title: tr('importFromURLList'), - items: [ - [ - GeneratedFormTextField( - 'appURLList', - label: tr('appURLList'), - max: 7, - additionalValidators: [ - (dynamic value) { - if (value != null && - value.isNotEmpty) { - var lines = value - .trim() - .split('\n'); - for (int i = 0; - i < lines.length; - i++) { - try { - sourceProvider - .getSource( - lines[i]); - } catch (e) { - return '${tr('line')} ${i + 1}: $e'; - } - } - } - return null; - } - ]) - ] - ], - ); - }).then((values) { - if (values != null) { - var urls = - (values['appURLList'] as String) - .split('\n'); - setState(() { - importInProgress = true; - }); - appsProvider - .addAppsByURL(urls) - .then((errors) { - if (errors.isEmpty) { - showError( - tr('importedX', args: [ - plural('apps', urls.length) - ]), - context); - } else { - showDialog( - context: context, - builder: (BuildContext ctx) { - return ImportErrorDialog( - urlsLength: urls.length, - errors: errors); - }); - } - }).catchError((e) { - showError(e, context); - }).whenComplete(() { - setState(() { - importInProgress = false; + Column( + children: [ + const Divider( + height: 32, + ), + TextButton( + onPressed: importInProgress + ? null + : () { + urlListImport(); + }, + child: Text( + tr('importFromURLList'), + )), + const SizedBox(height: 8), + TextButton( + onPressed: importInProgress + ? null + : () { + FilePicker.platform + .pickFiles() + .then((result) { + if (result != null) { + urlListImport( + overrideInitValid: true, + initValue: + RegExp('https?://[^"]+') + .allMatches(File(result + .files + .single + .path!) + .readAsStringSync()) + .map((e) => + e.input.substring( + e.start, e.end)) + .toSet() + .toList() + .where((url) { + try { + sourceProvider + .getSource(url); + return true; + } catch (e) { + return false; + } + }).join('\n')); + } }); - }); - } - }); - }, - child: Text( - tr('importFromURLList'), - )), + }, + child: Text( + tr('importFromURLsInFile'), + )), + ], + ), ...sourceProvider.sources .where((element) => element.canSearch) .map((source) => Column( @@ -280,6 +312,7 @@ class _ImportExportPageState extends State { if (urlsWithDescriptions .isNotEmpty) { var selectedUrls = + // ignore: use_build_context_synchronously await showDialog< List< String>?>( @@ -314,6 +347,7 @@ class _ImportExportPageState extends State { ]), context); } else { + // ignore: use_build_context_synchronously showDialog( context: context, builder: @@ -391,6 +425,7 @@ class _ImportExportPageState extends State { e.toString()) .toList()); var selectedUrls = + // ignore: use_build_context_synchronously await showDialog< List?>( context: context, @@ -418,6 +453,7 @@ class _ImportExportPageState extends State { ]), context); } else { + // ignore: use_build_context_synchronously showDialog( context: context, builder: From a8a47bb153b820885cd0801a70acdec1b58e384d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 24 Feb 2023 22:48:30 -0500 Subject: [PATCH 061/600] Unified version detection setting --- assets/translations/de.json | 4 ++- assets/translations/en.json | 4 ++- assets/translations/fa.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 | 15 +++------- lib/pages/app.dart | 21 ++++++-------- lib/pages/apps.dart | 2 +- lib/providers/apps_provider.dart | 4 +-- lib/providers/source_provider.dart | 44 ++++++++++++++++++------------ 12 files changed, 62 insertions(+), 52 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index c88c168..780b5fa 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -213,11 +213,13 @@ "removeFromObtainium": "Aus Obtainium entfernen", "uninstallFromDevice": "Vom Gerät deinstallieren", "onlyWorksWithNonVersionDetectApps": "Funktioniert nur bei Apps mit deaktivierter Versionserkennung.", - "useReleaseDateAsVersion": "Veröffentlichungsdatum als Version verwenden", + "releaseDateAsVersion": "Veröffentlichungsdatum als Version verwenden", "releaseDateAsVersionExplanation": "Diese Option sollte nur für Apps verwendet werden, bei denen die Versionserkennung nicht korrekt funktioniert, aber ein Veröffentlichungsdatum verfügbar ist.", "changes": "Änderungen", "releaseDate": "Veröffentlichungsdatum", "importFromURLsInFile": "Import from URLs in File (like OPML)", + "versionDetection": "Version Detection", + "standardVersionDetection": "Standard version detection", "removeAppQuestion": { "one": "App entfernen?", "other": "App entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index c271c8f..a48c185 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -213,11 +213,13 @@ "removeFromObtainium": "Remove from Obtainium", "uninstallFromDevice": "Uninstall from Device", "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", - "useReleaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", "releaseDate": "Release Date", "importFromURLsInFile": "Import from URLs in File (like OPML)", + "versionDetection": "Version Detection", + "standardVersionDetection": "Standard version detection", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 452eedf..1371e88 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -213,11 +213,13 @@ "removeFromObtainium": "از Obtainium حذف کنید", "uninstallFromDevice": "حذف نصب از دستگاه", "onlyWorksWithNonVersionDetectApps": "فقط برای برنامه‌هایی کار می‌کند که تشخیص نسخه غیرفعال است.", - "useReleaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", "releaseDate": "Release Date", "importFromURLsInFile": "Import from URLs in File (like OPML)", + "versionDetection": "Version Detection", + "standardVersionDetection": "Standard version detection", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 95dacf0..6427f71 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -212,11 +212,13 @@ "removeFromObtainium": "Eltávolítás az Obtainiumból", "uninstallFromDevice": "Eltávolítás a készülékről", "onlyWorksWithNonVersionDetectApps": "Csak azoknál az alkalmazásoknál működik, amelyeknél a verzióérzékelés le van tiltva.", - "useReleaseDateAsVersion": "Használja a Kiadás dátumát, mint verziót", + "releaseDateAsVersion": "Használja a Kiadás dátumát, mint verziót", "releaseDateAsVersionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzió érzékelése nem működik megfelelően, de elérhető a kiadás dátuma.", "changes": "Változtatások", "releaseDate": "Kiadás dátuma", "importFromURLsInFile": "Import from URLs in File (like OPML)", + "versionDetection": "Version Detection", + "standardVersionDetection": "Standard version detection", "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 ba3c839..120096e 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -213,11 +213,13 @@ "removeFromObtainium": "Rimuovi da Obtainium", "uninstallFromDevice": "Disinstalla dal dispositivo", "onlyWorksWithNonVersionDetectApps": "Funziona solo per le App con il rilevamento della versione disattivato.", - "useReleaseDateAsVersion": "Usa data di rilascio come versione", + "releaseDateAsVersion": "Usa data di rilascio come versione", "releaseDateAsVersionExplanation": "Questa opzione dovrebbe essere usata solo per le App in cui il rilevamento della versione non funziona correttamente, ma è disponibile una data di rilascio.", "changes": "Novità", "releaseDate": "Data di rilascio", "importFromURLsInFile": "Import from URLs in File (like OPML)", + "versionDetection": "Version Detection", + "standardVersionDetection": "Standard version detection", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 807ea30..276abc1 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -213,11 +213,13 @@ "removeFromObtainium": "Obtainiumから削除する", "uninstallFromDevice": "デバイスからアンインストールする", "onlyWorksWithNonVersionDetectApps": "バージョン検出を無効にしているアプリにのみ動作します。", - "useReleaseDateAsVersion": "リリース日をバージョンとして使用する", + "releaseDateAsVersion": "リリース日をバージョンとして使用する", "releaseDateAsVersionExplanation": "このオプションは、バージョン検出が正しく機能しないアプリで、リリース日が利用可能な場合にのみ使用する必要があります。", "changes": "変更点", "releaseDate": "リリース日", "importFromURLsInFile": "Import from URLs in File (like OPML)", + "versionDetection": "Version Detection", + "standardVersionDetection": "Standard version detection", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index f16798d..4f892ae 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -213,11 +213,13 @@ "filterAPKsByRegEx": "Filter APKs by Regular Expression", "removeFromObtainium": "Remove from Obtainium", "uninstallFromDevice": "Uninstall from Device", - "useReleaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Changes", "releaseDate": "Release Date", "importFromURLsInFile": "Import from URLs in File (like OPML)", + "versionDetection": "Version Detection", + "standardVersionDetection": "Standard version detection", "removeAppQuestion": { "one": "删除应用?", "other": "删除应用?" diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 0208c9e..f68ae3c 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -71,10 +71,6 @@ class _AddAppPageState extends State { var settingsProvider = context.read(); () async { var userPickedTrackOnly = additionalSettings['trackOnly'] == true; - var userPickedNoVersionDetection = - additionalSettings['noVersionDetection'] == true; - var userPickedReleaseDateAsVersion = - additionalSettings['releaseDateAsVersion'] == true; var cont = true; if ((userPickedTrackOnly || pickedSource!.enforceTrackOnly) && // ignore: use_build_context_synchronously @@ -95,13 +91,13 @@ class _AddAppPageState extends State { null) { cont = false; } - if (userPickedReleaseDateAsVersion && // ignore: use_build_context_synchronously + if (additionalSettings['versionDetection'] == 'releaseDateAsVersion' && // ignore: use_build_context_synchronously await showDialog( context: context, builder: (BuildContext ctx) { return GeneratedFormModal( - title: tr('useReleaseDateAsVersion'), + title: tr('releaseDateAsVersion'), items: const [], message: tr('releaseDateAsVersionExplanation'), ); @@ -109,8 +105,7 @@ class _AddAppPageState extends State { null) { cont = false; } - if (!userPickedReleaseDateAsVersion && - userPickedNoVersionDetection && + if (additionalSettings['versionDetection'] == 'noVersionDetection' && // ignore: use_build_context_synchronously await showDialog( context: context, @@ -129,9 +124,7 @@ class _AddAppPageState extends State { var trackOnly = pickedSource!.enforceTrackOnly || userPickedTrackOnly; App app = await sourceProvider.getApp( pickedSource!, userInput, additionalSettings, - trackOnlyOverride: trackOnly, - noVersionDetectionOverride: userPickedNoVersionDetection, - releaseDateAsVersionOverride: userPickedReleaseDateAsVersion); + trackOnlyOverride: trackOnly); if (!trackOnly) { await settingsProvider.getInstallPermission(); } diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 0cf9405..4a73b72 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -42,8 +42,6 @@ class _AppPageState extends State { getUpdate(app.app.id); } var trackOnly = app?.app.additionalSettings['trackOnly'] == true; - var noVersionDetection = - app?.app.additionalSettings['noVersionDetection'] == true; var infoColumn = Column( mainAxisAlignment: MainAxisAlignment.center, @@ -207,7 +205,8 @@ class _AppPageState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - if (noVersionDetection && + if (app?.app.additionalSettings['versionDetection'] != + 'standardVersionDetection' && !trackOnly && app?.app.installedVersion != null && app?.app.installedVersion != app?.app.latestVersion) @@ -295,13 +294,11 @@ class _AppPageState extends State { context); } if (app.app.additionalSettings[ - 'releaseDateAsVersion'] == - true) { - app.app.additionalSettings[ - 'noVersionDetection'] = true; + 'versionDetection'] == + 'releaseDateAsVersion') { if (originalSettings[ - 'releaseDateAsVersion'] != - true) { + 'versionDetection'] != + 'releaseDateAsVersion') { if (app.app.releaseDate != null) { bool isUpdated = app.app.installedVersion == @@ -318,10 +315,8 @@ class _AppPageState extends State { } } } else if (originalSettings[ - 'releaseDateAsVersion'] == - true) { - app.app.additionalSettings[ - 'noVersionDetection'] = false; + 'versionDetection'] == + 'releaseDateAsVersion') { app.app.installedVersion = app .installedInfo ?.versionName ?? diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index e733439..8d4f51d 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -704,7 +704,7 @@ class AppsPageState extends State { onPressed: () { HapticFeedback.selectionClick(); appsProvider.saveApps(selectedApps.map((a) { - if (a.installedVersion != null && a.additionalSettings['noVersionDetection'] == true) { + if (a.installedVersion != null && a.additionalSettings['versionDetection'] != 'standardVersionDetection') { a.installedVersion = a.latestVersion; } return a; diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index f24cc98..b436358 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -467,8 +467,8 @@ class AppsProvider with ChangeNotifier { App? getCorrectedInstallStatusAppIfPossible(App app, AppInfo? installedInfo) { var modded = false; var trackOnly = app.additionalSettings['trackOnly'] == true; - var noVersionDetection = - app.additionalSettings['noVersionDetection'] == true; + var noVersionDetection = app.additionalSettings['versionDetection'] != + 'standardVersionDetection'; if (installedInfo == null && app.installedVersion != null && !trackOnly) { app.installedVersion = null; modded = true; diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 2076600..8cead1e 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -100,6 +100,20 @@ class App { additionalSettings['noVersionDetection'] = json['noVersionDetection'] == 'true' || json['trackOnly'] == true; } + // Convert bool style version detection options to dropdown style + if (additionalSettings['noVersionDetection'] == true) { + additionalSettings['versionDetection'] = 'noVersionDetection'; + } + if (additionalSettings['releaseDateAsVersion'] == true) { + additionalSettings['versionDetection'] = 'releaseDateAsVersion'; + additionalSettings.remove('releaseDateAsVersion'); + } + if (additionalSettings['noVersionDetection'] != null) { + additionalSettings.remove('noVersionDetection'); + } + if (additionalSettings['releaseDateAsVersion'] != null) { + additionalSettings.remove('releaseDateAsVersion'); + } // Ensure additionalSettings are correctly typed for (var item in formItems) { if (additionalSettings[item.key] != null) { @@ -234,11 +248,16 @@ class AppSource { ) ], [ - GeneratedFormSwitch('releaseDateAsVersion', - label: tr('useReleaseDateAsVersion')) - ], - [ - GeneratedFormSwitch('noVersionDetection', label: tr('noVersionDetection')) + GeneratedFormDropdown( + 'versionDetection', + [ + MapEntry( + 'standardVersionDetection', tr('standardVersionDetection')), + MapEntry('releaseDateAsVersion', tr('releaseDateAsVersion')), + MapEntry('noVersionDetection', tr('noVersionDetection')) + ], + label: tr('versionDetection'), + defaultValue: 'standardVersionDetection') ], [ GeneratedFormTextField('apkFilterRegEx', @@ -373,26 +392,15 @@ class SourceProvider { Future getApp( AppSource source, String url, Map additionalSettings, - {App? currentApp, - bool trackOnlyOverride = false, - bool noVersionDetectionOverride = false, - bool releaseDateAsVersionOverride = false}) async { + {App? currentApp, bool trackOnlyOverride = false}) async { if (trackOnlyOverride || source.enforceTrackOnly) { additionalSettings['trackOnly'] = true; } - if (releaseDateAsVersionOverride) { - additionalSettings['releaseDateAsVersion'] = true; - noVersionDetectionOverride = - true; // Rel. date as version means no ver. det. - } - if (noVersionDetectionOverride) { - additionalSettings['noVersionDetection'] = true; - } var trackOnly = additionalSettings['trackOnly'] == true; String standardUrl = source.standardizeURL(preStandardizeUrl(url)); APKDetails apk = await source.getLatestAPKDetails(standardUrl, additionalSettings); - if (additionalSettings['releaseDateAsVersion'] == true && + if (additionalSettings['versionDetection'] == 'releaseDateAsVersion' && apk.releaseDate != null) { apk.version = apk.releaseDate!.microsecondsSinceEpoch.toString(); } From 8e52f9666d7781dada170a693fff2ef9850802fa Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 24 Feb 2023 22:58:56 -0500 Subject: [PATCH 062/600] UI Bugfix --- lib/pages/settings.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index e2ba218..3caf161 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -87,6 +87,7 @@ class _SettingsPageState extends State { }); var sortDropdown = DropdownButtonFormField( + isExpanded: true, decoration: InputDecoration(labelText: tr('appSortBy')), value: settingsProvider.sortColumn, items: [ @@ -114,6 +115,7 @@ class _SettingsPageState extends State { }); var orderDropdown = DropdownButtonFormField( + isExpanded: true, decoration: InputDecoration(labelText: tr('appSortOrder')), value: settingsProvider.sortOrder, items: [ From f10bb5ac91e171ac84de97f3e78d17a9d7acf63f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 24 Feb 2023 23:02:32 -0500 Subject: [PATCH 063/600] Increment version, upgrade packages --- lib/main.dart | 2 +- pubspec.lock | 8 ++++---- pubspec.yaml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8d398da..9a265f9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.2'; +const String currentVersion = '0.11.3'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 863f011..64df9f3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -234,10 +234,10 @@ packages: dependency: "direct dev" description: name: flutter_launcher_icons - sha256: ce0e501cfc258907842238e4ca605e74b7fd1cdf04b3b43e86c43f3e40a1592c + sha256: "02dcaf49d405f652b7160e882bacfc02cb497041bb2eab2a49b1c393cf9aac12" url: "https://pub.dev" source: hosted - version: "0.11.0" + version: "0.12.0" flutter_lints: dependency: "direct dev" description: @@ -329,10 +329,10 @@ packages: dependency: transitive description: name: image - sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6" + sha256: "483a389d6ccb292b570c31b3a193779b1b0178e7eb571986d9a49904b6861227" url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "4.0.15" install_plugin_v2: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 946f921..7848390 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.11.2+121 # When changing this, update the tag in main() accordingly +version: 0.11.3+122 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' @@ -64,7 +64,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_launcher_icons: ^0.11.0 + flutter_launcher_icons: ^0.12.0 # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is From 926e7b89ce698541aa73954aa5f1ae1ff2d2debf Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Sat, 25 Feb 2023 13:57:07 +0900 Subject: [PATCH 064/600] Update Japanese translation --- assets/translations/ja.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 276abc1..58ba851 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -107,7 +107,7 @@ "line": "行", "searchX": "{}で検索", "noResults": "結果は見つかりませんでした", - "importX": "{}をインポートする", + "importX": "{}をインポート", "importedAppsIdDisclaimer": "インポートしたアプリが「未インストール」と表示されることがあります。\nこれを解決するには、Obtainiumから再インストールしてください。\nアプリのデータには影響しません。\n\nURLとサードパーティのインポートメソッドにのみ影響します。", "importErrors": "インポートエラー", "importedXOfYApps": "{} / {} アプリをインポートしました", @@ -217,9 +217,9 @@ "releaseDateAsVersionExplanation": "このオプションは、バージョン検出が正しく機能しないアプリで、リリース日が利用可能な場合にのみ使用する必要があります。", "changes": "変更点", "releaseDate": "リリース日", - "importFromURLsInFile": "Import from URLs in File (like OPML)", - "versionDetection": "Version Detection", - "standardVersionDetection": "Standard version detection", + "importFromURLsInFile": "ファイル(OPMLなど)内のURLからインポート", + "versionDetection": "バージョン検出", + "standardVersionDetection": "標準のバージョン検出", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" From 7b1416e28e6bbcbf360ab7d207bcb3a092cb2302 Mon Sep 17 00:00:00 2001 From: gidano Date: Sat, 25 Feb 2023 11:17:17 +0100 Subject: [PATCH 065/600] Update hu.json --- assets/translations/hu.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 6427f71..c157ef7 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -56,7 +56,7 @@ "appsString": "Appok", "noApps": "Nincs App", "noAppsForFilter": "Nincsenek appok a szűrőhöz", - "byX": "{} által", + "byX": "Fejlesztő: {}", "percentProgress": "Folyamat: {}%", "pleaseWait": "Kis türelmet", "updateAvailable": "Frissítés érhető el", @@ -191,7 +191,7 @@ "update": "Frissít", "markUpdated": "Frissítettnek jelöl", "additionalOptions": "További lehetőségek", - "disableVersionDetection": "Verzióérzékelés letiltása", + "disableVersionDetection": "Verzió érzékelés letiltása", "noVersionDetectionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzióérzékelés nem működik megfelelően.", "downloadingX": "{} letöltés", "downloadNotifDescription": "Értesíti a felhasználót az app letöltésének előrehaladásáról", @@ -216,9 +216,9 @@ "releaseDateAsVersionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzió érzékelése nem működik megfelelően, de elérhető a kiadás dátuma.", "changes": "Változtatások", "releaseDate": "Kiadás dátuma", - "importFromURLsInFile": "Import from URLs in File (like OPML)", - "versionDetection": "Version Detection", - "standardVersionDetection": "Standard version detection", + "importFromURLsInFile": "Importálás fájlban található URL-ből (mint pl. OPML)", + "versionDetection": "Verzió érzékelés", + "standardVersionDetection": "Alapért. verzió érzékelés", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From 54d8dff32fed86a10aad5735e499ea24dc6d5da4 Mon Sep 17 00:00:00 2001 From: Mehdee <85278288+mehdijahann@users.noreply.github.com> Date: Sat, 25 Feb 2023 20:52:22 +0330 Subject: [PATCH 066/600] Update fa.json --- assets/translations/fa.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 1371e88..eb16617 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -213,13 +213,13 @@ "removeFromObtainium": "از Obtainium حذف کنید", "uninstallFromDevice": "حذف نصب از دستگاه", "onlyWorksWithNonVersionDetectApps": "فقط برای برنامه‌هایی کار می‌کند که تشخیص نسخه غیرفعال است.", - "releaseDateAsVersion": "Use Release Date as Version", - "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", - "changes": "Changes", - "releaseDate": "Release Date", - "importFromURLsInFile": "Import from URLs in File (like OPML)", - "versionDetection": "Version Detection", - "standardVersionDetection": "Standard version detection", + "releaseDateAsVersion": "از تاریخ انتشار به عنوان نسخه استفاده کنید", + "releaseDateAsVersionExplanation": "این گزینه فقط باید برای برنامه هایی استفاده شود که تشخیص نسخه به درستی کار نمی کند، اما تاریخ انتشار در دسترس است.", + "changes": "تغییرات", + "releaseDate": "تاریخ انتشار", + "importFromURLsInFile": "وارد کردن از آدرس های اینترنتی موجود در فایل (مانند OPML)", + "versionDetection": "تشخیص نسخه", + "standardVersionDetection": "تشخیص نسخه استاندارد", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" From e67a6b8627560fb36c5adeb0e9a7f26ef88a3a8e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 25 Feb 2023 15:57:04 -0500 Subject: [PATCH 067/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 9a265f9..477d983 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.3'; +const String currentVersion = '0.11.4'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 7848390..7363fb8 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.11.3+122 # When changing this, update the tag in main() accordingly +version: 0.11.4+123 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From ce526d8d2682ca6cbb4d7c483aa06e483f1a60ec Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 27 Feb 2023 19:00:50 -0500 Subject: [PATCH 068/600] Language bugfix + package upgrades + incr. ver. --- lib/main.dart | 10 +++++++++- lib/pages/settings.dart | 2 +- lib/providers/settings_provider.dart | 11 +++++++++++ pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 477d983..e992e75 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.4'; +const String currentVersion = '0.11.5'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES @@ -211,6 +211,14 @@ class _ObtainiumState extends State { false) ]); } + if (!supportedLocales + .map((e) => e.languageCode) + .contains(context.locale.languageCode) || + settingsProvider.forcedLocale == null && + context.deviceLocale.languageCode != + context.locale.languageCode) { + settingsProvider.resetLocaleSafe(context); + } // Register the background update task according to the user's setting if (existingUpdateInterval != settingsProvider.updateInterval) { if (existingUpdateInterval != -1) { diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 3caf161..6e707e4 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -152,7 +152,7 @@ class _SettingsPageState extends State { if (value != null) { context.setLocale(Locale(value)); } else { - context.resetLocale(); + settingsProvider.resetLocaleSafe(context); } }); diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index ea6985a..a7c6bc1 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -178,4 +178,15 @@ class SettingsProvider with ChangeNotifier { bool setEqual(Set a, Set b) => a.length == b.length && a.union(b).length == a.length; + + void resetLocaleSafe(BuildContext context) { + if (context.supportedLocales + .map((e) => e.languageCode) + .contains(context.deviceLocale.languageCode)) { + context.resetLocale(); + } else { + context.setLocale(context.fallbackLocale!); + context.deleteSaveLocale(); + } + } } diff --git a/pubspec.lock b/pubspec.lock index 64df9f3..c8a940f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -670,10 +670,10 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "78324387dc81df14f78df06019175a86a2ee0437624166c382e145d0a7fd9a4f" + sha256: "851d5040552cf911f4cabda08d003eca76b27da3ed0002978272e27c8fbf8ecc" url: "https://pub.dev" source: hosted - version: "2.2.4+1" + version: "2.2.5" sqflite_common: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 7363fb8..86a1cd0 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.11.4+123 # When changing this, update the tag in main() accordingly +version: 0.11.5+124 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From b22e2bab0cd9d8ce40616027f15998bb15c3450e Mon Sep 17 00:00:00 2001 From: Markus <82206269+markus-gitdev@users.noreply.github.com> Date: Wed, 1 Mar 2023 08:20:04 +0100 Subject: [PATCH 069/600] Update de.json Updated the following strings to a German translation: - importFromURLsInFile - versionDetection - standardVersionDetection --- assets/translations/de.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 12f8410..90f4ca9 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -217,9 +217,9 @@ "releaseDateAsVersionExplanation": "Diese Option sollte nur für Apps verwendet werden, bei denen die Versionserkennung nicht korrekt funktioniert, aber ein Veröffentlichungsdatum verfügbar ist.", "changes": "Änderungen", "releaseDate": "Veröffentlichungsdatum", - "importFromURLsInFile": "Import from URLs in File (like OPML)", - "versionDetection": "Version Detection", - "standardVersionDetection": "Standard version detection", + "importFromURLsInFile": "Importieren von URLs aus Datei ( z.B. OPML)", + "versionDetection": "Versionserkennung", + "standardVersionDetection": "Standardversionserkennung", "removeAppQuestion": { "one": "App entfernen?", "other": "App entfernen?" From 8648c1bea7d9a09462aa73a8480925388240d20d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 1 Mar 2023 20:20:34 -0500 Subject: [PATCH 070/600] Added icon for non-installed Apps --- lib/pages/apps.dart | 17 ++++++++++++++++- pubspec.yaml | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 8d4f51d..aedbde9 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -264,7 +264,22 @@ class AppsPageState extends State { listedApps[index].installedInfo!.icon!, gaplessPlayback: true, ) - : null, + : Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Transform( + alignment: Alignment.center, + transform: Matrix4.rotationZ(0.31), + child: Image( + image: const AssetImage( + 'assets/graphics/icon.png'), + color: Colors.white.withOpacity(0.1), + colorBlendMode: BlendMode.modulate, + gaplessPlayback: true, + ), + ), + ]), title: Text( maxLines: 1, listedApps[index].installedInfo?.name ?? diff --git a/pubspec.yaml b/pubspec.yaml index 86a1cd0..b948450 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -97,6 +97,7 @@ flutter: assets: - assets/translations/ + - assets/graphics/ # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware From 2e88c8eede2db65eaa48b54fbda93fce416a8b97 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 1 Mar 2023 21:37:18 -0500 Subject: [PATCH 071/600] UI improvements Update button for individual apps on list is now an icon. Less clipping on small screens on apps list page. --- lib/pages/apps.dart | 161 +++++++++++++++++++++----------------------- 1 file changed, 78 insertions(+), 83 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index aedbde9..9fe11b8 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -233,6 +233,31 @@ class AppsPageState extends State { .getSource(listedApps[index].app.url) .changeLogPageFromStandardUrl(listedApps[index].app.url); var transparent = const Color.fromARGB(0, 0, 0, 0).value; + var hasUpdate = listedApps[index].app.installedVersion != null && + listedApps[index].app.installedVersion != + listedApps[index].app.latestVersion; + var updateButton = IconButton( + visualDensity: VisualDensity.compact, + color: Theme.of(context).colorScheme.primary, + tooltip: + listedApps[index].app.additionalSettings['trackOnly'] == + true + ? tr('markUpdated') + : tr('update'), + onPressed: appsProvider.areDownloadsRunning() + ? null + : () { + appsProvider.downloadAndInstallLatestApps([ + listedApps[index].app.id + ], globalNavigatorKey.currentContext).catchError((e) { + showError(e, context); + }); + }, + icon: Icon( + listedApps[index].app.additionalSettings['trackOnly'] == + true + ? Icons.check_circle_outline + : Icons.install_mobile)); return Container( decoration: BoxDecoration( border: Border.symmetric( @@ -293,21 +318,33 @@ class AppsPageState extends State { ), subtitle: Text( tr('byX', args: [listedApps[index].app.author]), + maxLines: 1, style: TextStyle( + overflow: TextOverflow.ellipsis, fontWeight: listedApps[index].app.pinned ? FontWeight.bold : FontWeight.normal)), - trailing: SingleChildScrollView( - reverse: true, - child: listedApps[index].downloadProgress != null - ? Text(tr('percentProgress', args: [ - listedApps[index] - .downloadProgress - ?.toInt() - .toString() ?? - '100' - ])) - : (Column( + trailing: listedApps[index].downloadProgress != null + ? Text(tr('percentProgress', args: [ + listedApps[index] + .downloadProgress + ?.toInt() + .toString() ?? + '100' + ])) + : (Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + hasUpdate + ? updateButton + : const SizedBox.shrink(), + hasUpdate + ? const SizedBox( + width: 10, + ) + : const SizedBox.shrink(), + Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ @@ -321,80 +358,38 @@ class AppsPageState extends State { '${listedApps[index].app.installedVersion ?? tr('notInstalled')}${listedApps[index].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}', overflow: TextOverflow.ellipsis, textAlign: TextAlign.end, - )) + )), ]), - GestureDetector( - onTap: changesUrl == null - ? null - : () { - launchUrlString(changesUrl, - mode: LaunchMode - .externalApplication); - }, - child: Text( - listedApps[index].app.releaseDate == - null - ? tr('changes') - : DateFormat('yyyy-MM-dd').format( - listedApps[index] - .app - .releaseDate!), - style: const TextStyle( - fontStyle: FontStyle.italic, - decoration: - TextDecoration.underline), - )), - listedApps[index].app.installedVersion != - null && - listedApps[index] - .app - .installedVersion != - listedApps[index] - .app - .latestVersion - ? appsProvider.areDownloadsRunning() - ? Text(tr('pleaseWait')) - : Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: - MainAxisAlignment.end, - children: [ - GestureDetector( - onTap: () { - appsProvider - .downloadAndInstallLatestApps( - [ - listedApps[index] - .app - .id - ], - globalNavigatorKey - .currentContext).catchError( - (e) { - showError(e, context); - }); - }, - child: Text( - listedApps[index] - .app - .additionalSettings[ - 'trackOnly'] == - true - ? tr('markUpdated') - : tr('update'), - style: TextStyle( - color: - Theme.of(context) - .colorScheme - .primary, - fontWeight: - FontWeight.bold), - )), - ], - ) - : const SizedBox.shrink(), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: changesUrl == null + ? null + : () { + launchUrlString(changesUrl, + mode: LaunchMode + .externalApplication); + }, + child: Text( + listedApps[index].app.releaseDate == + null + ? tr('changes') + : DateFormat('yyyy-MM-dd') + .format(listedApps[index] + .app + .releaseDate!), + style: const TextStyle( + fontStyle: FontStyle.italic, + decoration: + TextDecoration.underline), + )) + ], + ), ], - ))), + ) + ], + )), onTap: () { if (selectedApps.isNotEmpty) { toggleAppSelected(listedApps[index].app); From e49c09c0ff14525671facf87b7ba0de4e990d432 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 1 Mar 2023 21:55:04 -0500 Subject: [PATCH 072/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index e992e75..2d79ce8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.5'; +const String currentVersion = '0.11.6'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index b948450..ffbcd1d 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.11.5+124 # When changing this, update the tag in main() accordingly +version: 0.11.6+125 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 83b770294df9f9c1bdf6b60c228074ceec1cf98f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 3 Mar 2023 23:00:14 -0500 Subject: [PATCH 073/600] Icon improvements (#267, #345) --- .../drawable-hdpi/ic_launcher_foreground.png | Bin 4892 -> 0 bytes .../drawable-mdpi/ic_launcher_foreground.png | Bin 2822 -> 0 bytes .../drawable-xhdpi/ic_launcher_foreground.png | Bin 7897 -> 0 bytes .../ic_launcher_foreground.png | Bin 15415 -> 0 bytes .../ic_launcher_foreground.png | Bin 25506 -> 0 bytes .../res/drawable/ic_launcher_foreground.xml | 46 +++++++++ .../mipmap-anydpi-v26/ic_launcher_round.xml | 6 ++ .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 1741 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 1086 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 2484 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 4038 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 6300 -> 0 bytes .../app/src/main/res/values-night/colors.xml | 4 + assets/graphics/icon.png | Bin 111605 -> 0 bytes assets/graphics/icon.psd | Bin 1073805 -> 0 bytes assets/graphics/icon.svg | 78 +++++++++++++++ lib/main.dart | 2 +- pubspec.lock | 92 ++---------------- pubspec.yaml | 9 +- 19 files changed, 146 insertions(+), 91 deletions(-) delete mode 100644 android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png delete mode 100644 android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png delete mode 100644 android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png delete mode 100644 android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png delete mode 100644 android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png create mode 100644 android/app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml delete mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/values-night/colors.xml delete mode 100755 assets/graphics/icon.png delete mode 100755 assets/graphics/icon.psd create mode 100644 assets/graphics/icon.svg diff --git a/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png deleted file mode 100644 index f0c677aabcac783ffd8877d0a20774a08ada9f56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4892 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 VJh?uWWSLDcR0(Nb9Fl zS-ez8)tQ|p3sCUVz6hItBF7#{mF8kHcdeGI*jif?O5zU8z<#%cCXjAqn zDWXc;h{3WM&g+>JCrLFy0~Pr?{S+X^xxa<;MUlU|?Ebg^TzqTOl{d{i(f_II{pDpH z7+3a#nwFhnW6$QYCns)|R@_*@E0_l#fd`)r`Vd7Lw)vatdg^cq7At~|W`Y|V){6zH zA|d9|JUc53#W8D0U*A_6aZwBwbl;SeLdn4*Hyyt(*JJtQltNSNNU-8WkpnfgnyP6QH&nw&5&(r2I@zyQl%X+OWdV~&ZvNn zByrgBL!3kvou8;*^+pTDdRGl@Q;ZBJeB3V2aKEFq0E`57z-YzR@!vaLmBvc7|Cq70 zqxyzDE1lS5U9W3gUk>72OW4FfD!j zl&&x;5IqJh*HP^G1j zZT^|9$O?Uh#y9Vbz3=j_Ya+uY#~MhE8u|ZA*#7{Jdi__)N|;}cC^i#hNUl2Zx^5S6 zN=D-s&mFY;l;-e;pU-2dN`TRP{S_)&0LVRt-s^cwwXpr4*c)<9nmV!9}})Yr}8Pz@erg2WIl6MK=Msl~qo}S@VyfCsJCpKKEIq3x9=k%!Bb_YTENz;jBQf zlnPdRJXAZ1O@)#ahsqN_W`iFC-HQxj#K+VUQE7P~)MernXGff6z!j zfZ|5IW`PBMWtWG);VjUj8;ah7^N9k$>?(ydLE%w85@mgwsBoKfGkvNJxPJ9eXIsr* zPF3AWq=n*|o~)#6!{or1{wPn$oApnY1={h^@0CCmc{TYl%qgEKH7UA=2a=2945}NA z8C^r{SX6w2l(e#MG?KG?;Z!K~HDt$ff^Y;>c~b(>A|!4}MfB8jO2Y?ZM&a0NTNG|4 z?qOVsE<(H$dsHq=`eyOyLIUBs5Zan0x6_G(JU(zjD0vMs3O?K9PtjkzWisF~ObE;uIMWCt`2VNlQ% zUVCcbKF!GL{dP`;Bgd-@(cQ&l+9Gb);eXB?4EUqCOoabY_5Tk)|KITQ{)rgr^R1S} TrB4qd>qjaIn)21MmSO)3$0tjr diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index 748f473f73804411f4153af8954b1f35cf7d243a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15415 zcmeIZ^;4Vc_XSGjw6qOvfg(X0+$FeEg1fu4kl^l4ds>18hv0CK;8MInTQmeK?$F{+ zafh3JzW>F&_lHboGMU-$v){efT3en7O?3r==M>NJ@bCzf6lJyX@E*wi{op^r{bI4L z(1V93cBdr!PS^LrUe>crs9w;)a7BGtS#wcBK-Op{km)^p$y-5Fk zX25={z@xOL)#K}qy;9Nh`PzxhgWDWqXPEE?0QVqPY3f3_uY`wR@bT~-;uGTGJ$_Ax zhll?b_pGm_!}0Lmeti7^PZ|&O5bqFIGF+*eE$g5Bu&SFxCCnaREI*k^|m=hxb! zU>EutOI^_l!Am`4hKS)eUweb|@EPV88I#XxtHZDP>e!QPQNJ)vBR-Y+QDJA(RK$BLb(Xh&(&5kEJ(pf+T$4A4 zct*z7zEAf;NKU?Skah-LcNBd8hKxzu5JvXTCxB+A6dgDsiq1&6GG_IBZ*NBCqtFLy zCo1@|J*wP^$#D;B9B&QGFqwk>_oZ_<*IP6%=lzyaCPBu`s<`vkKRtaFi(nlX( zi>apmOijl?J4~*NzYk2k-f~Y>)?*A)5a0f`sa6&W+!M)GjEro~g)As=j-u(&HVBuU zHf#ToJNNeO)3UQ#d?0us_Wf${9EV&R&-`)eXQ}x>wLlQ2-bWQ-Szz{JV+9hndAWX+@AT}-?ut7FN8qL&85 z&FlZ6WI`+hWnI<#y(%spk&An6|+6Jt31S2UG>`>Zw8&0eH6_$IzyNd15& z@c!tyn939yhjc-3@`pAO zpX5u;-PBg<6tR8JJJ2b|A|!@8!Q)^N7D!=lCnLlN zoWhJ(*gu(H@KSr!lB3zR{NS7{=Il1OA>@uZ$cE<5)!B8Otma_*^CmAX#(CXm^+Dew z8CCqsaCIOC?b-0pwy}&t-%maDaQuwR&0dQyzT-B}sbOFLpdyP3BK$4yuT zid%5S4*Q&_HLN7vMp3`=M^@t#QO<7Wb0k7Ae)*tZP3esqXlr1`)OHP zvd*0P?e^{`oyt9lm0$M*73A%`tl~gWSYX*d46pEc3FB-d)q~j}R&;23aV>2{U6%7F zj1-xeOj*~ap_Rm3wCR}xM=v>R%8A)^`2t4s>>Vw4Eb zqElW!Ry%DLv#3+=-nkv$y|VGQY20p$@(=Vm!3QxBi-{JcK#N zNaLm_)mY|eQmmlzsFPle&&AE@vPh@-xF~}*%&z`YR?23x8LHT$fSO}|G5dtqdj#y6 zBzKm=d~L2D{HsO9oxQhBYua_wV{3WW3eg+HM7X4@MEBbA;m`QAY|l!}PewM131IK& z$+&Zg9Zw;p0`=rXa+y%Y1(&&}bc1~YXd3oFO?P@h&NRqCL;UUPIyj~Ut z9n}UIYGsS}AYP`4Wra^Nj{H;$(}3${!M2TuW`i`V%XMS^r&q z0Al(m4P_>>qL-Fus)cCt=h-vU@rQQI%)4%9_L-&iD&xQ*OfxTNACq`XuKhGgFJE<~GOR{FrLbuQu4Y&4dDl zAZm@sQDm+pE6>U#BV>YW_K5+sc&~f~!UmZ^$}0=hS_a>*@2KP#nQ93;%?Xt3Zz+Jf zRv&_x@LE;tANQO<0r;b=qJ=*2_39%b*_Gq*iT6Y{F%;@s2%oZjtEcPW_g;S z5Z6B~qXd_qw%de3vrF1`^W2r33!O$5oer!MlB6JrU%%0X1DwAU28z#}?dz-lfr%sh z1jlMlmCw?$LA3o~l^46%$t8cDX3LA7o2CWY`a-eZ@?nN)APUPAK!F?sLV&f5C5 ztV(u|ukk3U(ceB~yL&8Pj5|#-&R+>OVv^7J4n{vaGaFCY*1iKNG6!FWRcjR;l(9Eq z>Qt-U>)IUe_UAS4^x%M!n>1upl3^yGK8XtaCPa8EMFl?Z3`qq<-!!GEPAK&v>e}VJ z?K}r*k-ZvzLEhcJxd&A_1M{ldn>}yt?Z1cM;w zSLO`&AWh|q_;`$FQk7)5Oiw`;CQfi720)+$cJ@^3=TgTZfhtOj9-;!*tx?8CS0MMz zL>mt2X@mM3r_4h(b{5}U9z4p_#W`vv31roypx==)%w_as%qFbmSe~}8#mzC`DiZt9 zL?ORKpVAX*D{nkd-so1;6Pegt)84q;vaP24Q8ltExt$eqbKp{1jy>uoJd>wt|+1mm+|iL*iHZeSK@=VmZ(JoPn>op zt17#0_#QAn!{>eQjSgasnz=kV8sO|a;-IARW4T?Auh?QIV{SQi`mIIXaA$liY)7jH zy}ggvyA%RsH@haji6F`$VQla=ZjVS8Y2GO6qUeD-7$*aH*Q`-)&Z?Fk#C~bWaEq0a zlGa6>Q`9VY+a$c?Dwa?G$#0W(v<(jf#-jcx2JFn;R1X}J_3C6CJ({?^O4&BeE36q0 z+ME;jIqqu6enkOhaN_Oxw;_#~z$i$YnP`-c6XHRYmL)$%P|d5I!wQ)ITlvv|Aoj3$ zE7zcHGMqDh80Zr{{xbcc_~-cJ70*#Lkfe zDMr$89&jwQ)ictElCwgrk#_w*f$?yz#6fLXYkN@N)tu=)lk^5o+7K`&PS2({n`xIQ z{9CKga?I>g#6>-~-)euCdag>E`dt=2pZ@Dp5JEA0oLwhL!)vzdtg^AH#dh7}l+ji0 zc@LSzUR1NYr`3*>!}?YJ`Kv`)#$pYCEJigpdPHb~h6u<8Y@&zwXAaRIt)m|$=R)QO z@A^r{Fggu6Mowzn)P5uELLp_*A)sG>!9A4+h*eTbNsr#!3@NA-_I25ALfJLQDJW~G z!d3gegCOoy&)yor7R9`rS*|meua06(+TYD%#)okFj&^i^K|Ej%^Z8Lu8TZc9&)_=f zazZXAd9{Xegfhp)Yz|e~R}7B~{79+@P;s^+^{K%cNqd34iY_Cix@VAn`suY;4CIS0 z9=MezNaAkq_dgzwr57JZS8iyw$5O4wxwU`rTw>8U(GpYQ<5Tz*^He}U1Yr5{sX zNsGerZPlk`V+ox;UrfD9GZZA#=e!X&E8ef*gsKa{isgt5nJD+1qm!%7cDT}A{u92k z;z&IGuL;>_>|F?mCS0$nfT~6?On7LwtG%MSDUC6Gmw*d70CQr_KY3;Pv*VIynJAHl zPrRb6pTXme1%d7gN?{Cav3a zpr`M8vTP#~AUGIkWvOtlkPJ|IL%|M7GeD)q=k9AH0S0f^$)xAbJA$Z;p*g1zYJdEkgJ??>4OAn)|JO-=Rv2bGcH~m927G5e;LyB!!AjACyG~3A|eKYT_sqee{^4*CZo6{k~khC|lpp zo^QAz&IKpcXfJ<|Z#sOUTmUHfnGeMvcwe+wEA}@&9?b%tVA<4u=R#q8c#DP&r&H$aQ$v{D!6Znr=oeU~QVP3<5vpoZ!2v8Yr87u9;~wwB48`r$$Ne=k;bs z>ogAR?zB(drhoVX2;J1aL`j5BtTd8N#so{4WiIU*=$IwOW*$x)O@DVVb92*#>ldg| ze!ytPMiFKyV7?ws?}%Il1??#Ybv(coa;kV&#{pN{V^(4x`R8hXq+5}iv^?R^M*-V*6>YWNEvmiBXsO8@Wc+Nma(BE2vXXQ_z} zd|mFTaT+2vCfsVkqAs6MCjjhtlQv_}V*f|xK%<2thamb%_p7?bMK{6riP1*bNtJv^ z{UQ2l@VUtq0`&s57b>vQ=;=b<$~&PaIw_v^MK(`mtlQ>^I^F}|Xd+&6ZeVaY0Nv*K zMF)OHWIV5NPScj=w>(EZj3_f+y~FG(2P8+fpSgEU86lO6dZ>B2*)?*7^h`#Uw! zZ@`!Jfcl@FA|v3Wr?$YzYrQHT>ySgA>!H*pk(1Mo9!d_$k}$_mfw86G)8YGX;v=^Y zb57WkOKA3t1-xuNEL;qt*Z9sU*Gdv2&=c4+m`Y+lmtIg_kN~teU_0P15*>&2H?v&hCB`UXLHo}E;Qgyyt zyB_tvjW7KqNpT!XNxJ!vrK2M&e#IjIx(-1<3ngU(aItAL01gEresHtYOHt+RH}{QomvV zYCsCYYAUjs1LF8x@vU&rs)L^fex>|-{(gA>W5h6Cq~FS7;nwGp6zvBB$C|7_!aQJd zs#d{;aBQWL!Y5gHZaS7B9U<#H*>-F}1lpN_Rcxy@c#gnL$e>0>C;e_AD{mg)Ohu#i^;)$Nr1F;&uv8` zyxO7^B*-8>*Dah8LZO9Y)fjm%&yw?gI+2p1yO1VU-pYD9xn;ylqYKF<*%$;(w+&@K zaX;63+mu{D4|*nu4MJfx2OigmBLNx@$2L{<6wy$V_JnlRj9uqn5hOgtk<$3%lBJya zjJ70oS%`tM{;FXib8dX>9Am1bhaB7)=pK|gzzrj!>+H$zD4hw3KpOBoM9eNl%FeM? zadlOHN=XCP(TnVOLav?qG;!q)BKfH&&HV*yy8y>Xp~!j zW;&nrEao%UazOU!Dfp0|tqUN^k;%D|LqH(bbC{cCYIwfp=EjQF&Y@&rjgsC?WnBmA8%4 z!>!Zq zu{ipWuB(U!S3lXQB8-!Z;Ix>Qs!KyT+kv?F*UQZIjU8>$`UiePf$Lu706B zm6`4D2yDuxHCN&cxQY6G8}>R8@Ff+m@T|bRPB>n4DUP&gjK>si--P`tKR->Z*N$9A z=H41-MBWSQ958JllMfDN_>W^HiiYO3Vjn9M+^9ZiI37vIe|B~B5FbSJ=6d&)uYq;I zkWsq%8Q26q1Op58?)JsyQe1abAJoo|tKU2@|b3F<0(f^(`-`l-I^fr`bXzw8=Rg+tb! zK}|#TwwM~|E^wRXpUJ9wewHI~Ig_nc+gRj2vGr%ILe(cqQ|(T$GJ-rQ8&Vqc%Jo{0 z+k(RE(w`MrQu7h8hA;AkEDltpK)FGETp$O<=%`qkyKP$F>~Z1j;TjW{kJ|OQ$m11v zUM32yk6S~P%9-mEez^7FUSZZ561Wsgg;YxN@y$nSm}A_x?5QTcS{Y9*hHTitgh&6VKUVmSyDSQ@k=+#mr@|t zQ?DHizA(UJua(%)FGQMAPy>576Hog-##Dpc!9DWnY!#xNO<{LHnLztTAn&*esZ{^= z>|)M;!F8cMh!%|-_3rL#S;J#`QPS$ABpF+v)A$NEDj=oDpsgny-~=qS6_$nTXWC#jVoaDO4$cg<3IF(GBjR7bDA>OwLt`@p>DLVE%Qfm5%V3# z{EQ6F`E-~gOnO=Lw7UHJf)v?Mb>L`L1K@LfE(G3ksMp#m)IcIK7yE7*SD=3Xv*OXN zm3`R2zdvTHsV1A;Gsw>>NC(*)D#qZDYo}&@ijTijgTg`pIYJy;ano^PtvNPJTy(JcvAzwL6FtB)#eIt{Un?P((Znv`WD1EkKs+~U=TLzh< zAO@y`-_XC0c1s0#r7LdE-Ayt3Kg7dLm&E&aza4D448>fK3GP!G)a$eBiPoR4;N~Bs zxkhkYav#|OuQHRU<8n#-+^fF27TjYmuk^{5+fTE+F6d|OW}ceR4u5cp0G&mXR(m2x zY@DjU=8DdpKV0w;@Pz}S!!;r`qAwEPcFte4a)j)*oiW-5TRp`^@gYO)@#2h-kn`4R zKHo)OJcy9mYJC;=PT5qAm|5o%a?1w{)`%`A&y$(`xqz45Mr33f5@$2nd@qAWRrKf= zedFE3F9+y0;Iiqbh)O>lvo2r|k=AoQI!I7nH4Jll;jthvTILHBJR?01j;1!ywLN?E zKeIK$7DH6NuDNaFDkCKh*og40XZ@OyF{H)YqoaDgJs8dYP;4BfQ@NDl@SfC~#(LOw z)uzPCAB86U*i@GmMPOu9Q%|ctxvy2XO$lmb!a%DV4P}{QoP}mlb!ja(RK!kBgP{|4 zldbnd#AaNO@V>_~;t^DHLLu_?yA|3xQ975HfC1KYVO*X6+0qN6Ny5eW9YL=K1T&JM zXiTO}_w1a5Sp#Or^NSXcB43XrBr;wFvor@D+4x6r*xRk-y*g8HVbl4{UCim_RH)*U zzoZKI~MrRHhuP6Gr~V?Cw;xFR3Ld@>t9lcvMpZ>_l1@kQ@}BC@k-8b zhC4&pbdxKvQE|Cf8jNvQCDWg`aMHMznMU-w$P2VM6R^JTpks#0wT^JQuPgR~WsGW24)kL z_p7-HuOhA=;z)(QUL25^%UO*NR4$>Ase{=n^|AI{-J%Zf`g;%Be=Xl^=imRVzuF`y z*+-k@*8DLcyJ>9iH8tUIG)*^k6Vci83^zIJ6&;DePcJ$FwvBqu`4T zT;@o;?MhT^i>oj{+^P-Un9G^Doyb*SGtfj8hlgS`H7HULjx)Rv_@_QKD{;v4mq4}> z!;xHiFn#QD9jnc1T4Mx)X6^1Br6?UcnL z?^%g`pGg%{9wUU$pJDWOkFEd|MJFnXF8R3(Rs0omqz5g%lb3@xG0Z9qwRrk@u1%n- z*Q)xefLC)J@SvP^bEn*i`Z#uvsTNaM;OS1emfsOn@!Cl)MO7XSMmcOg)zF2%wglr^ zrqXTf8&Vq+lVrm`%Z`;)$^y0`TUyku|I2)Lo%YCFsc?aSxtTskaEt8XGx zJ?-O!SR)inp|%Zkv9Df=90u4h}A- z$16KbCP-Xmpe%!y^3Lyo%4u%y2!v+`RIwXK@}Nf^j##aR7ArFym2!IL2pvyfN)4XG zE*MQ;T!gh&imceE?N}`*$2tYN7`CGTj6Hpw{MF8%7#Yn-sROigs516jg@mM(gIh-4 zzZL!R`tNGO2Z}MeIUR|nyMKreHpL`Du7Bs8EE%S0I63coVB&OGc~s0B040wBpqY3U zr`UXP75~zh*TC7{Ee1~3Wf)@-cKp{`@|I1TxR`LDmGfY>MgTf=eJ2VMjPu)Rz~Cr%J*T1^Lgebt&P9IRsz@*{A%HS7KQij@p5i$1&%&-13b5ib+LJ$H30bAR1bX-k)U8rZL&2r~W ze%zd$D=5nS-~KlPt*)g9AGc+z4zfN&fjZ!#GRpb$g4I)t6eq;dpO8Y7>k4*=jStnGp)Z|$Nh(>v6!uhXG zqUP@8B{jA!t9sexdQ1%7Otn6IhTA0ICrm5~7+mHSY_;E&Q8$HE_RRl@q8x{LjT&>{x?tHiw zV1%G{bs0^;M#FLD-EQta4wiBwm%U_FdS5a8)wXqfCCD7H)3t0Jn*$0z*I!LDx7|Vl z?T4eHseP1uSI^=>X6B=t>NHz%xmsbZU-%!xus>Nc#;mBcfE80Q`g(pR4DZ>ro<%C_ zoqtEjq9x_);~O~t+=TDRnv0FY8S`xXX%(q(dR@x{UWgC& zrD|Qv|J1A>B5;S0eJiW03zvr~buC8%2(+fb0C^o}Acfn1COE{_h1a#}!c}RVkdWRV zAV^T#Px^e1jG(bmr<>E1n~wbq4aIQ88SA%K3@>n}nyv!%IHA{~Or}~d{`7CWB(o4d z`}u1F%ZGkZ{L%Pa28t>6#Sp@AcDM`HWI~cn0wv3 z^~pP^hPpt~->Uzo(9!r9U*h@k{7(%HMRlT{j&H@#N3^qQXA zIrB;?w0>+UXHno!LkTsz)V@IriKh|k4j8J4l11i-y6}Jz$slGT?MvJ=cAOH|ClK!$ zi3bD5i;hOK39Fyx$rjS6+*J0u*cyDazZ^{C4dw!lM#X+w#lvkxr2JYvAZjFw<~hw^ zFvoJAXNg>)_M?fH$OCK#$;e_jnnz=9>bfviI!Z5rP00Kjs-PC&=|3=*ZU~I!7_4WW z3V`X#VI$&mD~H)~PNI{X#hp*bxG&8D4s12T=SP;l1{QvN=l=0Eu{4i=+z1_^${eLt zi7Cu|Ekx`O{4%%AMOCul>NpuaKc+@FQmh!}X+6G5nn9!_4KHMXz%VeHQo}5HSh0_t zmp1Em>r3D^GHvZ~-aBJa9kC4N^xf(JbffUX(6_Rq@rm!$eh5LCh`&0R=TihdSLE#c zl%an2Egf~1}zy?|Um_gQz5p;ZRyBTZJm(U(#_7h!vuAIEt+&T>`kMHZ2=e~%}o z`W`*63a#)#qFa}$yPxrOmvxWHyRem0HV64nmA)F-mso=!0v7C#YRG{J;R3j1`_g?% zNlY03VO+t%^Y$p0G}b626A*EsChn01_BK&==SC?*2E{1SI;jEb+LQPWh zz51;kZrKSQMO*Ho0uSCHx_08o-&>-OH);Cz&1YupytUTmI5&21*Z8_Rl%9QY@mmKD z*9%kP`N04V0SL61Q5qYOkgG+X{2?5nC0JT)i$ z5v~{i>(yfV2v1GulwCQD;oHwS+)NhQ%qztgeTEhtUQmWr<;u%Xt`xEu*rAF+|#?IkxH zjlTH&ceF)LJt(Kj!TRRtQudr7@!X0|jc&s8{AT~|MZ^7%1jvR2%re2K9w|UW;QyB+wuHc&P z)N~MVd=?mLEPo}H%=i}4inA^6>Rx3=tF!jFULlfckBOI~q!$Ucs;{ILf-876-C!`h z%J5am|JzX|@=&9ZAY56pJ%qKTPSH_*;T$$91W(oaE#-JuP+uL*FRJBmM3;Yy6j+SW za?3VseMfAi@F>$p5?!TKtN+@g30J#o2(f@x1v%M{TIJ ze26=T5znm64=bgo(*NRc>LU>Ng!`0)t-1Ian^YcgV_yVSJae)I6R;fQIMAMyg8^KZ$3BISbDN(H6679#9c{I9KXugHHsr^7 zL7ZRH6L)Aw!y)FR0M}1X0*SyrKE{P&>ie#qfoD*asy!itR9}f|g6bZ*G|P}emt7l) zjTnhW@tP|ERA;f@vdPo%8ugAmYZiM-~afKzH&x8+d*%i z?lkKRw(*>58%e_pdXWH;8EPg7r}~va|4$-jowRQ9vGAXaoma)y@Po6~EfAv_+huWe zbq++px`4Yuys!H2IO^H=I5WzB9iGH<_}lF%^y%$7I4BJ+RB?l=jJIdM?LoHg=%^yQCI?=Ssd4?{Q`kLAtG$NSzT0YQ)e z+UjbM{Qu%@tg?&l9~%|E^?V^MmDTT!W|oUT)Jd3wC%o3Vx%viPihJ0djQi*nX`nN& z&3_#evT+;a zt*G^2h;95q+1v_kq-9i?JOw*==PY-&3EU7Wmd? zeA?xsHIR%d2Tse_$-#aTe{J=N3L?q+w#L|&+d-9hEGszKRNAPL&LI}U(7u(DqSqtT z;%v7%(Eg|FGCCd%EnMCFwrQ){b|w$Ar7p^J;2PPosH{ovhe>&ChRM&#Tyrw)#^r)+ zlI5=|WNoojf92WOpI=9lH>Kuv-z{NEOtud04IzHje>mk!z4QuG4%!))d^U%$xG*WR z%8;7Bc;Bc4mkrdm*Osi{XOm_ltPn5UKm0ywv{AQOiX2KVF}B`hMkvjMB697&m?Xh3 zR{K8j)&geKYH0r_1zo3P6Ntm_j?6Kn6oZN%BG;TgV_fR$PMyfmm({decFGcZMg!&Z zcWL7_twQ?p*=IHrTLe@5!N1%ghBH#m<~dk1kyPI)8iV$1^8Y~;%RYUoN5d;9^AVyp2pd(iMtaW zC75YGDn65m{GYCvk9<9MU5F(Pc_ioL)CL-B;@NYPjjwrC5Mus&dYCUG*w@*~d$8YL zCu6Bk`7^imyoyqq9W{1p%TW5Q>9e9!jOm?md_Dv&YSF4uGIDRALVM@8+t)?dy(4H0 zUahe5Ob;3zTl<8Yb$L^O{qmr;Er}e==7x*pekHd9nJtB`O3kw*xwiQ?%DL1M^|Sj1 zt=W(zHL_R1Qx=AYfRLM(;Xk9lq8<|QA^ZF->HyK9UIhS3T@RCc(QZg!QY#s=?xH z0GG9n$s(3%_*(p!?%Q&<+4H0 z;`&Q0aJxln!y{u6i%xM6NNO?16f>j+SHy9Z0b5<NYn4T&X?FZ_wLLi! zCsHYfAMy3P;}_DD{0nmUENkCn%!da9P(dv^Ek;er+fV=Tw1=a zwFfe@?|;iyGrur0H@;Ptm%~JZh`qL`mEpYoP$N}=+S@{DF+)vfd0Crw>&*nv*a$uS zQSDj@#S@}`Z~(DNRGU?1si0EQin13Y%g{@3uH!5v0*9O5ypBmS1pvGCQI-o`Ol* z-T(Xje>*_N#LQQ7EN(9LU%yq|X?^P6b!kviUre2%G&wq)FgP~W=0DH*N`4#`GGOph zB5E-E`hlR&elJjk#OZhata3`XEZjZNE>^a|-aF%497M%CQ=H8B3qKeYWZCr6ib@7r zyl>Taql+67@NoVXVVFMKxb1+kEU7tTl~Wcn$qtk1ZT1e% z8g%h1YxG?gXwjdxZPg}kRxOMbW~VN*_FiP8umAYRv1H~tHF*gHQOD|z*2_hZ^Tz+> zZ@O~@>3R_xj6yD*4vz1-+&h&9 z&Ssc`S04aNKUMY#=~&W3CiE9Hj?tE%P_?Ba*x_%S5H{yH23!zZ$y@Ai_Qm{M{Swn6 z?da%<@hq5{6w>P=$~L7bTd2AYeXjmIkMomG3D=NrK=6q*ck?0TR;W#2%mmWxR}v^C z*4S%OyHl#vkN6sGY_EX%>0Fg%kxcm}`!=0{q=@B-j4BI`5_r2`AJ$7;##FxfkSV>4 zoZqHi7R1`uRiI_gPbs-SO%1Bwt=pV0>FkJIn3!*s3l)%YUp-z4B^YdAHH%P?kxU*q zt15Y_J|a2_Q<8N)J6u0z*%?1AJ)C%So^$@{xj5);*W>q!Z2W9QewM-G=KVbKhBENI zw)i~mBjrWuEsXVfnX%QSLc9Lpev5>e=zZ(fkxO7wwWn5;Qe9edZ`sy@j~gjfihkjy zkis{N6^)Bz2>1snqhDV1|6L_QAU}w;S5ei(s-Wxh2ADU(_O?h7rdFuH1i>D(FQ=zn zbwc|+H+vd&<0R^0(Q^$U#FK5p)$7Z8y~90@GOP*37C?=7vS#eGV$*I@MJxhz&oyS- zd0fSDab&&F|M@23;yJID+1@^| zWZYARXE;(3-!U4tjK2S#IAj`hZC^zBAlvx=zij#cu`8w*_ZctN^ZsMs)WTiB#Z!_~ Lm#vg}|L^|;{s$?h diff --git a/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index b08c86401aef10fb629924fe685bdf37c0a1befd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25506 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 C|C%=d diff --git a/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..eb5ee1b --- /dev/null +++ b/android/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..b26e945 --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 09f69ad9730bce0b23484c0671114c9907496ba4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1741 zcmbuAi9Ztz1IKsBy^zctiFk763a{H_Ypxt)jv+Bw7}}PjIU1rIIbyk+%~3tQ<}p`V zay*H*=6JO{jojwQ^*$kwgtzBkc;CT01zif1p22P|Bk5e z&&F)Dpa1~j5+{VccOr13GMeCpfema$$Hq>!MR7XvOPeiDhpJktHM)^-hPx)M)nc1{4m`<9^ zkLOI;FUYwJ+ue?LoBY7B?LN3OY_lA{VE9%N6GH4b0RNal0%Z{Y2X$gK-a7R{cMS~y z0P+N1Er&TKE_S2Kh#Om_Vq%jkjrc}8>Y^n5)v;c-Zr&Lk85xSjVp|=NN^ns|x*_R+ zuYrFErRp0plXfWd2y#!q9Z-mnIo7NiUjDD=w1RRd@k!$zB_YItTb-$aGA`$xgCHw_ zXfijMRlaUUP~!M~cQfwOOM}%Hq+Lua8O`h(AD>-eLmIF%_Fj$40C=dk5R(+xxI?!R zy?;ttTU+hK?Yn7(ah`*?WDN&-H!aqCXxr=vp9IKnj!;P4sz9WZK_DN`0#qAL@)66h)ax+C7$$RQ(BSu zTIFg8U+r+B1-r<6mNAx}_Hs3ZH_xd{>YW*|6GH?t;f1Gm_r6S4Nu|Z`k(crFBI7r9 z88D8=kj05JG!s3A4MDqMzp!Kcl|;#@1VJ6^qD<%-NfuEaPZ|B~*}DC2UZ8B?=@6$Y zi|-NLZ7DJSLo-c5jAQ3q>#&F~s(S_8fNbenaa5|_UH;2L-#@s%Im_4O%b_A8J<|`r z?Wgrrrdar?y}=GxwGBEv3a6e5@tE6MFk7MtKgQ^wb%Vw_yc@-|sOG47{J1v}@^)u; z%sS&%`(TqLE*Swci1o@;@1i$z+|M=WGmt856R-(?sMUGV2N$FL1>clu;QVoh5 z`v{rzp#>V-*x9p2(pI$CQH}f+_cjzhu#aJ))U)P~lMJ3c zRn~CX@5x$3AaRSBZS>OYVm-Kh?|4kBX~G^5S7%AXGGlXza+WT9q8_t`ECu{3T13ZQdrd;Zdu@n=)}rO^Ad<;D~2i(gae(@u+7T zSOLs@Q^@-Mt}<}72X!rZ-xh}D{Ytp7)E9z?|C%7OUPB@MZ^7E*vj!n1L$}{9fB#AZ0wEM$bkm2eemTF}>pfZuIXx1hD<|oPW5CZ6*lP)P)Hn*U^RTl?{EFkXcb?0R-A!yqLL#X=t-62d(>Ge}uK&N8 zZ@%$548sr}WI1>n*sW{;-m(FB%Ld>r8-TZL0N%0zcfDj4@A%PH53ykq*ZVd#m zQb;N~+W{&?6i(bQK3k2;uRthzm@#b5<$9XN zqyU)oJYF0xsGY~RnP-`;AS)?d+Uxczm7V(76~O$jGm#CkoFH zSx{<5eg9nBsfS$we0I5Gq&jTHMn#|X`i&$Oooy^Vmz3lAHTyi`%cMcN0Sk6QS5i)#D`^BC54x)02 z3&5dgg5USYlkeR534VynLf7^_Z@4RSkr9&WI4$p;`$Sub450?|Y>Zs-G3(TBJAmwv z$eyRP%RQd-*XpEqBs(1#F-`loAnvwFBt=l_;Q4JET`VMku=q>;AmjkRRQoeVs+#{$ z@vInG99z8=K384r95NxK&024&`K@w;p2U}yd9DCfm%$Q9d!yN5BkZ_XnCboq=Q>~5 z>^7|%onrIwjeo@*fc>!5Wmv9(DBzZ}FY_V__)ma^z6)6M#acHyloo!3B)@2xXA{8% zpm7CQwxR~&TK`$>NgktXU2mYZ!=soe`|4#x1zoxQMWcDH0F5iK4F&>=+<$+L!qeAL zvHyKqK0JaA2y{Ag1EMYS+yG*+n9$qXyZI&dA5k`Alw#Kv0|%l=h(KztL}PFPh(@FT z_mS1RaZmN|e$?MDvH^I@2H-6lfVXS_-m(FB>wyRO7cBAYwTx$0tN;K207*qoM6N<$ Eg3H|masU7T diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index bce23a79db06c44442e2466ef47ae4ff2bf90585..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2484 zcmb`J_ct2~8^?od)QHw5C8y(+&4C~ zIoU4%83Dc%Wo8H80su~h-8a;?4dGhP6ZI9Rfw~6vx)!m7Qx@GYIYX;Su8(8YDM96K zVo##2>&&bIWn$~xBpvJQ-0~8~>?O*)Y;v0F#f(=+B>8GpSB|`8O6W1QA0%Zw?C5vA z1b`;oY6-Jg0_bp!xX0MIfY+i21BIWH?}s`s|Je8@s}l~}{K>$FEu4}Umdp=Xg1M9? zaRa1y0apY84ibPW6@ZI1ptTSXb&m`1KN`OL1?!!i=dw~Ow!8AUmIA>}w)<*LV3)kGU>qeKi)RgzYG z)7v7ZoqzUc<<<0Ais07=pKqZi_Msb%2}J^`hD1y9L)h3bPA_b&zEI_jRDq12C&|fP z*hrx`n_@MB@&~e+JWL+K?ZwRP_yG00F6Z?ht*J^^{7{qi^T)TOqS@XSNHP;s`0$-FV7ulyW*OeQeCOk8|Z=RVe9y1PSF?r zAai=p7d#&<3;T!+=Y_~=ELwVW?uV6AQX1KqN9Ka7mZJUNIuL%0jr`!Ft`+?5>u*k8 z)gXXIcIpp1*66J@V}v{Df)+JGVX_N-#XZOKTP*=fajVJvGb_31;&ilG@QTTI+%hF) zh?9uIfc3*osCyie#apa11-HSh1$SH&cF~W4uIM zAw{y%^My(31mo*S-rTgv^}k95hvPs7{hEyrLD%P-{6ugybRqMo2!IVrqh@BfXl>I@ zeB5WaH*`paVi?u|cO++Ml{9c0S#@@3rC+|`N}EIhbvze7(k>hgk@*()nL%NHp7NBi zmEJ*M@DW?T_0dvBPmLM05&r?IyUcG7y+tzG^TZXt)@eQ=WwKt*7z7;_2o;N3jbvPG zYe2cNQEFrds!(5fdsM)y1}Lp!kEgPJPBz|cH*&`w9m^I@8_hRxc;$$7H~fsq4xx0d z@9Lj56R?TPnHgRSDi>7%_g$`A$m%nVnVRA_1!XE=b>3c1MFGdV>?};Gr1bcq^z76f37tT>m$gyGqQudu zaB2u?GW@kl<=BWC60$SU6I;6ytKRNTHFxayAq{buOYdF3Oa2U1IVrLUgq2QR`<0dJ zj3NzYAGXqSbmumVNgV?0_#rPSOXyLhUE(3lHrvvtzboZ#^o}s81jesK=RzEvh80S; zK1vA^UN~%0c6xencVF#et`niu8PQ}wrL#2i+r5v(j2e&9`0vU2e``FZqXsk zpFGsYzjY6EUbCn*4QyEkLN_~&>zB+(gM`dK3tvn zLEJ#f6k@Nthl9)e@E_O@@X5N1yE!czF=E|j*@263j`p4nY^i|jv6dPe11U*+j8@F; z_lh#KQ7C!p@9{neGw#^_url;DmkOD_vp7)u$)Y0noIg5#_ZNJ+a!ko_Z<>DvJElxP zXY%KyblExW!XQTRBRMFq6&WxiFvt=#+x|VL~^rik@P1M)o)Se$irAbJI+ucFndW;870x_GDX~x-%A+ z#4&Yc$_w5JlYc_NymfFpJd=Lc(9=y&bcDm;+n)f`4L{RA1Va zt-paa;uSl?i8F(NU#Zg8Y2Lq=zY{s;ljb3blW_g6LTSwSgMHxlRG@8}%Orx; z-}8I$T1-gqA3FDoXNhdWJ>s*r3600&L#*h*LlZp~(pKoRbaY>Rf@53>Gjtt)XX#=7 z_8B{ttD4`3CwUU!(+d4(z5buw=IU_i5(D0Ix>^|KjX-M$>!jC2J=ZF U;2O~4gvJ2(?^zgD-gSxo7rxWJ;{X5v diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index e074d5ca1900749d950fb0c11a605b0c990e73a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4038 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 GdG;T)rGBme diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 37228ebff8f12f8210933e87393494e62ca212bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6300 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 + + #1b1827 + \ No newline at end of file diff --git a/assets/graphics/icon.png b/assets/graphics/icon.png deleted file mode 100755 index b7b1e068dbb600d3032ca3cbaea9823a0b5441cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 111605 zcmeEtcUY6#(r>n+s3@o)D2N~^NDVb~5CM_idkHNdHS}IYRGNT@G!c;AJ0x_F-g^yI zdPhotBqX`fUCz1pp7VX*t$*!24-e~IYu;J2X3hL&R(V5Jm1S>SqrL_J0B*>=kX8o( zhzLa@z?I8{e*v^?L4~ggwO=e(@D1lz&zO8R&nJxY~*_NdD}QUROz# zUJB|Ap$BntahP*)@z4thadLzB_yh&n>3O(#xPV*&KyEG$9v)#XkT5?l{U1LDLT}C% zmcr`N&;RI)@Fd3Y($&>b7zp(6@Zj{|<%Bw00l9^Qgn(Q;Kpq|r0tJVQmxHURCx?Rz zO!F9{)^V}CDaw_@)G)QSpU`h-*rGxt&-ATef&#V z?Ct;R!o^j_oiL0)6!I^rT{OKMAwYGA3)Ico93taR5R>uG(YUy(L;j)9|HA78^1oho zwYK~>@BVE0?*;|&wEj1wKU@AHbrhCzhM2lSoi(9QyFYD5^-nF*^YCzT(Ld3#cCdhY zxUl>j!yhj|q)lBRVhjXB;^E*DXU!!aM>TT>SqaC0MbAsjKOKN^D^+YzcL?Hzmx0wY{ko1nB5s#X$ep%nD0E z?V!$tjtSE7{&T&Yl$5G7)Y96H(BPsj`;1;rMhe6&1OjpJaB}|=S4l}&&cVgi)WIAg zCoRT67%Qi>wS};dAQuQ?%EQZHVP*>A09o+yahM94nsV?#EVv+Cf)@N1eEfgDFAX(! z`)QRw-~Zh~EuiKE9{&&z#KpyHYRWCd!381c>UVBDX677bX8e|B0+xbYLY99?qvC8$ zzz9>jf9CpADvO^|Sz7Y&@>!a52$*tPatK=T32+Enm|7Az3JUUZSrB9rAPoPfSqKx@ z5JWQl>4;(s1m?dgb$^~gg#MwjKZh?#m>3s=sk;0DQO``R z{wUd5i~k#Kn{x5;2!MDvEV)h1IQaPaxHwD+RUAURrd$LtgqWG}T8aXHq7#7y{qLpU z*#iIL{(oVH@C)mo@_79rg$BgwFL~&H!Gy4>`R@ug|LJ593x+?ct^bvo{g)>6ceWlc zA%v;?51j9JG8d?&tB0vGMAC{d|Np6T1OJ`yE~f7PvFJQPLR@AbeqIhfkPw7}+mw%& zL(q(1;+8^YW)N;(2%jlG!94z*=mfan6Xxgo6F2^MME`@g`Abs=D+nQ$0vZ1I2O}t8 zVJc{0Cd6TGA!N=0;v$%gkf|vFs|2_qAZ`dZH^iLa?*G$Z{x!1wKOT%Z)WIF%{7;7E zXzFZA$Ojtb zTdtFww4|ozmmRF_2c~JSh0x?e1rIl*y|*RT#lA)H`uE+#ereJ5q|d)naq+z|Pq)AF z+ta|W6xVwkyCShICT}DJFQga7)?{v8>1KG$3AwG?q9DnoV_pa#x-g{3eka}iN*G1p zL+<9%^?9-QMokYl!VkH6){3!QbLscBeMxMT+(aj6l*l~jHQ?gVeI((Hb+v0Q}7s@V62O=J2-?{#L^8sPMNX{A~$;Tf*NV67YAPKyZVBd?kc@6oZtWWCUSU8qfqI&onUs+?1B*aRxK>dB$He?zDjR{#LH4n=u&M2mi{gmGbIC+m3Dlr)= z@wgSv)aRQ_vRz0Q*BE6lWRwr+7L>$VO?Mwo*XKvDM;4G!JuX(7uBk*fpV-<493W~g z1|ZR^<4um+=))j*2~bQ`fu&!*q1<xu zqo~7a)S#bIcvg5tw_ZA{<*Zr+~qxR_{>1ZHn=vf>@L`D$z05vtYu|p@a~RCDEqhTl`Ia~ z4z4fF4MSwY`if3s5QuA+lVmj>IdD3BaZ{1sZR$uV2+8zib#UIJRQ)svQ}UU#Wu&~A zpW0@H&iyn}#M)OYcUU=rzIW|&;hYbDPL&@0%P=ah@)~52B4aa;N08%!)iQMj7V4=J zB;menjf?Wznl~P6FIVYMa5ZDg0xDIdWq*+$33@u!5)%i|B6+&xiT*3O{(I7aK;D z-HGMBsb?)@xhy^Yv3wglAv>}_O>ltE3T#!gQ~E+qC=`;+zQK9pK>PTV#jYeWkDxdm zu-I{8LCFJjUq?k}s^AH(A1sEGif=+NgWRRTg=_u~F9l?fy9PQFODgb!uk4iDdXT=D zi6~_hY3hEC{?3pmzSLS#76W{M@_A(-YCR+1-2!cC;hz{{PC;G-=o0eaSAI$yS)Wib zrUKD?U8mDlE>>*QOPgkAvt!C(XwIq@+W`wPDEr&n397<+bas;>I_><374*E!>7Yp1JJ zcZz#8#}`0)0fVai;I(A<)NR+jv1a2DtBjoU;+^kL`EipYyF@maPma00GXCJlG^bnc zy&%H&3KwCctr=&TJ*2*Ak&%D&qGl?2KbjkVHaA28_p48B9Z;&g+MX%gSAaL@uTffr zjn*Ey1HbJwv3hX5IjN+}YyL6=8ugCRPR${AXYsG)(okWIpwJLsHWs~RyCy=a91;eo z6G_L+JThZr_4OI6s)^XZgq0T-_&vxLd0y){%5ghEhG)6K`=uz;%9>a093MlZh(NN= zr1iKH#;oQfM&)D1?rPSja?}z!BMC_By@Q}34)8tg=^=hidZ$~}!%m(l61{9oMVeB3 zB66CH@IB}%xsM6#ZSr3+GElJ%kX}$i*Hq?aB#7GLClOuZ{&(Alvr>+=^P+-sBIzIx z?(oY z?9Px~jMK*o?E6wMf5U|4R;DUB`n~f1$jY4UzFi*;|E@7HU-vEQPJYpe{WmoAaNJts z6p!GyVW?ERM8L)t!d`8HkS{z4D-Z@P0Y~nrC-6@wXD%8h`eKOrZ4UF%KE&<^40aL? zB(1>vDE5LUV>?6QrY9(?3uOiL)*>&=serDY?8;fC8tR-qjGKj8SVn(u7uhUUb0?MxZi)RW7~%2-@{l%7mXlV0(7x{K#A5yD z@O*Z4LwSz^o95YtMGoS}L|JFHG(}?j^D-YeCV>=lwPls=tL;@yji`~dC}aDDZ88#l z^f%j{TtmH^A}}eDqnMdG1u|p*y|Y2EAM%IF1HX;K!8z>uK!Er$xAw7VO4Zy&sQ)wR z_7nj-{yOtoyVWze-;0T+KA(AUtS%SbL%!8Xq{TVB5mCSD7N{M_kP=ADca z%8t2b6oBTopC7Hw{A5^Ne%kk7h=4vlr|7JJz<%{Mhj`N}Dr2QoJ7$)Pi~_|)qP_=- zKH_j>Pc$LW1;zUxoRQhNHr=Ji=q*@ffNq&T!y10w+ZpzIjB9D)ls>Bn;OT3)ozWS* zO(O}KPAE>hF&qzZ&ws?DT*Z0EkB(d91|pyzm<9kSUL_oyZ$TG*)UBA>S(JRNy#Szi>RtbS= zH}8!+42ZEc*4^$IQt2ytHHxHHsq7k(kk2h>o~a0b3Io4mkejY3xtPGi1PNi~Dqhb8 z>ZU!iVY3ZK3BCw7#Zpqu4qRI3))Im(82Y_DdW(#*Yp6Xb+osY{L7dwp?)F{v(=tVk z7#Q|h%t~`p4n)y@PWMD=kcZL0`HdufVAAsof+?9ZFhVA`>Ygi<9TYa( zYb2ub5OH(IGfn1RCSN{0v`pWxFMB=VLt}AEF~mS;H)sDfs+d)3yfXs(;MoUzs>R0S z59_u8Jxa2@(od6ufjM`C`5m8lk8B;ncO9ga7#ZFbX@(ndazUziI6bYKwfCAiuX^2W z@V|+3mW+Q(ArBJCV2aqEJFvH}{_NVY-N-CrrS+g{$AKfY+SeN^rDJUDq5}t}tvqEI0?w z7gp}>G^&=(pe!42f>Tw+ZSk(@dJI3o&u^BN$TdO0+NS~mz0rwvKEZjVtdaI=06_LN z0^*bgls#)vJh9EISa_(j&l!K)pJ_1cDdv+u<&%N+l6!aczB3hQp9`hRyxVEL{)xtI#-K%BzldC0jYKuEWZdQs@p4yPAmK^Su zuK3QG2~#N%iOeV6+Z@wIwDF^BX7; zBw&%>@m6BcQUh+uW7hRMKZ^EQz-{Cb#dw3?Y7|Fdd(HMxkxnG;c)TJQzc+kpj0^U_ zcA)~woHsh&RV8y!qoWki+_^1oliJ_6aGxTQOBE-`ga(#y6R5|WZ$LW@Y@W0oVZKSG zO|IsRiD`$V;lu#0t3TtD$g9BVFUeD%ulgp8*b@VBb%4WGr)c8ngmMPf7ZiP35fyTJ zg$onD$b&iZF_Z`SC$1+|gQJ2v3M{Mc^h~xQmr9Zu6JI&eH7STw2$Dych1Vaa-7PDQ z+y&m!P17=vRrKqw<=bT+L-}V=r7?c!arzQ%B#pfF*OKyVfz!M#QmOPE%Y!WW4 z98o(dgy}Ue@0KNM)+W+ErEz<`Bt`5zrgPq7b6xp-<6J7RT*(fjDHLaMKR_b1iFt@_ zJ7;G&J<#)U8%hoB8u5ZzzOZRk*9T90{?cQn($s+}{y@)+>cJS8oES+4&mLHEa_V2Ij@PLC%45Am{{+(_2;4+q^oH)qOVE9B$T;D&_T zs7;LQqC#wWPq8&}Rg**tR)Tq*FsQUr0^rMvD}dhj+&Db4rK>sYL39>F3sd^^Ip^}s zF!p@n_I^3sZk7jU0wAif$nkTf%T6_J_N(8+16=plVa8%;^3Df{v-S)!qjQ@CwRLm8 zVx@rawgC7O0g=7-DtSTOYw)fi%jEY|bzO^nmscxyS1AV=25Z@8=Q1T={hbU1h`sw0 zV(G}QPAJbMa>Z+=zGE$A*@M^ax^J664~Aq9lde)}kKkZ)r1tv4CTR-3 zBPnJbc}ZD4euCG{_wst^;>uNExB`QgQgRCc8|LKwtVDiLrjmR8+?DP)GP#Gy4eVMZ_5E){h11x zgrlDC6Rxg+LU3*wi>k15}R z-vs~{0jPPaqCjz!*8hFrrq;M?0TvGB5y(L2d*w47_AL`dfNRX>~Lqop#p|lO8c3g zAY|djVqfRC=>|EjgwyzPLB^nCT3Qi)4by`!NbhoU6EobXW&;|Dz;T<&F59Wb0Y9dI z^GK<6-1N7)l4MGb$4g179zKU#)7qw*1}Ez*nBMXzRHXGxC-60e)@t(U#QtJv(_Tgu ze0jE%q{Xk+op|a({}q5^XY0@9ICzAk0Oge&zz8Nkw@67&06CYLa*|u%A`<(wF;dQ1 zd|LI?Cd?y#109%oDk_PD{^#WQy&=&+2WoCp2YD73e60qviLG64No#H&l8wlrqvWIJ zoiCL+c?LARv7wAq-a3Wq-4;Qc%okM#-SX$F&l25eJNYwi`i3$^%sa&uO@pazNZ3l3 zRwL~^zOAm4iPgHTHAmSuc>h?gOJbu75!a{kN!3A`)K+qKd>~B1?Ji-|Cq|Q+{p|)S$)zG7|cmnRWK%%+&`Z}M#RQ6=xLCyr%8T#h`XmU z8G34F)VY875faU97EQexvv(y_S@G7GQR_*oL4O(B-~#q&#wrTCGJI-uUSlrdhzsxE zDxzgehv2Yq<$U|4ukRV?Z=SLL^zY~Zs}kOlvRrdUYV7d(j6b)2pl{dH@`l`V z;i~t-?b&CM_34yP&_Os_Pa|TGIjXq+j`-nb<`#Eg$OwJ_`_X{d=8L#**tQ*$4~r(^ zd4sOHJc~dvXKMBFEF!qLzVhU39OZ-k&Ja=dAU#QfQ^71NHcIV!JOj1BZrQG-S6t1F z_;?mA?Ey3BE#YMY5jHX~de1L)M%ZPCIkExYLfHHQW73*0^$fLN?Z~-bmwZF$X42Ou zBMPbEm1;_X7~CzmX2eqdh~|-);)0IW^5fH2mpc^q9#~#V9?pC#BUO!e)_~XbJgP(94ed=(Ii1x4-y>nL$%QAoI=IM>t3_Dr)6PtY+ zv-gh+ZlVWF(f(G0@77ksuyB!hyDy$p7Xi&vL}qc!JM$E z^Y6tYMEQcESJ_E?F`0RWH8x9yZIaLnBz4I| zJ=c~kuQEVVFv5zu>dspb8HDkiml0yf`PtsuA+chp^qt8rd!0u3eLG?k>y~OKeW01r zkLL8|>fnK@MT=aY$W_L=jR90^YNI>uM-JRr2*=jxzc?#l! zLy`{GV7|%B$COU7Bb^ctx2$&%6~%Rv4gJ326`pXJzM(jO^u=9~Ia zD7x9YFvR&*Sju}CD0Y$dHvMpnRSlgsjzQ8EoD+|?tSgwa5Jf+mUZlh}DhI<}D>&(g zpPA@bC}xqzF1%DLAg@+=ZB4^a>o7OpXt+^|9LKw+G%kv(+`ZYX4G$)@(%T`RaV?Vpo#V7Tx>_mc`w^;^(XF<2B%}*$$3F^V(UKQ zYUM)%Yt+FGHTiBrKEZD zG9SU}%J_Xs@Q1y`bWPqT%{dU1XnKG!o!b}Ds(Vz*$*AM$y4jkfM&);u**sE>Conzj0MSw7GViQK?u={ zk!i6rpuPd`qASVCq)OB4dGD--1MkAq^m9?kfQytfa>ezv8{`Mg?tH|N*waZK7D&a7 z)VRw{RC~)EuV=NJuxgzn2~ct(k}IGR{jn06{AXvAJPc*zJ0D-hdwoo%a!YxRqO@z6 z2p4F%GYUUOyjRt|NO!j2i(AalF&6t_o&==3GQSP}q<=2Lz*O-_npQ`|!R^~J_m|al zpoRC45v@^c7YxfhPZaEZ#VT==l#5kMNnD`#!C7+$UDGnyNX+LvG-F=`uQIXVc91v! zo^8PVmX68!=xCNOkbzQJ6gy4jI(w30q8fJs5$}h+qF92B{SP4e;v@YAN&{ z`icp2>rRZ&QChv;=Z?#H0v!tWeWysoX};TiNUM)XX;FQ3cY)7gsvVrn#kLQ#JOR_X zvDS;pkF+y>{)n%ee?9JYhc?et%T-%O&FJ#JV0h)6 z9{ueC(R}fg7`E|jQgniW=8(UAQyF?FYm~6C@peZNP^38Juuf3k(X8C@LLd4zv%Aqy zoBJm5{X=V>0!G|*qLBH|268Ena{RTx271D9HpnAMou;F}s=6}&t(J~DWg|aiF<1zV z6TokNgWHRfXOCXAU(2{#uz3MunPGILw5gtfxKx+uOT$U@j`MA%^2zHfXA>koJbp+J z0KjzpXEuV*lfhm$WZ5(IqUnB@uyB#xhE=bQ&zXt(s{HA_n)LXa`Cf-P3y-^+I2V+n zF`;gWVr2tNi`dx)JRmVn$I^_Gsb}wW*Iu8EE6K)p+l?2@nQKCt|ic+@n>_E<#vTTF~TvS{4i#N$$?+fj}CaIAuFg z_(@uSJgKNZawkw_duR4Rm}Z0f1J~kl`tDcF<-1#7kk%O7_UM|B_4ldvDnD`8Z00lH zS%comtb4c9EPdI(Ji8xyxj5?+VMiR*S0xbTyY@o_h}#*a^VA4Zo9GeM} z7fD^K5UJ2`U}@3s9#II+-qN)>w5Cv|((s!Ft9->0V+#{DmkYp5T&z!KFW8Y$lS`Ck zG0*Yf^=fhIT(M*${pmf`YZqO%)Pc{>N!_g zOQl>zmcc=PUOZGzd2{>G#m(0*vvoSvf^bma4EQ#!>}k-qOv$;`P0OM>6@g4DtMW{WuP14D)HonVvE#Cw5=|#lvGHWSz8)@{ z7yaxG1U6J8H6RY3UVN|$JzBbM!F0*k#IH}uXU=xGy$xJ@{ZR+3T%gHf+cnKwJs<-e zp_B{T=&;8vwG`3xk{Jv6EdY&tuxATG=X*y@jw@-CO^mkdvA&%ratI&?OW$SxV_TtWVgcZ@vUz-T#7OFo;VbevTROZ5w$-~bFLn=>7j_l8t zw#RuSGYWHxPmiVsG`?rt$&VIG^x)(_2N@bX1Q{KE>RaKh%>7DfxboPxm2yt}Kx6wx z^p&B_S`(z!56#ebOA2<)8zu5|7rvQ?4R;nWMX*T4>l{W_xGhW!j!$aS)w-e=cN%a4 z+A7vjc1|(gFM`~DGe2lbkmFTfP8ffi*@=*zr5ESxqOYW*oeud{t+Lx5XLGopAV~wK zdxtw^VGI{2d2rsmx-WiK0t44=hcfO9ovKXG)&KZJD^OAC%F|t!9|jdHn^?T zc_+Z=UV098;vH*PN$|^4azgO^nb7WC`AC*haFnf;ly^6>E}!$m(0E!TuZEp# z)T*LDa!VGY|B6cdU_}qJYUH5-i3yIO;Ud{unDvW-j2OdOR0(WJKCYDmB z%WhI|9JV;SZCd#}KUa~RC{D^PpKOy=So~2mXKBAYT@@1#7X5KHQBaUt>sKJOMo!di zUtRp%O(|e@SiV*eXf@N(^ME#7Vp@Pk{o_Wc@AYM%X1PVZSGUn?gV%$SRgJqeff9PS zd?=}bqkXy0=8rrQnqUD)GZD0W63`s|bJh0F;au*EGA(N8K`HXl{nJRs0D>-O*y)aC0KvEMlCiW?iz zLmd^i_@rK75$Ex!UmAc~VGKR|+=0jXo&nFeEeE=?L-EFIjZ`JN;`SRkiUPrs)9{Nt z&=wzMmNkAC=;*#hx628V5mC0qmDoI8(Eb*VwOyY*7~J_Hf=fga1J8H9pVp&j3OeD+ z1?T7i)i$3CM+c(|L1V99>1OVvv`v1^wA{Hzyo`~e642YyJXLf7v&f9o0-7m)rDzhC zJd?T)A(tQ$+dJmfehb}gbNyAww$V1&HH}A=A{Q0Cx66}-b=Y22J+0Eq-XHgHGUF$= zpVnsRw;#WwbCEjKTrr(fq>Ac({h-|vL1gy?4&hL)*B z&pZ{l#CK!~4-)4Qy{T#IW)Lv0GaX)C{pw|iZ`tVLH|C^3r`?EoPAFW@W9G+9&bVCm zw9cj!{*y__rD}>(r^FSqD~RXYgMOvQ3J@klM_dtpW>O_~x)0X_e)*v$Smm+XGz3;W zd*r#L^T37!io>Bh2PIrKtcszW0bk|bhL^PJuc+MO%vP8)m`&^I%Uj#uY0D<<&>kT^ z^lkm3o@8DtI1nJ}vEF?l)-Xn%Hh+1?croj+ltZBL!opTW7I8@>MT{!NX$GRFIneS`Jy8Y53>3At%|=OvkkLSpI(K2}@S>;L|5F zG9-5&^VPmW_#J(X`z!&8Z^)EyiZvb9a@(rFW`&;&!;Al5>!_a(;Vt$%1HP^HLHWbc)PI_xDX9sfK%ee$xguj}gOQqulW z67zfY=C0$sg=d3A5yLaPTWQ0?Ewx|rVopYA@J`reDDE2?*gpb9gp7Qn_h$7yZVA0F ziw-9Z45VknYxgXx>n62Q4`eKQoAO4}SIO=`+nr5{i7_6}7abL~jkFVm6&e z#?toV`ZgLe4c-#A9IJ@8tHc8m6(_tfc4}1Mv%K!g>ibl}&#zxHH|dghbDAj|N#PfF zw)QC@d2n1o*9e=xAV+mKb~P{Cbv!G4chh-G{6lPJ!$?Tvo%6HTVRqX_$f~asyaE;y zk(6w!7ZNx#_K54KqWsZI0qAdd>tzY-A|BbX%1GAjlrEajU_Y*HLzBJ791&8`=^`*s z&3*Dds=TB|T(BvC@2DIo&P0gBcE7STB@JX{NveL5T-p_FmD2T!GgbBiF58L|@C&LX zB_+>YWx#5+7wcR?pR|AS&7Jk}HS22s6iXM4*F)lYyr|r%iGZY>ksJDjFS*&ZBI2mD z@H?;VDU+MnVo{UqhZ`XB-R1YwujW&(sgYhi$oe>gyL*K%CZ5uy%FugnG1x;OUgCp9 z&U?uFc?VCe!{dM4!*YaMfIKBu!y-(PM^a)s-7ziYvq0ClJp?64$5-ccf5nm+7}4C0eBVq$G*vI#f{S1xo|HL+LQD=kpJncs~bwO zFFds}?o{0@XE0Jav}IFWA(BW~J)xR=%<%>C>PTI#c_jBuZMD=9q(V^beLqeyPEX>k z8!Pink!t?*96gok`_Q&c#j~zUM3}08O{){}^26TyR2rA>*j+1iaatYZNLP8U<3;oK z`v{b_^W-D9i=Rfq+sd(fsZyU6k#ke=#p4}lYY#mf+u?A*t8yA)#&A*8z7nvJZ}fC# ztL4N@YON@>4es=jn@c-IU%p}d{*3=>W2yxHI0`o~u}O?~PbxlYK&T&M8*&AUB>g0+ zPF1jP!0!k5Qh4cN;K(UH{#)_1f8N8Sf*a}KnV#ZCUEFODGmcBV{WF^|@hFo+#I)_2 zu)(zulo#GaAw)>yvQ~C>98=l?1`G6%812ZV!iu}`P< zf&R7))EmvUdg(avDU4r*aP%f^IVDxRX|{U?=pEn!*usm6YDu!eM^4lEcR*u|u3PDq9id z+a=@1qOvmFAkDhBuVJ~~>Jakh)M|89bx&*`=9A26&zU{rkipfzF1!SEMoXh)@$awm zL~8nQw6S}4;l4bMX2O2BT5F?qtI$Jjf2@1vO?JJc+;c3g;Qq59TAuR4>~K=;a>}yJ z2k~kFtv=FY#C@UEJ%KJ8C14KPs`a0@!fl;s+EXHy&!Xbv3X1nRpCz9B2o#SCpDJmYARTxHFdGelI9>> z?wef`ElssMAy=r2Ta-@gR}*)3*lDYFs~+foWKF)%aQ6;um)vc$>dA3o{YYG*CR>u1 z{~^0yY|DfA^nf_kv8V!O2m?#f4-ZS_iH1C}tcmm!{vK&|^&q?0cQxu;m^;)v8Zjrt)}%aH&JF&W22S=jPs~^N>oN zf)n>g?HA6xdv96ZIL)ZIehU1OVUx>F3s?XCOb zm_cpA@pL6OMK%_qE0J}# zv@EG|^F{JIMz*32^aW)u6;3SEM_&EV*wHlqVd^?jmTl{|laNDs^#qW+ky^Il*Ryg5 zKfUlUNI6+CDFm^gH^!OBO}v^`r}X~Ccqa9dW~04*k@RLcx+^7pQoRQ$u#eh|Silc2 zES%3vNw{pI1IhFE^UB8NMe-Zkt6N@x+b=Vf`DBxg;j~N{!7qOUB;5YFh@pMP^lq*Y zp?Kxu!w-W8t(PuieMkMDs@4s0zVHkv3V?GHp&CP>uv6( z)Y0SblpZFpa~hPdPIguZ?0Q=*&b}K60L1+KKz$0HYY(%$Om|JaZdFXU0BuMj2n70a zYPVag7X=r^c3hR;EZH>hr0TH>3pF?2*&`R@cY0p=FI3->=s!KiKK7r~uL9FBZ&>VwzT{Z#3aV>L4Xrp4 zp(vIi=8K4=>aI1szB$io|H$0>sm_hwV*fVQ?|av3?glZ6X+;L6GV0}jE)@xS{;{`c zulq^Jtj4?5p>P9tT$9b{W0=tccf%Q2)W?%a=>C1rvn`T+^lV4K`4M>9AGs?ruV?4& zqxS6_n?bu>rNSIp_x&+~o{QUj$D9fP@DTht?~R?}(TC4qwQ?}OD`PLdO-$!~KiH`+ ztI)*0sYwVepAIv&1)gDw4ja~oN6(9&a5lGTt*7s7ZC00%H#E(Cddf-h0!&kp^z|eL zJw&yd6Jj;f8#j3^5v2d*&4uB~I5_3x0BAvP2iJ?wPZ@a&;IP!JKA%J7`$eowqOo;3 zllyfC(o2vV#Dgv37W0si{(Bo2Qh) zl)HD)sVeoU$5NpI-;he;Olh_@L?s*EGWNm(>1uGTQeD3EZG-z|5!2DGk&SC|0iY83 zvf;S?F+He^SVLTl8>U%V%r&0eL+w`n8?8=_T}ZF>SmXKlrMeAOX`il~)1uO$kFJ#9 zMu{Ei*EboGD|uCLGW^GNWGkaMn-OZ$(f#a~qhrO?gae&r8g1S7{avzKS5hyHz>P{v zX!TTw9a!sceEev4iwY^YZBw}QSsnE#tB|uT((0bZOl7vxHYrtFg43<%A9C#RA04J< zk6@sT9P$B>GDRE*kE>JdK^{3eS%fDQM&xw;p8xX5feP5`Bsiu1I9LKb=mC5XkhwjX zeaq^Uo;z}E6bFks-mK;3^t&;t1r{e{SKoep4kK*Jxqj&Gkke*r(Mqg|BzG77=$-yR zB$mXHc6lKgjPM@RaOOJ-mN2<6b(VJckN*wAdWAlS~5ns!m<)C%F zHDs7VGsPJ5jSTW$yKB!@80hFcBXZlM(IV68&|#Rkqt_mf((*DJh-wH}-&Pa4Tp(0^ z^IGk1<+%>SOkEQ3uM(4ZTvs@dm%?xEi3XUIV7_!y zfMj-zfDCOMC6L8aTX>pAQ^d`S37a-i?sL#)#fkmSxKMLAM~B0}VUu((TSds)#c~S- zyy)O0$wnV&Rm$+;QCA2{S+bwUECWxk>fBme3en&;Ej)brAcsXg?h(0P&d%lR6Ybr6 z&xzAq_5-3RlD@zk!c}8zpOMzHRVO&tSEi$JEg7vUtJEp&$5$*Y-2+=ie@q@^)^PTJ z*ms#$EhzDrB)0gR;AE=js>hI~^A_BbUzDUjvA-bZcNRDYoT7cG<}dzYul6qa7pGEo zD|Y?mYH|B_c0S*8Zb!B9^si|s(1*s5S1?V0yU9tw89X~`niCsbn|gYNJ`&p(@)f8M z{5t8j)5J&5L^9mgJEsO{PW{}M$#5C`}rr9ZumUU z=p-Y<{|5N!BqD&*6$87|9mczI8VYJLnv9hQW@T*Vs8v2ZEvaZwz8cLuJ`9@CRn%Qj zSl8KzyLHQ9#lG!yEivu^E?g8cBBS)3kocBl2ae}FQNtfSYB6lyi{76@{ZCVPD?DcZBKl0 zkAkHuGptzM$TyyoYvrh0I3G@pdimMC+1RIM&nYA%px_3b-2G{imQ^cWKi*xjR7H+$ zbP^nE0;VZ*GGF~>The$G&xxG}qjqge>bI9G3fmL%K{DGZ8?u%jA0-NH>ML#o02;q; zFLZWU`D?vBRo@~|$QIhwn8|<>eU-b%EyS-LJ6t*`qLwRDB;N(y(FzE4~ z?@&}LQdE!Q)u%?EaVN28x@|&FYoWE=Z*lKpQeb{A2e7+vpOC6z>D%b<3lYsTf zU06*OujJRUr-(1Cbq$1?zKqM??}eTDc&{%!A{A3R6@r$=sXOcy`k8E_PVof_0YBn# zNJ5T*H-Q#~@f!*`gxgqQN$&0H+Vzh52#nYe!iwmxqm;*=d-=t~KEvFvJq_Vxq&Oxr zR8HR=c>TiMm3Mq3tlr@>^hg_zd_CkfLbDOHqK)J9V^_4X7fv1bfn`y^1sTd&<%tr^ z>zZ$Vl8e_fC`GyPo+Ie;LAP;r$MzzjCm(q-!CYLZy4OkmBNJ7es(5ls`v*KJtR8A} zY4K)$*;=$$tJD?r>b5(kTgmotmiHv%`Z?Rq;=1iNn!H!#GPPh;NVR;4yms~vyWif} zm{WC6x|AvlxSO$4V59pVGTXa#W1b2wQ93i)b$m;HEJbwSONSf|F2B+$yET_x%q$TJMdk!JC2;!qGB{r4>}j(m_S57xuBkP)TBb!Z>_9J(5FuhutWHVO(EW zZPr!gEF5NE4!^KKV!Hn+rdN6R(tvGeM1=7hR+c0?=3?=#>D?63=c{?b&~et#?aujz zqt)g+<_k2`qk;L}VP1z|d$6r*x+cR3%=aBkxe#ck$WCuI+Usu6eLfXga-v?{`t6M? z$*b|xfmv=ZU@2B)P~~#nM`;mib%C*u>Ng)wKQ8~k6$!nKYLOgQn+t6sd`4JD!z^Bb z>Py8BOq~7#Ofm`jISr3D`A0vR;vPDfxR?I+#{mgmqv~azCE<=g(WFw?>Pi)ojJ0#XM| zsM};L_@*?_Ei^Ggo9=yucf_kxS2S~-RaV%{^t9{Ck0!_+ec;%H%|$x&?7{|^y&gT& z0@oSITd#Ov-+z98^!aL(Z_mEb$w&9)nsLHqNh36y&Vnv(yDq7pY+=^=!AtG!*wrB9 z4kC0W!0~uaAhmuUXpFbX9IB#7v7mj}{c2%JA5XZBrNVC@o@XFA%CT=mL(W;an@ zsqaoIQHp6-Sdci@Gf2;!qnrQ*dKT15wpRP}v}USnQGw+mY;Vm?Y0B*!J05p8-G5k7 z%vHZFY48ziWKe;EfJXltPhTC@^!xp7qoM+$prW9lgv1o2VMv#Bw}9kGX;>J9v`9%y zNjIZm(%p;!BcvN7w!y}>XZrd6oB=bR_WgSN(+)Z zDB+3t&N6T6_h%-_hcvbq6hInkt<4|?!Kuti-%7NbHAQjRx(MIfvmq3%yIgyK=DBhU zzvV&UaD963%Jqyhbm-nrb()ZYa8;CCK})IdT%*r~JQS{9g)}y$4s;NViI3P>?}6kL z_S45(*EK09_3>^m%Di^)a&y(;dz{};%3ADGll+R9JGp4g2du?!ba`-7G?fi!%P0T< z@;a{X1V{)tg9t-cKO$<5sJHj){QUJ@Bl|QGISw1cBoAy;Dmc|SzUxV_VN79k^@ZMl zsHvQxDS%>0{1|GVlwn$5B)b23BBqedLs?i6p1Jm-2FNK~5?zzBURX}e-)|$Wt5=|f z^|p`n-LFl^tEj>&x2=A;YsN#dYLwz!L}1%?c7W^HOb4dW@XZ8rvMF+I(u_8{wF7g_ zAj%2o{^wB{DfXgk0Fldx58}GT=$=JD0mz4d5YokSvzz~BTEIuQI1cr*kWUqi$?|)b z@`qAY_w5QRrc#p1p3gYxNCPw`+EM%&C#oN(rk&2jCs{MFz32fMM9SNmA0s!uDC7;` zJ%yyqRJ4LV4(>&hXfwMe19%fHjQv)|a0x7EiK;{4(liS(hyJ9{5^cx&v$j4v7gKRh zGJ%wcCKEp6W+l)GYA9PZr@?4fDx~F6Su-N)hpVA`-u6-rT>){LBKr@({|;r+Fkdi~ zyuZ&$H~pQB@wR<;5LAXYDh7A6-Z!qpY^4_#psZpk#Ya@$a@D1ihE^c_e)$>&%X{CE zYO=d*HMPbveUk<2NqwUonlF2Ben154R=|qZ5;bXP46X-zY)=)W3=?|_w%7N`@t<*N zL=3WV0W8Kqt|4|3na{n=`ir{zTynV}ku%RKZQY3=&iUiSvHn)6*T-Hzp5fR(a3Mmo z9I^KTW%&CHRFWLozNb;k+`Ofd?Z)we+d2(R1FmVLl55yK8obDuVMhG3%BZjI+*|{G z&X8^H6v}dS=kJd#B&-(OC7V}6@_Eiuwvyd$rT=aM`QQtBvJ^=a7<`(csbW&8xB4l1 zFfT59zky_eqVTyYFssbu>U8>uv5d!K7iPdO56ZfcS@-3#1sQ&~ymh%}SQ{Kr7b)?r zEl1eqp<1G@EPGk@3j*X5r-F;ahOz0oJM%L}B=vEw$e!Ddu}Xb~`>>sh)9g{w->R{r znZ@;A)!{Pe8pid}SuKuiCvLIDXIrK>1*F$gK763SRhfoPWAHcyw9wN!@9!Vl zOX&c(8#Wm)M>P>VJfm4%1hK2J zr}RgqoY%;z+}1u(f0SspE@jx%RKY-Pl;0ZMFG8Cw&H@u;L--R12~v##2YVUD&Fhh{ zChTvD190;f=4Sm5A*OUB&o9c0MNet%-!8CnctgJ5t#E#GTE;NeJal-Wp@MZ%1J#%f zHGr|_N0RrrvipoU?01J=+2HP14~b(MUS~V22(X%Gr>mvxOsq_6Otrhx=HHW_u3cJP z!s)Zj`MR7|P?%ZpQkVXbTSleYa%TvVD&|M|5#eaToRHMWGEZFFia|5goXzNK)38<* zF69j!J8PM#^IasnfO#A#;(lV1EN&NALG0S%0u6PkRUTFr6&15bylUiM(NpKYpa6d- z(O_kA=*q(dfqfwq_6m+Qf4t^pK!^Me$#Tz=Hap0y6q})awIIYN9?_bOFONHQ)Q6B3km!S^5zhVdBo#iPXpMx z<{}ofJ7l-tkpj}|9zmDG!5EEgLQo(H5)hMRi_QpoyYcOwE3%OwyGoga1$yrqp@VMM zx-HEw>=Vb(bwN_o-Xy>2Vv7_2pVa#U0_6s7shmZi0O9d(&PqC%z}oieWftc6U-kPB z!Do+P&V-{OjaU%i3uYW*Qd2#@GU;=wdK)YIA@h-u_LGqYU-&~mw>*<`_r7(}A(<8T ziBuS4=Ra?+wAvEiypDR{m9W-2?3Rhck5Hl!GkrH6P?430cKh0T=rRfCG?Z&`U35SMzgc1)+9E*uKEa4(yYp6 z!KHb6Z}W-z3VpBffVUOh^kg`s-&C?hAbvM}Wss(3SeVB2Y;P+BAc+8PZGrmp-b+80 z=$FgpO5`!SQ)@$c>N9-1Ex0pKHY$N36$PbwkXdImK*kWMy#%P;&Uo6tVvbi);$1zF zMK6fpLKKBu7aXIeJ?ZpvTvZ6mk@8HDI>`wv{RL{)Dx`$Kxva5)aK%I+sZk-7c(r;> z(n0LD2%-)+;QrlVr|R~w5kKK(`1#S4$;M`>>3(Qklx})+*;LW8APcTvWUiznJFnE4 z_@{u033t}_u@-TxVGv~owrw4{e9lerpO3;d^&U<3N)>vE<11;?)ny){CpPfrx)a-t zj)+Ogk2lQE_teC57wO-*CLXC351-jxIC$DjaA?ZE@iW-P%yn{zJlfYADP`n$*4N)p zk$hA=tg3j2U)1;>`bW+|36)hX&X}NKezw<2lkR(h*C~`}t!Vt&0UKQ`RC@ykp#)W% ze1BN=>|c-5zLj3*hy8OA1v~2F24!5M&+$`M``*+1vLf;FbrzeZW(g!_nVYt@wN9ne zN0Y>9z%`&l=fuAuVe+~hP$-x}q3g6HJptO5rGDKrg4;A&S=EfsY6t>w+JY^~+KG8K zN6@ne85ipp>OA);H|{*K02wfR)(-ap;$W@`u6sA?ZvKC3$v5RXddFQYL5&eJC+;gn z_{}EZ@H>9VL(290qkktTa9Rt*3uAi>vqJ(Nd@s_McxR*R#K~pr75&opU^-q=INb#5 zbkw=3vEw3012~i`>)qn#l2zad#*e7x8A$mrEvDtE9JHC{enrMyz1i$bE1n%hVdM8E zz8um*?~$Wg0@nM97hZq$Vy^^gqm1;v97#L;&})A z*%%SEhg0ze38XH#M->jQDD`17sMD&`pB)%nRu%;+*#lFQV;Xy=rX<883HR+{9!CR) zTALYEJVR|K_1t9O=_=K;6R`z&=5uSGUG6^dXc&sdN$PZs<)I&T4O@BQmW5G7$(}6A zD)R1LKwfx1`A!I65WoELg%oXEznEE~5MdrfFL)rqM6%BEPS6;KM?02fg5y3*i=k{| zbV?OWZBM^5v4qC}EN7CewQI zKY;h@xwnoy#D7sdd6_ADNxcRBw&r%R>bz6cD}NSf2QntQwsfv`B|W(9w^>krC(v=p zlo)8BkypeJ^O12fPyf5J@Enf%%_u%^xVctuVibO)O4D?>uTRFZKu9A9DAuABvOc(A zae4|`Pf))y&+zEyQSZg-p7JFrp&u&0on{;6B`D%%Dq!&)Gn9@a7kslV=dF4tVo+AB zD2f1iR5+)1T>r;q+&l8OiJt>zawvwX6!!8tX5{onwp?T3*AfZacJqSfM)?HY%QuW4 zn0|lZ?0OVN8oEd7Yb3n2+xgzx7H>3sMXQ=}@m2ohiz!pIGdF51|68vQ$3A zND2tOd^L%5uK04u9#n<1fG9rld5XbIj#X^iEs*Ooe0Lbh=2ln#&sVY_GCE663|-k^ z^WIz;y&AN|#wmYW<-?m@A#Z-}KugbOeO2OjgS;=t&8r?b1g4r+e_aFd)_Nzyg-Od> z(Xjn+5cy0T(Sn^5AVV=8CS|;7Vcf8L94}b4ewRk(NBsVFm)5}C=u|U9b+;|vK&7PT zc&*O){gad3z1v)c*{HJsI>*FpxrO*SP&$&*;1ZI#JunWcC8d!e_gqC61CRVQ^t+y= znpbR>Yj`zFE({Yi(QDzjNvIPh6R+kga2T6OdrK{*|EtdC#$i#S$_w;yWw(L5Wjra5ooJJlhL)C8`0IKZeCy{ss@A~v&cM5J=Hz!UT0C=9q!U z*ofCkFD+SgRWI}WX(KTBu&~&^KXiU&Y7kS>G{5Yd$)OyqN>zh^V@a;CEflHILPYZI zLrQska{Wtm$V-;&db_RjPr!D~x{owEY)lE>M^od&q)v>RRiT_A{#iLN&;GUqz-L8+ zHxmEb@~lEMCWbaS(ZUqEvQ*U{?Hq=~+dX>_4>OI2%l) z2=&d*jVu{=fRfFt#VuxVE6Y%8i?aN~X8e|wy_S8(8`ST2r1d}IK2VUIHRj#%k=GU@ zlXiSU?^Iw;glz}U+n#QV*N8j~ukLiqsTSZ?@&h|;o+Qo`M6D~&-jH%Uqge=!xWt@$ z!8{O9ZqnBMr8~RoB`c|jWcS#Pd@FE*uqm0H@ScFrq?xVrB`d0MAyVI6pu9K#p!xvE zahID6IzxpVAGbnUR3CFj{HkbE0fq}C*cuEnyK{BzxMqV6@>wwG5?q(^e%WZ0S;UN| z@@#bzR&UH44MZIO3X(F%|H)lX)NoG2m=GxX-BL!c-o+(jSU~M^#1*GnRP{S5#TUC&CrQvp-M8T~RWerEy8f^Z0U(!wBQy#v1T8@6Wi7^hcE* zidB7ar~Y{^Z8}Bx63!aISW~SxzWu&wnQygIU0Le`)(sU&<41r?giTJ z2>I*Id-24VGVx$}?S_Yd8|HI?72>JGn1NR#*UMVd&g+GPm{4!n=lp7R=Ut9!p}O4g z2M6Y^>3JzP&_NfTn7Zu7!H;TcH>(-c$i`6-IFmyqCMRp9k4>?Pmz z)pu?^lRxM^VrKGc>B*WA?DQ+XtR}0WJ=Gf7LZWiicRl#PuA8Ib!$b4i3v-UlLzfzk zkfDDrUsC0(_Y6x$z0PqB?$B;2m!w9VowasHAz(O%`0V$c{n1G@GJpDEYRv|Ov)^!zn&C$xdf{a>IxDTeP493>dhB)2cOY(!Vzy+0Z&49`3|pSR za6TQh)ww-Ae-Zzu?rp$)(#zYUv(v#u!;W|UDI?~D29w_;t0v>>n^o-B_n);!1skgr zc%9le*T1)aB|srG{ux`z{P`o@8F{D9N9;ATY%D-O0i7M5y|2Dr8d33zMDZPkGkNrg zj+Oz40(Xr4?KsY+R{wPz!UP$ij%&Q8IVv zp-R;kr6dylY|A_+!S!9y?#d$eMC^Ch2Usat*MfbNg<`AR5*~uBPuVt4ABzizeJR@t z09Xy<_jh@%dZG}9#huMUML&-Tw9(*XZi?gGSA)y7Zi~@Yy7%KHJkZ_+?f~+eP=E(9phZojI?&v5t{= zE6SKXUHa*P8PgC)bSY)+46h{kfTGRDkxoGtUg${Kn-+~8r&`iPwTo!nv6XayG#m*= zlXoytj~AX_c;H-=pnYrJYk6nUXXk7!-e3}#-B%wX#uWYoUpZAK#r~YleJ$mc`aQt4 z8|igTDHXsizUo~hmE97oClV^n%|Jf*(+A4gf`QGYeGR*xFQ0g%TT`-9&X?2lX$-%;fu-b zhlVc}4-y9^ECVQ>^^e{Ar$=auUE0iXa4 zW&=!P0c11dIX^5)3b(Mcl78XbtkJ(BNJt7UkF_shJ+pd!3@+9fAtjQAH73_z z%J7#Y=tf5iJa>uE@cIb3s$gpF=Y`P`XVfRP&ddo9hauz5Zy3`VS&JWHsBxFzC2Q|| zURU2k;+iI1SZ&r@<}nuyG9<_$-RaHs&1dD2LKDW;nf@PHzf`?u>f~>@QzBFao+vko z$c#qGkFFwGo^%`(!{nLXIaT^DzLvWM)q0%R6kcnl>!UT0$w7|E$1e7A>Y91fMdzzp z+4cXy$-IyCa_RO;h~Xgfs%|I3>|R+@PX5)uXpcp#hI;n3lB6c%)}K)WjA$k%i}ZDi z2e^GVI~{we^Fs_5XQmP@4EqRm5&buetporW7A=hIvC#+f90}l zsYrLAtS1IrvNn~wehYd+LijHq@zH>)yg&A38G~={rjot=XKAWw;}JZX-%cQ5wv@h^ zQvTqB!_D>#jNYcrTVtJU=d{{gR(3*l=!Y9Jn34Op+hax^xpS&L!c3gRhsbx3ztViJ zsM>4!m8i^k8gw4yS|%%L{J3w1RnXZ2abKB^Pj`afUpCx7)iGRA# z2*39^%%rJM>lTq0^hd;47>D^_!dBP7>-e{tF#?vXKL^Yv9L;kD`QN#K2&PAr_uiQF zr)$#|YYsEannHm;F%M*2Tznw}AI|$z!(-Gm>+Nfs@x#vHn-T>Ymh>W9@MZuyT?+Ic z_2S}5-@fd1BEsUPVw_WO3`Q_*_rY6HEp`M@q6Q1eDOHF^?|ZbfZ2c~jZjj|#>yzod zqu#8J=NhY;A$^QViI}qX;)_VCRp=#yv&Ek8Dvb0Dg=+LulWEEVuV}lSs7N%;+IP?; zi|%W3hD^J><3gI+HJll_pV13=S2BUzKi+haOc;eYTeT&3sxu91t{Lu`rK{+VhVxU2j5hoRf+sF zay>-eCPP{1$Hgm%-^}l9g7nxsLT*eOI_sdc`>{+#d8JM7f5&9+H<2Pd$53V&3isWi z6Cy42lX^rip;h6_#d!C-X8jcNEd>AjpfSA(>VU}^aJD?yPXTI(bABQSFsenq#JPlq zF-WZpU3NdY6L7HNdTm;&Rsvif*Q7kC7jIx^W7)X?y9M8`XdE*EZz}!>d=}I@tJ@x9k}%tr~0N@583mNJZ&j zW4)0wnyVEeQcZv6auor8kM<#TYXGr;jW67DtR*qen>sZ7JbDf_>YU(ZPvy!ZjR%yh zo8$MHJJOw7Jb!mbH67sv_O3P0NV9f8c{`nu8)V%KeS-F9Z2BVuk7kDEw<`?nZww^P zhCm3ohlBiClQmhGB=hMmNlV-|t;c8!JjAAJlT*}Xh`KWAWvB;Z)Bv`$!VGt|%6;$f z9qvJ&_p-%gI1y+F$0H{~i?UY0f}lN#xktB80ntb*{c+=sXt`z_%i07YEo~t zKbn00fAOP?0x2Lzq!ey_DVeKk`sokBq;$hA)VXR;`#8f_pNa}{)g<`z9qW(J#@Lwh z5}{7Z8p+Yl875+)Pn$i&vE{e8T1S4#SlMX#u&x@vKajF-Q25w>>&CS>ZUD=P;b}&q z#ZU*#l&EXPM1+%}u-K>BC zO)RAR!_4Hv=w$Bx?Zotxn>FN%zb^el93>AQk<15D9E#HrwygPe4kZD%@2<>SdK0 zuRJr{xoBSx(!!^Ob8`SBVZTS0_YtJ(qk1gKK66~Ep>*rnyFAjaW#SM%7Q)e5CO-je z>A{YmODVZ4gdxTn3rgl*6pPjz0!S)P9z*6l^DSOfoS4@1rM21VExj?&f#8E_(gc`t z_V~0%%X&GAtJuUXQbW19hX!s`zU(%ZR|v_aACAc{TDxY0la zn=r2^~&XEL-bA1I642Okw0p1V4VepwtMAMf&JB1u#7 z;Tz&0dCJ16SnK!+!MllX9{qyg64>=icRPg9Y3}A!GaS(YDalsT zO}AaDj;684g~#8Z)QzKvNj}?dZ}GBJo(!_f(MDI5YP6Yu=4r=X{F>!9;g9}Wr(D+v zHI>)LSg?AA6sCxEoyVC=R%Upz6v59)l8-lG=}s5x1hu#22ViTMv)daxjWD#3C~}7rT~& z(uCXdbZ;0&H=^;WeXtL}l4{|@w&CCRuq5SmPsGFeM5J~Cjm62}FnLW%GDZC2Ik)xy zuDHYKlEFOE`z6kd$Ne0KdL8?vwNKJ2Ui%)?YhZK&T%gAN*!s1PN3iO%MQT{nF+F;{ zub0Oq(Ti40WL2nY)jms#N4{9o>~V_rh31Sm~JQagTrjwpX5!}fuTmAk!peC0T->xPnO^XI$Frl?*k?~ z)O^j6Yt2wGOo35P|Lkj}L7L4uM0V%B_ub7OaMMA3CaZe7qEu$ZShqK&Yi!wkv~2X` z(=5H@v3-T>;9fvPbgULVAI~56kHFhFR7{ID&hS%C>C*hVQT_G~BNZQ|p&$L*%lXhY zzoxhARJWU3(eJ3$Sj<+gp9yo6kNgrqY8=d7M>L-ugb(u)=cYAqMq2ky(i8haXr`|Q zYJ#25YuzN~dK%CZzD z#fgBCX6@UD5)5i2rt|O~pM7*u$U;5QruN)ptM8@TrGTe9tN|VwZD$u!TErtl>tmqF z#~1x>&t2}?@ocs9J+^GR+(EuTw%#7vkUZVqH0V1ZDWwv$AMW-^!~8Pl;5;C{`}FSG}VYW zG1PS^Whm}`RJsQ`X`diNRmcTgwmgDKVSA&5f^O&FyqFZe&K_X(-Ze~@)RK7gq)BWtK5QQZJ^ zH`YkpG6MMBpntQBhdkgzZj6Vqgpq}k$oEh4-)+Y0Kjo8&kD*rs3c>ePEL2C=s(0Pg zB@H9qoY`Hj{v_5ib0dM1)&id3UnS~&sxb*Hrk?5c*W-Z(381_5| zU&(vs*fU!jZ(RoA4Zm{k#pQqPY53hRY(YhWyIyCR73*{yDd4>RS24*c^~RucJn)2F zkJXQMz}iEmGUEK$@Nf+wB@q5S)EOQew9u|W+Ksc2Y%LjkFX5ipmYE!wkkFAf z=vK8a15~cJhF#P%e^Q=(Pe|jw&(Z4VycGuGUMNCa7VhzQ3s5@3UNTgR?e-=#6`VXj z60#{~AEJc&K-9$GJ=_nB;M`ga@T9}${SW$6dQ4uNI*UcKUNM-LCPUBpkBPl}fWV(? zHeUiG4~3FrIIe^#E!Z;WEUUVMy8IJlH_Qj2@w*BVtj zY8t_lbnJncEPo1z@!|MZ2pfxw_7Qy;5>DI@2TgI^EQ2Z{~cpI!!wBj>%fy}mvX~uTQ-*bsybnhYrA}*`S3wl;+k;&Aw&7y zF9n$=DuIdGloU@%IA*I=G4(gi7&;H1mR2YwZHP>I#oAFwE2{Tp(>SPjhk@pSR)3qz z?(#!F+~hb_)IM;tk1z0$)uf^1YW(W3Rj-id;HG+|1Z1mPRo9Pm+vBM;El-25vD7Hv z*9Spp-9j^Gd>ssaD!=S&PnXp^=T+0xzodly@j!lz^bBdBf+AMh1BZK@W-O~=jyJ-9 z{FB+B0-Mu~dH~Jw^K&1R{{^AD?hKU8edA^I9p$)9B{1q@C0cFZ$Gkd;sl<*6Cz46= z1}Qq7GkYCL=`FUOEZ=;`)O^}3?M2s*5$|Wbz+KQmMWT~;hxlRI!xspm+V6UJx;V)5 zxo<9+ib4Lo+$`D?hm%bRFG@hfabpx!{MB#of70y3TGUsNq_XX+B^Tm>18tKmQ>2ou z!|R4hRMSekCofP}oN|dd)XvQ%4ff%6jA1I%{?dDGby0VtPnFJ0&@T^Y0@fDlMo#4+ zTwjXM`dgmS!lhdv^VsbdCYE&!DXIzf8rC8ZNvmSTyLxu;xUu3riN^P+Bv-zfB8qiS z_wN}X_Mi2FaBn7tMnPQgm!njdoSZ8`#>a!!iP|cDq@sRuw<dF* z0;WvqSVg}@|Hs|@sWCuD99T;Rfqg6&bFAf*D23lEDYI*vVl=f@y(d&FTH$^?6?$|H zq9P@nluHj0tmbIHxbBpi={|Yogr_P!0eD(l;c;GKNh2w-HrZR{Ci~=@wu*+WPbv1p z!I9H9KS;QEe%ooePaXaqkQEnd48&>SB$Lx!4E0 zbK-uD?O)nZZYn=oW8s7RiIg(MJFS_pGmM>FTx>3|A7eIjZ?k-<6`zMP()Y57k?D#( zeNBB+TvK`p@^Kt&=b5s6w!;d^{wp2~g>P~IPS;N@ViSNfP{o%P1N06pM`^`7X`u9~rZ?WdyA z_yW8=3&;q37Hx5!vPR+`9}b)8Z5&Zj(bpC5E5#SYL*|j2dh*we7 z44q|E{=LOIE928!-yTR$_xw32NW1%Ry4v8B_IkAC0cW99HFr3xya8#YMe6zjBcFeF zum;P7V>U>};ORU`` zhb(ySrZ_yIQr8LHVlc72F9;W(Flfa0;1SF|*)tkm?K2z#mNi7h%Owr><&yAC<4<#4 z$2lb$ewd&XHq6hy>`v=e^vk0{T*`s!<35WyOC7YdM6vCcS&!OYriwEA@j+PZ$2l{M zRXjGv=()QsU=0lh9TZ{TKMbxc$@yp>p}Bq>l{}i<+j7U4pLoW?&AIXv2VXG5ACw3T zayh>_naF)e(h}Qsf=W)f3)bnk>$27N6nO2KL~{FRzO!L!U`+aib6y;u0zvW_Z|(N> z7|V7~CVkGRgPTl((@@&UK-XrG9HE_*5|Y4!lA4aCPZ;-k=J%N@5?VE7%*XS+Q3jNe z%>|Ne)Y4p#&Pj7s)6V4X+$1#q!TTxuPXh%)LOiv1Lw^M&>x-aoba-Y<-q)!p>*c)O zW-}+MW%}7IMxNx@`oUE`5nW4|dXxp%Qq(>nSf<*=y=t_JoM^0jyoa4@_C4K5(Fly8 zIGeBjonu@#YhXU;;GpM43a{h4oEUK$CC7Xp72a?%J!!FRItWpP`Ha-^OUO@7eyWy% zaMlYPr$8=bGUE4?>=KmDMu zb{K%XLY)sYQ)}g>h3AlJ;r^?upQG(QHQnJ&#P&*1Zd1{ z=;LmAnKgpV)vOMRlr4;kuk~Fw`4v0r=--xNeC*#gPY^Tb7;WD(7rD{=^LNIb7Qv6A;eM->lq54m-QjDP zvd{-w(ZVr*EeD_L$3invHt1e|2^ue%5^t98<>I&F!jIam_nQw_`ep|0LR3JEVyp+b zW5@EG(p>EVOwU8+ev}tEmz)?bt18dbJ-7L;8>f`Z#60XUc=@@=^B@i8_}Z?eg}R54 z>i26wh;OqN46H1tbBM@WYTcHoYu3X!e&{Z74SNP&o!Yi=7sBeAQ*c!3e>iG3BHuh5 z|5eXHK3QeN!eHNdI4=dME`{mv{0k>`dH53$sq4{$+~XW%dGz;3U5F<@iSyCyV=;`t zq`SsRp1rG@$Hwv|HJ7~~KBe=IX<&48^8WP(P48HeJMR=_25crRVw>Vx$_DY#Ut{&+ zX7^svmF3w#5fWIjpt6tMGPu$}n!yN`oHbm&gobhxRHSc@@SPqsPBAgrd{`XdGf=1J!ZsWai6w!R2 zgEFxEi8}W4#m2u=iOWp)c1T#PhlFo`kO2FquI{1 zQFgP};7^P5`C?7nh=E_spl%z)c1MIRa2Ii;6vEO}$Z+nR=(|z;T9io}eni~5(=0Wb zXUKdtk*}&(;-Ggewk6u!6m!39oR8%y(Ko!l#>P>iS4TV@WjG>!Wj7KD;Xh`yl4#gR z*LYIfaN!XR>kqmOq7WoeBKgX^%=*Q1b?yIREdhcl`ieSMPY!1T7WLFPk(bQAJF4(9 z!N$PF;=)^FVQxv}^4AGMy20+RJjVL#@-TZ$ zXZ>>fVSa_vUGU0zBkEgHf*D?cZX3Ca6(ybCrW+SU&5KL^&M0Q9p(m7$Ab)cP0R@`6 ztSZB=k>cZPO?Qr(&#}49pS9=GxMYCTXFyem!{zg`=?|nrvbfz}}rId8PnN)t-hPVEBJ)`rMd<#R#t`2k>r3x6IIuN0flC^hBt%EDvkXCDv@E8-T1_&j#Pbps-X= zcibi6KfGIr$$h2Ag1wy6LV|`#to?=J++px88yM8Zi8Lp9+-ehQS~aPny1sHi8?ScZHf_-PKU_ zD;l_7pwVuhPJkH}?LzmOi@Az+lr$RYy|HTmGl`d;Od~0xuX(1FZqE~`Tehc1vvgV33 zC+G|K+=7AJ!}I1A9LEap0VUo~7>|&I=cdO-g*bc@MZIarjfaaJ(^WKO99 zZ*r}kf%RQ%L_c#9ntlaB*FjI4$wVU3>6b-Ez>UWs_OFfcUjddk})R}bGu#5 zxoP-*1_pBs_X(Fl&je%bT}_s)Etj04K{3ZNhUrgakw59W1NzDeo&SW#B9$N79d*LH zXPUCc`rbBjW_1u#6;jd8WQYa>#CV2rNelX?Qa9Evu{yen6jg*+rRHO5#|fi_3hK6- zx4d)eG-L8@GEE`P!e{!G%jSR;b_MW$L)dv8!4Lc&9mH6Oo1c*?j!#I(SUn2 z*;l5%`QbHF$X?4opF6IaCpYkI(DNuSd@?%o`UdD^oLcvbq*SuMOup)v=@Bavc zW%sv_A7<95R`N^B=u_uPuwN-nHzRcHGWCP{qGr5ZbKjV-sD%2c*NQ)_yl?`|-)+3i zm*&gR-gGz?rybSgvAz8q8d<_q^P^Jun&70a{;x?^P|Y2);fh5UVTDT090nY#R?{ zu9s9p{t!P@hyU?=>$`50lM+IW4vE|`b55zMMv+zgb~NmSZ*xMnpE~G8#t(h(eBnfY;c81+87s8F=b0;N!L1Qnavhw|P$| zrkq=FzAgG`wX3{vC-srR~?0D$MyZ( z?t3J@*O#yOF+Zgy!|U|qOxB{Ppk1V)Pqx-#1vc_h@6H@zc>p{+NyX@rYAANNMnCDz zlzZfq|AW$~{Feiu7*6F;l2Tnbjex#K-+wvk$Xi>Q2oGN{!S@1f;>f?+KHRozU739r zZc7|}Du#Pn<6IL-b^RG2qk?y7hGR)g&xw*WK-cN8b{eUqwJh(|P5mUy8v}<^n$~Lk z>;33jQThdEW5hdwZEd})NMH+tklBhld@Aod9P5tczEGG#NDx0P+ZBA7TKg`dFei$(Bvo3)Om+jd9{nU$>KQ$r@3y7S4&1;PEIcfZXJp7r;p7DA+uB zF=ggRF0f`EATp*Td_srZ`dU`;#ooHiu)Y1()8Ve|UvheCGmLZ$ z?KgJS^06Y{o7XiK)g(?WlDj69bCj=i=<09%euCHZG;v4GJh}>j_N8Px8{c{L7W&QrO z{u&^|WW@V`GvA>Y8ux}AXtO>yWosK|Yo=iS=N*Q~f+HcF0vCC6?Z>^ITZYFY_WPBz zr`iLexW*00Mkb*Yc)u&Y_sY!Fbxw4G^^7RvwvoBt_lHG7lZL`-#5eP&wV5-~BpCJV zEz|qO(iTi}N^WMY_-|eg&jNE17o&`&W_KMp$46#V~B;I)A-T*$vlx@&>)`Y+X z8a0{zIxhd+bc_N5k@Kis($$!pmP+8`b7f5p$0J=CuQGZonZK=9{29Ehhw1hgiZh6R zncMYhaXNNYeLp9wRefgrEa=dZjzd0^US0ns`zGODWcXb z&bZky__b}@-pRDyknY(Rd=6)FVrFab@qpXY$z?6GoE5chXEz%SrsEL7EuP}dvIvuS zzwV0eZ7vmB%;DqVj{(8kNppj89BSD1oat?7dK~aYwdY%ciKHG&cG$MY_FbQ5Uyr5b5;DM-~QUHW1jp@>|h!Fw2;0zv7sb3`fILLU$vIcE2(L) zJMpDO-~(W8B5RZIIIiDZ3g@2u8+opNWCW1Dk@g(V_PHzgKK0<%ZW_GSjA+G#hBoo- zd-&g&hTc|SoHJ>OV(Wx`e|+s*7XOwCQlWI~v5(%dfDNxP^;8^iRn36g$(OmW=^P@3~taXM6>G)yJ0x_4)eeW`sK^KJlf{e2`i5o|--3 zHYF1Vg9jL~*X5i)@F3VM^*H)yB9c3VaKCj(j+Zi#9ST0%3X{CIby1ppL^l|^@a%Ud z?CYx|&K{_Y{DS(M(9km0&*b^gV3FP{DDUn1}Nn`ExP+$ z{jNt59U88ye>Q?TQz$GevvpPJVc;8*43u|0h*IlypEu&;8I)zpzu;V*8;rM{`t7+WF1$n_UcXX5Ys4nr znGsv|^Ol;9&P%piV}5&I%TJLRjz@P`es?bg2{BDev;491|qpL0{B>*H{7DV-q$u=E7&MXz-+0-^;iv_Xng5hUDdx~R212a-U@URCwpiF zuRBD3m};I)tvi!BQnqBz@KwCPFX}$#knUU+;s6nJkXOblx!hh*k2vbBE55kvozQdj z$40fS)$>?t)?rSGYI;B+kIZqD2bT?L-tDpGdQ8o5DdZ5J8&AcWG~QD}Fncz2xuAuz z-)J*_19@6gQ9WOVE$231(I@bGq3pUT9PlaT<1HrSK)DM)L>prAnj+aX5qEKp?R!Kk zmJIcGqNxJvhV*F@9mFnWEpldm5$f64&S5YsoI#pxgXl{mPJXlyyd>>L!l8*uZ@G8a zP6y=@-rcz0?Mkp1P^zjt+8L`bKx{^;vUJ*)gwH!uL~U>Wm3hCD70<$QEo;pdW5sSv zYQOiV;y4uf?dd^^_~7TxyphwydVA1igI56z>GD5UI>5e55<)?)4etZ#v90%AH7VH5 zH}yC*QCYRho~&RxPunMUH=d~>sanEB4=3O6+R1-@Yd)0HIQW@j{U8so-^W1|fqqVS zyJ(e_f$c%`hF&{^6`0>YvFzq^JAyX4PiLmbKyKt?~oQ(l7A+3~9RD zQ-#^9g%z%m{qoPIUCb6JIRxO#Ibq~yi0995_i!9x)AekCKTAt+6h7&pD6Z4iD?nCi zw``_t$YN3C+%LKR#l4k`4=>GP9Wyg+QS#TheiV|f`xn4X#pY5SWyk!MzFxTAq5073 zz{oybu5bRSoknEzg?>r!(Kzfbx7jAhCA?-HQZH@s z-#BQ59gih8Tz&tf4;V$$)|gzTM^^dtg%_$;0*T0&7H>$Tk#~u0eJCp86tFdIq@uz?-{4F zrWWBGo!+dEl(#EFUHC{Eb3AR-apOcxF;jJOzW!)=B_NNFf_snWbDJwIgzFcxgn5{sq zRTj#i^%7v?;jzp}j)bTdtY-kt{n@HG(VOR9y!>~D)Xs902ae-JxaEg_AjjMMzIiN| zlTr?o1*F)O7@8`3cwW&rRE_)I-Y?FZ_B}9CC3JO^yM1kB2b;4wcxc4dJbY|sf6ue^ zvOI!3-+6Ps-xXjc>9Ns$3jrY{0c95SN5yewGtW!zuXl7Wy&Dgin=y_td$w_I(zYPC zm>De^u+dUPKHN&OmMXCZEl@RR`9j{b$+Nb^*?ZnX|39A2GN8%+eft=QinM@8Nhs1v z=TM|1M7lv*x;u7*A|Tx*ARyAsXqa>}X&EuPN3*f9cy@dLf6tq}zpiWFIM4GqK1UrN z>r#mCW!|_TONaeAQ0Ag34*y=?^~ihf^A%yDXty;tQP7+pRBqJP8ghW%eKpLjX_7~gH)w_!hB|Iw(P`yams8t2Dq7h#WSwM}i>coY@lf*GjN_{RI$1-_ z=gdO5EB%|0_osPm`-iV5y*gsX#vM`Out_p&NAhnqG)kDhs%)vvQmmeF`|`D+dy^<%q7-K-M9DG=HTMNUkU~%r`wix)|s~P1U zrA(YPNxO7bgI)osx2O=kO*;k)<7)gMzN!@|uhr@*px4QYnuR%V6_YYPQpK!CQ4Vm- zQS`Hfcg1L0fZZ{EuBHIb5mHM*<8uS*a6p#h3LqksczC;Rb%-+h{GrDurLH@jA}T3y z-7+t_kQZ3F-gzZ{P%FVFaX2R4)~La~)zpf&t68lj(2!{U(vZN0Ng~qERk3qC78JQ5 zyfvz9bBq4x(xY5877i@&=RD7RWg1xX^p7;Q(VW&am{#@jfNzcnNi_=nF?a?FQ43%3L*)cjf`8lOkmp=&~`+O|jB6cAq{!*3d7hxE9h; zInwlX18~zoFRzL;5*D&I9A^(h99HF~McPW`8>oY^ZOUp`g|Rz<-fO2iYLf2AZF=&h zkgc4^mC#ehQROCxua>jy1*_^^0^N7?tRR=(EKA-Z1t8>3@rd!Y&x?1#TF5FzI#Rk; zKZUTSW|Y(;H{tW*+p|Z#>v9K-AVS0F;?jbjL>!_|mH8Df;QZU@f2xI`)PG#=^wli4 zS3f%fnOg5YW^hScf*MeqPRp2QB~-;#CB@c99G}*CvANy8mgT%Uf}aZ`h`<&> z0{yzR&&%|q3bGJCj9NRrcDt$sT|0y4?U9Jf!It=XF|B3L+x0J2%@n4x!SLZvZtWNo zCpYlb-eb~1V(ud7!i5!(Wl zX}|crJ*sx(v};b0wSfEQ)$yt3GDm$$yjbP4gS)*ti-wp*<{Mg=S3H7G;%M>_68IzR z#a?6|kTEs7?IqsUNTv{?m4UR^-I;Tz{=miUVN`C4wNx*aXZmS$uL@^vR zt)_(;k?hy!;e)Q0GjJ9rg3S2J3AQKH&}t3p0+~mNJFUSd0}Uj{%b0a2HlwS_7uH{5 z?@>`IJt=LLdzF1${@UNfjlW77&p{=!%WlKDGC_r6 zx=YrXTXcn~1zlCVQ6rat8p%5ul51wyR3rn-MDNA86BHPxqme(q}H^THvK-OKZabX@Lc0_VFB z9p5idXM!T!+$7*?Wb^=tt!C}Q=*{09Cc$R!&eAsMz5Y6k^T&ur?K1l@2#ms_mhVKa z_-5SWkE(!nxu-&AZVx!`IQk{aM zf{LM+i2cLd`~?r);|9{LIS>d*<{SRYDWl|VbJWms1!es4t&NSsJAIOd(=njo=vs{IrUT z_J4_**v^Pnj(0xrMFs=ZpN}RzqHChhM+mTgC46=56=!J=D`mOmF$DLI=-x*QVkedS z%ES=U2s7CR+?AP}H>$$S4AOgTAu%0N_f^8I*1x2OG}OK)?Ja32FNTqJKFvN40$r@x zBqhpC|9YK!Y}@T0-GpVl1fCr6T1dDtjBZ`kuiEG0_} zn&3M@(0ek#kJ-8owc2(oEhO&BlaM&V=+VCBA5BSqP7{BwP1xM9dXdj(as29|bY(s& zqS)FV%+mB`zEO{OuJ9m}jNmQ&FHAFT8OLWI2KW<`VXP{N%-tePh)kr)IFQflEN4bf zWIRoSDUO*kcMiqw@CgMm2MUAJFJy1h3Qo9Coz`sF_jvu1OYt@2*1qQnpeg^Zg(|}B6bJu=bOodUt2zZuYr-}%L>+(M z>Fg}u-}@IlzPw~iF#y#5SqkCAs+7bHc3b%+1&k4&MWf}d-uI_r#V}bAKFuwiae;d` z080iKmB|QmV>x_8@h5uC3TE{wymN^%W4{>t|Kh&+Pi9J+E!EE&~l`(Y}l|$sxhiY*sSx7R^oNs z(yR^4WzN>x@jd+zUMgxmy&(P}11KH3NjmZRNsnKSZLi|->qW#1Qej@grcnvr7^yJ} zSUbu`Zap|`73%YO6v1Bu2L!Di5pETM*Tpqeogo{0wU0N~qd$(Vo&CANxBt^Ya2I>4 zopBK7+1cr>zEzhInn#V~Gy}%KB>#SZ?k+%G7L&+XOIbiNwtUWAISkv&v|lX zcF}fE=4|~hYU*?tJwj~gUl~(BExn#2aIFCx=pI9j}0y$`0wSZY&); zBZQyhDZuiB{&-_oP>fd^BETASnRB*Hxy96Z^T{>+ z|KizXL*Lmecs|Q?;288x{jIlnjPDb4xi$D_nPF&vXT^!`k^qtb)rM?s~9hM|U&kD6)7@(=L2jCW);h%!tds8v4-+^@wID@RPwvgV@dgMEvB`} zyvf&ComvwI8|pWS2eT$gzfmaNH*D}_=*lNFDN+B8V;s4rRQJ3!Rj-X)eD(xn!QSOD z9OQ?e1DvV9$=+zVx3qIeSI^dOWhW^ISz+^Qz3s~1;r;}#swK8*^Kca85G1>z2|H@c zVDC}0KNo*rCZtsF1xp>xa68|+9Gru7VaF;d>(%SA_4Okqu-DoQ&2wEji*50AOrHY} z=?rX`A8mPKA}#QkxKStI(f)$9oC`MUhx2t!W%I1Hv}W~k5UP3ZXb}S^oFjl~l*_0& z=-2^F3**_%d09FS9WmI;jTL77bWSSmwuDUzblS@VaovjmKKW+9%NiFuFlmBXg`G^W z1A#*!8fe?S#Tr_CjH(T`lh}o0gx6>M&pDN&krWy_ulf@7?XbKq#A%G4(4+pV2DPRR z`;AMJe;uOYhB)4$PiI+>YWFT5@ekY64sX^U+&Lk=V*2BLXVCLe0Hc4>uq(f#Q!^d^ zr#T-C=Tg1`{g*EKM9iI6Q+GBjuICH;@8dcK*o_tz+YwOopi>$6J7AS-3HewdwNuB` ze5UOzZ6y!)%9fL^;>AJDZX%8w9xdm$4K6QEhc^rYjr|HbeADM#Wr9vtcr9eS@x?XF zge{~5w2C}-D1kXA(pNkjvper%Yz|C%72+*m{GzP*&|Kp5rAzNs!>_Bd?yQHX$xB67 zCQo`5+*~l(nc?S_j-TRvz7^7sK8`N6eiZ39bMgJn1ogMt+g&Kpi{Y}C?IgAlCnOr& z`;WN`y;lLWI%vLspesBPVvlnBdG2u?<`5usB7fat8h_KOV5iUN>Z4Qu3^>G)m7f&> z?w=a_1S=<0OG?KE6bw;5SazfS@WAIT&&5K*m#bzeOha+IBnh2v=iIdOQ9;PGGpJob z>enld18zFxq|TqYrm9)TsciOiZB--V#pRZ3!OkLIe0(Q}?agu+3GDB6 z{j2?8ytub`roN-=dVOT=K#))opw!(aqWGto_8`{_%rs50#_+vllC4Xa$qSF|P%}9{ zr1joiBWJ@q%0a4`Bz`{4;vBE1$^S%c94cb2p9jF0TN%lM7M7rnCAFOEGX8%wE1%flIBsba5S0 zV)~DbzMPWF(oJ(Q#%Gzw-RWRppCqS?#!1O13tTj$Z=W21jmcf}KxMtek&CmToZp2P z#*S%%?+`SlV^jGc0@B}&_WFBG_J(ggEL7I?eq7v6I*TCB*dy+BG6z~fb5^t^?PwGp zcm26I`ywgMIM9sNj1-dlOEsAEpn5`a-96rM#3gS2zZ~veipC#Bo<_l3K#oxH3KRds}U?>n(t>e zfDbP1IMu+e3j)1R-RyP5RCsHJ0+4O z=KBvx=`ZKh%@(s&WAs0LHy)XqobO`qbQz34%$fb+(3!lYaCM95?@7a4u{w5J_uek* zhsVL#)Ej~UQchT;f1+l#|5-yZ+5q7s$B>4LkfgYOM=t9at{mOC>`yK8!ti+gjo;7btd@fNCZGHo)*fXshJJpKAq2{YIrRRUhlEx$f>}*fr76AA7(|<-rz5AO--~s=G-77_z2+=Lm?_GySky^=Zj*aWw^{ytDO~?+% z3=7e2Qb|44g-~m(&b%PA|C90rT* zF0^g!w<2|3OhiQEkyA#(k+Kj(%y{u`+!-XHOu&!hkPt1#ecMm`C~$M2cq3n*&T-c6 z=^Ffdf*}5&h8)>s+-D`9c9~er*y{E}{2Nco2(&(3IqIxA$Z>!_Zg9>#{qHvilvw>i zlrBWf4NBZ6`lb7y%HCI~WCw^)u0(IdO{=j^-@E>#Vyb9x9`GYTsnj{=LaEPNIn0B5 zS$;rZrbTR%?t-mI^qvKi*3FELY%p4N*H4#T%=4^6Y=Zm#A#uf+-qs;nh5J(9%lTl- znzdI%(H_D2jS7C=$Vfza#p{j1zLqpNrdehoW zO+cup?poF1XcdJSvxpf=&&>PCAVb+Ae&r`Xz%h2_IbN)qCPmMroE-+Ge;NxDkkOlz zE01EMu4v1@CS=&ERjpfpF5agIZ32j&%eV^Ez|9FTa1I;Z|zW z;ox&Q$nalxnMSxs69848TLTd%32$HTn>NvMKQ?eXrr2L@^rAPuz6I*ExR3pHj3_HV zD4C=?F#c+Ox0K!Ww>x|o?kwCoTym+n#XssakOulAUdA8^G6lOMH|on%)*jb>yiORL z#PS`Oc;HzeoNB*GcRjq;4c<9Y%b5(TA1cdAB*+#SEd==P^^xM=%*#3NJVd?%y>Pgr z09N80oHFO3C5%h|YG0ZaXz=Eh=zBGxQ@4kZ^x%X#tb~_O#dL+VhdV!*JJ6!ut zA=(&4GLBKH>tl3lkeuf=V(MjcitUF(6TH>yy{}GFs*GzN&+2m6ZXEF27xlSfS-pQ7 zS0){k!pQV+fN(_ZF(VeJrfhy~oIjCT7?%?bT+HvwWT<{XQ0wQX{g=eZ)9}{%iA?z0 zm16n~*1siHT%rcFN`fVu*KzHkVX0W>h0l;HSj+rvo`{z7{JRdXwd3=V5z7dZXc9KnA9`Hzt6)$+B!;nDz!*guY z0aUizZ*g^p?7hZQP;uf~n?N?exjOvEI|I?@E}4P*y~bcgEU~rLmkRG`0;cE-BW_ z%cM;lO&U9s-W>ArrgVv9%c+7FVPGp}f-3*ob=<1bFW@`Um9lc5;Kw2Q>&MaR5zKLc zY<$Bb&S0rKR54%i1@LuLhi4K)N&1~LBNG7}y|p^#`u9&88r(~1$3odmwc(u&`5AJX z;&;|>MN&&3OIwmwAJxAsceJ5bR9+}|Rz1#d{FxNqhRx2K)BVYdSc@BP?^6^Jo6$Us zi)v2hyRGnUoKAXM{^fEP+(`!%w`UEXb_~(nt+5D#cTuc#1n%0bC;QEA)6+S3*Oqz9714`ZEsF9n@ZLBLAD@WmP#6{IO z4}_2sefawK%13wly`=BVX`m|C&gEZh=!0>@#xU?7$U^s_Q54f5Ngcaq`|g;F=G$KMKNY9qv3_dj$~Kmsy>gmiqWQuJYmConbYg3At!@We7z4K0x*;0sWdoi@gB>2+L^AM zZIUyp3<)lR`1<~i^F4KpUHn32*X|xiM5KQ6FSvP1EgIEI)dolX3!^?Fpiu`+5S^yu zB~jJ}>(QRant4t4&R~mPGPzBD_CsIz1A+*_WPxV@K6lgI%GECDm*DprkFLP45ap~Q zLXGz}xa^YMjWUg0Va8HI(lf`u1V1Q(>0UHbF@1R~c`$vd@4etldYJgO=}$?#h@M5l z*>0hKlH10Ch04j6HZD!u^_WSfuH9pvtN7i6dNKQGIH9|1H5dBYeb>6ESFBzH9rKt} zI8-{5bpScioc=o4Vxo|rIRI-g+CAP7(xHUXxrJX+mhW|+R5T(X)c=3IgC=xX32eW8 zh8*qiW9d#)|96@9MzZSOf3V4)aE!>#V7A^mzuEus`wgqLZ_xuU>N`JhL9Op8hMlJm zr$S48QU+p19P16;xnKADz#r@WIqNoY`%x%1nG7d6uY`A9O?_GV>89{orn20JEZ>3e z$JRSKyvvOP*ssvrI)g5mWs#2)ZfupjrGNNCrEGZsj2P%-Ef+VKsR3rD9#uA2LPbmz z+`G@xqJ+GWr}iEz>#E~jr7zz{zQ#>rdrac^QIAlC6Yt;a&J}aig!Cg%#o}E)ePANE zIO*%RIEnt*`>(^%CnDX zt69I7|3<^QE98Ze9x$+Odt|)|uA#r6(xvh3 z;oaD|um*r(`p<+0&#QrEa@pF;V<*pLQ7=(?=f%$^yVvkZM2P>6&$D-mEws>OfmEo) zG{~yrX5+LARlOnhEvJp`f}eQ2oagz-q|O|{7<7wO_9BT!+{ypj z)A+9yBlZ70XJsbKl7j48L)PU)e>f{4O>$#Q*q{$j6is>lQ-l$j4$@Mla$<>@Ma9A&>;Nm8j>n z<>R(A9>ml}c+x0wbicefZHSe^YXbfF-WsYI0Z&GD$XVJ$o95xq3<|2@?ZeeBODRBW z!Kn{~TX*NK7;4OGeliYwXdN=CqtD%zN|e&0j$(t8UE9!;luMs#hWSBY*Mt4DZKzF7QjbeN(C41{;>GqVcgk(OrJI=#)e1r-{B1;o;In8%DXK^D)y+oq|r&U z`)K?)Mx=m$i^U~FKx#Ce{^UtOkF-@8`cWtkO9{mR?>HAt<=eb4wgYP#v(f#w^m^O` zFW7%wc?AP1)z~T=W|z}UhYKWy=!AZU3|1L?`xTd4Mzp!_L}_r5&A$lcm%rcU`vL@) z1`z<81E6*AjJ6wL%0Xy7o_>F#2vmR|lN1%LEHdgJq0DTDXiP$Uf3>v4MBzV-U21$d z@>~gfO;?_O7)1Pf-444%pA8}{DQW^?8-sj!8RU4BXP+kFh=~3g8(+<`j^${ciRGE# zK8ggmLcE-w#Z$dYl4X4PM;6u}Z3D4lAyZUSFvP=mFo

sGrh!~~xsyLxJ?;ZS3tdNgx;3gLQm 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 SOS#qpA{n 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 diff --git a/assets/graphics/icon.psd b/assets/graphics/icon.psd deleted file mode 100755 index 9c89925527ebaa9bd0fd4edcbfbe16e2032b75d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1073805 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%0DL4}^kS&WZZufOtq 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

ubXy&A* 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 diff --git a/assets/graphics/icon.svg b/assets/graphics/icon.svg new file mode 100644 index 0000000..091d825 --- /dev/null +++ b/assets/graphics/icon.svg @@ -0,0 +1,78 @@ + + + + diff --git a/lib/main.dart b/lib/main.dart index 2d79ce8..52cdebb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.6'; +const String currentVersion = '0.11.7'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index c8a940f..de8753a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,14 +25,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.7" - archive: - dependency: transitive - description: - name: archive - sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d - url: "https://pub.dev" - source: hosted - version: "3.3.6" args: dependency: transitive description: @@ -65,22 +57,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" - url: "https://pub.dev" - source: hosted - version: "2.0.2" - cli_util: - dependency: transitive - description: - name: cli_util - sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c" - url: "https://pub.dev" - source: hosted - version: "0.3.5" clock: dependency: transitive description: @@ -97,14 +73,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.0" - convert: - dependency: transitive - description: - name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" - url: "https://pub.dev" - source: hosted - version: "3.1.1" cross_file: dependency: transitive description: @@ -230,14 +198,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.2.2" - flutter_launcher_icons: - dependency: "direct dev" - description: - name: flutter_launcher_icons - sha256: "02dcaf49d405f652b7160e882bacfc02cb497041bb2eab2a49b1c393cf9aac12" - url: "https://pub.dev" - source: hosted - version: "0.12.0" flutter_lints: dependency: "direct dev" description: @@ -279,10 +239,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "4bef634684b2c7f3468c77c766c831229af829a0cd2d4ee6c1b99558bd14e5d2" + sha256: c224ac897bed083dabf11f238dd11a239809b446740be0c2044608c50029ffdf url: "https://pub.dev" source: hosted - version: "2.0.8" + version: "2.0.9" flutter_test: dependency: "direct dev" description: flutter @@ -305,10 +265,10 @@ packages: dependency: "direct main" description: name: html - sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269 + sha256: "79d498e6d6761925a34ee5ea8fa6dfef38607781d2fa91e37523474282af55cb" url: "https://pub.dev" source: hosted - version: "0.15.1" + version: "0.15.2" http: dependency: "direct main" description: @@ -325,14 +285,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" - image: - dependency: transitive - description: - name: image - sha256: "483a389d6ccb292b570c31b3a193779b1b0178e7eb571986d9a49904b6861227" - url: "https://pub.dev" - source: hosted - version: "4.0.15" install_plugin_v2: dependency: "direct main" description: @@ -365,14 +317,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.5" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 - url: "https://pub.dev" - source: hosted - version: "4.8.0" lints: dependency: transitive description: @@ -557,14 +501,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - pointycastle: - dependency: transitive - description: - name: pointycastle - sha256: db7306cf0249f838d1a24af52b5a5887c5bf7f31d8bb4e827d071dc0939ad346 - url: "https://pub.dev" - source: hosted - version: "3.6.2" process: dependency: transitive description: @@ -830,18 +766,18 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: "9ba213434f13e760ea0f175fbc4d6bb6aeafd7dfc6c7d973f15d3e47a5d6686e" + sha256: b6cd42db3ced5411f3d01599906156885b18e4188f7065a8a351eb84bee347e0 url: "https://pub.dev" source: hosted - version: "4.0.5" + version: "4.0.6" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: "48c8cfb023168473c0a3a4c21ffea6c23a32cc7156701c39f618b303c6a3c96e" + sha256: "5dd3f32b5c2d8f4bf9d05a349e4a65fa718eb137f396f336c3893d558a58fe84" url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.3.2" webview_flutter_platform_interface: dependency: transitive description: @@ -854,10 +790,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "283a38c2a2544768033864c698e0133aa9eee0f2c800f494b538a3d1044f7ecb" + sha256: "87b6353b40e04f04d5f895a484ad6d92d682d9cce4d2d5b32d2d8aca2448d46e" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.2.0" win32: dependency: transitive description: @@ -882,14 +818,6 @@ packages: url: "https://pub.dev" source: hosted version: "6.2.2" - yaml: - dependency: transitive - description: - name: yaml - sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" - url: "https://pub.dev" - source: hosted - version: "3.1.1" sdks: dart: ">=2.18.2 <3.0.0" flutter: ">=3.4.0-17.0.pre" diff --git a/pubspec.yaml b/pubspec.yaml index ffbcd1d..a724b56 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.11.6+125 # When changing this, update the tag in main() accordingly +version: 0.11.7+127 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' @@ -64,7 +64,6 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_launcher_icons: ^0.12.0 # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is @@ -73,12 +72,6 @@ dev_dependencies: # rules and activating additional ones. flutter_lints: ^2.0.1 -flutter_icons: - android: true - image_path: "assets/graphics/icon.png" - adaptive_icon_background: "#FFFFFF" - adaptive_icon_foreground: "assets/graphics/icon.png" - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From 1596a44ec56119cf25e2405816a83c13604c6b5d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 3 Mar 2023 23:31:21 -0500 Subject: [PATCH 074/600] Bugfixes from prev. commit --- .../app/src/main/res/values-night/colors.xml | 4 ---- lib/pages/apps.dart | 22 ++++++++++--------- pubspec.yaml | 2 +- 3 files changed, 13 insertions(+), 15 deletions(-) delete mode 100644 android/app/src/main/res/values-night/colors.xml diff --git a/android/app/src/main/res/values-night/colors.xml b/android/app/src/main/res/values-night/colors.xml deleted file mode 100644 index 604d9b4..0000000 --- a/android/app/src/main/res/values-night/colors.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #1b1827 - \ No newline at end of file diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 9fe11b8..49e21db 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -294,16 +294,18 @@ class AppsPageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Transform( - alignment: Alignment.center, - transform: Matrix4.rotationZ(0.31), - child: Image( - image: const AssetImage( - 'assets/graphics/icon.png'), - color: Colors.white.withOpacity(0.1), - colorBlendMode: BlendMode.modulate, - gaplessPlayback: true, - ), - ), + alignment: Alignment.center, + transform: Matrix4.rotationZ(0.31), + child: Padding( + padding: const EdgeInsets.all(15), + child: Image( + image: const AssetImage( + 'assets/graphics/icon_small.png'), + color: Colors.white.withOpacity(0.1), + colorBlendMode: BlendMode.modulate, + gaplessPlayback: true, + ), + )), ]), title: Text( maxLines: 1, diff --git a/pubspec.yaml b/pubspec.yaml index a724b56..c854b49 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.11.7+127 # When changing this, update the tag in main() accordingly +version: 0.11.7+128 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 2e706aac4750bcc9650ece3864101c61d7b9bdd4 Mon Sep 17 00:00:00 2001 From: Darlene Sonalder <73744170+sonalder-darlene@users.noreply.github.com> Date: Sun, 5 Mar 2023 17:16:48 +0000 Subject: [PATCH 075/600] Add french translation just added a fr.json with everything translated --- assets/translations/fr.json | 271 ++++++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 assets/translations/fr.json diff --git a/assets/translations/fr.json b/assets/translations/fr.json new file mode 100644 index 0000000..bd80501 --- /dev/null +++ b/assets/translations/fr.json @@ -0,0 +1,271 @@ +{ + "invalidURLForSource": "Not a valid {} App URL", + "noReleaseFound": "Impossible de trouver une version appropriée", + "noVersionFound": "Impossible de déterminer la version de la version", + "urlMatchesNoSource": "L'URL ne correspond pas à une source connue", + "cantInstallOlderVersion": "Impossible d'installer une ancienne version d'une application", + "appIdMismatch": "L'ID de paquet téléchargé ne correspond pas à l'ID de l'application existante", + "functionNotImplemented": "Cette classe n'a pas implémenté cette fonction", + "placeholder": "Espace réservé", + "someErrors": "Des erreurs se sont produites", + "unexpectedError": "Erreur inattendue", + "ok": "Okay", + "and": "et", + "startedBgUpdateTask": "Démarrage de la tâche de vérification de mise à jour en arrière-plan", + "bgUpdateIgnoreAfterIs": "Mise à jour en arrière-plan est ignoré après {}", + "startedActualBGUpdateCheck": "Démarrage de la vérification de la mise à jour en arrière-plan", + "bgUpdateTaskFinished": "Tâche de vérification de la mise à jour en arrière-plan terminée", + "firstRun": "Il s'agit de la toute première exécution d'Obtainium", + "settingUpdateCheckIntervalTo": "Définition de l'intervalle de mise à jour sur {}", + "githubPATLabel": "Jeton d'Accès Personnel GitHub (Augmente la limite de débit)", + "githubPATHint": "Le JAP doit être dans ce format : username:token", + "githubPATFormat": "username:token", + "githubPATLinkText": "À propos des JAP GitHub", + "includePrereleases": "Inclure les avant-premières", + "fallbackToOlderReleases": "Retour aux anciennes versions", + "filterReleaseTitlesByRegEx": "Filtrer les titres de version par expression régulière", + "invalidRegEx": "Expression régulière invalide", + "noDescription": "Pas de description", + "cancel": "Annuler", + "continue": "Continuer", + "requiredInBrackets": "(Requis)", + "dropdownNoOptsError": "ERREUR : LE DÉROULEMENT DOIT AVOIR AU MOINS UNE OPT", + "colour": "Couleur", + "githubStarredRepos": "Dépôts étoilés GitHub", + "uname": "Nom d'utilisateur", + "wrongArgNum": "Mauvais nombre d'arguments fournis", + "xIsTrackOnly": "{} est en 'Suivi uniquement'", + "source": "Source", + "app": "Application", + "appsFromSourceAreTrackOnly": "Les applications de cette source sont en 'Suivi uniquement'.", + "youPickedTrackOnly": "Vous avez sélectionné l'option 'Suivi uniquement'.", + "trackOnlyAppDescription": "L'application sera suivie pour les mises à jour, mais Obtainium ne pourra pas la télécharger ou l'installer.", + "cancelled": "Annulé", + "appAlreadyAdded": "Application déjà ajoutée", + "alreadyUpToDateQuestion": "Application déjà à jour ?", + "addApp": "Ajouter une application", + "appSourceURL": "URL de la source de l'application", + "error": "Erreur", + "add": "Ajoutée", + "searchSomeSourcesLabel": "Rechercher (certaines sources uniquement)", + "search": "Rechercher", + "additionalOptsFor": "Options supplémentaires pour {}", + "supportedSourcesBelow": "Sources prises en charge :", + "trackOnlyInBrackets": "(Suivi uniquement)", + "searchableInBrackets": "(Recherchable)", + "appsString": "Applications", + "noApps": "Aucune application", + "noAppsForFilter": "Aucune application pour le filtre", + "byX": "Par {}", + "percentProgress": "Progrès: {}%", + "pleaseWait": "Veuillez patienter", + "updateAvailable": "Mise à jour disponible", + "estimateInBracketsShort": "(Est.)", + "notInstalled": "Pas installé", + "estimateInBrackets": "(Estimation)", + "selectAll": "Tout sélectionner", + "deselectN": "Déselectionner {}", + "xWillBeRemovedButRemainInstalled": "{} sera supprimé d'Obtainium mais restera installé sur l'appareil.", + "removeSelectedAppsQuestion": "Supprimer les applications sélectionnées ?", + "removeSelectedApps": "Supprimer les applications sélectionnées", + "updateX": "Mise à jour {}", + "installX": "Installer {}", + "markXTrackOnlyAsUpdated": "Marquer {}\n(Suivi uniquement)\nas mis à jour", + "changeX": "Changer {}", + "installUpdateApps": "Installer/Mettre à jour les applications", + "installUpdateSelectedApps": "Installer/Mettre à jour les applications sélectionnées", + "markXSelectedAppsAsUpdated": "Marquer {} les applications sélectionnées comme mises à jour ?", + "no": "Non", + "yes": "Oui", + "markSelectedAppsUpdated": "Marquer les applications sélectionnées comme mises à jour", + "pinToTop": "Épingler en haut", + "unpinFromTop": "Détacher du haut", + "resetInstallStatusForSelectedAppsQuestion": "Réinitialiser l'état d'installation des applications sélectionnées ?", + "installStatusOfXWillBeResetExplanation": "L'état d'installation de toutes les applications sélectionnées sera réinitialisé.\n\nCela peut aider lorsque la version de l'application affichée dans Obtainium est incorrecte en raison d'échecs de mises à jour ou d'autres problèmes.", + "shareSelectedAppURLs": "Partager les URL d'application sélectionnées", + "resetInstallStatus": "Réinitialiser le statut d'installation", + "more": "Plus", + "removeOutdatedFilter": "Supprimer le filtre d'application obsolète", + "showOutdatedOnly": "Afficher uniquement les applications obsolètes", + "filter": "Filtre", + "filterActive": "Filtre *", + "filterApps": "Filtrer les applications", + "appName": "Nom de l'application", + "author": "Auteur", + "upToDateApps": "Applications à jour", + "nonInstalledApps": "Applications non installées", + "importExport": "Importer/Exporter", + "settings": "Paramètres", + "exportedTo": "Exporté vers {}", + "obtainiumExport": "Exportation d'Obtainium", + "invalidInput": "Entrée invalide", + "importedX": "Importé {}", + "obtainiumImport": "Importation d'Obtainium", + "importFromURLList": "Importer à partir de la liste d'URL", + "searchQuery": "Requête de recherche", + "appURLList": "Liste d'URL d'application", + "line": "Queue", + "searchX": "Rechercher {}", + "noResults": "Aucun résultat trouvé", + "importX": "Importer {}", + "importedAppsIdDisclaimer": "Les applications importées peuvent s'afficher à tort comme \"Non installées\".\nPour résoudre ce problème, réinstallez-les via Obtainium.\nCela ne devrait pas affecter les données de l'application.\n\nN'affecte que les URL et les méthodes d'importation tierces.", + "importErrors": "Erreurs d'importation", + "importedXOfYApps": "{} sur {} applications importées.", + "followingURLsHadErrors": "Les URL suivantes comportaient des erreurs :", + "okay": "Okay", + "selectURL": "Sélectionnez l'URL", + "selectURLs": "Sélectionnez les URLs", + "pick": "Prendre", + "theme": "Thème", + "dark": "Sombre", + "light": "Clair", + "followSystem": "Suivre le système", + "obtainium": "Obtainium", + "materialYou": "Material You", + "appSortBy": "Applications triées par", + "authorName": "Auteur/Nom", + "nameAuthor": "Nom/Auteur", + "asAdded": "Comme ajouté", + "appSortOrder": "Ordre de tri des applications", + "ascending": "Ascendant", + "descending": "Descendanr", + "bgUpdateCheckInterval": "Intervalle de vérification des mises à jour en arrière-plan", + "neverManualOnly": "Jamais - Manuel uniquement", + "appearance": "Apparence", + "showWebInAppView": "Afficher la page Web source dans la vue de l'application", + "pinUpdates": "Épingler les mises à jour dans la vue Top des applications", + "updates": "Mises à jour", + "sourceSpecific": "Spécifique à la source", + "appSource": "Source de l'application", + "noLogs": "Aucun journal", + "appLogs": "Journaux d'application", + "close": "Fermer", + "share": "Partager", + "appNotFound": "Application introuvable", + "obtainiumExportHyphenatedLowercase": "obtainium-export", + "pickAnAPK": "Choisissez un APK", + "appHasMoreThanOnePackage": "{} a plus d'un paquet :", + "deviceSupportsXArch": "Votre appareil prend en charge l'architecture de processeur {}.", + "deviceSupportsFollowingArchs": "Votre appareil prend en charge les architectures CPU suivantes :", + "warning": "Avertissement", + "sourceIsXButPackageFromYPrompt": "La source de l'application est '{}' mais le paquet de version provient de '{}'. Continuer?", + "updatesAvailable": "Mises à jour disponibles", + "updatesAvailableNotifDescription": "Avertit l'utilisateur que des mises à jour sont disponibles pour une ou plusieurs applications suivies par Obtainium", + "noNewUpdates": "Aucune nouvelle mise à jour.", + "xHasAnUpdate": "{} a une mise à jour.", + "appsUpdated": "Applications mises à jour", + "appsUpdatedNotifDescription": "Avertit l'utilisateur que les mises à jour d'une ou plusieurs applications ont été appliquées en arrière-plan", + "xWasUpdatedToY": "{} a été mis à jour pour {}.", + "errorCheckingUpdates": "Erreur lors de la vérification des mises à jour", + "errorCheckingUpdatesNotifDescription": "Une notification qui s'affiche lorsque la vérification de la mise à jour en arrière-plan échoue", + "appsRemoved": "Applications supprimées", + "appsRemovedNotifDescription": "Avertit l'utilisateur qu'une ou plusieurs applications ont été supprimées en raison d'erreurs lors de leur chargement", + "xWasRemovedDueToErrorY": "{} a été supprimé en raison de cette erreur : {}", + "completeAppInstallation": "Installation complète de l'application", + "obtainiumMustBeOpenToInstallApps": "Obtainium doit être ouvert pour installer des applications", + "completeAppInstallationNotifDescription": "Demande à l'utilisateur de retourner sur Obtainium pour terminer l'installation d'une application", + "checkingForUpdates": "Vérification des mises à jour", + "checkingForUpdatesNotifDescription": "Notification transitoire qui apparaît lors de la recherche de mises à jour", + "pleaseAllowInstallPerm": "Veuillez autoriser Obtainium à installer des applications", + "trackOnly": "Suivi uniquement", + "errorWithHttpStatusCode": "Erreur {}", + "versionCorrectionDisabled": "Correction de version désactivée (le plugin ne semble pas fonctionner)", + "unknown": "Inconnu", + "none": "Aucun", + "never": "Jamais", + "latestVersionX": "Dernière version: {}", + "installedVersionX": "Version installée : {}", + "lastUpdateCheckX": "Vérification de la dernière mise à jour : {}", + "remove": "Retirer", + "yesMarkUpdated": "Oui, marquer comme mis à jour", + "fdroid": "F-Droid", + "appIdOrName": "ID ou nom de l'application", + "appWithIdOrNameNotFound": "Aucune application n'a été trouvée avec cet identifiant ou ce nom", + "reposHaveMultipleApps": "Les dépôts peuvent contenir plusieurs applications", + "fdroidThirdPartyRepo": "Dépôt tiers F-Droid", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Chat", + "install": "Installer", + "markInstalled": "Marquer installée", + "update": "Mettre à jour", + "markUpdated": "Marquer à jour", + "additionalOptions": "Options additionelles", + "disableVersionDetection": "Désactiver la détection de version", + "noVersionDetectionExplanation": "Cette option ne doit être utilisée que pour les applications où la détection de version ne fonctionne pas correctement.", + "downloadingX": "Téléchargement {}", + "downloadNotifDescription": "Avertit l'utilisateur de la progression du téléchargement d'une application", + "noAPKFound": "Aucun APK trouvé", + "noVersionDetection": "Pas de détection de version", + "categorize": "Catégoriser", + "categories": "Catégories", + "category": "Catégorie", + "noCategory": "No Category", + "noCategories": "Aucune catégorie", + "deleteCategoriesQuestion": "Supprimer les catégories ?", + "categoryDeleteWarning": "Toutes les applications dans les catégories supprimées seront définies sur non catégorisées.", + "addCategory": "Ajouter une catégorie", + "label": "Étiquette", + "language": "Langue", + "storagePermissionDenied": "Autorisation de stockage refusée", + "selectedCategorizeWarning": "Cela remplacera tous les paramètres de catégorie existants pour les applications sélectionnées.", + "filterAPKsByRegEx": "Filtrer les APK par expression régulière", + "removeFromObtainium": "Supprimer d'Obtainium", + "uninstallFromDevice": "Désinstaller de l'appareil", + "onlyWorksWithNonVersionDetectApps": "Fonctionne uniquement pour les applications avec la détection de version désactivée.", + "releaseDateAsVersion": "Utiliser la date de sortie comme version", + "releaseDateAsVersionExplanation": "Cette option ne doit être utilisée que pour les applications où la détection de version ne fonctionne pas correctement, mais une date de sortie est disponible.", + "changes": "Changements", + "releaseDate": "Date de sortie", + "importFromURLsInFile": "Importer à partir d'URL dans un fichier (comme OPML)", + "versionDetection": "Détection des versions", + "standardVersionDetection": "Détection de version standard", + "removeAppQuestion": { + "one": "Supprimer l'application ?", + "other": "Supprimer les applications ?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Trop de demandes (taux limité) - réessayez dans {} minute", + "other": "Trop de demandes (taux limité) - réessayez dans {} minutes" + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "La vérification de la mise à jour en arrière-plan a rencontré un {}, planifiera une nouvelle tentative de vérification dans {} minute", + "other": "La vérification de la mise à jour en arrière-plan a rencontré un {}, planifiera une nouvelle tentative de vérification dans {} minutes" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "La vérification des mises à jour en arrière-plan trouvée {} mise à jour - avertira l'utilisateur si nécessaire", + "other": "La vérification des mises à jour en arrière-plan a trouvé {} mises à jour - avertira l'utilisateur si nécessaire" + }, + "apps": { + "one": "{} Application", + "other": "{} Applications" + }, + "url": { + "one": "{} URL", + "other": "{} URLs" + }, + "minute": { + "one": "{} Minute", + "other": "{} Minutes" + }, + "hour": { + "one": "{} Heure", + "other": "{} Heures" + }, + "day": { + "one": "{} Jour", + "other": "{} Jours" + }, + "clearedNLogsBeforeXAfterY": { + "one": "{n} journal effacé (avant = {before}, après = {after})", + "other": "{n} journaux effacés (avant = {before}, après = {after})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "{} et 1 autre application ont des mises à jour.", + "other": "{} et {} autres applications ont des mises à jour." + }, + "xAndNMoreUpdatesInstalled": { + "one": "{} et 1 autre application ont été mises à jour.", + "other": "{} et {} autres applications ont été mises à jour." + } +} \ No newline at end of file From dfb5f5596c6a6d1554e3fbab1e28d3daf5de1fef Mon Sep 17 00:00:00 2001 From: Darlene Sonalder <73744170+sonalder-darlene@users.noreply.github.com> Date: Sun, 5 Mar 2023 17:19:04 +0000 Subject: [PATCH 076/600] Add a missing translation --- assets/translations/fr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/fr.json b/assets/translations/fr.json index bd80501..e4d99f8 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -1,5 +1,5 @@ { - "invalidURLForSource": "Not a valid {} App URL", + "invalidURLForSource": "URL d'application {} invalide", "noReleaseFound": "Impossible de trouver une version appropriée", "noVersionFound": "Impossible de déterminer la version de la version", "urlMatchesNoSource": "L'URL ne correspond pas à une source connue", @@ -268,4 +268,4 @@ "one": "{} et 1 autre application ont été mises à jour.", "other": "{} et {} autres applications ont été mises à jour." } -} \ No newline at end of file +} From 0528936e5a6d303aeaeaa0dc9cc1a8060dbed3aa Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 5 Mar 2023 13:07:31 -0500 Subject: [PATCH 077/600] Added FR menu option, increment version --- lib/main.dart | 5 +++-- pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 52cdebb..d0ec925 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.7'; +const String currentVersion = '0.11.8'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES @@ -34,7 +34,8 @@ const supportedLocales = [ Locale('ja'), Locale('hu'), Locale('de'), - Locale('fa') + Locale('fa'), + Locale('fr') ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; diff --git a/pubspec.yaml b/pubspec.yaml index c854b49..373ad10 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.11.7+128 # When changing this, update the tag in main() accordingly +version: 0.11.8+129 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From c0120f4e40c28f187535655817bf770b4f0d1464 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 17 Mar 2023 16:48:06 -0400 Subject: [PATCH 078/600] Made download start more responsive (#361, #327) --- lib/providers/apps_provider.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index b436358..650068a 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -145,6 +145,10 @@ class AppsProvider with ChangeNotifier { } Future downloadApp(App app, BuildContext? context) async { + if (apps[app.id] != null) { + apps[app.id]!.downloadProgress = 0; + notifyListeners(); + } var fileName = '${app.id}-${app.latestVersion}-${app.preferredApkIndex}.apk'; String downloadUrl = await SourceProvider() From 0f3e029312a485531a2b686c100865704713b13a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 17 Mar 2023 22:49:12 -0400 Subject: [PATCH 079/600] Bugfix for previous commit --- lib/providers/apps_provider.dart | 99 +++++++++++++++++--------------- 1 file changed, 53 insertions(+), 46 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 650068a..b79b89e 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -149,56 +149,63 @@ class AppsProvider with ChangeNotifier { apps[app.id]!.downloadProgress = 0; notifyListeners(); } - var fileName = - '${app.id}-${app.latestVersion}-${app.preferredApkIndex}.apk'; - String downloadUrl = await SourceProvider() - .getSource(app.url) - .apkUrlPrefetchModifier(app.apkUrls[app.preferredApkIndex]); - NotificationsProvider? notificationsProvider = - context?.read(); - var notif = DownloadNotification(app.name, 100); - notificationsProvider?.cancel(notif.id); - int? prevProg; - File downloadedFile = - await downloadFile(downloadUrl, fileName, (double? progress) { - int? prog = progress?.ceil(); + try { + var fileName = + '${app.id}-${app.latestVersion}-${app.preferredApkIndex}.apk'; + String downloadUrl = await SourceProvider() + .getSource(app.url) + .apkUrlPrefetchModifier(app.apkUrls[app.preferredApkIndex]); + NotificationsProvider? notificationsProvider = + context?.read(); + var notif = DownloadNotification(app.name, 100); + notificationsProvider?.cancel(notif.id); + int? prevProg; + File downloadedFile = + await downloadFile(downloadUrl, fileName, (double? progress) { + int? prog = progress?.ceil(); + if (apps[app.id] != null) { + apps[app.id]!.downloadProgress = progress; + notifyListeners(); + } + notif = DownloadNotification(app.name, prog ?? 100); + if (prog != null && prevProg != prog) { + notificationsProvider?.notify(notif); + } + prevProg = prog; + }); + notificationsProvider?.cancel(notif.id); + // Delete older versions of the APK if any + for (var file in downloadedFile.parent.listSync()) { + var fn = file.path.split('/').last; + if (fn.startsWith('${app.id}-') && + fn.endsWith('.apk') && + fn != fileName) { + file.delete(); + } + } + // If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed + // The former case should be handled (give the App its real ID), the latter is a security issue + var newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); + if (app.id != newInfo.packageName) { + if (apps[app.id] != null && !SourceProvider().isTempId(app)) { + throw IDChangedError(); + } + var originalAppId = app.id; + app.id = newInfo.packageName; + downloadedFile = downloadedFile.renameSync( + '${downloadedFile.parent.path}/${app.id}-${app.latestVersion}-${app.preferredApkIndex}.apk'); + if (apps[originalAppId] != null) { + await removeApps([originalAppId]); + await saveApps([app]); + } + } + return DownloadedApk(app.id, downloadedFile); + } finally { if (apps[app.id] != null) { - apps[app.id]!.downloadProgress = progress; + apps[app.id]!.downloadProgress = null; notifyListeners(); } - notif = DownloadNotification(app.name, prog ?? 100); - if (prog != null && prevProg != prog) { - notificationsProvider?.notify(notif); - } - prevProg = prog; - }); - notificationsProvider?.cancel(notif.id); - // Delete older versions of the APK if any - for (var file in downloadedFile.parent.listSync()) { - var fn = file.path.split('/').last; - if (fn.startsWith('${app.id}-') && - fn.endsWith('.apk') && - fn != fileName) { - file.delete(); - } } - // If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed - // The former case should be handled (give the App its real ID), the latter is a security issue - var newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); - if (app.id != newInfo.packageName) { - if (apps[app.id] != null && !SourceProvider().isTempId(app)) { - throw IDChangedError(); - } - var originalAppId = app.id; - app.id = newInfo.packageName; - downloadedFile = downloadedFile.renameSync( - '${downloadedFile.parent.path}/${app.id}-${app.latestVersion}-${app.preferredApkIndex}.apk'); - if (apps[originalAppId] != null) { - await removeApps([originalAppId]); - await saveApps([app]); - } - } - return DownloadedApk(app.id, downloadedFile); } bool areDownloadsRunning() => apps.values From 1143b6a5468fc252854b68a05a9b6f983baaa4c1 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 17 Mar 2023 23:03:38 -0400 Subject: [PATCH 080/600] Better form UI spacing --- lib/components/generated_form.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/components/generated_form.dart b/lib/components/generated_form.dart index c84b630..a9cdfc0 100644 --- a/lib/components/generated_form.dart +++ b/lib/components/generated_form.dart @@ -460,10 +460,9 @@ class _GeneratedFormState extends State { if (rowInputs.key > 0) { rows.add([ SizedBox( - height: widget.items[rowInputs.key][0] is GeneratedFormSwitch && - widget.items[rowInputs.key - 1][0] is! GeneratedFormSwitch - ? 25 - : 8, + height: widget.items[rowInputs.key - 1][0] is GeneratedFormSwitch + ? 8 + : 25, ) ]); } From 83390f648af454df1a36e05f2697e24eedae6adf Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 17 Mar 2023 23:10:18 -0400 Subject: [PATCH 081/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 84 +++++++++++++++++++++++++-------------------------- pubspec.yaml | 2 +- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index d0ec925..3843c79 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.8'; +const String currentVersion = '0.11.9'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index de8753a..9dea795 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -181,10 +181,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: d090ae03df98b0247b82e5928f44d1b959867049d18d73635e2e0bc3f49542b9 + sha256: d8e9ca7e5d1983365c277f12c21b4362df6cf659c99af146ad4d04eb33033013 url: "https://pub.dev" source: hosted - version: "5.2.5" + version: "5.2.6" flutter: dependency: "direct main" description: flutter @@ -401,26 +401,26 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "7623b7d4be0f0f7d9a8b5ee6879fc13e4522d4c875ab86801dee4af32b54b83e" + sha256: "019f18c9c10ae370b08dce1f3e3b73bc9f58e7f087bb5e921f06529438ac0ae7" url: "https://pub.dev" source: hosted - version: "2.0.23" + version: "2.0.24" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: eec003594f19fe2456ea965ae36b3fc967bc5005f508890aafe31fa75e41d972 + sha256: "12eee51abdf4d34c590f043f45073adbb45514a108bd9db4491547a2fd891059" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.2.0" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: "525ad5e07622d19447ad740b1ed5070031f7a5437f44355ae915ff56e986429a" + sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" url: "https://pub.dev" source: hosted - version: "2.1.9" + version: "2.1.10" path_provider_platform_interface: dependency: transitive description: @@ -433,10 +433,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "642ddf65fde5404f83267e8459ddb4556316d3ee6d511ed193357e25caa3632d" + sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" permission_handler: dependency: "direct main" description: @@ -545,26 +545,26 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: a51a4f9375097f94df1c6e0a49c0374440d31ab026b59d58a7e7660675879db4 + sha256: ad423a80fe7b4e48b50d6111b3ea1027af0e959e49d485712e134863d9c1c521 url: "https://pub.dev" source: hosted - version: "2.0.16" + version: "2.0.17" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "6b84fdf06b32bb336f972d373cd38b63734f3461ba56ac2ba01b56d052796259" + sha256: "1e755f8583229f185cfca61b1d80fb2344c9d660e1c69ede5450d8f478fa5310" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: d7fb71e6e20cd3dfffcc823a28da3539b392e53ed5fc5c2b90b55fdaa8a7e8fa + sha256: "3a59ed10890a8409ad0faad7bb2957dab4b92b8fbe553257b05d30ed8af2c707" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" shared_preferences_platform_interface: dependency: transitive description: @@ -577,18 +577,18 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "6737b757e49ba93de2a233df229d0b6a87728cea1684da828cbc718b65dcf9d7" + sha256: "0dc2633f215a3d4aa3184c9b2c5766f4711e4e5a6b256e62aafee41f89f1bfb8" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.0.6" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: bd014168e8484837c39ef21065b78f305810ceabc1d4f90be6e3b392ce81b46d + sha256: "71bcd669bb9cdb6b39f22c4a7728b6d49e934f6cba73157ffa5a54f1eed67436" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" sky_engine: dependency: transitive description: flutter @@ -606,18 +606,18 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "851d5040552cf911f4cabda08d003eca76b27da3ed0002978272e27c8fbf8ecc" + sha256: "500d6fec583d2c021f2d25a056d96654f910662c64f836cd2063167b8f1fa758" url: "https://pub.dev" source: hosted - version: "2.2.5" + version: "2.2.6" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: bfd6973aaeeb93475bc0d875ac9aefddf7965ef22ce09790eb963992ffc5183f + sha256: "963dad8c4aa2f814ce7d2d5b1da2f36f31bd1a439d8f27e3dc189bb9d26bc684" url: "https://pub.dev" source: hosted - version: "2.4.2+2" + version: "2.4.3" stack_trace: dependency: transitive description: @@ -694,34 +694,34 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "1f4d9ebe86f333c15d318f81dcdc08b01d45da44af74552608455ebdc08d9732" + sha256: "845530e5e05db5500c1a4c1446785d60cbd8f9bd45e21e7dd643a3273bb4bbd1" url: "https://pub.dev" source: hosted - version: "6.0.24" + version: "6.0.25" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: c9cd648d2f7ab56968e049d4e9116f96a85517f1dd806b96a86ea1018a3a82e5 + sha256: "7ab1e5b646623d6a2537aa59d5d039f90eebef75a7c25e105f6f75de1f7750c3" url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.1.2" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: e29039160ab3730e42f3d811dc2a6d5f2864b90a70fb765ea60144b03307f682 + sha256: "206fb8334a700ef7754d6a9ed119e7349bc830448098f21a69bf1b4ed038cabc" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "2dddb3291a57b074dade66b5e07e64401dd2487caefd4e9e2f467138d8c7eb06" + sha256: "0ef2b4f97942a16523e51256b799e9aa1843da6c60c55eefbfa9dbc2dcb8331a" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" url_launcher_platform_interface: dependency: transitive description: @@ -734,18 +734,18 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "574cfbe2390666003c3a1d129bdc4574aaa6728f0c00a4829a81c316de69dd9b" + sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa" url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.0.16" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "97c9067950a0d09cbd93e2e3f0383d1403989362b97102fbf446473a48079a4b" + sha256: a83ba3607a507758669cfafb03f9de09bf6e6280c14d9b9cb18f013e406dcacd url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.0.5" uuid: dependency: transitive description: @@ -774,26 +774,26 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "5dd3f32b5c2d8f4bf9d05a349e4a65fa718eb137f396f336c3893d558a58fe84" + sha256: "34f83c2f0f64c75ad75c77a2ccfc8d2e531afbe8ad41af1fd787d6d33336aa90" url: "https://pub.dev" source: hosted - version: "3.3.2" + version: "3.4.3" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - sha256: df6472164b3f4eaf3280422227f361dc8424b106726b7f21d79a8656ba53f71f + sha256: "1939c39e2150fb4d30fd3cc59a891a49fed9935db53007df633ed83581b6117b" url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.0" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "87b6353b40e04f04d5f895a484ad6d92d682d9cce4d2d5b32d2d8aca2448d46e" + sha256: ab12479f7a0cf112b9420c36aaf206a1ca47cd60cd42de74a4be2e97a697587b url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 373ad10..6962da3 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.11.8+129 # When changing this, update the tag in main() accordingly +version: 0.11.9+130 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From fe540f5e61bbcbd06903bae69964f452fd8c841f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Mar 2023 22:54:58 -0400 Subject: [PATCH 082/600] Added Neutron Code as a Source --- README.md | 1 + lib/app_sources/neutroncode.dart | 109 +++++++++++++++++++++++++++++ lib/providers/source_provider.dart | 2 + 3 files changed, 112 insertions(+) create mode 100644 lib/app_sources/neutroncode.dart diff --git a/README.md b/README.md index 2b4b120..ddd731b 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Currently supported App sources: - Third Party F-Droid Repos - Any URLs ending with `/fdroid/`, where `` can be anything - most often `repo` - [Steam](https://store.steampowered.com/mobile) +- [Neutron Code](https://neutroncode.com) - "HTML" (Fallback) - Any other URL that returns an HTML page with links to APK files (if multiple, the last file alphabetically is picked) diff --git a/lib/app_sources/neutroncode.dart b/lib/app_sources/neutroncode.dart new file mode 100644 index 0000000..0fdbc6c --- /dev/null +++ b/lib/app_sources/neutroncode.dart @@ -0,0 +1,109 @@ +import 'dart:convert'; +import 'package:html/parser.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class NeutronCode extends AppSource { + NeutronCode() { + host = 'neutroncode.com'; + } + + @override + String standardizeURL(String url) { + RegExp standardUrlRegEx = RegExp('^https?://$host/downloads/file/[^/]+'); + RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); + if (match == null) { + throw InvalidURLError(name); + } + return url.substring(0, match.end); + } + + @override + String? changeLogPageFromStandardUrl(String standardUrl) => standardUrl; + + String monthNameToNumberString(String s) { + switch (s.toLowerCase()) { + case 'january': + return '01'; + case 'february': + return '02'; + case 'march': + return '03'; + case 'april': + return '04'; + case 'may': + return '05'; + case 'june': + return '06'; + case 'july': + return '07'; + case 'august': + return '08'; + case 'september': + return '09'; + case 'october': + return '10'; + case 'november': + return '11'; + case 'december': + return '12'; + default: + throw ArgumentError('Invalid month name: $s'); + } + } + + customDateParse(String dateString) { + List parts = dateString.split(' '); + if (parts.length != 3) { + return null; + } + String result = ''; + for (var s in parts.reversed) { + try { + try { + int.parse(s); + result += '$s-'; + } catch (e) { + result += '${monthNameToNumberString(s)}-'; + } + } catch (e) { + return null; + } + } + return result.substring(0, result.length - 1); + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + Response res = await get(Uri.parse(standardUrl)); + if (res.statusCode == 200) { + var http = parse(res.body); + var name = http.querySelector('.pd-title')?.innerHtml; + var filename = http.querySelector('.pd-filename .pd-float')?.innerHtml; + if (filename == null) { + throw NoReleasesError(); + } + var version = + http.querySelector('.pd-version-txt')?.nextElementSibling?.innerHtml; + if (version == null) { + throw NoVersionError(); + } + String? apkUrl = 'https://$host/download/$filename'; + var dateStringOriginal = + http.querySelector('.pd-date-txt')?.nextElementSibling?.innerHtml; + var dateString = dateStringOriginal != null + ? (customDateParse(dateStringOriginal)) + : null; + + return APKDetails(version, [apkUrl], + AppNames(runtimeType.toString(), name ?? standardUrl.split('/').last), + releaseDate: dateString != null ? DateTime.parse(dateString) : null); + } else { + throw getObtainiumHttpError(res); + } + } +} diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 8cead1e..5b51c7f 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -15,6 +15,7 @@ import 'package:obtainium/app_sources/gitlab.dart'; import 'package:obtainium/app_sources/izzyondroid.dart'; import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/app_sources/mullvad.dart'; +import 'package:obtainium/app_sources/neutroncode.dart'; import 'package:obtainium/app_sources/signal.dart'; import 'package:obtainium/app_sources/sourceforge.dart'; import 'package:obtainium/app_sources/steammobile.dart'; @@ -338,6 +339,7 @@ class SourceProvider { APKMirror(), FDroidRepo(), SteamMobile(), + NeutronCode(), HTML() // This should ALWAYS be the last option as they are tried in order ]; From 53d33976517126cafc2f7340d7bcd92f7cd27263 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Mar 2023 22:58:37 -0400 Subject: [PATCH 083/600] Remove download notification when download fails --- lib/providers/apps_provider.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index b79b89e..dc4f9c0 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -145,6 +145,9 @@ class AppsProvider with ChangeNotifier { } Future downloadApp(App app, BuildContext? context) async { + NotificationsProvider? notificationsProvider = + context?.read(); + var notifId = DownloadNotification(app.name, 0).id; if (apps[app.id] != null) { apps[app.id]!.downloadProgress = 0; notifyListeners(); @@ -155,8 +158,6 @@ class AppsProvider with ChangeNotifier { String downloadUrl = await SourceProvider() .getSource(app.url) .apkUrlPrefetchModifier(app.apkUrls[app.preferredApkIndex]); - NotificationsProvider? notificationsProvider = - context?.read(); var notif = DownloadNotification(app.name, 100); notificationsProvider?.cancel(notif.id); int? prevProg; @@ -173,7 +174,6 @@ class AppsProvider with ChangeNotifier { } prevProg = prog; }); - notificationsProvider?.cancel(notif.id); // Delete older versions of the APK if any for (var file in downloadedFile.parent.listSync()) { var fn = file.path.split('/').last; @@ -201,6 +201,7 @@ class AppsProvider with ChangeNotifier { } return DownloadedApk(app.id, downloadedFile); } finally { + notificationsProvider?.cancel(notifId); if (apps[app.id] != null) { apps[app.id]!.downloadProgress = null; notifyListeners(); From e49a6e311b825c3cf4eda19a77fff8559d8fcfa8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Mar 2023 23:09:11 -0400 Subject: [PATCH 084/600] Added Telegram App as a Source --- lib/app_sources/neutroncode.dart | 1 - lib/app_sources/telegramapp.dart | 43 ++++++++++++++++++++++++++++++ lib/providers/source_provider.dart | 2 ++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 lib/app_sources/telegramapp.dart diff --git a/lib/app_sources/neutroncode.dart b/lib/app_sources/neutroncode.dart index 0fdbc6c..6baa0a1 100644 --- a/lib/app_sources/neutroncode.dart +++ b/lib/app_sources/neutroncode.dart @@ -1,4 +1,3 @@ -import 'dart:convert'; import 'package:html/parser.dart'; import 'package:http/http.dart'; import 'package:obtainium/custom_errors.dart'; diff --git a/lib/app_sources/telegramapp.dart b/lib/app_sources/telegramapp.dart new file mode 100644 index 0000000..6b249fd --- /dev/null +++ b/lib/app_sources/telegramapp.dart @@ -0,0 +1,43 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:html/parser.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class TelegramApp extends AppSource { + TelegramApp() { + host = 'telegram.org'; + name = 'Telegram ${tr('app')}'; + } + + @override + String standardizeURL(String url) { + return 'https://$host'; + } + + @override + String? changeLogPageFromStandardUrl(String standardUrl) => null; + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + Response res = await get(Uri.parse('https://t.me/s/TAndroidAPK')); + if (res.statusCode == 200) { + var http = parse(res.body); + var messages = + http.querySelectorAll('.tgme_widget_message_text.js-message_text'); + var version = messages.isNotEmpty + ? messages.last.innerHtml.split('\n').first.trim().split(' ').first + : null; + if (version == null) { + throw NoVersionError(); + } + String? apkUrl = 'https://telegram.org/dl/android/apk'; + return APKDetails(version, [apkUrl], AppNames('Telegram', 'Telegram')); + } else { + throw getObtainiumHttpError(res); + } + } +} diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 5b51c7f..f2b7afd 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -19,6 +19,7 @@ import 'package:obtainium/app_sources/neutroncode.dart'; import 'package:obtainium/app_sources/signal.dart'; import 'package:obtainium/app_sources/sourceforge.dart'; import 'package:obtainium/app_sources/steammobile.dart'; +import 'package:obtainium/app_sources/telegramapp.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart'; @@ -339,6 +340,7 @@ class SourceProvider { APKMirror(), FDroidRepo(), SteamMobile(), + TelegramApp(), NeutronCode(), HTML() // This should ALWAYS be the last option as they are tried in order ]; From 26e6eef72e33fa026dfafbef64ea8e09aad8df96 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Mar 2023 23:10:14 -0400 Subject: [PATCH 085/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 3843c79..5e49a1a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.9'; +const String currentVersion = '0.11.10'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 6962da3..f3871a6 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.11.9+130 # When changing this, update the tag in main() accordingly +version: 0.11.10+131 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From bd0e322465f68bbe7612b1c7aa1d0aa811b13391 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Mar 2023 23:20:04 -0400 Subject: [PATCH 086/600] Updated README sources section --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ddd731b..3766352 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Currently supported App sources: - Third Party F-Droid Repos - Any URLs ending with `/fdroid/`, where `` can be anything - most often `repo` - [Steam](https://store.steampowered.com/mobile) +- [Telegram App](https://telegram.org) - [Neutron Code](https://neutroncode.com) - "HTML" (Fallback) - Any other URL that returns an HTML page with links to APK files (if multiple, the last file alphabetically is picked) From ef06ae289e530495979a75f0f41d21a8061ce729 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 18 Mar 2023 23:53:42 -0400 Subject: [PATCH 087/600] Open changelog inside App for supported Sources (#82) --- lib/app_sources/codeberg.dart | 4 +- lib/app_sources/fdroid.dart | 3 -- lib/app_sources/github.dart | 4 +- lib/app_sources/html.dart | 3 -- lib/app_sources/izzyondroid.dart | 3 -- lib/app_sources/neutroncode.dart | 7 ++- lib/app_sources/signal.dart | 3 -- lib/app_sources/sourceforge.dart | 3 -- lib/app_sources/steammobile.dart | 3 -- lib/app_sources/telegramapp.dart | 3 -- lib/main.dart | 2 +- lib/pages/apps.dart | 58 +++++++++++++++++++----- lib/providers/source_provider.dart | 71 ++++++++++++++++-------------- pubspec.yaml | 2 +- 14 files changed, 100 insertions(+), 69 deletions(-) diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index aa21171..1d181bc 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -118,9 +118,11 @@ class Codeberg extends AppSource { if (version == null) { throw NoVersionError(); } + var changeLog = targetRelease['body'].toString(); return APKDetails(version, targetRelease['apkUrls'] as List, getAppNames(standardUrl), - releaseDate: releaseDate); + releaseDate: releaseDate, + changeLog: changeLog.isEmpty ? null : changeLog); } else { throw getObtainiumHttpError(res); } diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 01f9293..3c2bba8 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -27,9 +27,6 @@ class FDroid extends AppSource { return url.substring(0, match.end); } - @override - String? changeLogPageFromStandardUrl(String standardUrl) => null; - @override String? tryInferringAppId(String standardUrl, {Map additionalSettings = const {}}) { diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 1ce8cfc..9506453 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -160,9 +160,11 @@ class GitHub extends AppSource { if (version == null) { throw NoVersionError(); } + var changeLog = targetRelease['body'].toString(); return APKDetails(version, targetRelease['apkUrls'] as List, getAppNames(standardUrl), - releaseDate: releaseDate); + releaseDate: releaseDate, + changeLog: changeLog.isEmpty ? null : changeLog); } else { rateLimitErrorCheck(res); throw getObtainiumHttpError(res); diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 003eef0..5d44b98 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -10,9 +10,6 @@ class HTML extends AppSource { return url; } - @override - String? changeLogPageFromStandardUrl(String standardUrl) => null; - @override Future getLatestAPKDetails( String standardUrl, diff --git a/lib/app_sources/izzyondroid.dart b/lib/app_sources/izzyondroid.dart index 8d61693..a3f388c 100644 --- a/lib/app_sources/izzyondroid.dart +++ b/lib/app_sources/izzyondroid.dart @@ -18,9 +18,6 @@ class IzzyOnDroid extends AppSource { return url.substring(0, match.end); } - @override - String? changeLogPageFromStandardUrl(String standardUrl) => null; - @override String? tryInferringAppId(String standardUrl, {Map additionalSettings = const {}}) { diff --git a/lib/app_sources/neutroncode.dart b/lib/app_sources/neutroncode.dart index 6baa0a1..b5e499a 100644 --- a/lib/app_sources/neutroncode.dart +++ b/lib/app_sources/neutroncode.dart @@ -97,10 +97,13 @@ class NeutronCode extends AppSource { var dateString = dateStringOriginal != null ? (customDateParse(dateStringOriginal)) : null; - + var changeLogElements = http.querySelectorAll('.pd-fdesc p'); return APKDetails(version, [apkUrl], AppNames(runtimeType.toString(), name ?? standardUrl.split('/').last), - releaseDate: dateString != null ? DateTime.parse(dateString) : null); + releaseDate: dateString != null ? DateTime.parse(dateString) : null, + changeLog: changeLogElements.isNotEmpty + ? changeLogElements.last.innerHtml + : null); } else { throw getObtainiumHttpError(res); } diff --git a/lib/app_sources/signal.dart b/lib/app_sources/signal.dart index ad3c7b9..38af04a 100644 --- a/lib/app_sources/signal.dart +++ b/lib/app_sources/signal.dart @@ -13,9 +13,6 @@ class Signal extends AppSource { return 'https://$host'; } - @override - String? changeLogPageFromStandardUrl(String standardUrl) => null; - @override Future getLatestAPKDetails( String standardUrl, diff --git a/lib/app_sources/sourceforge.dart b/lib/app_sources/sourceforge.dart index 2c80838..ed484a6 100644 --- a/lib/app_sources/sourceforge.dart +++ b/lib/app_sources/sourceforge.dart @@ -18,9 +18,6 @@ class SourceForge extends AppSource { return url.substring(0, match.end); } - @override - String? changeLogPageFromStandardUrl(String standardUrl) => null; - @override Future getLatestAPKDetails( String standardUrl, diff --git a/lib/app_sources/steammobile.dart b/lib/app_sources/steammobile.dart index a5e07cf..db6def3 100644 --- a/lib/app_sources/steammobile.dart +++ b/lib/app_sources/steammobile.dart @@ -24,9 +24,6 @@ class SteamMobile extends AppSource { return 'https://$host'; } - @override - String? changeLogPageFromStandardUrl(String standardUrl) => null; - @override Future getLatestAPKDetails( String standardUrl, diff --git a/lib/app_sources/telegramapp.dart b/lib/app_sources/telegramapp.dart index 6b249fd..c152ed9 100644 --- a/lib/app_sources/telegramapp.dart +++ b/lib/app_sources/telegramapp.dart @@ -15,9 +15,6 @@ class TelegramApp extends AppSource { return 'https://$host'; } - @override - String? changeLogPageFromStandardUrl(String standardUrl) => null; - @override Future getLatestAPKDetails( String standardUrl, diff --git a/lib/main.dart b/lib/main.dart index 5e49a1a..fec7297 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.10'; +const String currentVersion = '0.11.11'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 49e21db..8da87c2 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -232,6 +232,49 @@ class AppsPageState extends State { String? changesUrl = SourceProvider() .getSource(listedApps[index].app.url) .changeLogPageFromStandardUrl(listedApps[index].app.url); + String? changeLog = listedApps[index].app.changeLog; + var showChanges = (changeLog == null && changesUrl == null) + ? null + : () { + if (changeLog != null) { + showDialog( + context: context, + builder: (BuildContext context) { + return GeneratedFormModal( + title: tr('changes'), + items: [], + additionalWidgets: [ + Text(changeLog), + changesUrl != null + ? const SizedBox( + height: 16, + ) + : const SizedBox.shrink(), + changesUrl != null + ? GestureDetector( + child: Text( + changesUrl, + style: const TextStyle( + decoration: + TextDecoration.underline, + fontStyle: FontStyle.italic), + ), + onTap: () { + launchUrlString(changesUrl, + mode: LaunchMode + .externalApplication); + }, + ) + : const SizedBox.shrink() + ], + singleNullReturnButton: tr('ok'), + ); + }); + } else { + launchUrlString(changesUrl!, + mode: LaunchMode.externalApplication); + } + }; var transparent = const Color.fromARGB(0, 0, 0, 0).value; var hasUpdate = listedApps[index].app.installedVersion != null && listedApps[index].app.installedVersion != @@ -366,13 +409,7 @@ class AppsPageState extends State { mainAxisSize: MainAxisSize.min, children: [ GestureDetector( - onTap: changesUrl == null - ? null - : () { - launchUrlString(changesUrl, - mode: LaunchMode - .externalApplication); - }, + onTap: showChanges, child: Text( listedApps[index].app.releaseDate == null @@ -381,10 +418,11 @@ class AppsPageState extends State { .format(listedApps[index] .app .releaseDate!), - style: const TextStyle( + style: TextStyle( fontStyle: FontStyle.italic, - decoration: - TextDecoration.underline), + decoration: showChanges != null + ? TextDecoration.underline + : TextDecoration.none), )) ], ), diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index f2b7afd..270b4c4 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -36,8 +36,10 @@ class APKDetails { late List apkUrls; late AppNames names; late DateTime? releaseDate; + late String? changeLog; - APKDetails(this.version, this.apkUrls, this.names, {this.releaseDate}); + APKDetails(this.version, this.apkUrls, this.names, + {this.releaseDate, this.changeLog}); } class App { @@ -54,6 +56,7 @@ class App { bool pinned = false; List categories; late DateTime? releaseDate; + late String? changeLog; App( this.id, this.url, @@ -67,7 +70,8 @@ class App { this.lastUpdateCheck, this.pinned, {this.categories = const [], - this.releaseDate}); + this.releaseDate, + this.changeLog}); @override String toString() { @@ -130,34 +134,35 @@ class App { preferredApkIndex = 0; } return App( - json['id'] as String, - json['url'] as String, - json['author'] as String, - json['name'] as String, - json['installedVersion'] == null - ? null - : json['installedVersion'] as String, - json['latestVersion'] as String, - json['apkUrls'] == null - ? [] - : List.from(jsonDecode(json['apkUrls'])), - preferredApkIndex, - additionalSettings, - json['lastUpdateCheck'] == null - ? null - : DateTime.fromMicrosecondsSinceEpoch(json['lastUpdateCheck']), - json['pinned'] ?? false, - categories: json['categories'] != null - ? (json['categories'] as List) - .map((e) => e.toString()) - .toList() - : json['category'] != null - ? [json['category'] as String] - : [], - releaseDate: json['releaseDate'] == null - ? null - : DateTime.fromMicrosecondsSinceEpoch(json['releaseDate']), - ); + json['id'] as String, + json['url'] as String, + json['author'] as String, + json['name'] as String, + json['installedVersion'] == null + ? null + : json['installedVersion'] as String, + json['latestVersion'] as String, + json['apkUrls'] == null + ? [] + : List.from(jsonDecode(json['apkUrls'])), + preferredApkIndex, + additionalSettings, + json['lastUpdateCheck'] == null + ? null + : DateTime.fromMicrosecondsSinceEpoch(json['lastUpdateCheck']), + json['pinned'] ?? false, + categories: json['categories'] != null + ? (json['categories'] as List) + .map((e) => e.toString()) + .toList() + : json['category'] != null + ? [json['category'] as String] + : [], + releaseDate: json['releaseDate'] == null + ? null + : DateTime.fromMicrosecondsSinceEpoch(json['releaseDate']), + changeLog: + json['changeLog'] == null ? null : json['changeLog'] as String); } Map toJson() => { @@ -173,7 +178,8 @@ class App { 'lastUpdateCheck': lastUpdateCheck?.microsecondsSinceEpoch, 'pinned': pinned, 'categories': categories, - 'releaseDate': releaseDate?.microsecondsSinceEpoch + 'releaseDate': releaseDate?.microsecondsSinceEpoch, + 'changeLog': changeLog }; } @@ -437,7 +443,8 @@ class SourceProvider { DateTime.now(), currentApp?.pinned ?? false, categories: currentApp?.categories ?? const [], - releaseDate: apk.releaseDate); + releaseDate: apk.releaseDate, + changeLog: apk.changeLog); } // Returns errors in [results, errors] instead of throwing them diff --git a/pubspec.yaml b/pubspec.yaml index f3871a6..e061020 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.11.10+131 # When changing this, update the tag in main() accordingly +version: 0.11.11+132 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 280827d8ec1a23d8668150c171740e958d4b5213 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 19 Mar 2023 12:38:57 -0400 Subject: [PATCH 088/600] Changelog now rendered as MarkDown --- lib/components/generated_form.dart | 1 + lib/pages/apps.dart | 34 +++++++++++++++++++++++------- pubspec.lock | 16 ++++++++++++++ pubspec.yaml | 1 + 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/lib/components/generated_form.dart b/lib/components/generated_form.dart index a9cdfc0..a281899 100644 --- a/lib/components/generated_form.dart +++ b/lib/components/generated_form.dart @@ -476,6 +476,7 @@ class _GeneratedFormState extends State { rowItems.add(Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, children: [ rowInput.value, ...widget.items[rowInputs.key][rowInput.key].belowWidgets diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 8da87c2..393c2ff 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -1,6 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:obtainium/components/custom_app_bar.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/components/generated_form_modal.dart'; @@ -14,6 +15,7 @@ import 'package:obtainium/providers/source_provider.dart'; import 'package:provider/provider.dart'; import 'package:share_plus/share_plus.dart'; import 'package:url_launcher/url_launcher_string.dart'; +import 'package:markdown/markdown.dart' as md; class AppsPage extends StatefulWidget { const AppsPage({super.key}); @@ -242,14 +244,8 @@ class AppsPageState extends State { builder: (BuildContext context) { return GeneratedFormModal( title: tr('changes'), - items: [], + items: const [], additionalWidgets: [ - Text(changeLog), - changesUrl != null - ? const SizedBox( - height: 16, - ) - : const SizedBox.shrink(), changesUrl != null ? GestureDetector( child: Text( @@ -265,7 +261,29 @@ class AppsPageState extends State { .externalApplication); }, ) - : const SizedBox.shrink() + : const SizedBox.shrink(), + changesUrl != null + ? const SizedBox( + height: 16, + ) + : const SizedBox.shrink(), + SizedBox( + width: MediaQuery.of(context).size.width, + height: + MediaQuery.of(context).size.height - + 350, + child: Markdown( + data: changeLog, + extensionSet: md.ExtensionSet( + md.ExtensionSet.gitHubFlavored + .blockSyntaxes, + [ + md.EmojiSyntax(), + ...md.ExtensionSet.gitHubFlavored + .inlineSyntaxes + ], + ), + )), ], singleNullReturnButton: tr('ok'), ); diff --git a/pubspec.lock b/pubspec.lock index 9dea795..b0b7d14 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -235,6 +235,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_markdown: + dependency: "direct main" + description: + name: flutter_markdown + sha256: "7b25c10de1fea883f3c4f9b8389506b54053cd00807beab69fd65c8653a2711f" + url: "https://pub.dev" + source: hosted + version: "0.6.14" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -325,6 +333,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + markdown: + dependency: transitive + description: + name: markdown + sha256: b3c60dee8c2af50ad0e6e90cceba98e47718a6ee0a7a6772c77846a0cc21f78b + url: "https://pub.dev" + source: hosted + version: "7.0.1" matcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e061020..932daf5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -59,6 +59,7 @@ dependencies: sqflite: ^2.2.0+3 easy_localization: ^3.0.1 android_intent_plus: ^3.1.5 + flutter_markdown: ^0.6.14 dev_dependencies: From f1fc43a3e70f369c4dc4f35d9ca850a071a51924 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 19 Mar 2023 12:44:17 -0400 Subject: [PATCH 089/600] Don't show 'Changes' button if it doesn't do anything --- lib/pages/apps.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 393c2ff..3e5084e 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -431,7 +431,9 @@ class AppsPageState extends State { child: Text( listedApps[index].app.releaseDate == null - ? tr('changes') + ? showChanges != null + ? tr('changes') + : '' : DateFormat('yyyy-MM-dd') .format(listedApps[index] .app From 48d2532323c9a5fa7649e4c4f04af61cec2c1a8a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 19 Mar 2023 12:49:43 -0400 Subject: [PATCH 090/600] Links in changelog openable --- lib/pages/apps.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 3e5084e..412d8f1 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -274,6 +274,18 @@ class AppsPageState extends State { 350, child: Markdown( data: changeLog, + onTapLink: (text, href, title) { + if (href != null) { + launchUrlString( + href.startsWith('http://') || + href.startsWith( + 'https://') + ? href + : '${Uri.parse(listedApps[index].app.url).origin}/$href', + mode: LaunchMode + .externalApplication); + } + }, extensionSet: md.ExtensionSet( md.ExtensionSet.gitHubFlavored .blockSyntaxes, From 6db31e2b240842c7284bfb5d13e875a0e6aec0e8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 19 Mar 2023 12:52:34 -0400 Subject: [PATCH 091/600] Support for normal text changelogs (by Source) --- lib/pages/apps.dart | 68 +++++++++++++++++------------- lib/providers/source_provider.dart | 1 + 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 412d8f1..a0beb61 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -231,8 +231,9 @@ class AppsPageState extends State { SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { - String? changesUrl = SourceProvider() - .getSource(listedApps[index].app.url) + AppSource appSource = + SourceProvider().getSource(listedApps[index].app.url); + String? changesUrl = appSource .changeLogPageFromStandardUrl(listedApps[index].app.url); String? changeLog = listedApps[index].app.changeLog; var showChanges = (changeLog == null && changesUrl == null) @@ -267,35 +268,42 @@ class AppsPageState extends State { height: 16, ) : const SizedBox.shrink(), - SizedBox( - width: MediaQuery.of(context).size.width, - height: - MediaQuery.of(context).size.height - + appSource.changeLogIfAnyIsMarkDown + ? SizedBox( + width: + MediaQuery.of(context).size.width, + height: MediaQuery.of(context) + .size + .height - 350, - child: Markdown( - data: changeLog, - onTapLink: (text, href, title) { - if (href != null) { - launchUrlString( - href.startsWith('http://') || - href.startsWith( - 'https://') - ? href - : '${Uri.parse(listedApps[index].app.url).origin}/$href', - mode: LaunchMode - .externalApplication); - } - }, - extensionSet: md.ExtensionSet( - md.ExtensionSet.gitHubFlavored - .blockSyntaxes, - [ - md.EmojiSyntax(), - ...md.ExtensionSet.gitHubFlavored - .inlineSyntaxes - ], - ), - )), + child: Markdown( + data: changeLog, + onTapLink: (text, href, title) { + if (href != null) { + launchUrlString( + href.startsWith( + 'http://') || + href.startsWith( + 'https://') + ? href + : '${Uri.parse(listedApps[index].app.url).origin}/$href', + mode: LaunchMode + .externalApplication); + } + }, + extensionSet: md.ExtensionSet( + md.ExtensionSet.gitHubFlavored + .blockSyntaxes, + [ + md.EmojiSyntax(), + ...md + .ExtensionSet + .gitHubFlavored + .inlineSyntaxes + ], + ), + )) + : Text(changeLog), ], singleNullReturnButton: tr('ok'), ); diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 270b4c4..fd4254d 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -228,6 +228,7 @@ class AppSource { String? host; late String name; bool enforceTrackOnly = false; + bool changeLogIfAnyIsMarkDown = true; AppSource() { name = runtimeType.toString(); From 08555bac753419adda8c7c757c78684eb851260f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 19 Mar 2023 13:50:14 -0400 Subject: [PATCH 092/600] Added VLC as a Source --- README.md | 1 + lib/app_sources/vlc.dart | 62 ++++++++++++++++++++++++++++++ lib/providers/source_provider.dart | 2 + 3 files changed, 65 insertions(+) create mode 100644 lib/app_sources/vlc.dart diff --git a/README.md b/README.md index 3766352..107e70f 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Currently supported App sources: - Any URLs ending with `/fdroid/`, where `` can be anything - most often `repo` - [Steam](https://store.steampowered.com/mobile) - [Telegram App](https://telegram.org) +- [VLC](https://www.videolan.org/vlc/download-android.html) - [Neutron Code](https://neutroncode.com) - "HTML" (Fallback) - Any other URL that returns an HTML page with links to APK files (if multiple, the last file alphabetically is picked) diff --git a/lib/app_sources/vlc.dart b/lib/app_sources/vlc.dart new file mode 100644 index 0000000..e4678d7 --- /dev/null +++ b/lib/app_sources/vlc.dart @@ -0,0 +1,62 @@ +import 'package:html/parser.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/app_sources/html.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class VLC extends AppSource { + VLC() { + host = 'videolan.org'; + } + + @override + String standardizeURL(String url) { + return 'https://$host'; + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + Response res = await get( + Uri.parse('https://www.videolan.org/vlc/download-android.html')); + if (res.statusCode == 200) { + var dwUrlBase = 'get.videolan.org/vlc-android'; + var dwLinks = parse(res.body) + .querySelectorAll('a') + .where((element) => + element.attributes['href']?.contains(dwUrlBase) ?? false) + .toList(); + String? version = dwLinks.isNotEmpty + ? dwLinks.first.attributes['href'] + ?.split('/') + .where((s) => s.isNotEmpty) + .last + : null; + if (version == null) { + throw NoVersionError(); + } + String? targetUrl = 'https://$dwUrlBase/$version/'; + Response res2 = await get(Uri.parse(targetUrl)); + String mirrorDwBase = + 'https://plug-mirror.rcac.purdue.edu/vlc/vlc-android/$version/'; + List apkUrls = []; + if (res2.statusCode == 200) { + apkUrls = parse(res2.body) + .querySelectorAll('a') + .map((e) => e.attributes['href']) + .where((h) => + h != null && h.isNotEmpty && h.toLowerCase().endsWith('.apk')) + .map((e) => mirrorDwBase + e!) + .toList(); + } else { + throw getObtainiumHttpError(res2); + } + + return APKDetails(version, apkUrls, AppNames('VideoLAN', 'VLC')); + } else { + throw getObtainiumHttpError(res); + } + } +} diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index fd4254d..1b19c19 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -20,6 +20,7 @@ import 'package:obtainium/app_sources/signal.dart'; import 'package:obtainium/app_sources/sourceforge.dart'; import 'package:obtainium/app_sources/steammobile.dart'; import 'package:obtainium/app_sources/telegramapp.dart'; +import 'package:obtainium/app_sources/vlc.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart'; @@ -348,6 +349,7 @@ class SourceProvider { FDroidRepo(), SteamMobile(), TelegramApp(), + VLC(), NeutronCode(), HTML() // This should ALWAYS be the last option as they are tried in order ]; From 1112c79c149e7a8dc88b0d03d16e8fa3f9f1e2da Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 19 Mar 2023 13:53:40 -0400 Subject: [PATCH 093/600] Increment version --- lib/main.dart | 2 +- pubspec.lock | 8 ++++---- pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index fec7297..7be4cea 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.11'; +const String currentVersion = '0.11.12'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index b0b7d14..66602aa 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -718,10 +718,10 @@ packages: dependency: transitive description: name: url_launcher_ios - sha256: "7ab1e5b646623d6a2537aa59d5d039f90eebef75a7c25e105f6f75de1f7750c3" + sha256: "3dedc66ca3c0bef9e6a93c0999aee102556a450afcc1b7bcfeace7a424927d92" url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "6.1.3" url_launcher_linux: dependency: transitive description: @@ -782,10 +782,10 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: b6cd42db3ced5411f3d01599906156885b18e4188f7065a8a351eb84bee347e0 + sha256: "47663d51a9061451aa3880a214ee9a65dcbb933b77bc44388e194279ab3ccaf6" url: "https://pub.dev" source: hosted - version: "4.0.6" + version: "4.0.7" webview_flutter_android: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 932daf5..0a5d632 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.11.11+132 # When changing this, update the tag in main() accordingly +version: 0.11.12+133 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 9c6068b27063b62c79790c9201e610473630c166 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 20 Mar 2023 15:18:55 -0400 Subject: [PATCH 094/600] Added WhatsApp (not activated) + rearranged sources --- lib/app_sources/whatsapp.dart | 75 ++++++++++++++++++++++++++++++ lib/providers/source_provider.dart | 12 +++-- 2 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 lib/app_sources/whatsapp.dart diff --git a/lib/app_sources/whatsapp.dart b/lib/app_sources/whatsapp.dart new file mode 100644 index 0000000..6d08549 --- /dev/null +++ b/lib/app_sources/whatsapp.dart @@ -0,0 +1,75 @@ +import 'package:html/parser.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class WhatsApp extends AppSource { + WhatsApp() { + host = 'whatsapp.com'; + } + + @override + String standardizeURL(String url) { + return 'https://$host'; + } + + @override + Future apkUrlPrefetchModifier(String apkUrl) async { + Response res = await get(Uri.parse('https://www.whatsapp.com/android')); + if (res.statusCode == 200) { + var targetLinks = parse(res.body) + .querySelectorAll('a') + .map((e) => e.attributes['href']) + .where((e) => e != null) + .where((e) => + e!.contains('scontent.whatsapp.net') && + e.contains('WhatsApp.apk')) + .toList(); + if (targetLinks.isEmpty) { + throw NoAPKError(); + } + return targetLinks[0]!; + } else { + throw getObtainiumHttpError(res); + } + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + Response res = await get(Uri.parse('https://www.whatsapp.com/android')); + if (res.statusCode == 200) { + var targetElements = parse(res.body) + .querySelectorAll('p') + .where((element) => element.innerHtml.contains('Version ')) + .toList(); + if (targetElements.isEmpty) { + throw NoVersionError(); + } + var vLines = targetElements[0] + .innerHtml + .split('\n') + .where((element) => element.contains('Version ')) + .toList(); + if (vLines.isEmpty) { + throw NoVersionError(); + } + var versionMatch = RegExp('[0-9]+(\\.[0-9]+)+').firstMatch(vLines[0]); + if (versionMatch == null) { + throw NoVersionError(); + } + String version = + vLines[0].substring(versionMatch.start, versionMatch.end); + return APKDetails( + version, + [ + 'https://www.whatsapp.com/android?v=$version&=thisIsaPlaceholder&a=realURLPrefetchedAtDownloadTime' + ], + AppNames('Meta', 'WhatsApp')); + } else { + throw getObtainiumHttpError(res); + } + } +} diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 1b19c19..0f3eb16 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -21,6 +21,7 @@ import 'package:obtainium/app_sources/sourceforge.dart'; import 'package:obtainium/app_sources/steammobile.dart'; import 'package:obtainium/app_sources/telegramapp.dart'; import 'package:obtainium/app_sources/vlc.dart'; +import 'package:obtainium/app_sources/whatsapp.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart'; @@ -342,14 +343,15 @@ class SourceProvider { Codeberg(), FDroid(), IzzyOnDroid(), - Mullvad(), - Signal(), + FDroidRepo(), SourceForge(), APKMirror(), - FDroidRepo(), - SteamMobile(), - TelegramApp(), + Mullvad(), + Signal(), VLC(), + // WhatsApp(), // As of 2023-03-20 this is unusable as the version on the webpage is months out of date + TelegramApp(), + SteamMobile(), NeutronCode(), HTML() // This should ALWAYS be the last option as they are tried in order ]; From 9fbe52481850137f5cb812186a6d235b76c347da Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 22 Mar 2023 22:36:04 -0400 Subject: [PATCH 095/600] Bugfix: Infinite load on corrupt App JSON (#378) --- lib/main.dart | 2 +- lib/providers/apps_provider.dart | 16 +++++++++++++++- pubspec.yaml | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 7be4cea..9d7f7ad 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.12'; +const String currentVersion = '0.11.13'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index dc4f9c0..f3069df 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -571,7 +571,21 @@ class AppsProvider with ChangeNotifier { List newApps = (await getAppsDir()) .listSync() .where((item) => item.path.toLowerCase().endsWith('.json')) - .map((e) => App.fromJson(jsonDecode(File(e.path).readAsStringSync()))) + .map((e) { + try { + return App.fromJson(jsonDecode(File(e.path).readAsStringSync())); + } catch (err) { + if (err is FormatException) { + logs.add('Corrupt JSON when loading App (will be ignored): $e'); + e.renameSync('${e.path}.corrupt'); + return App( + '', '', '', '', '', '', [], 0, {}, DateTime.now(), false); + } else { + rethrow; + } + } + }) + .where((element) => element.id.isNotEmpty) .toList(); var idsToDelete = apps.values .map((e) => e.app.id) diff --git a/pubspec.yaml b/pubspec.yaml index 0a5d632..d546491 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.11.12+133 # When changing this, update the tag in main() accordingly +version: 0.11.13+134 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From a081d553bb4ade74fc252715bd73cb3a92428b39 Mon Sep 17 00:00:00 2001 From: atilluF <110931720+atilluF@users.noreply.github.com> Date: Fri, 24 Mar 2023 20:11:03 +0100 Subject: [PATCH 096/600] Update it.json --- assets/translations/it.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/it.json b/assets/translations/it.json index 120096e..9363303 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -217,9 +217,9 @@ "releaseDateAsVersionExplanation": "Questa opzione dovrebbe essere usata solo per le App in cui il rilevamento della versione non funziona correttamente, ma è disponibile una data di rilascio.", "changes": "Novità", "releaseDate": "Data di rilascio", - "importFromURLsInFile": "Import from URLs in File (like OPML)", - "versionDetection": "Version Detection", - "standardVersionDetection": "Standard version detection", + "importFromURLsInFile": "Importa da URL in file (come OPML)", + "versionDetection": "Rilevamento di versione", + "standardVersionDetection": "Rilevamento di versione standard", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" From 07c490bb0e5897c419eef090d1b8ccd5bbab4200 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 25 Mar 2023 00:47:26 -0400 Subject: [PATCH 097/600] Fixed "return after delete" bug (#359) --- lib/main.dart | 2 +- lib/pages/add_app.dart | 2 +- lib/providers/apps_provider.dart | 19 +++++++++++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 9d7f7ad..3ad511e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -210,7 +210,7 @@ class _ObtainiumState extends State { {'includePrereleases': true}, null, false) - ]); + ], onlyIfExists: false); } if (!supportedLocales .map((e) => e.languageCode) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index f68ae3c..0138db1 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -149,7 +149,7 @@ class _AddAppPageState extends State { app.installedVersion = app.latestVersion; } app.categories = pickedCategories; - await appsProvider.saveApps([app]); + await appsProvider.saveApps([app], onlyIfExists: false); return app; } diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index f3069df..572f40b 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -628,7 +628,8 @@ class AppsProvider with ChangeNotifier { } Future saveApps(List apps, - {bool attemptToCorrectInstallStatus = true}) async { + {bool attemptToCorrectInstallStatus = true, + bool onlyIfExists = true}) async { attemptToCorrectInstallStatus = attemptToCorrectInstallStatus && (await doesInstalledAppsPluginWork()); for (var app in apps) { @@ -639,9 +640,15 @@ class AppsProvider with ChangeNotifier { } File('${(await getAppsDir()).path}/${app.id}.json') .writeAsStringSync(jsonEncode(app.toJson())); - this.apps.update( - app.id, (value) => AppInMemory(app, value.downloadProgress, info), - ifAbsent: () => AppInMemory(app, null, info)); + try { + this.apps.update( + app.id, (value) => AppInMemory(app, value.downloadProgress, info), + ifAbsent: onlyIfExists ? null : () => AppInMemory(app, null, info)); + } catch (e) { + if (e is! ArgumentError || e.name != 'key') { + rethrow; + } + } } notifyListeners(); } @@ -824,7 +831,7 @@ class AppsProvider with ChangeNotifier { a.installedVersion = apps[a.id]?.app.installedVersion; } } - await saveApps(importedApps); + await saveApps(importedApps, onlyIfExists: false); notifyListeners(); return importedApps.length; } @@ -844,7 +851,7 @@ class AppsProvider with ChangeNotifier { if (apps.containsKey(app.id)) { errorsMap.addAll({app.id: tr('appAlreadyAdded')}); } else { - await saveApps([app]); + await saveApps([app], onlyIfExists: false); } } List> errors = From 4c04af38689f1d0486211cd49235f20ea669fb64 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 25 Mar 2023 00:54:12 -0400 Subject: [PATCH 098/600] Bugfix: App add doesn't redirect if nav away during add --- lib/pages/add_app.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 0138db1..a2e3cda 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -156,7 +156,7 @@ class _AddAppPageState extends State { }() .then((app) { if (app != null) { - Navigator.push(context, + Navigator.push(globalNavigatorKey.currentContext ?? context, MaterialPageRoute(builder: (context) => AppPage(appId: app.id))); } }).catchError((e) { From 895deeead5b94a4909c8ec8a887781d9b4f81a87 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 25 Mar 2023 00:54:34 -0400 Subject: [PATCH 099/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 3ad511e..e88a276 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.13'; +const String currentVersion = '0.11.14'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index d546491..76f4868 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.11.13+134 # When changing this, update the tag in main() accordingly +version: 0.11.14+135 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 3a38cedcf5e3b8a42790306768cf284d0ca12828 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 25 Mar 2023 22:55:40 -0400 Subject: [PATCH 100/600] Bugfix: Don't show uninstall option for track-only apps --- lib/providers/apps_provider.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 572f40b..b0c9675 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -669,8 +669,11 @@ class AppsProvider with ChangeNotifier { } Future removeAppsWithModal(BuildContext context, List apps) async { - var showUninstallOption = - apps.where((a) => a.installedVersion != null).isNotEmpty; + var showUninstallOption = apps + .where((a) => + a.installedVersion != null && + a.additionalSettings['trackOnly'] != true) + .isNotEmpty; var values = await showDialog( context: context, builder: (BuildContext ctx) { From a8a3fce33ae1cdab3837ef8a249d410bb7ace609 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 26 Mar 2023 07:37:35 -0400 Subject: [PATCH 101/600] Attempt to fix bug (#375) --- assets/ca/lets-encrypt-r3.pem | 30 ++++++++++++++++++++++++++++++ lib/main.dart | 10 +++++++++- pubspec.yaml | 3 ++- 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 assets/ca/lets-encrypt-r3.pem diff --git a/assets/ca/lets-encrypt-r3.pem b/assets/ca/lets-encrypt-r3.pem new file mode 100644 index 0000000..43b222a --- /dev/null +++ b/assets/ca/lets-encrypt-r3.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw +WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg +RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP +R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx +sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm +NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg +Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG +/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB +Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA +FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw +AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw +Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB +gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W +PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl +ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz +CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm +lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 +avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 +yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O +yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids +hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ +HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv +MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX +nLRbwHOoq7hHwg== +-----END CERTIFICATE----- diff --git a/lib/main.dart b/lib/main.dart index e88a276..8b3737a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.14'; +const String currentVersion = '0.11.15'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES @@ -147,6 +147,14 @@ Future bgUpdateCheck(int taskId, Map? params) async { void main() async { WidgetsFlutterBinding.ensureInitialized(); + try { + ByteData data = + await PlatformAssetBundle().load('assets/ca/lets-encrypt-r3.pem'); + SecurityContext.defaultContext + .setTrustedCertificatesBytes(data.buffer.asUint8List()); + } catch (e) { + // Already added, do nothing (see #375) + } await EasyLocalization.ensureInitialized(); if ((await DeviceInfoPlugin().androidInfo).version.sdkInt >= 29) { SystemChrome.setSystemUIOverlayStyle( diff --git a/pubspec.yaml b/pubspec.yaml index 76f4868..e2e1dea 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.11.14+135 # When changing this, update the tag in main() accordingly +version: 0.11.15+136 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' @@ -92,6 +92,7 @@ flutter: assets: - assets/translations/ - assets/graphics/ + - assets/ca/ # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware From 9fba7478023691d4e1a7720d86f4a32699acf9ca Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Thu, 30 Mar 2023 17:27:36 -0400 Subject: [PATCH 102/600] Version detection improvements, Mullvad web scraping fix and changelog addition, code readability improvements, general tweaks/bugfixes (#400) 1. Apps that don't have "standard" versioning formats now automatically stop using version detection. This will prevent users from having to learn about this feature and enable it manually. - For such Apps, the "standard" version detection option is greyed out. 2. The Mullvad Source recently broke due to a slight change in their website design. This is now fixed. - Mullvad also now provides an in-app changelog via their official GitHub repo. 3. Code has been refactored for readability (specifically the version detection code and UI code for most screens). 4. Minor UI tweaks and bugfixes. --- lib/app_sources/mullvad.dart | 37 +- lib/components/generated_form.dart | 15 +- lib/main.dart | 2 +- lib/pages/add_app.dart | 544 +++++----- lib/pages/app.dart | 787 +++++++------- lib/pages/apps.dart | 1528 +++++++++++++--------------- lib/pages/import_export.dart | 486 ++++----- lib/providers/apps_provider.dart | 143 ++- lib/providers/source_provider.dart | 21 +- pubspec.lock | 28 +- pubspec.yaml | 2 +- 11 files changed, 1720 insertions(+), 1873 deletions(-) diff --git a/lib/app_sources/mullvad.dart b/lib/app_sources/mullvad.dart index 0d8fed9..a7449dd 100644 --- a/lib/app_sources/mullvad.dart +++ b/lib/app_sources/mullvad.dart @@ -1,5 +1,7 @@ import 'package:html/parser.dart'; import 'package:http/http.dart'; +import 'package:obtainium/app_sources/github.dart'; +import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -27,23 +29,24 @@ class Mullvad extends AppSource { String standardUrl, Map additionalSettings, ) async { - Response res = await get(Uri.parse('$standardUrl/en/download/android')); - if (res.statusCode == 200) { - var version = parse(res.body) - .querySelector('p.subtitle.is-6') - ?.querySelector('a') - ?.attributes['href'] - ?.split('/') - .last; - if (version == null) { - throw NoVersionError(); - } - return APKDetails( - version, - ['https://mullvad.net/download/app/apk/latest'], - AppNames(name, 'Mullvad-VPN')); - } else { - throw getObtainiumHttpError(res); + var details = await HTML().getLatestAPKDetails( + '$standardUrl/en/download/android', additionalSettings); + var fileName = details.apkUrls[0].split('/').last; + var versionMatch = RegExp('[0-9]+(\\.[0-9]+)+').firstMatch(fileName); + if (versionMatch == null) { + throw NoVersionError(); } + details.version = fileName.substring(versionMatch.start, versionMatch.end); + details.names = AppNames(name, 'Mullvad-VPN'); + try { + details.changeLog = (await GitHub().getLatestAPKDetails( + 'https://github.com/mullvad/mullvadvpn-app', + {'fallbackToOlderReleases': true})) + .changeLog; + } catch (e) { + print(e); + // Ignore + } + return details; } } diff --git a/lib/components/generated_form.dart b/lib/components/generated_form.dart index a281899..3f892c8 100644 --- a/lib/components/generated_form.dart +++ b/lib/components/generated_form.dart @@ -48,6 +48,7 @@ class GeneratedFormTextField extends GeneratedFormItem { class GeneratedFormDropdown extends GeneratedFormItem { late List>? opts; + List? disabledOptKeys; GeneratedFormDropdown( String key, @@ -55,6 +56,7 @@ class GeneratedFormDropdown extends GeneratedFormItem { String label = 'Input', List belowWidgets = const [], String defaultValue = '', + this.disabledOptKeys, List additionalValidators = const [], }) : super(key, label: label, @@ -225,10 +227,15 @@ class _GeneratedFormState extends State { return DropdownButtonFormField( decoration: InputDecoration(labelText: formItem.label), value: values[formItem.key], - items: formItem.opts! - .map((e2) => - DropdownMenuItem(value: e2.key, child: Text(e2.value))) - .toList(), + items: formItem.opts!.map((e2) { + var enabled = + formItem.disabledOptKeys?.contains(e2.key) != true; + return DropdownMenuItem( + value: e2.key, + enabled: enabled, + child: Opacity( + opacity: enabled ? 1 : 0.5, child: Text(e2.value))); + }).toList(), onChanged: (value) { setState(() { values[formItem.key] = value ?? formItem.opts!.first.key; diff --git a/lib/main.dart b/lib/main.dart index 8b3737a..02ce25a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.15'; +const String currentVersion = '0.11.16'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index a2e3cda..64d7f3c 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -33,10 +33,10 @@ class _AddAppPageState extends State { bool additionalSettingsValid = true; List pickedCategories = []; int searchnum = 0; + SourceProvider sourceProvider = SourceProvider(); @override Widget build(BuildContext context) { - SourceProvider sourceProvider = SourceProvider(); AppsProvider appsProvider = context.read(); bool doingSomething = gettingAppInfo || searching; @@ -64,65 +64,56 @@ 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)); + } + + getReleaseDateAsVersionConfirmationIfNeeded( + bool userPickedTrackOnly) async { + return (!(additionalSettings['versionDetection'] == + 'releaseDateAsVersion' && + // ignore: use_build_context_synchronously + await showDialog( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: tr('releaseDateAsVersion'), + items: const [], + message: tr('releaseDateAsVersionExplanation'), + ); + }) == + null)); + } + addApp({bool resetUserInputAfter = false}) async { setState(() { gettingAppInfo = true; }); - var settingsProvider = context.read(); - () async { + try { + var settingsProvider = context.read(); var userPickedTrackOnly = additionalSettings['trackOnly'] == true; - var cont = true; - if ((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) { - cont = false; - } - if (additionalSettings['versionDetection'] == 'releaseDateAsVersion' && - // ignore: use_build_context_synchronously - await showDialog( - context: context, - builder: (BuildContext ctx) { - return GeneratedFormModal( - title: tr('releaseDateAsVersion'), - items: const [], - message: tr('releaseDateAsVersionExplanation'), - ); - }) == - null) { - cont = false; - } - if (additionalSettings['versionDetection'] == 'noVersionDetection' && - // ignore: use_build_context_synchronously - await showDialog( - context: context, - builder: (BuildContext ctx) { - return GeneratedFormModal( - title: tr('disableVersionDetection'), - items: const [], - message: tr('noVersionDetectionExplanation'), - ); - }) == - null) { - cont = false; - } - if (cont) { - HapticFeedback.selectionClick(); + App? app; + if ((await getTrackOnlyConfirmationIfNeeded(userPickedTrackOnly)) && + (await getReleaseDateAsVersionConfirmationIfNeeded( + userPickedTrackOnly))) { var trackOnly = pickedSource!.enforceTrackOnly || userPickedTrackOnly; - App app = await sourceProvider.getApp( + app = await sourceProvider.getApp( pickedSource!, userInput, additionalSettings, trackOnlyOverride: trackOnly); if (!trackOnly) { @@ -150,27 +141,232 @@ class _AddAppPageState extends State { } app.categories = pickedCategories; await appsProvider.saveApps([app], onlyIfExists: false); - - return app; } - }() - .then((app) { if (app != null) { Navigator.push(globalNavigatorKey.currentContext ?? context, - MaterialPageRoute(builder: (context) => AppPage(appId: app.id))); + MaterialPageRoute(builder: (context) => AppPage(appId: app!.id))); } - }).catchError((e) { + } catch (e) { showError(e, context); - }).whenComplete(() { + } finally { setState(() { gettingAppInfo = false; if (resetUserInputAfter) { changeUserInput('', false, true); } }); - }); + } } + Widget getUrlInputRow() => Row( + children: [ + Expanded( + child: GeneratedForm( + key: Key(searchnum.toString()), + items: [ + [ + GeneratedFormTextField('appSourceURL', + label: tr('appSourceURL'), + defaultValue: userInput, + additionalValidators: [ + (value) { + try { + sourceProvider + .getSource(value ?? '') + .standardizeURL( + preStandardizeUrl(value ?? '')); + } catch (e) { + return e is String + ? e + : e is ObtainiumError + ? e.toString() + : tr('error'); + } + return null; + } + ]) + ] + ], + onValueChanges: (values, valid, isBuilding) { + changeUserInput( + values['appSourceURL']!, valid, isBuilding); + })), + const SizedBox( + width: 16, + ), + gettingAppInfo + ? const CircularProgressIndicator() + : ElevatedButton( + onPressed: doingSomething || + pickedSource == null || + (pickedSource!.combinedAppSpecificSettingFormItems + .isNotEmpty && + !additionalSettingsValid) + ? null + : () { + HapticFeedback.selectionClick(); + addApp(); + }, + child: Text(tr('add'))) + ], + ); + + runSearch() async { + setState(() { + searching = true; + }); + try { + var results = await Future.wait(sourceProvider.sources + .where((e) => e.canSearch) + .map((e) => e.search(searchQuery))); + + // .then((results) async { + // Interleave results instead of simple reduce + Map res = {}; + var si = 0; + var done = false; + while (!done) { + done = true; + for (var r in results) { + if (r.length > si) { + done = false; + res.addEntries([r.entries.elementAt(si)]); + } + } + si++; + } + List? selectedUrls = res.isEmpty + ? [] + // ignore: use_build_context_synchronously + : await showDialog?>( + context: context, + builder: (BuildContext ctx) { + return UrlSelectionModal( + urlsWithDescriptions: res, + selectedByDefault: false, + onlyOneSelectionAllowed: true, + ); + }); + if (selectedUrls != null && selectedUrls.isNotEmpty) { + changeUserInput(selectedUrls[0], true, false, isSearch: true); + } + } catch (e) { + showError(e, context); + } finally { + setState(() { + searching = false; + }); + } + } + + bool shouldShowSearchBar() => + sourceProvider.sources.where((e) => e.canSearch).isNotEmpty && + pickedSource == null && + userInput.isEmpty; + + Widget getSearchBarRow() => Row( + children: [ + Expanded( + child: GeneratedForm( + items: [ + [ + GeneratedFormTextField('searchSomeSources', + label: tr('searchSomeSourcesLabel'), required: false), + ] + ], + onValueChanges: (values, valid, isBuilding) { + if (values.isNotEmpty && valid && !isBuilding) { + setState(() { + searchQuery = values['searchSomeSources']!.trim(); + }); + } + }), + ), + const SizedBox( + width: 16, + ), + ElevatedButton( + onPressed: searchQuery.isEmpty || doingSomething + ? null + : () { + runSearch(); + }, + child: Text(tr('search'))) + ], + ); + + Widget getAdditionalOptsCol() => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Divider( + height: 64, + ), + Text( + tr('additionalOptsFor', + args: [pickedSource?.name ?? tr('source')]), + style: TextStyle(color: Theme.of(context).colorScheme.primary)), + const SizedBox( + height: 16, + ), + GeneratedForm( + key: Key(pickedSource.runtimeType.toString()), + items: pickedSource!.combinedAppSpecificSettingFormItems, + onValueChanges: (values, valid, isBuilding) { + if (!isBuilding) { + setState(() { + additionalSettings = values; + additionalSettingsValid = valid; + }); + } + }), + Column( + children: [ + const SizedBox( + height: 16, + ), + CategoryEditorSelector( + alignment: WrapAlignment.start, + onSelected: (categories) { + pickedCategories = categories; + }), + ], + ), + ], + ); + + Widget getSourcesListWidget() => Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox( + height: 48, + ), + Text( + tr('supportedSourcesBelow'), + ), + const SizedBox( + height: 8, + ), + ...sourceProvider.sources + .map((e) => GestureDetector( + onTap: e.host != null + ? () { + launchUrlString('https://${e.host}', + mode: LaunchMode.externalApplication); + } + : null, + child: Text( + '${e.name}${e.enforceTrackOnly ? ' ${tr('trackOnlyInBrackets')}' : ''}${e.canSearch ? ' ${tr('searchableInBrackets')}' : ''}', + style: TextStyle( + decoration: e.host != null + ? TextDecoration.underline + : TextDecoration.none, + fontStyle: FontStyle.italic), + ))) + .toList() + ])); + return Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, body: CustomScrollView(slivers: [ @@ -181,230 +377,16 @@ class _AddAppPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Row( - children: [ - Expanded( - child: GeneratedForm( - key: Key(searchnum.toString()), - items: [ - [ - GeneratedFormTextField('appSourceURL', - label: tr('appSourceURL'), - defaultValue: userInput, - additionalValidators: [ - (value) { - try { - sourceProvider - .getSource(value ?? '') - .standardizeURL( - preStandardizeUrl( - value ?? '')); - } catch (e) { - return e is String - ? e - : e is ObtainiumError - ? e.toString() - : tr('error'); - } - return null; - } - ]) - ] - ], - onValueChanges: (values, valid, isBuilding) { - changeUserInput(values['appSourceURL']!, - valid, isBuilding); - })), - const SizedBox( - width: 16, - ), - gettingAppInfo - ? const CircularProgressIndicator() - : ElevatedButton( - onPressed: doingSomething || - pickedSource == null || - (pickedSource! - .combinedAppSpecificSettingFormItems - .isNotEmpty && - !additionalSettingsValid) - ? null - : addApp, - child: Text(tr('add'))) - ], - ), - if (sourceProvider.sources - .where((e) => e.canSearch) - .isNotEmpty && - pickedSource == null && - userInput.isEmpty) + getUrlInputRow(), + if (shouldShowSearchBar()) const SizedBox( height: 16, ), - if (sourceProvider.sources - .where((e) => e.canSearch) - .isNotEmpty && - pickedSource == null && - userInput.isEmpty) - Row( - children: [ - Expanded( - child: GeneratedForm( - items: [ - [ - GeneratedFormTextField( - 'searchSomeSources', - label: tr('searchSomeSourcesLabel'), - required: false), - ] - ], - onValueChanges: (values, valid, isBuilding) { - if (values.isNotEmpty && - valid && - !isBuilding) { - setState(() { - searchQuery = - values['searchSomeSources']!.trim(); - }); - } - }), - ), - const SizedBox( - width: 16, - ), - ElevatedButton( - onPressed: searchQuery.isEmpty || doingSomething - ? null - : () { - setState(() { - searching = true; - }); - Future.wait(sourceProvider.sources - .where((e) => e.canSearch) - .map((e) => - e.search(searchQuery))) - .then((results) async { - // Interleave results instead of simple reduce - Map res = {}; - var si = 0; - var done = false; - while (!done) { - done = true; - for (var r in results) { - if (r.length > si) { - done = false; - res.addEntries( - [r.entries.elementAt(si)]); - } - } - si++; - } - List? selectedUrls = res - .isEmpty - ? [] - : await showDialog?>( - context: context, - builder: (BuildContext ctx) { - return UrlSelectionModal( - urlsWithDescriptions: res, - selectedByDefault: false, - onlyOneSelectionAllowed: - true, - ); - }); - if (selectedUrls != null && - selectedUrls.isNotEmpty) { - changeUserInput( - selectedUrls[0], true, false, - isSearch: true); - } - }).catchError((e) { - showError(e, context); - }).whenComplete(() { - setState(() { - searching = false; - }); - }); - }, - child: Text(tr('search'))) - ], - ), + if (shouldShowSearchBar()) getSearchBarRow(), if (pickedSource != null) - Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Divider( - height: 64, - ), - Text( - tr('additionalOptsFor', - args: [pickedSource?.name ?? tr('source')]), - style: TextStyle( - color: - Theme.of(context).colorScheme.primary)), - const SizedBox( - height: 16, - ), - GeneratedForm( - key: Key(pickedSource.runtimeType.toString()), - items: pickedSource! - .combinedAppSpecificSettingFormItems, - onValueChanges: (values, valid, isBuilding) { - if (!isBuilding) { - setState(() { - additionalSettings = values; - additionalSettingsValid = valid; - }); - } - }), - Column( - children: [ - const SizedBox( - height: 16, - ), - CategoryEditorSelector( - alignment: WrapAlignment.start, - onSelected: (categories) { - pickedCategories = categories; - }), - ], - ), - ], - ) + getAdditionalOptsCol() else - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox( - height: 48, - ), - Text( - tr('supportedSourcesBelow'), - ), - const SizedBox( - height: 8, - ), - ...sourceProvider.sources - .map((e) => GestureDetector( - onTap: e.host != null - ? () { - launchUrlString( - 'https://${e.host}', - mode: LaunchMode - .externalApplication); - } - : null, - child: Text( - '${e.name}${e.enforceTrackOnly ? ' ${tr('trackOnlyInBrackets')}' : ''}${e.canSearch ? ' ${tr('searchableInBrackets')}' : ''}', - style: TextStyle( - decoration: e.host != null - ? TextDecoration.underline - : TextDecoration.none, - fontStyle: FontStyle.italic), - ))) - .toList() - ])), + getSourcesListWidget(), const SizedBox( height: 8, ), diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 4a73b72..701cb56 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'; @@ -34,406 +35,414 @@ class _AppPageState extends State { }); } + bool areDownloadsRunning = appsProvider.areDownloadsRunning(); + var sourceProvider = SourceProvider(); AppInMemory? app = appsProvider.apps[widget.appId]; var source = app != null ? sourceProvider.getSource(app.app.url) : null; - if (!appsProvider.areDownloadsRunning() && prevApp == null && app != null) { + if (!areDownloadsRunning && prevApp == null && app != null) { prevApp = app; getUpdate(app.app.id); } var trackOnly = app?.app.additionalSettings['trackOnly'] == true; - var infoColumn = Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - GestureDetector( - onTap: () { - if (app?.app.url != null) { - launchUrlString(app?.app.url ?? '', - mode: LaunchMode.externalApplication); - } - }, - child: Text( - app?.app.url ?? '', - textAlign: TextAlign.center, - style: const TextStyle( - decoration: TextDecoration.underline, - fontStyle: FontStyle.italic, - fontSize: 12), - )), - const SizedBox( - height: 32, - ), - Text( - tr('latestVersionX', args: [app?.app.latestVersion ?? tr('unknown')]), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.bodyLarge, - ), - Text( - '${tr('installedVersionX', args: [ - app?.app.installedVersion ?? tr('none') - ])}${trackOnly ? ' ${tr('estimateInBrackets')}\n\n${tr('xIsTrackOnly', args: [ - tr('app') - ])}' : ''}', - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.bodyLarge, - ), - const SizedBox( - height: 32, - ), - Text( - tr('lastUpdateCheckX', args: [ - app?.app.lastUpdateCheck == null - ? tr('never') - : '\n${app?.app.lastUpdateCheck?.toLocal()}' - ]), - textAlign: TextAlign.center, - style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 12), - ), - const SizedBox( - height: 48, - ), - CategoryEditorSelector( - alignment: WrapAlignment.center, - preselected: - app?.app.categories != null ? app!.app.categories.toSet() : {}, - onSelected: (categories) { - if (app != null) { - app.app.categories = categories; - appsProvider.saveApps([app.app]); - } - }), - ], - ); + bool isVersionDetectionStandard = + app?.app.additionalSettings['versionDetection'] == + 'standardVersionDetection'; - var fullInfoColumn = Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox(height: 125), - app?.installedInfo != null - ? Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.memory( - app!.installedInfo!.icon!, - height: 150, - gaplessPlayback: true, - ) - ]) - : Container(), - const SizedBox( - height: 25, - ), - Text( - app?.installedInfo?.name ?? app?.app.name ?? tr('app'), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.displayLarge, - ), - Text( - tr('byX', args: [app?.app.author ?? tr('unknown')]), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.headlineMedium, - ), - const SizedBox( - height: 8, - ), - Text( - app?.app.id ?? '', - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.labelSmall, - ), - app?.app.releaseDate == null - ? const SizedBox.shrink() - : Text( - app!.app.releaseDate.toString(), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.labelSmall, + getInfoColumn() => Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + GestureDetector( + onTap: () { + if (app?.app.url != null) { + launchUrlString(app?.app.url ?? '', + mode: LaunchMode.externalApplication); + } + }, + child: Text( + app?.app.url ?? '', + textAlign: TextAlign.center, + style: const TextStyle( + decoration: TextDecoration.underline, + fontStyle: FontStyle.italic, + fontSize: 12), + )), + const SizedBox( + height: 32, + ), + Text( + tr('latestVersionX', + args: [app?.app.latestVersion ?? tr('unknown')]), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyLarge, + ), + Text( + '${tr('installedVersionX', args: [ + app?.installedInfo?.versionName ?? + app?.app.installedVersion ?? + tr('none') + ])}${trackOnly ? ' ${tr('estimateInBrackets')}\n\n${tr('xIsTrackOnly', args: [ + tr('app') + ])}' : ''}', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyLarge, + ), + if (app?.app.installedVersion != null && + !isVersionDetectionStandard) + Column( + children: [ + const SizedBox( + height: 4, + ), + Text( + tr('noVersionDetection'), + style: Theme.of(context).textTheme.labelSmall, + ) + ], ), - const SizedBox( - height: 32, - ), - infoColumn, - const SizedBox(height: 150) - ], - ); + const SizedBox( + height: 32, + ), + Text( + tr('lastUpdateCheckX', args: [ + app?.app.lastUpdateCheck == null + ? tr('never') + : '\n${app?.app.lastUpdateCheck?.toLocal()}' + ]), + textAlign: TextAlign.center, + style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 12), + ), + const SizedBox( + height: 48, + ), + CategoryEditorSelector( + alignment: WrapAlignment.center, + preselected: app?.app.categories != null + ? app!.app.categories.toSet() + : {}, + onSelected: (categories) { + if (app != null) { + app.app.categories = categories; + appsProvider.saveApps([app.app]); + } + }), + ], + ); + + getFullInfoColumn() => Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 125), + app?.installedInfo != null + ? Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + Image.memory( + app!.installedInfo!.icon!, + height: 150, + gaplessPlayback: true, + ) + ]) + : Container(), + const SizedBox( + height: 25, + ), + Text( + app?.installedInfo?.name ?? app?.app.name ?? tr('app'), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.displayLarge, + ), + Text( + tr('byX', args: [app?.app.author ?? tr('unknown')]), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.headlineMedium, + ), + const SizedBox( + height: 8, + ), + Text( + app?.app.id ?? '', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.labelSmall, + ), + app?.app.releaseDate == null + ? const SizedBox.shrink() + : Text( + app!.app.releaseDate.toString(), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.labelSmall, + ), + const SizedBox( + height: 32, + ), + getInfoColumn(), + const SizedBox(height: 150) + ], + ); + + getAppWebView() => app != null + ? WebViewWidget( + controller: WebViewController() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setBackgroundColor(Theme.of(context).colorScheme.background) + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setNavigationDelegate( + NavigationDelegate( + onWebResourceError: (WebResourceError error) { + if (error.isForMainFrame == true) { + showError( + ObtainiumError(error.description, unexpected: true), + context); + } + }, + ), + ) + ..loadRequest(Uri.parse(app.app.url))) + : Container(); + + showMarkUpdatedDialog() { + return showDialog( + context: context, + builder: (BuildContext ctx) { + return AlertDialog( + title: Text(tr('alreadyUpToDateQuestion')), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(tr('no'))), + TextButton( + onPressed: () { + HapticFeedback.selectionClick(); + var updatedApp = app?.app; + if (updatedApp != null) { + updatedApp.installedVersion = updatedApp.latestVersion; + appsProvider.saveApps([updatedApp]); + } + Navigator.of(context).pop(); + }, + child: Text(tr('yesMarkUpdated'))) + ], + ); + }); + } + + showAdditionalOptionsDialog() async { + return await showDialog?>( + context: context, + builder: (BuildContext ctx) { + var items = + (source?.combinedAppSpecificSettingFormItems ?? []).map((row) { + row = row.map((e) { + if (app?.app.additionalSettings[e.key] != null) { + e.defaultValue = app?.app.additionalSettings[e.key]; + } + return e; + }).toList(); + return row; + }).toList(); + + items = items.map((row) { + row = row.map((e) { + if (e.key == 'versionDetection' && e is GeneratedFormDropdown) { + e.disabledOptKeys ??= []; + if (app?.app.installedVersion != null && + !appsProvider.isVersionDetectionPossible(app)) { + e.disabledOptKeys!.add('standardVersionDetection'); + } + if (app?.app.releaseDate == null) { + e.disabledOptKeys!.add('releaseDateAsVersion'); + } + } + return e; + }).toList(); + return row; + }).toList(); + + return GeneratedFormModal( + title: tr('additionalOptions'), + items: items, + ); + }); + } + + handleAdditionalOptionChanges(Map? values) { + if (app != null && values != null) { + Map originalSettings = app.app.additionalSettings; + app.app.additionalSettings = values; + if (source?.enforceTrackOnly == true) { + app.app.additionalSettings['trackOnly'] = true; + // ignore: use_build_context_synchronously + showError(tr('appsFromSourceAreTrackOnly'), context); + } + if (app.app.additionalSettings['versionDetection'] == + 'releaseDateAsVersion') { + if (originalSettings['versionDetection'] != 'releaseDateAsVersion') { + if (app.app.releaseDate != null) { + bool isUpdated = + app.app.installedVersion == app.app.latestVersion; + app.app.latestVersion = + app.app.releaseDate!.microsecondsSinceEpoch.toString(); + if (isUpdated) { + app.app.installedVersion = app.app.latestVersion; + } + } + } + } else if (originalSettings['versionDetection'] == + 'releaseDateAsVersion') { + app.app.installedVersion = + app.installedInfo?.versionName ?? app.app.installedVersion; + } + appsProvider.saveApps([app.app]).then((value) { + getUpdate(app.app.id); + }); + } + } + + getInstallOrUpdateButton() => TextButton( + onPressed: (app?.app.installedVersion == null || + app?.app.installedVersion != app?.app.latestVersion) && + !areDownloadsRunning + ? () 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) { + Navigator.of(context).pop(); + } + } catch (e) { + showError(e, context); + } + } + : null, + child: Text(app?.app.installedVersion == null + ? !trackOnly + ? tr('install') + : tr('markInstalled') + : !trackOnly + ? tr('update') + : tr('markUpdated'))); + + getBottomSheetMenu() => Padding( + padding: + EdgeInsets.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + if (app?.app.installedVersion != null && + app?.app.installedVersion != app?.app.latestVersion && + !isVersionDetectionStandard && + !trackOnly) + IconButton( + onPressed: app?.downloadProgress != null + ? null + : showMarkUpdatedDialog, + tooltip: tr('markUpdated'), + icon: const Icon(Icons.done)), + if (source != null && + source.combinedAppSpecificSettingFormItems.isNotEmpty) + IconButton( + onPressed: app?.downloadProgress != null + ? null + : () async { + var values = + await showAdditionalOptionsDialog(); + handleAdditionalOptionChanges(values); + }, + tooltip: tr('additionalOptions'), + icon: const Icon(Icons.edit)), + if (app != null && app.installedInfo != null) + IconButton( + onPressed: () { + appsProvider.openAppSettings(app.app.id); + }, + icon: const Icon(Icons.settings), + tooltip: tr('settings'), + ), + if (app != null && settingsProvider.showAppWebpage) + IconButton( + onPressed: () { + showDialog( + context: context, + builder: (BuildContext ctx) { + return AlertDialog( + scrollable: true, + content: getInfoColumn(), + title: Text( + '${app.app.name} ${tr('byX', args: [ + app.app.author + ])}'), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(tr('continue'))) + ], + ); + }); + }, + icon: const Icon(Icons.more_horiz), + tooltip: tr('more')), + const SizedBox(width: 16.0), + Expanded(child: getInstallOrUpdateButton()), + const SizedBox(width: 16.0), + Expanded( + child: TextButton( + onPressed: app?.downloadProgress != null + ? null + : () { + appsProvider.removeAppsWithModal( + context, [app!.app]).then((value) { + if (value == true) { + Navigator.of(context).pop(); + } + }); + }, + style: TextButton.styleFrom( + foregroundColor: + Theme.of(context).colorScheme.error, + surfaceTintColor: + Theme.of(context).colorScheme.error), + child: Text(tr('remove')), + )), + ])), + if (app?.downloadProgress != null) + Padding( + padding: const EdgeInsets.fromLTRB(0, 8, 0, 0), + child: LinearProgressIndicator( + value: app!.downloadProgress! / 100)) + ], + )); return Scaffold( - appBar: settingsProvider.showAppWebpage ? AppBar() : null, - backgroundColor: Theme.of(context).colorScheme.surface, - body: RefreshIndicator( - child: settingsProvider.showAppWebpage - ? app != null - ? WebViewWidget( - controller: WebViewController() - ..setJavaScriptMode(JavaScriptMode.unrestricted) - ..setBackgroundColor( - Theme.of(context).colorScheme.background) - ..setJavaScriptMode(JavaScriptMode.unrestricted) - ..setNavigationDelegate( - NavigationDelegate( - onWebResourceError: (WebResourceError error) { - if (error.isForMainFrame == true) { - showError( - ObtainiumError(error.description, - unexpected: true), - context); - } - }, - ), - ) - ..loadRequest(Uri.parse(app.app.url))) - : Container() - : CustomScrollView( - slivers: [ - SliverToBoxAdapter( - child: Column(children: [fullInfoColumn])), - ], - ), - onRefresh: () async { - if (app != null) { - getUpdate(app.app.id); - } - }), - bottomSheet: Padding( - padding: EdgeInsets.fromLTRB( - 0, 0, 0, MediaQuery.of(context).padding.bottom), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.fromLTRB(16, 8, 16, 0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - if (app?.app.additionalSettings['versionDetection'] != - 'standardVersionDetection' && - !trackOnly && - app?.app.installedVersion != null && - app?.app.installedVersion != app?.app.latestVersion) - IconButton( - onPressed: app?.downloadProgress != null - ? null - : () { - showDialog( - context: context, - builder: (BuildContext ctx) { - return AlertDialog( - title: Text(tr( - 'alreadyUpToDateQuestion')), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context) - .pop(); - }, - child: Text(tr('no'))), - TextButton( - onPressed: () { - HapticFeedback - .selectionClick(); - var updatedApp = app?.app; - if (updatedApp != null) { - updatedApp - .installedVersion = - updatedApp - .latestVersion; - appsProvider.saveApps( - [updatedApp]); - } - Navigator.of(context) - .pop(); - }, - child: Text( - tr('yesMarkUpdated'))) - ], - ); - }); - }, - tooltip: tr('markUpdated'), - icon: const Icon(Icons.done)), - if (source != null && - source - .combinedAppSpecificSettingFormItems.isNotEmpty) - IconButton( - onPressed: app?.downloadProgress != null - ? null - : () { - showDialog?>( - context: context, - builder: (BuildContext ctx) { - var items = source - .combinedAppSpecificSettingFormItems - .map((row) { - row.map((e) { - if (app?.app.additionalSettings[ - e.key] != - null) { - e.defaultValue = app?.app - .additionalSettings[ - e.key]; - } - return e; - }).toList(); - return row; - }).toList(); - return GeneratedFormModal( - title: tr('additionalOptions'), - items: items, - ); - }).then((values) { - if (app != null && values != null) { - Map - originalSettings = - app.app.additionalSettings; - app.app.additionalSettings = values; - if (source.enforceTrackOnly) { - app.app.additionalSettings[ - 'trackOnly'] = true; - showError( - tr('appsFromSourceAreTrackOnly'), - context); - } - if (app.app.additionalSettings[ - 'versionDetection'] == - 'releaseDateAsVersion') { - if (originalSettings[ - 'versionDetection'] != - 'releaseDateAsVersion') { - if (app.app.releaseDate != null) { - bool isUpdated = - app.app.installedVersion == - app.app.latestVersion; - app.app.latestVersion = app - .app - .releaseDate! - .microsecondsSinceEpoch - .toString(); - if (isUpdated) { - app.app.installedVersion = - app.app.latestVersion; - } - } - } - } else if (originalSettings[ - 'versionDetection'] == - 'releaseDateAsVersion') { - app.app.installedVersion = app - .installedInfo - ?.versionName ?? - app.app.installedVersion; - } - appsProvider.saveApps([app.app]).then( - (value) { - getUpdate(app.app.id); - }); - } - }); - }, - tooltip: tr('additionalOptions'), - icon: const Icon(Icons.edit)), - if (app != null && app.installedInfo != null) - IconButton( - onPressed: () { - appsProvider.openAppSettings(app.app.id); - }, - icon: const Icon(Icons.settings), - tooltip: tr('settings'), - ), - if (app != null && settingsProvider.showAppWebpage) - IconButton( - onPressed: () { - showDialog( - context: context, - builder: (BuildContext ctx) { - return AlertDialog( - scrollable: true, - content: infoColumn, - title: Text( - '${app.app.name} ${tr('byX', args: [ - app.app.author - ])}'), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text(tr('continue'))) - ], - ); - }); - }, - icon: const Icon(Icons.more_horiz), - tooltip: tr('more')), - const SizedBox(width: 16.0), - Expanded( - child: TextButton( - onPressed: (app?.app.installedVersion == null || - app?.app.installedVersion != - app?.app.latestVersion) && - !appsProvider.areDownloadsRunning() - ? () { - HapticFeedback.heavyImpact(); - () async { - if (app?.app.additionalSettings[ - 'trackOnly'] != - true) { - await settingsProvider - .getInstallPermission(); - } - }() - .then((value) { - appsProvider - .downloadAndInstallLatestApps( - [app!.app.id], - globalNavigatorKey - .currentContext).then( - (res) { - if (res.isNotEmpty && mounted) { - Navigator.of(context).pop(); - } - }).catchError((e) { - showError(e, context); - }); - }).catchError((e) { - showError(e, context); - }); - } - : null, - child: Text(app?.app.installedVersion == null - ? !trackOnly - ? tr('install') - : tr('markInstalled') - : !trackOnly - ? tr('update') - : tr('markUpdated')))), - const SizedBox(width: 16.0), - Expanded( - child: TextButton( - onPressed: app?.downloadProgress != null - ? null - : () { - appsProvider.removeAppsWithModal( - context, [app!.app]).then((value) { - if (value == true) { - Navigator.of(context).pop(); - } - }); - }, - style: TextButton.styleFrom( - foregroundColor: - Theme.of(context).colorScheme.error, - surfaceTintColor: - Theme.of(context).colorScheme.error), - child: Text(tr('remove')), - )), - ])), - if (app?.downloadProgress != null) - Padding( - padding: const EdgeInsets.fromLTRB(0, 8, 0, 0), - child: LinearProgressIndicator( - value: app!.downloadProgress! / 100)) - ], - )), - ); + appBar: settingsProvider.showAppWebpage ? AppBar() : null, + backgroundColor: Theme.of(context).colorScheme.surface, + body: RefreshIndicator( + child: settingsProvider.showAppWebpage + ? getAppWebView() + : CustomScrollView( + slivers: [ + SliverToBoxAdapter( + child: Column(children: [getFullInfoColumn()])), + ], + ), + onRefresh: () async { + if (app != null) { + getUpdate(app.app.id); + } + }), + bottomSheet: getBottomSheetMenu()); } } diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index a0beb61..d8b59f6 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -187,6 +187,722 @@ class AppsPageState extends State { } listedApps = [...tempPinned, ...tempNotPinned]; + showChangeLogDialog( + String? changesUrl, AppSource appSource, String changeLog, int index) { + showDialog( + context: context, + builder: (BuildContext context) { + return GeneratedFormModal( + title: tr('changes'), + items: const [], + additionalWidgets: [ + changesUrl != null + ? GestureDetector( + child: Text( + changesUrl, + style: const TextStyle( + decoration: TextDecoration.underline, + fontStyle: FontStyle.italic), + ), + onTap: () { + launchUrlString(changesUrl, + mode: LaunchMode.externalApplication); + }, + ) + : const SizedBox.shrink(), + changesUrl != null + ? const SizedBox( + height: 16, + ) + : const SizedBox.shrink(), + appSource.changeLogIfAnyIsMarkDown + ? SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height - 350, + child: Markdown( + data: changeLog, + onTapLink: (text, href, title) { + if (href != null) { + launchUrlString( + href.startsWith('http://') || + href.startsWith('https://') + ? href + : '${Uri.parse(listedApps[index].app.url).origin}/$href', + mode: LaunchMode.externalApplication); + } + }, + extensionSet: md.ExtensionSet( + md.ExtensionSet.gitHubFlavored.blockSyntaxes, + [ + md.EmojiSyntax(), + ...md.ExtensionSet.gitHubFlavored.inlineSyntaxes + ], + ), + )) + : Text(changeLog), + ], + singleNullReturnButton: tr('ok'), + ); + }); + } + + getLoadingWidgets() { + return [ + if (appsProvider.loadingApps || listedApps.isEmpty) + SliverFillRemaining( + child: Center( + child: appsProvider.loadingApps + ? const CircularProgressIndicator() + : Text( + appsProvider.apps.isEmpty + ? tr('noApps') + : tr('noAppsForFilter'), + style: Theme.of(context).textTheme.headlineMedium, + textAlign: TextAlign.center, + ))), + if (refreshingSince != null) + SliverToBoxAdapter( + child: LinearProgressIndicator( + value: appsProvider.apps.values + .where((element) => !(element.app.lastUpdateCheck + ?.isBefore(refreshingSince!) ?? + true)) + .length / + appsProvider.apps.length, + ), + ) + ]; + } + + getChangeLogFn(int appIndex) { + AppSource appSource = + SourceProvider().getSource(listedApps[appIndex].app.url); + String? changesUrl = + appSource.changeLogPageFromStandardUrl(listedApps[appIndex].app.url); + String? changeLog = listedApps[appIndex].app.changeLog; + return (changeLog == null && changesUrl == null) + ? null + : () { + if (changeLog != null) { + showChangeLogDialog(changesUrl, appSource, changeLog, appIndex); + } else { + launchUrlString(changesUrl!, + mode: LaunchMode.externalApplication); + } + }; + } + + getUpdateButton(int appIndex) { + return IconButton( + visualDensity: VisualDensity.compact, + color: Theme.of(context).colorScheme.primary, + tooltip: + listedApps[appIndex].app.additionalSettings['trackOnly'] == true + ? tr('markUpdated') + : tr('update'), + onPressed: appsProvider.areDownloadsRunning() + ? null + : () { + appsProvider.downloadAndInstallLatestApps( + [listedApps[appIndex].app.id], + globalNavigatorKey.currentContext).catchError((e) { + showError(e, context); + }); + }, + icon: Icon( + listedApps[appIndex].app.additionalSettings['trackOnly'] == true + ? Icons.check_circle_outline + : Icons.install_mobile)); + } + + getAppIcon(int appIndex) { + return listedApps[appIndex].installedInfo != null + ? Image.memory( + listedApps[appIndex].installedInfo!.icon!, + gaplessPlayback: true, + ) + : Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Transform( + alignment: Alignment.center, + transform: Matrix4.rotationZ(0.31), + child: Padding( + padding: const EdgeInsets.all(15), + child: Image( + image: const AssetImage( + 'assets/graphics/icon_small.png'), + color: Colors.white.withOpacity(0.1), + colorBlendMode: BlendMode.modulate, + gaplessPlayback: true, + ), + )), + ]); + } + + getVersionText(int appIndex) { + return '${listedApps[appIndex].app.installedVersion ?? tr('notInstalled')}${listedApps[appIndex].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}'; + } + + getChangesButtonString(int appIndex, bool hasChangeLogFn) { + return listedApps[appIndex].app.releaseDate == null + ? hasChangeLogFn + ? tr('changes') + : '' + : DateFormat('yyyy-MM-dd') + .format(listedApps[appIndex].app.releaseDate!); + } + + getSingleAppHorizTile(int index) { + var showChangesFn = getChangeLogFn(index); + var hasUpdate = listedApps[index].app.installedVersion != null && + listedApps[index].app.installedVersion != + listedApps[index].app.latestVersion; + Widget trailingRow = Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + hasUpdate ? getUpdateButton(index) : const SizedBox.shrink(), + hasUpdate + ? const SizedBox( + width: 10, + ) + : const SizedBox.shrink(), + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row(mainAxisSize: MainAxisSize.min, children: [ + Container( + constraints: const BoxConstraints(maxWidth: 150), + child: Text( + getVersionText(index), + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.end, + )), + ]), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: showChangesFn, + child: Text( + getChangesButtonString(index, showChangesFn != null), + style: TextStyle( + fontStyle: FontStyle.italic, + decoration: showChangesFn != null + ? TextDecoration.underline + : TextDecoration.none), + )) + ], + ), + ], + ) + ], + ); + + var transparent = const Color.fromARGB(0, 0, 0, 0).value; + return Container( + decoration: BoxDecoration( + border: Border.symmetric( + vertical: BorderSide( + width: 4, + color: Color(listedApps[index].app.categories.isNotEmpty + ? settingsProvider.categories[ + listedApps[index].app.categories.first] ?? + transparent + : transparent)))), + child: ListTile( + tileColor: listedApps[index].app.pinned + ? Colors.grey.withOpacity(0.1) + : Colors.transparent, + selectedTileColor: Theme.of(context) + .colorScheme + .primary + .withOpacity(listedApps[index].app.pinned ? 0.2 : 0.1), + selected: selectedApps.contains(listedApps[index].app), + onLongPress: () { + toggleAppSelected(listedApps[index].app); + }, + leading: getAppIcon(index), + title: Text( + maxLines: 1, + listedApps[index].installedInfo?.name ?? + listedApps[index].app.name, + style: TextStyle( + overflow: TextOverflow.ellipsis, + fontWeight: listedApps[index].app.pinned + ? FontWeight.bold + : FontWeight.normal, + ), + ), + subtitle: Text(tr('byX', args: [listedApps[index].app.author]), + maxLines: 1, + style: TextStyle( + overflow: TextOverflow.ellipsis, + fontWeight: listedApps[index].app.pinned + ? FontWeight.bold + : FontWeight.normal)), + trailing: listedApps[index].downloadProgress != null + ? Text(tr('percentProgress', args: [ + listedApps[index].downloadProgress?.toInt().toString() ?? + '100' + ])) + : trailingRow, + onTap: () { + if (selectedApps.isNotEmpty) { + toggleAppSelected(listedApps[index].app); + } else { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + AppPage(appId: listedApps[index].app.id)), + ); + } + }, + )); + } + + getSelectAllButton() { + return selectedApps.isEmpty + ? TextButton.icon( + style: const ButtonStyle(visualDensity: VisualDensity.compact), + onPressed: () { + selectThese(listedApps.map((e) => e.app).toList()); + }, + icon: Icon( + Icons.select_all_outlined, + color: Theme.of(context).colorScheme.primary, + ), + label: Text(listedApps.length.toString())) + : TextButton.icon( + style: const ButtonStyle(visualDensity: VisualDensity.compact), + onPressed: () { + selectedApps.isEmpty + ? selectThese(listedApps.map((e) => e.app).toList()) + : clearSelected(); + }, + icon: Icon( + selectedApps.isEmpty + ? Icons.select_all_outlined + : Icons.deselect_outlined, + color: Theme.of(context).colorScheme.primary, + ), + label: Text(selectedApps.length.toString())); + } + + getMassObtainFunction() { + return appsProvider.areDownloadsRunning() || + (existingUpdateIdsAllOrSelected.isEmpty && + newInstallIdsAllOrSelected.isEmpty && + trackOnlyUpdateIdsAllOrSelected.isEmpty) + ? null + : () { + HapticFeedback.heavyImpact(); + List formItems = []; + if (existingUpdateIdsAllOrSelected.isNotEmpty) { + formItems.add(GeneratedFormSwitch('updates', + label: tr('updateX', args: [ + plural('apps', existingUpdateIdsAllOrSelected.length) + ]), + defaultValue: true)); + } + if (newInstallIdsAllOrSelected.isNotEmpty) { + formItems.add(GeneratedFormSwitch('installs', + label: tr('installX', args: [ + plural('apps', newInstallIdsAllOrSelected.length) + ]), + defaultValue: existingUpdateIdsAllOrSelected.isNotEmpty)); + } + if (trackOnlyUpdateIdsAllOrSelected.isNotEmpty) { + formItems.add(GeneratedFormSwitch('trackonlies', + label: tr('markXTrackOnlyAsUpdated', args: [ + plural('apps', trackOnlyUpdateIdsAllOrSelected.length) + ]), + defaultValue: existingUpdateIdsAllOrSelected.isNotEmpty || + newInstallIdsAllOrSelected.isNotEmpty)); + } + showDialog?>( + context: context, + builder: (BuildContext ctx) { + var totalApps = existingUpdateIdsAllOrSelected.length + + newInstallIdsAllOrSelected.length + + trackOnlyUpdateIdsAllOrSelected.length; + return GeneratedFormModal( + title: tr('changeX', args: [plural('apps', totalApps)]), + items: formItems.map((e) => [e]).toList(), + initValid: true, + ); + }).then((values) { + if (values != null) { + if (values.isEmpty) { + values = getDefaultValuesFromFormItems([formItems]); + } + bool shouldInstallUpdates = values['updates'] == true; + 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); + } + if (shouldInstallNew) { + toInstall.addAll(newInstallIdsAllOrSelected); + } + if (shouldMarkTrackOnlies) { + toInstall.addAll(trackOnlyUpdateIdsAllOrSelected); + } + appsProvider + .downloadAndInstallLatestApps( + toInstall, globalNavigatorKey.currentContext) + .catchError((e) { + showError(e, context); + }); + }); + } + }); + }; + } + + launchCategorizeDialog() { + return () async { + try { + Set? preselected; + var showPrompt = false; + for (var element in selectedApps) { + var currentCats = element.categories.toSet(); + if (preselected == null) { + preselected = currentCats; + } else { + if (!settingsProvider.setEqual(currentCats, preselected)) { + showPrompt = true; + break; + } + } + } + var cont = true; + if (showPrompt) { + cont = await showDialog?>( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: tr('categorize'), + items: const [], + initValid: true, + message: tr('selectedCategorizeWarning'), + ); + }) != + null; + } + if (cont) { + // ignore: use_build_context_synchronously + await showDialog?>( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: tr('categorize'), + items: const [], + initValid: true, + singleNullReturnButton: tr('continue'), + additionalWidgets: [ + CategoryEditorSelector( + preselected: !showPrompt ? preselected ?? {} : {}, + showLabelWhenNotEmpty: false, + onSelected: (categories) { + appsProvider.saveApps(selectedApps.map((e) { + e.categories = categories; + return e; + }).toList()); + }, + ) + ], + ); + }); + } + } catch (err) { + showError(err, context); + } + }; + } + + showMassMarkDialog() { + return showDialog( + context: context, + builder: (BuildContext ctx) { + return AlertDialog( + title: Text(tr('markXSelectedAppsAsUpdated', + args: [selectedApps.length.toString()])), + content: Text( + tr('onlyWorksWithNonVersionDetectApps'), + style: const TextStyle( + fontWeight: FontWeight.bold, fontStyle: FontStyle.italic), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(tr('no'))), + TextButton( + onPressed: () { + HapticFeedback.selectionClick(); + appsProvider.saveApps(selectedApps.map((a) { + if (a.installedVersion != null && + !appsProvider.isVersionDetectionPossible( + appsProvider.apps[a.id])) { + a.installedVersion = a.latestVersion; + } + return a; + }).toList()); + + Navigator.of(context).pop(); + }, + child: Text(tr('yes'))) + ], + ); + }).whenComplete(() { + Navigator.of(context).pop(); + }); + } + + pinSelectedApps() { + () { + var pinStatus = selectedApps.where((element) => element.pinned).isEmpty; + appsProvider.saveApps(selectedApps.map((e) { + e.pinned = pinStatus; + return e; + }).toList()); + Navigator.of(context).pop(); + }; + } + + resetSelectedAppsInstallStatuses() { + () async { + try { + var values = await showDialog( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: tr('resetInstallStatusForSelectedAppsQuestion'), + items: const [], + initValid: true, + message: tr('installStatusOfXWillBeResetExplanation', + args: [plural('app', selectedApps.length)]), + ); + }); + if (values != null) { + appsProvider.saveApps(selectedApps.map((e) { + e.installedVersion = null; + return e; + }).toList()); + } + } finally { + Navigator.of(context).pop(); + } + }; + } + + showMoreOptionsDialog() { + return showDialog( + context: context, + builder: (BuildContext ctx) { + return AlertDialog( + scrollable: true, + content: Padding( + padding: const EdgeInsets.only(top: 6), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + IconButton( + onPressed: appsProvider.areDownloadsRunning() + ? null + : showMassMarkDialog, + tooltip: tr('markSelectedAppsUpdated'), + icon: const Icon(Icons.done)), + IconButton( + onPressed: pinSelectedApps, + tooltip: selectedApps + .where((element) => element.pinned) + .isEmpty + ? tr('pinToTop') + : tr('unpinFromTop'), + icon: Icon(selectedApps + .where((element) => element.pinned) + .isEmpty + ? Icons.bookmark_outline_rounded + : Icons.bookmark_remove_outlined), + ), + IconButton( + onPressed: () { + String urls = ''; + for (var a in selectedApps) { + urls += '${a.url}\n'; + } + urls = urls.substring(0, urls.length - 1); + Share.share(urls, + subject: tr('selectedAppURLsFromObtainium')); + Navigator.of(context).pop(); + }, + tooltip: tr('shareSelectedAppURLs'), + icon: const Icon(Icons.share), + ), + IconButton( + onPressed: resetSelectedAppsInstallStatuses(), + tooltip: tr('resetInstallStatus'), + icon: const Icon(Icons.restore_page_outlined), + ), + ]), + ), + ); + }); + } + + getMainBottomButtonsRow() { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + IconButton( + visualDensity: VisualDensity.compact, + onPressed: selectedApps.isEmpty + ? null + : () { + appsProvider.removeAppsWithModal( + context, selectedApps.toList()); + }, + tooltip: tr('removeSelectedApps'), + icon: const Icon(Icons.delete_outline_outlined), + ), + IconButton( + visualDensity: VisualDensity.compact, + onPressed: getMassObtainFunction(), + tooltip: selectedApps.isEmpty + ? tr('installUpdateApps') + : tr('installUpdateSelectedApps'), + icon: const Icon( + Icons.file_download_outlined, + )), + IconButton( + visualDensity: VisualDensity.compact, + onPressed: selectedApps.isEmpty ? null : launchCategorizeDialog(), + tooltip: tr('categorize'), + icon: const Icon(Icons.category_outlined), + ), + IconButton( + visualDensity: VisualDensity.compact, + onPressed: selectedApps.isEmpty ? null : showMoreOptionsDialog, + tooltip: tr('more'), + icon: const Icon(Icons.more_horiz), + ), + ], + ); + } + + showFilterDialog() async { + var values = await showDialog?>( + context: context, + builder: (BuildContext ctx) { + var vals = filter.toFormValuesMap(); + return GeneratedFormModal( + initValid: true, + title: tr('filterApps'), + items: [ + [ + GeneratedFormTextField('appName', + label: tr('appName'), + required: false, + defaultValue: vals['appName']), + GeneratedFormTextField('author', + label: tr('author'), + required: false, + defaultValue: vals['author']) + ], + [ + GeneratedFormSwitch('upToDateApps', + label: tr('upToDateApps'), + defaultValue: vals['upToDateApps']) + ], + [ + GeneratedFormSwitch('nonInstalledApps', + label: tr('nonInstalledApps'), + defaultValue: vals['nonInstalledApps']) + ] + ], + additionalWidgets: [ + const SizedBox( + height: 16, + ), + CategoryEditorSelector( + preselected: filter.categoryFilter, + onSelected: (categories) { + filter.categoryFilter = categories.toSet(); + }, + ) + ], + ); + }); + if (values != null) { + setState(() { + filter.setFormValuesFromMap(values); + }); + } + } + + getFilterButtonsRow() { + return Row( + children: [ + getSelectAllButton(), + const VerticalDivider(), + Expanded( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: getMainBottomButtonsRow())), + const VerticalDivider(), + IconButton( + visualDensity: VisualDensity.compact, + onPressed: () { + setState(() { + if (currentFilterIsUpdatesOnly) { + filter = AppsFilter(); + } else { + filter = updatesOnlyFilter; + } + }); + }, + tooltip: currentFilterIsUpdatesOnly + ? tr('removeOutdatedFilter') + : tr('showOutdatedOnly'), + icon: Icon( + currentFilterIsUpdatesOnly + ? Icons.update_disabled_rounded + : Icons.update_rounded, + color: Theme.of(context).colorScheme.primary, + ), + ), + TextButton.icon( + style: const ButtonStyle(visualDensity: VisualDensity.compact), + label: Text( + filter.isIdenticalTo(neutralFilter, settingsProvider) + ? tr('filter') + : tr('filterActive'), + style: TextStyle( + fontWeight: + filter.isIdenticalTo(neutralFilter, settingsProvider) + ? FontWeight.normal + : FontWeight.bold), + ), + onPressed: showFilterDialog, + icon: const Icon(Icons.filter_list_rounded)) + ], + ); + } + return Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, body: RefreshIndicator( @@ -205,823 +921,17 @@ class AppsPageState extends State { }, child: CustomScrollView(slivers: [ CustomAppBar(title: tr('appsString')), - if (appsProvider.loadingApps || listedApps.isEmpty) - SliverFillRemaining( - child: Center( - child: appsProvider.loadingApps - ? const CircularProgressIndicator() - : Text( - appsProvider.apps.isEmpty - ? tr('noApps') - : tr('noAppsForFilter'), - style: Theme.of(context).textTheme.headlineMedium, - textAlign: TextAlign.center, - ))), - if (refreshingSince != null) - SliverToBoxAdapter( - child: LinearProgressIndicator( - value: appsProvider.apps.values - .where((element) => !(element.app.lastUpdateCheck - ?.isBefore(refreshingSince!) ?? - true)) - .length / - appsProvider.apps.length, - ), - ), + ...getLoadingWidgets(), SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { - AppSource appSource = - SourceProvider().getSource(listedApps[index].app.url); - String? changesUrl = appSource - .changeLogPageFromStandardUrl(listedApps[index].app.url); - String? changeLog = listedApps[index].app.changeLog; - var showChanges = (changeLog == null && changesUrl == null) - ? null - : () { - if (changeLog != null) { - showDialog( - context: context, - builder: (BuildContext context) { - return GeneratedFormModal( - title: tr('changes'), - items: const [], - additionalWidgets: [ - changesUrl != null - ? GestureDetector( - child: Text( - changesUrl, - style: const TextStyle( - decoration: - TextDecoration.underline, - fontStyle: FontStyle.italic), - ), - onTap: () { - launchUrlString(changesUrl, - mode: LaunchMode - .externalApplication); - }, - ) - : const SizedBox.shrink(), - changesUrl != null - ? const SizedBox( - height: 16, - ) - : const SizedBox.shrink(), - appSource.changeLogIfAnyIsMarkDown - ? SizedBox( - width: - MediaQuery.of(context).size.width, - height: MediaQuery.of(context) - .size - .height - - 350, - child: Markdown( - data: changeLog, - onTapLink: (text, href, title) { - if (href != null) { - launchUrlString( - href.startsWith( - 'http://') || - href.startsWith( - 'https://') - ? href - : '${Uri.parse(listedApps[index].app.url).origin}/$href', - mode: LaunchMode - .externalApplication); - } - }, - extensionSet: md.ExtensionSet( - md.ExtensionSet.gitHubFlavored - .blockSyntaxes, - [ - md.EmojiSyntax(), - ...md - .ExtensionSet - .gitHubFlavored - .inlineSyntaxes - ], - ), - )) - : Text(changeLog), - ], - singleNullReturnButton: tr('ok'), - ); - }); - } else { - launchUrlString(changesUrl!, - mode: LaunchMode.externalApplication); - } - }; - var transparent = const Color.fromARGB(0, 0, 0, 0).value; - var hasUpdate = listedApps[index].app.installedVersion != null && - listedApps[index].app.installedVersion != - listedApps[index].app.latestVersion; - var updateButton = IconButton( - visualDensity: VisualDensity.compact, - color: Theme.of(context).colorScheme.primary, - tooltip: - listedApps[index].app.additionalSettings['trackOnly'] == - true - ? tr('markUpdated') - : tr('update'), - onPressed: appsProvider.areDownloadsRunning() - ? null - : () { - appsProvider.downloadAndInstallLatestApps([ - listedApps[index].app.id - ], globalNavigatorKey.currentContext).catchError((e) { - showError(e, context); - }); - }, - icon: Icon( - listedApps[index].app.additionalSettings['trackOnly'] == - true - ? Icons.check_circle_outline - : Icons.install_mobile)); - return Container( - decoration: BoxDecoration( - border: Border.symmetric( - vertical: BorderSide( - width: 4, - color: Color( - listedApps[index].app.categories.isNotEmpty - ? settingsProvider.categories[ - listedApps[index] - .app - .categories - .first] ?? - transparent - : transparent)))), - child: ListTile( - tileColor: listedApps[index].app.pinned - ? Colors.grey.withOpacity(0.1) - : Colors.transparent, - selectedTileColor: Theme.of(context) - .colorScheme - .primary - .withOpacity(listedApps[index].app.pinned ? 0.2 : 0.1), - selected: selectedApps.contains(listedApps[index].app), - onLongPress: () { - toggleAppSelected(listedApps[index].app); - }, - leading: listedApps[index].installedInfo != null - ? Image.memory( - listedApps[index].installedInfo!.icon!, - gaplessPlayback: true, - ) - : Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Transform( - alignment: Alignment.center, - transform: Matrix4.rotationZ(0.31), - child: Padding( - padding: const EdgeInsets.all(15), - child: Image( - image: const AssetImage( - 'assets/graphics/icon_small.png'), - color: Colors.white.withOpacity(0.1), - colorBlendMode: BlendMode.modulate, - gaplessPlayback: true, - ), - )), - ]), - title: Text( - maxLines: 1, - listedApps[index].installedInfo?.name ?? - listedApps[index].app.name, - style: TextStyle( - overflow: TextOverflow.ellipsis, - fontWeight: listedApps[index].app.pinned - ? FontWeight.bold - : FontWeight.normal, - ), - ), - subtitle: Text( - tr('byX', args: [listedApps[index].app.author]), - maxLines: 1, - style: TextStyle( - overflow: TextOverflow.ellipsis, - fontWeight: listedApps[index].app.pinned - ? FontWeight.bold - : FontWeight.normal)), - trailing: listedApps[index].downloadProgress != null - ? Text(tr('percentProgress', args: [ - listedApps[index] - .downloadProgress - ?.toInt() - .toString() ?? - '100' - ])) - : (Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - hasUpdate - ? updateButton - : const SizedBox.shrink(), - hasUpdate - ? const SizedBox( - width: 10, - ) - : const SizedBox.shrink(), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - constraints: const BoxConstraints( - maxWidth: 150), - child: Text( - '${listedApps[index].app.installedVersion ?? tr('notInstalled')}${listedApps[index].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}', - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.end, - )), - ]), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - GestureDetector( - onTap: showChanges, - child: Text( - listedApps[index].app.releaseDate == - null - ? showChanges != null - ? tr('changes') - : '' - : DateFormat('yyyy-MM-dd') - .format(listedApps[index] - .app - .releaseDate!), - style: TextStyle( - fontStyle: FontStyle.italic, - decoration: showChanges != null - ? TextDecoration.underline - : TextDecoration.none), - )) - ], - ), - ], - ) - ], - )), - onTap: () { - if (selectedApps.isNotEmpty) { - toggleAppSelected(listedApps[index].app); - } else { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - AppPage(appId: listedApps[index].app.id)), - ); - } - }, - )); + return getSingleAppHorizTile(index); }, childCount: listedApps.length)) ])), persistentFooterButtons: appsProvider.apps.isEmpty ? null : [ - Row( - children: [ - selectedApps.isEmpty - ? TextButton.icon( - style: const ButtonStyle( - visualDensity: VisualDensity.compact), - onPressed: () { - selectThese(listedApps.map((e) => e.app).toList()); - }, - icon: Icon( - Icons.select_all_outlined, - color: Theme.of(context).colorScheme.primary, - ), - label: Text(listedApps.length.toString())) - : TextButton.icon( - style: const ButtonStyle( - visualDensity: VisualDensity.compact), - onPressed: () { - selectedApps.isEmpty - ? selectThese( - listedApps.map((e) => e.app).toList()) - : clearSelected(); - }, - icon: Icon( - selectedApps.isEmpty - ? Icons.select_all_outlined - : Icons.deselect_outlined, - color: Theme.of(context).colorScheme.primary, - ), - label: Text(selectedApps.length.toString())), - const VerticalDivider(), - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - IconButton( - visualDensity: VisualDensity.compact, - onPressed: selectedApps.isEmpty - ? null - : () { - appsProvider.removeAppsWithModal( - context, selectedApps.toList()); - }, - tooltip: tr('removeSelectedApps'), - icon: const Icon(Icons.delete_outline_outlined), - ), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: appsProvider - .areDownloadsRunning() || - (existingUpdateIdsAllOrSelected - .isEmpty && - newInstallIdsAllOrSelected - .isEmpty && - trackOnlyUpdateIdsAllOrSelected - .isEmpty) - ? null - : () { - HapticFeedback.heavyImpact(); - List formItems = - []; - if (existingUpdateIdsAllOrSelected - .isNotEmpty) { - formItems.add(GeneratedFormSwitch( - 'updates', - label: tr('updateX', args: [ - plural( - 'apps', - existingUpdateIdsAllOrSelected - .length) - ]), - defaultValue: true)); - } - if (newInstallIdsAllOrSelected - .isNotEmpty) { - formItems.add(GeneratedFormSwitch( - 'installs', - label: tr('installX', args: [ - plural( - 'apps', - newInstallIdsAllOrSelected - .length) - ]), - defaultValue: - existingUpdateIdsAllOrSelected - .isNotEmpty)); - } - if (trackOnlyUpdateIdsAllOrSelected - .isNotEmpty) { - formItems.add(GeneratedFormSwitch( - 'trackonlies', - label: tr( - 'markXTrackOnlyAsUpdated', - args: [ - plural( - 'apps', - trackOnlyUpdateIdsAllOrSelected - .length) - ]), - defaultValue: - existingUpdateIdsAllOrSelected - .isNotEmpty || - newInstallIdsAllOrSelected - .isNotEmpty)); - } - showDialog?>( - context: context, - builder: (BuildContext ctx) { - var totalApps = existingUpdateIdsAllOrSelected - .length + - newInstallIdsAllOrSelected - .length + - trackOnlyUpdateIdsAllOrSelected - .length; - return GeneratedFormModal( - title: tr('changeX', args: [ - plural('apps', totalApps) - ]), - items: formItems - .map((e) => [e]) - .toList(), - initValid: true, - ); - }).then((values) { - if (values != null) { - if (values.isEmpty) { - values = - getDefaultValuesFromFormItems( - [formItems]); - } - bool shouldInstallUpdates = - values['updates'] == true; - 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); - } - if (shouldInstallNew) { - toInstall.addAll( - newInstallIdsAllOrSelected); - } - if (shouldMarkTrackOnlies) { - toInstall.addAll( - trackOnlyUpdateIdsAllOrSelected); - } - appsProvider - .downloadAndInstallLatestApps( - toInstall, - globalNavigatorKey - .currentContext) - .catchError((e) { - showError(e, context); - }); - }); - } - }); - }, - tooltip: selectedApps.isEmpty - ? tr('installUpdateApps') - : tr('installUpdateSelectedApps'), - icon: const Icon( - Icons.file_download_outlined, - )), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: selectedApps.isEmpty - ? null - : () async { - try { - Set? preselected; - var showPrompt = false; - for (var element in selectedApps) { - var currentCats = - element.categories.toSet(); - if (preselected == null) { - preselected = currentCats; - } else { - if (!settingsProvider.setEqual( - currentCats, preselected)) { - showPrompt = true; - break; - } - } - } - var cont = true; - if (showPrompt) { - cont = await showDialog< - Map?>( - context: context, - builder: - (BuildContext ctx) { - return GeneratedFormModal( - title: tr('categorize'), - items: const [], - initValid: true, - message: tr( - 'selectedCategorizeWarning'), - ); - }) != - null; - } - if (cont) { - // ignore: use_build_context_synchronously - await showDialog< - Map?>( - context: context, - builder: (BuildContext ctx) { - return GeneratedFormModal( - title: tr('categorize'), - items: const [], - initValid: true, - singleNullReturnButton: - tr('continue'), - additionalWidgets: [ - CategoryEditorSelector( - preselected: !showPrompt - ? preselected ?? {} - : {}, - showLabelWhenNotEmpty: - false, - onSelected: - (categories) { - appsProvider.saveApps( - selectedApps - .map((e) { - e.categories = - categories; - return e; - }).toList()); - }, - ) - ], - ); - }); - } - } catch (err) { - showError(err, context); - } - }, - tooltip: tr('categorize'), - icon: const Icon(Icons.category_outlined), - ), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: selectedApps.isEmpty - ? null - : () { - showDialog( - context: context, - builder: (BuildContext ctx) { - return AlertDialog( - scrollable: true, - content: Padding( - padding: - const EdgeInsets.only( - top: 6), - child: Row( - mainAxisAlignment: - MainAxisAlignment - .spaceAround, - children: [ - IconButton( - onPressed: appsProvider - .areDownloadsRunning() - ? null - : () { - showDialog( - context: - context, - builder: - (BuildContext - ctx) { - return AlertDialog( - title: - Text(tr('markXSelectedAppsAsUpdated', args: [ - selectedApps.length.toString() - ])), - content: - Text( - tr('onlyWorksWithNonVersionDetectApps'), - style: const TextStyle(fontWeight: FontWeight.bold, fontStyle: FontStyle.italic), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text(tr('no'))), - TextButton( - onPressed: () { - HapticFeedback.selectionClick(); - appsProvider.saveApps(selectedApps.map((a) { - if (a.installedVersion != null && a.additionalSettings['versionDetection'] != 'standardVersionDetection') { - a.installedVersion = a.latestVersion; - } - return a; - }).toList()); - - Navigator.of(context).pop(); - }, - child: Text(tr('yes'))) - ], - ); - }).whenComplete(() { - Navigator.of( - context) - .pop(); - }); - }, - tooltip: tr( - 'markSelectedAppsUpdated'), - icon: const Icon( - Icons.done)), - IconButton( - onPressed: () { - var pinStatus = selectedApps - .where((element) => - element - .pinned) - .isEmpty; - appsProvider - .saveApps( - selectedApps - .map( - (e) { - e.pinned = - pinStatus; - return e; - }).toList()); - Navigator.of( - context) - .pop(); - }, - tooltip: selectedApps - .where((element) => - element - .pinned) - .isEmpty - ? tr('pinToTop') - : tr( - 'unpinFromTop'), - icon: Icon(selectedApps - .where((element) => - element - .pinned) - .isEmpty - ? Icons - .bookmark_outline_rounded - : Icons - .bookmark_remove_outlined), - ), - IconButton( - onPressed: () { - String urls = ''; - for (var a - in selectedApps) { - urls += - '${a.url}\n'; - } - urls = - urls.substring( - 0, - urls.length - - 1); - Share.share(urls, - subject: tr( - 'selectedAppURLsFromObtainium')); - Navigator.of( - context) - .pop(); - }, - tooltip: tr( - 'shareSelectedAppURLs'), - icon: const Icon( - Icons.share), - ), - IconButton( - onPressed: () { - showDialog( - context: - context, - builder: - (BuildContext - ctx) { - return GeneratedFormModal( - title: tr( - 'resetInstallStatusForSelectedAppsQuestion'), - items: const [], - initValid: - true, - message: tr( - 'installStatusOfXWillBeResetExplanation', - args: [ - plural( - 'app', - selectedApps.length) - ]), - ); - }).then((values) { - if (values != - null) { - appsProvider.saveApps( - selectedApps - .map( - (e) { - e.installedVersion = - null; - return e; - }).toList()); - } - }).whenComplete(() { - Navigator.of( - context) - .pop(); - }); - }, - tooltip: tr( - 'resetInstallStatus'), - icon: const Icon(Icons - .restore_page_outlined), - ), - ]), - ), - ); - }); - }, - tooltip: tr('more'), - icon: const Icon(Icons.more_horiz), - ), - ], - ))), - const VerticalDivider(), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: () { - setState(() { - if (currentFilterIsUpdatesOnly) { - filter = AppsFilter(); - } else { - filter = updatesOnlyFilter; - } - }); - }, - tooltip: currentFilterIsUpdatesOnly - ? tr('removeOutdatedFilter') - : tr('showOutdatedOnly'), - icon: Icon( - currentFilterIsUpdatesOnly - ? Icons.update_disabled_rounded - : Icons.update_rounded, - color: Theme.of(context).colorScheme.primary, - ), - ), - TextButton.icon( - style: const ButtonStyle( - visualDensity: VisualDensity.compact), - label: Text( - filter.isIdenticalTo(neutralFilter, settingsProvider) - ? tr('filter') - : tr('filterActive'), - style: TextStyle( - fontWeight: filter.isIdenticalTo( - neutralFilter, settingsProvider) - ? FontWeight.normal - : FontWeight.bold), - ), - onPressed: () { - showDialog?>( - context: context, - builder: (BuildContext ctx) { - var vals = filter.toFormValuesMap(); - return GeneratedFormModal( - initValid: true, - title: tr('filterApps'), - items: [ - [ - GeneratedFormTextField('appName', - label: tr('appName'), - required: false, - defaultValue: vals['appName']), - GeneratedFormTextField('author', - label: tr('author'), - required: false, - defaultValue: vals['author']) - ], - [ - GeneratedFormSwitch('upToDateApps', - label: tr('upToDateApps'), - defaultValue: vals['upToDateApps']) - ], - [ - GeneratedFormSwitch('nonInstalledApps', - label: tr('nonInstalledApps'), - defaultValue: vals['nonInstalledApps']) - ] - ], - additionalWidgets: [ - const SizedBox( - height: 16, - ), - CategoryEditorSelector( - preselected: filter.categoryFilter, - onSelected: (categories) { - filter.categoryFilter = - categories.toSet(); - }, - ) - ], - ); - }).then((values) { - if (values != null) { - setState(() { - filter.setFormValuesFromMap(values); - }); - } - }); - }, - icon: const Icon(Icons.filter_list_rounded)) - ], - ), + getFilterButtonsRow(), ], ); } diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index 71ec42c..9372f20 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -30,6 +30,7 @@ class _ImportExportPageState extends State { SourceProvider sourceProvider = SourceProvider(); var appsProvider = context.read(); var settingsProvider = context.read(); + var outlineButtonStyle = ButtonStyle( shape: MaterialStateProperty.all( StadiumBorder( @@ -101,6 +102,193 @@ class _ImportExportPageState extends State { }); } + runObtainiumExport() { + HapticFeedback.selectionClick(); + appsProvider.exportApps().then((String path) { + showError(tr('exportedTo', args: [path]), context); + }).catchError((e) { + showError(e, context); + }); + } + + runObtainiumImport() { + HapticFeedback.selectionClick(); + FilePicker.platform.pickFiles().then((result) { + setState(() { + importInProgress = true; + }); + if (result != null) { + String data = File(result.files.single.path!).readAsStringSync(); + try { + jsonDecode(data); + } catch (e) { + throw ObtainiumError(tr('invalidInput')); + } + appsProvider.importApps(data).then((value) { + var cats = settingsProvider.categories; + appsProvider.apps.forEach((key, value) { + for (var c in value.app.categories) { + if (!cats.containsKey(c)) { + cats[c] = generateRandomLightColor().value; + } + } + }); + settingsProvider.categories = cats; + showError(tr('importedX', args: [plural('apps', value)]), context); + }); + } else { + // User canceled the picker + } + }).catchError((e) { + showError(e, context); + }).whenComplete(() { + setState(() { + importInProgress = false; + }); + }); + } + + runUrlImport() { + FilePicker.platform.pickFiles().then((result) { + if (result != null) { + urlListImport( + overrideInitValid: true, + initValue: RegExp('https?://[^"]+') + .allMatches( + File(result.files.single.path!).readAsStringSync()) + .map((e) => e.input.substring(e.start, e.end)) + .toSet() + .toList() + .where((url) { + try { + sourceProvider.getSource(url); + return true; + } catch (e) { + return false; + } + }).join('\n')); + } + }); + } + + runSourceSearch(AppSource source) { + () async { + var values = await showDialog?>( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: tr('searchX', args: [source.name]), + items: [ + [ + GeneratedFormTextField('searchQuery', + label: tr('searchQuery')) + ] + ], + ); + }); + if (values != null && + (values['searchQuery'] as String?)?.isNotEmpty == true) { + setState(() { + importInProgress = true; + }); + var urlsWithDescriptions = + await source.search(values['searchQuery'] as String); + if (urlsWithDescriptions.isNotEmpty) { + var selectedUrls = + // ignore: use_build_context_synchronously + await showDialog?>( + context: context, + builder: (BuildContext ctx) { + return UrlSelectionModal( + urlsWithDescriptions: urlsWithDescriptions, + selectedByDefault: false, + ); + }); + if (selectedUrls != null && selectedUrls.isNotEmpty) { + var errors = await appsProvider.addAppsByURL(selectedUrls); + if (errors.isEmpty) { + // ignore: use_build_context_synchronously + showError( + tr('importedX', args: [plural('app', selectedUrls.length)]), + context); + } else { + // ignore: use_build_context_synchronously + showDialog( + context: context, + builder: (BuildContext ctx) { + return ImportErrorDialog( + urlsLength: selectedUrls.length, errors: errors); + }); + } + } + } else { + throw ObtainiumError(tr('noResults')); + } + } + }() + .catchError((e) { + showError(e, context); + }).whenComplete(() { + setState(() { + importInProgress = false; + }); + }); + } + + runMassSourceImport(MassAppUrlSource source) { + () async { + var values = await showDialog?>( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: tr('importX', args: [source.name]), + items: source.requiredArgs + .map((e) => [GeneratedFormTextField(e, label: e)]) + .toList(), + ); + }); + if (values != null) { + setState(() { + importInProgress = true; + }); + var urlsWithDescriptions = await source.getUrlsWithDescriptions( + values.values.map((e) => e.toString()).toList()); + var selectedUrls = + // ignore: use_build_context_synchronously + await showDialog?>( + context: context, + builder: (BuildContext ctx) { + return UrlSelectionModal( + urlsWithDescriptions: urlsWithDescriptions); + }); + if (selectedUrls != null) { + var errors = await appsProvider.addAppsByURL(selectedUrls); + if (errors.isEmpty) { + // ignore: use_build_context_synchronously + showError( + tr('importedX', args: [plural('app', selectedUrls.length)]), + context); + } else { + // ignore: use_build_context_synchronously + showDialog( + context: context, + builder: (BuildContext ctx) { + return ImportErrorDialog( + urlsLength: selectedUrls.length, errors: errors); + }); + } + } + } + }() + .catchError((e) { + showError(e, context); + }).whenComplete(() { + setState(() { + importInProgress = false; + }); + }); + } + return Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, body: CustomScrollView(slivers: [ @@ -120,18 +308,7 @@ class _ImportExportPageState extends State { onPressed: appsProvider.apps.isEmpty || importInProgress ? null - : () { - HapticFeedback.selectionClick(); - appsProvider - .exportApps() - .then((String path) { - showError( - tr('exportedTo', args: [path]), - context); - }).catchError((e) { - showError(e, context); - }); - }, + : runObtainiumExport, child: Text(tr('obtainiumExport')))), const SizedBox( width: 16, @@ -141,59 +318,7 @@ class _ImportExportPageState extends State { style: outlineButtonStyle, onPressed: importInProgress ? null - : () { - HapticFeedback.selectionClick(); - FilePicker.platform - .pickFiles() - .then((result) { - setState(() { - importInProgress = true; - }); - if (result != null) { - String data = File( - result.files.single.path!) - .readAsStringSync(); - try { - jsonDecode(data); - } catch (e) { - throw ObtainiumError( - tr('invalidInput')); - } - appsProvider - .importApps(data) - .then((value) { - var cats = - settingsProvider.categories; - appsProvider.apps - .forEach((key, value) { - for (var c - in value.app.categories) { - if (!cats.containsKey(c)) { - cats[c] = - generateRandomLightColor() - .value; - } - } - }); - settingsProvider.categories = - cats; - showError( - tr('importedX', args: [ - plural('apps', value) - ]), - context); - }); - } else { - // User canceled the picker - } - }).catchError((e) { - showError(e, context); - }).whenComplete(() { - setState(() { - importInProgress = false; - }); - }); - }, + : runObtainiumImport, child: Text(tr('obtainiumImport')))) ], ), @@ -216,49 +341,15 @@ class _ImportExportPageState extends State { height: 32, ), TextButton( - onPressed: importInProgress - ? null - : () { - urlListImport(); - }, + onPressed: + importInProgress ? null : urlListImport, child: Text( tr('importFromURLList'), )), const SizedBox(height: 8), TextButton( - onPressed: importInProgress - ? null - : () { - FilePicker.platform - .pickFiles() - .then((result) { - if (result != null) { - urlListImport( - overrideInitValid: true, - initValue: - RegExp('https?://[^"]+') - .allMatches(File(result - .files - .single - .path!) - .readAsStringSync()) - .map((e) => - e.input.substring( - e.start, e.end)) - .toSet() - .toList() - .where((url) { - try { - sourceProvider - .getSource(url); - return true; - } catch (e) { - return false; - } - }).join('\n')); - } - }); - }, + onPressed: + importInProgress ? null : runUrlImport, child: Text( tr('importFromURLsInFile'), )), @@ -275,106 +366,7 @@ class _ImportExportPageState extends State { onPressed: importInProgress ? null : () { - () async { - var values = await showDialog< - Map?>( - context: context, - builder: - (BuildContext ctx) { - return GeneratedFormModal( - title: tr('searchX', - args: [ - source.name - ]), - items: [ - [ - GeneratedFormTextField( - 'searchQuery', - label: tr( - 'searchQuery')) - ] - ], - ); - }); - if (values != null && - (values['searchQuery'] - as String?) - ?.isNotEmpty == - true) { - setState(() { - importInProgress = true; - }); - var urlsWithDescriptions = - await source.search( - values['searchQuery'] - as String); - if (urlsWithDescriptions - .isNotEmpty) { - var selectedUrls = - // ignore: use_build_context_synchronously - await showDialog< - List< - String>?>( - context: context, - builder: - (BuildContext - ctx) { - return UrlSelectionModal( - urlsWithDescriptions: - urlsWithDescriptions, - selectedByDefault: - false, - ); - }); - if (selectedUrls != - null && - selectedUrls - .isNotEmpty) { - var errors = - await appsProvider - .addAppsByURL( - selectedUrls); - if (errors.isEmpty) { - // ignore: use_build_context_synchronously - showError( - tr('importedX', - args: [ - plural( - 'app', - selectedUrls - .length) - ]), - context); - } else { - // ignore: use_build_context_synchronously - showDialog( - context: context, - builder: - (BuildContext - ctx) { - return ImportErrorDialog( - urlsLength: - selectedUrls - .length, - errors: - errors); - }); - } - } - } else { - throw ObtainiumError( - tr('noResults')); - } - } - }() - .catchError((e) { - showError(e, context); - }).whenComplete(() { - setState(() { - importInProgress = false; - }); - }); + runSourceSearch(source); }, child: Text( tr('searchX', args: [source.name]))) @@ -390,93 +382,7 @@ class _ImportExportPageState extends State { onPressed: importInProgress ? null : () { - () async { - var values = await showDialog< - Map?>( - context: context, - builder: - (BuildContext ctx) { - return GeneratedFormModal( - title: tr('importX', - args: [ - source.name - ]), - items: - source - .requiredArgs - .map( - (e) => [ - GeneratedFormTextField(e, - label: e) - ]) - .toList(), - ); - }); - if (values != null) { - setState(() { - importInProgress = true; - }); - var urlsWithDescriptions = - await source - .getUrlsWithDescriptions( - values.values - .map((e) => - e.toString()) - .toList()); - var selectedUrls = - // ignore: use_build_context_synchronously - await showDialog< - List?>( - context: context, - builder: - (BuildContext - ctx) { - return UrlSelectionModal( - urlsWithDescriptions: - urlsWithDescriptions); - }); - if (selectedUrls != null) { - var errors = - await appsProvider - .addAppsByURL( - selectedUrls); - if (errors.isEmpty) { - // ignore: use_build_context_synchronously - showError( - tr('importedX', - args: [ - plural( - 'app', - selectedUrls - .length) - ]), - context); - } else { - // ignore: use_build_context_synchronously - showDialog( - context: context, - builder: - (BuildContext - ctx) { - return ImportErrorDialog( - urlsLength: - selectedUrls - .length, - errors: - errors); - }); - } - } - } - }() - .catchError((e) { - showError(e, context); - }).whenComplete(() { - setState(() { - importInProgress = false; - }); - }); + runMassSourceImport(source); }, child: Text( tr('importX', args: [source.name]))) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index b0c9675..cf19488 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -73,6 +73,18 @@ List generateStandardVersionRegExStrings() { List standardVersionRegExStrings = generateStandardVersionRegExStrings(); +Set findStandardFormatsForVersion(String version, bool strict) { + // If !strict, even a substring match is valid + Set results = {}; + for (var pattern in standardVersionRegExStrings) { + if (RegExp('${strict ? '^' : ''}$pattern${strict ? '\$' : ''}') + .hasMatch(version)) { + results.add(pattern); + } + } + return results; +} + class AppsProvider with ChangeNotifier { // In memory App state (should always be kept in sync with local storage versions) Map apps = {}; @@ -472,94 +484,113 @@ class AppsProvider with ChangeNotifier { return res; } - // If the App says it is installed but installedInfo is null, set it to not installed - // If there is any other mismatch between installedInfo and installedVersion, try reconciling them intelligently - // If that fails, just set it to the actual version string (all we can do at that point) - // Don't save changes, just return the object if changes were made (else null) + bool isVersionDetectionPossible(AppInMemory? app) { + return app?.app.additionalSettings['trackOnly'] != true && + app?.installedInfo?.versionName != null && + app?.app.installedVersion != null && + reconcileVersionDifferences( + app!.installedInfo!.versionName!, app.app.installedVersion!) != + null; + } + + // Given an App and it's on-device info... + // Reconcile unexpected differences between its reported installed version, real installed version, and reported latest version App? getCorrectedInstallStatusAppIfPossible(App app, AppInfo? installedInfo) { var modded = false; var trackOnly = app.additionalSettings['trackOnly'] == true; var noVersionDetection = app.additionalSettings['versionDetection'] != 'standardVersionDetection'; + // FIRST, COMPARE THE APP'S REPORTED AND REAL INSTALLED VERSIONS, WHERE ONE IS NULL if (installedInfo == null && app.installedVersion != null && !trackOnly) { + // App says it's installed but isn't really (and isn't track only) - set to not installed app.installedVersion = null; modded = true; } else if (installedInfo?.versionName != null && app.installedVersion == null) { + // App says it's not installed but really is - set to installed and use real package versionName app.installedVersion = installedInfo!.versionName; modded = true; - } else if (installedInfo?.versionName != null && + } + // SECOND, RECONCILE DIFFERENCES BETWEEN THE APP'S REPORTED AND REAL INSTALLED VERSIONS, WHERE NEITHER IS NULL + if (installedInfo?.versionName != null && installedInfo!.versionName != app.installedVersion && !noVersionDetection) { - String? correctedInstalledVersion = reconcileRealAndInternalVersions( + // App's reported version and real version don't match (and it uses standard version detection) + // If they share a standard format (and are still different under it), update the reported version accordingly + var correctedInstalledVersion = reconcileVersionDifferences( installedInfo.versionName!, app.installedVersion!); - if (correctedInstalledVersion != null) { - app.installedVersion = correctedInstalledVersion; + if (correctedInstalledVersion?.key == false) { + app.installedVersion = correctedInstalledVersion!.value; modded = true; } } + // THIRD, RECONCILE THE APP'S REPORTED INSTALLED AND LATEST VERSIONS if (app.installedVersion != null && app.installedVersion != app.latestVersion && !noVersionDetection) { - app.installedVersion = reconcileRealAndInternalVersions( - app.installedVersion!, app.latestVersion, - matchMode: true) ?? - app.installedVersion; + // App's reported installed and latest versions don't match (and it uses standard version detection) + // If they share a standard format, make sure the App's reported installed version uses that format + var correctedInstalledVersion = + reconcileVersionDifferences(app.installedVersion!, app.latestVersion); + if (correctedInstalledVersion?.key == true) { + app.installedVersion = correctedInstalledVersion!.value; + modded = true; + } + } + // FOURTH, DISABLE VERSION DETECTION IF ENABLED AND THE REPORTED/REAL INSTALLED VERSIONS ARE NOT STANDARDIZED + if (installedInfo != null && + !isVersionDetectionPossible(AppInMemory(app, null, installedInfo))) { + app.additionalSettings['versionDetection'] = 'noVersionDetection'; + logs.add('Could not reconcile version formats for: ${app.id}'); modded = true; } + // if (app.installedVersion != null && + // app.additionalSettings['versionDetection'] == + // 'standardVersionDetection') { + // var correctedInstalledVersion = + // reconcileVersionDifferences(app.installedVersion!, app.latestVersion); + // if (correctedInstalledVersion == null) { + // app.additionalSettings['versionDetection'] = 'noVersionDetection'; + // logs.add('Could not reconcile version formats for: ${app.id}'); + // modded = true; + // } + // } + return modded ? app : null; } - String? reconcileRealAndInternalVersions( - String realVersion, String internalVersion, - {bool matchMode = false}) { - // 1. If one or both of these can't be converted to a "standard" format, return null (leave as is) - // 2. If both have a "standard" format under which they are equal, return null (leave as is) - // 3. If both have a "standard" format in common but are unequal, return realVersion (this means it was changed externally) - // If in matchMode, the outcomes of rules 2 and 3 are reversed, and the "real" version is not matched strictly - // Matchmode to be used when comparing internal install version and internal latest version - - bool doStringsMatchUnderRegEx( - String pattern, String value1, String value2) { - var r = RegExp(pattern); - var m1 = r.firstMatch(value1); - var m2 = r.firstMatch(value2); - return m1 != null && m2 != null - ? value1.substring(m1.start, m1.end) == - value2.substring(m2.start, m2.end) - : false; - } - - Set findStandardFormatsForVersion(String version, bool strict) { - Set results = {}; - for (var pattern in standardVersionRegExStrings) { - if (RegExp('${strict ? '^' : ''}$pattern${strict ? '\$' : ''}') - .hasMatch(version)) { - results.add(pattern); - } - } - return results; - } - - var realStandardVersionFormats = - findStandardFormatsForVersion(realVersion, true); - var internalStandardVersionFormats = - findStandardFormatsForVersion(internalVersion, false); + MapEntry? reconcileVersionDifferences( + String templateVersion, String comparisonVersion) { + // Returns null if the versions don't share a common standard format + // Returns if they share a common format and are equal + // Returns if they share a common format but are not equal + // templateVersion must fully match a standard format, while comparisonVersion can have a substring match + var templateVersionFormats = + findStandardFormatsForVersion(templateVersion, true); + var comparisonVersionFormats = + findStandardFormatsForVersion(comparisonVersion, false); var commonStandardFormats = - realStandardVersionFormats.intersection(internalStandardVersionFormats); + templateVersionFormats.intersection(comparisonVersionFormats); if (commonStandardFormats.isEmpty) { - return null; // Incompatible; no "enhanced detection" + return null; } for (String pattern in commonStandardFormats) { - if (doStringsMatchUnderRegEx(pattern, internalVersion, realVersion)) { - return matchMode - ? internalVersion - : null; // Enhanced detection says no change + if (doStringsMatchUnderRegEx( + pattern, comparisonVersion, templateVersion)) { + return MapEntry(true, comparisonVersion); } } - return matchMode - ? null - : realVersion; // Enhanced detection says something changed + return MapEntry(false, templateVersion); + } + + bool doStringsMatchUnderRegEx(String pattern, String value1, String value2) { + var r = RegExp(pattern); + var m1 = r.firstMatch(value1); + var m2 = r.firstMatch(value2); + return m1 != null && m2 != null + ? value1.substring(m1.start, m1.end) == + value2.substring(m2.start, m2.end) + : false; } Future loadApps() async { diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 0f3eb16..be18176 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -21,7 +21,6 @@ import 'package:obtainium/app_sources/sourceforge.dart'; import 'package:obtainium/app_sources/steammobile.dart'; import 'package:obtainium/app_sources/telegramapp.dart'; import 'package:obtainium/app_sources/vlc.dart'; -import 'package:obtainium/app_sources/whatsapp.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart'; @@ -111,16 +110,16 @@ class App { // Convert bool style version detection options to dropdown style if (additionalSettings['noVersionDetection'] == true) { additionalSettings['versionDetection'] = 'noVersionDetection'; - } - if (additionalSettings['releaseDateAsVersion'] == true) { - additionalSettings['versionDetection'] = 'releaseDateAsVersion'; - additionalSettings.remove('releaseDateAsVersion'); - } - if (additionalSettings['noVersionDetection'] != null) { - additionalSettings.remove('noVersionDetection'); - } - if (additionalSettings['releaseDateAsVersion'] != null) { - additionalSettings.remove('releaseDateAsVersion'); + if (additionalSettings['releaseDateAsVersion'] == true) { + additionalSettings['versionDetection'] = 'releaseDateAsVersion'; + additionalSettings.remove('releaseDateAsVersion'); + } + if (additionalSettings['noVersionDetection'] != null) { + additionalSettings.remove('noVersionDetection'); + } + if (additionalSettings['releaseDateAsVersion'] != null) { + additionalSettings.remove('releaseDateAsVersion'); + } } // Ensure additionalSettings are correctly typed for (var item in formItems) { diff --git a/pubspec.lock b/pubspec.lock index 66602aa..b58e952 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -409,10 +409,10 @@ packages: dependency: "direct main" description: name: path_provider - sha256: "04890b994ee89bfa80bf3080bfec40d5a92c5c7a785ebb02c13084a099d2b6f9" + sha256: c7edf82217d4b2952b2129a61d3ad60f1075b9299e629e149a8d2e39c2e6aad4 url: "https://pub.dev" source: hosted - version: "2.0.13" + version: "2.0.14" path_provider_android: dependency: transitive description: @@ -425,10 +425,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: "12eee51abdf4d34c590f043f45073adbb45514a108bd9db4491547a2fd891059" + sha256: "818b2dc38b0f178e0ea3f7cf3b28146faab11375985d815942a68eee11c2d0f7" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" path_provider_linux: dependency: transitive description: @@ -473,10 +473,10 @@ packages: dependency: transitive description: name: permission_handler_apple - sha256: "9c370ef6a18b1c4b2f7f35944d644a56aa23576f23abee654cf73968de93f163" + sha256: ee96ac32f5a8e6f80756e25b25b9f8e535816c8e6665a96b6d70681f8c4f7e85 url: "https://pub.dev" source: hosted - version: "9.0.7" + version: "9.0.8" permission_handler_platform_interface: dependency: transitive description: @@ -553,10 +553,10 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: ee6257848f822b8481691f20c3e6d2bfee2e9eccb2a3d249907fcfb198c55b41 + sha256: "78528fd87d0d08ffd3e69551173c026e8eacc7b7079c82eb6a77413957b7e394" url: "https://pub.dev" source: hosted - version: "2.0.18" + version: "2.0.20" shared_preferences_android: dependency: transitive description: @@ -585,10 +585,10 @@ packages: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "824bfd02713e37603b2bdade0842e47d56e7db32b1dcdd1cae533fb88e2913fc" + sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.2.0" shared_preferences_web: dependency: transitive description: @@ -710,10 +710,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "845530e5e05db5500c1a4c1446785d60cbd8f9bd45e21e7dd643a3273bb4bbd1" + sha256: dd729390aa936bf1bdf5cd1bc7468ff340263f80a2c4f569416507667de8e3c8 url: "https://pub.dev" source: hosted - version: "6.0.25" + version: "6.0.26" url_launcher_ios: dependency: transitive description: @@ -806,10 +806,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: ab12479f7a0cf112b9420c36aaf206a1ca47cd60cd42de74a4be2e97a697587b + sha256: d601aba11ad8d4481e17a34a76fa1d30dee92dcbbe2c58b0df3120e9453099c7 url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.3" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index e2e1dea..82a25b7 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.11.15+136 # When changing this, update the tag in main() accordingly +version: 0.11.16+138 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 6b7d962b8795b630ee5a4533908032f5c28113d7 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 30 Mar 2023 17:44:39 -0400 Subject: [PATCH 103/600] Bugfix: "releaseDateAsVersion" resets to "noVersionDetection" Also 2 related UI fixes --- lib/pages/app.dart | 6 +++--- lib/providers/apps_provider.dart | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 701cb56..3e015de 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -80,9 +80,7 @@ class _AppPageState extends State { ), Text( '${tr('installedVersionX', args: [ - app?.installedInfo?.versionName ?? - app?.app.installedVersion ?? - tr('none') + app?.app.installedVersion ?? tr('none') ])}${trackOnly ? ' ${tr('estimateInBrackets')}\n\n${tr('xIsTrackOnly', args: [ tr('app') ])}' : ''}', @@ -249,6 +247,8 @@ class _AppPageState extends State { if (e.key == 'versionDetection' && e is GeneratedFormDropdown) { e.disabledOptKeys ??= []; if (app?.app.installedVersion != null && + app?.app.additionalSettings['versionDetection'] != + 'releaseDateAsVersion' && !appsProvider.isVersionDetectionPossible(app)) { e.disabledOptKeys!.add('standardVersionDetection'); } diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index cf19488..2afd95e 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -486,6 +486,8 @@ class AppsProvider with ChangeNotifier { bool isVersionDetectionPossible(AppInMemory? app) { return app?.app.additionalSettings['trackOnly'] != true && + app?.app.additionalSettings['versionDetection'] != + 'releaseDateAsVersion' && app?.installedInfo?.versionName != null && app?.app.installedVersion != null && reconcileVersionDifferences( @@ -539,6 +541,8 @@ class AppsProvider with ChangeNotifier { } // FOURTH, DISABLE VERSION DETECTION IF ENABLED AND THE REPORTED/REAL INSTALLED VERSIONS ARE NOT STANDARDIZED if (installedInfo != null && + app.additionalSettings['versionDetection'] == + 'standardVersionDetection' && !isVersionDetectionPossible(AppInMemory(app, null, installedInfo))) { app.additionalSettings['versionDetection'] = 'noVersionDetection'; logs.add('Could not reconcile version formats for: ${app.id}'); From 4e17bbcfd1b56600f32802dc0fc4db9faa3e5845 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 30 Mar 2023 23:40:32 -0400 Subject: [PATCH 104/600] Added "Group by Category" setting --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/zh.json | 1 + lib/main.dart | 2 +- lib/pages/apps.dart | 101 +++++++++++++++++++++++---- lib/pages/settings.dart | 12 ++++ lib/providers/settings_provider.dart | 9 +++ pubspec.yaml | 2 +- 13 files changed, 118 insertions(+), 16 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 90f4ca9..0662300 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -220,6 +220,7 @@ "importFromURLsInFile": "Importieren von URLs aus Datei ( z.B. OPML)", "versionDetection": "Versionserkennung", "standardVersionDetection": "Standardversionserkennung", + "groupByCategory": "Group by Category", "removeAppQuestion": { "one": "App entfernen?", "other": "App entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index a48c185..9296a27 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -220,6 +220,7 @@ "importFromURLsInFile": "Import from URLs in File (like OPML)", "versionDetection": "Version Detection", "standardVersionDetection": "Standard version detection", + "groupByCategory": "Group by Category", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index eb16617..969d2b1 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -220,6 +220,7 @@ "importFromURLsInFile": "وارد کردن از آدرس های اینترنتی موجود در فایل (مانند OPML)", "versionDetection": "تشخیص نسخه", "standardVersionDetection": "تشخیص نسخه استاندارد", + "groupByCategory": "Group by Category", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index e4d99f8..d159d88 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -220,6 +220,7 @@ "importFromURLsInFile": "Importer à partir d'URL dans un fichier (comme OPML)", "versionDetection": "Détection des versions", "standardVersionDetection": "Détection de version standard", + "groupByCategory": "Group by Category", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index c157ef7..638a74a 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -219,6 +219,7 @@ "importFromURLsInFile": "Importálás fájlban található URL-ből (mint pl. OPML)", "versionDetection": "Verzió érzékelés", "standardVersionDetection": "Alapért. verzió érzékelés", + "groupByCategory": "Group by Category", "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 9363303..c3e15cc 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -220,6 +220,7 @@ "importFromURLsInFile": "Importa da URL in file (come OPML)", "versionDetection": "Rilevamento di versione", "standardVersionDetection": "Rilevamento di versione standard", + "groupByCategory": "Group by Category", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 58ba851..40cd428 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -220,6 +220,7 @@ "importFromURLsInFile": "ファイル(OPMLなど)内のURLからインポート", "versionDetection": "バージョン検出", "standardVersionDetection": "標準のバージョン検出", + "groupByCategory": "Group by Category", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 4f892ae..466ed23 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -220,6 +220,7 @@ "importFromURLsInFile": "Import from URLs in File (like OPML)", "versionDetection": "Version Detection", "standardVersionDetection": "Standard version detection", + "groupByCategory": "Group by Category", "removeAppQuestion": { "one": "删除应用?", "other": "删除应用?" diff --git a/lib/main.dart b/lib/main.dart index 02ce25a..e9251aa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.16'; +const String currentVersion = '0.11.17'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index d8b59f6..616b065 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -187,6 +187,25 @@ class AppsPageState extends State { } listedApps = [...tempPinned, ...tempNotPinned]; + List getListedCategories() { + var temp = listedApps + .map((e) => e.app.categories.isNotEmpty ? e.app.categories : [null]); + return temp.isNotEmpty + ? { + ...temp.reduce((v, e) => [...v, ...e]) + }.toList() + : []; + } + + var listedCategories = getListedCategories(); + listedCategories.sort((a, b) { + return a != null && b != null + ? a.compareTo(b) + : a == null + ? 1 + : -1; + }); + showChangeLogDialog( String? changesUrl, AppSource appSource, String changeLog, int index) { showDialog( @@ -402,17 +421,37 @@ class AppsPageState extends State { ], ); - var transparent = const Color.fromARGB(0, 0, 0, 0).value; + var transparent = + Theme.of(context).colorScheme.background.withAlpha(0).value; + List stops = [ + ...listedApps[index] + .app + .categories + .asMap() + .entries + .map((e) => + ((e.key / (listedApps[index].app.categories.length - 1)))) + .toList(), + 1 + ]; + if (stops.length == 2) { + stops[0] = 1; + } return Container( decoration: BoxDecoration( - border: Border.symmetric( - vertical: BorderSide( - width: 4, - color: Color(listedApps[index].app.categories.isNotEmpty - ? settingsProvider.categories[ - listedApps[index].app.categories.first] ?? - transparent - : transparent)))), + gradient: LinearGradient( + stops: stops, + begin: const Alignment(-1, 0), + end: const Alignment(-0.97, 0), + colors: [ + ...listedApps[index] + .app + .categories + .map((e) => + Color(settingsProvider.categories[e]!).withAlpha(255)) + .toList(), + Color(transparent) + ])), child: ListTile( tileColor: listedApps[index].app.pinned ? Colors.grey.withOpacity(0.1) @@ -465,6 +504,28 @@ class AppsPageState extends State { )); } + getCategoryCollapsibleTile(int index) { + var tiles = listedApps + .asMap() + .entries + .where((e) => + e.value.app.categories.contains(listedCategories[index]) || + e.value.app.categories.isEmpty && listedCategories[index] == null) + .map((e) => getSingleAppHorizTile(e.key)) + .toList(); + + capFirstChar(String str) => str[0].toUpperCase() + str.substring(1); + return ExpansionTile( + initiallyExpanded: true, + title: Text( + capFirstChar(listedCategories[index] ?? tr('noCategory')), + style: const TextStyle(fontWeight: FontWeight.bold), + ), + controlAffinity: ListTileControlAffinity.leading, + trailing: Text(tiles.length.toString()), + children: tiles); + } + getSelectAllButton() { return selectedApps.isEmpty ? TextButton.icon( @@ -903,6 +964,22 @@ class AppsPageState extends State { ); } + getDisplayedList() { + return settingsProvider.groupByCategory && + !(listedCategories.isEmpty || + (listedCategories.length == 1 && listedCategories[0] == null)) + ? SliverList( + delegate: + SliverChildBuilderDelegate((BuildContext context, int index) { + return getCategoryCollapsibleTile(index); + }, childCount: listedCategories.length)) + : SliverList( + delegate: + SliverChildBuilderDelegate((BuildContext context, int index) { + return getSingleAppHorizTile(index); + }, childCount: listedApps.length)); + } + return Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, body: RefreshIndicator( @@ -922,11 +999,7 @@ class AppsPageState extends State { child: CustomScrollView(slivers: [ CustomAppBar(title: tr('appsString')), ...getLoadingWidgets(), - SliverList( - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - return getSingleAppHorizTile(index); - }, childCount: listedApps.length)) + getDisplayedList() ])), persistentFooterButtons: appsProvider.apps.isEmpty ? null diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 6e707e4..6888f7a 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -262,6 +262,18 @@ class _SettingsPageState extends State { }) ], ), + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(tr('groupByCategory')), + Switch( + value: settingsProvider.groupByCategory, + onChanged: (value) { + settingsProvider.groupByCategory = value; + }) + ], + ), const Divider( height: 16, ), diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index a7c6bc1..9f0d8f9 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -139,6 +139,15 @@ class SettingsProvider with ChangeNotifier { notifyListeners(); } + bool get groupByCategory { + return prefs?.getBool('groupByCategory') ?? false; + } + + set groupByCategory(bool show) { + prefs?.setBool('groupByCategory', show); + notifyListeners(); + } + String? getSettingString(String settingId) { return prefs?.getString(settingId); } diff --git a/pubspec.yaml b/pubspec.yaml index 82a25b7..eca32fa 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.11.16+138 # When changing this, update the tag in main() accordingly +version: 0.11.17+139 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From cd27ff7f2d2cf4b14bd9f192e245852ff256cc66 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 31 Mar 2023 09:24:15 -0400 Subject: [PATCH 105/600] Fixed Mullvad web scraping (again) --- lib/app_sources/mullvad.dart | 54 +++++++++++++++++++++++------------- lib/main.dart | 2 +- pubspec.yaml | 2 +- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/lib/app_sources/mullvad.dart b/lib/app_sources/mullvad.dart index a7449dd..763befd 100644 --- a/lib/app_sources/mullvad.dart +++ b/lib/app_sources/mullvad.dart @@ -1,7 +1,6 @@ import 'package:html/parser.dart'; import 'package:http/http.dart'; import 'package:obtainium/app_sources/github.dart'; -import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -29,24 +28,41 @@ class Mullvad extends AppSource { String standardUrl, Map additionalSettings, ) async { - var details = await HTML().getLatestAPKDetails( - '$standardUrl/en/download/android', additionalSettings); - var fileName = details.apkUrls[0].split('/').last; - var versionMatch = RegExp('[0-9]+(\\.[0-9]+)+').firstMatch(fileName); - if (versionMatch == null) { - throw NoVersionError(); + Response res = await get(Uri.parse('$standardUrl/en/download/android')); + if (res.statusCode == 200) { + var versions = parse(res.body) + .querySelectorAll('p') + .map((e) => e.innerHtml) + .where((p) => p.contains('Latest version: ')) + .map((e) { + var match = RegExp('[0-9]+(\\.[0-9]+)*').firstMatch(e); + if (match == null) { + return ''; + } else { + return e.substring(match.start, match.end); + } + }) + .where((element) => element.isNotEmpty) + .toList(); + if (versions.isEmpty) { + throw NoVersionError(); + } + String? changeLog; + try { + changeLog = (await GitHub().getLatestAPKDetails( + 'https://github.com/mullvad/mullvadvpn-app', + {'fallbackToOlderReleases': true})) + .changeLog; + } catch (e) { + // Ignore + } + return APKDetails( + versions[0], + ['https://mullvad.net/download/app/apk/latest'], + AppNames(name, 'Mullvad-VPN'), + changeLog: changeLog); + } else { + throw getObtainiumHttpError(res); } - details.version = fileName.substring(versionMatch.start, versionMatch.end); - details.names = AppNames(name, 'Mullvad-VPN'); - try { - details.changeLog = (await GitHub().getLatestAPKDetails( - 'https://github.com/mullvad/mullvadvpn-app', - {'fallbackToOlderReleases': true})) - .changeLog; - } catch (e) { - print(e); - // Ignore - } - return details; } } diff --git a/lib/main.dart b/lib/main.dart index e9251aa..94f7d2e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.17'; +const String currentVersion = '0.11.18'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index eca32fa..0f6c57f 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.11.17+139 # When changing this, update the tag in main() accordingly +version: 0.11.18+140 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 7981ca29c58e7b38bf21b8c4cd26e26183922a53 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 31 Mar 2023 15:36:51 -0400 Subject: [PATCH 106/600] Bugfix #405 + general categories bugfixes --- lib/main.dart | 2 +- lib/pages/apps.dart | 3 ++- lib/pages/import_export.dart | 2 +- lib/pages/settings.dart | 7 +++++-- lib/providers/apps_provider.dart | 12 ++++++++++++ lib/providers/settings_provider.dart | 19 ++++++++++++++++++- pubspec.yaml | 2 +- 7 files changed, 40 insertions(+), 7 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 94f7d2e..5cfcf56 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.18'; +const String currentVersion = '0.11.19'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 616b065..f8e04d5 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -448,7 +448,8 @@ class AppsPageState extends State { .app .categories .map((e) => - Color(settingsProvider.categories[e]!).withAlpha(255)) + Color(settingsProvider.categories[e] ?? transparent) + .withAlpha(255)) .toList(), Color(transparent) ])), diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index 9372f20..3234919 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -133,7 +133,7 @@ class _ImportExportPageState extends State { } } }); - settingsProvider.categories = cats; + appsProvider.addMissingCategories(settingsProvider); showError(tr('importedX', args: [plural('apps', value)]), context); }); } else { diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 6888f7a..7fde4f6 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -6,6 +6,7 @@ import 'package:obtainium/components/custom_app_bar.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/main.dart'; +import 'package:obtainium/providers/apps_provider.dart'; import 'package:obtainium/providers/logs_provider.dart'; import 'package:obtainium/providers/settings_provider.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -444,6 +445,7 @@ class _CategoryEditorSelectorState extends State { @override Widget build(BuildContext context) { var settingsProvider = context.watch(); + var appsProvider = context.watch(); storedValues = settingsProvider.categories.map((key, value) => MapEntry( key, MapEntry(value, @@ -467,8 +469,9 @@ class _CategoryEditorSelectorState extends State { if (!isBuilding) { storedValues = values['categories'] as Map>; - settingsProvider.categories = - storedValues.map((key, value) => MapEntry(key, value.key)); + settingsProvider.setCategories( + storedValues.map((key, value) => MapEntry(key, value.key)), + appsProvider: appsProvider); if (widget.onSelected != null) { widget.onSelected!(storedValues.keys .where((k) => storedValues[k]!.value) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 2afd95e..e901fd5 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -757,6 +757,18 @@ class AppsProvider with ChangeNotifier { await intent.launch(); } + addMissingCategories(SettingsProvider settingsProvider) { + var cats = settingsProvider.categories; + apps.forEach((key, value) { + for (var c in value.app.categories) { + if (!cats.containsKey(c)) { + cats[c] = generateRandomLightColor().value; + } + } + }); + settingsProvider.setCategories(cats, appsProvider: this); + } + Future checkUpdate(String appId) async { App? currentApp = apps[appId]!.app; SourceProvider sourceProvider = SourceProvider(); diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 9f0d8f9..0373857 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -7,6 +7,8 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:obtainium/app_sources/github.dart'; import 'package:obtainium/main.dart'; +import 'package:obtainium/providers/apps_provider.dart'; +import 'package:obtainium/providers/source_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -160,7 +162,22 @@ class SettingsProvider with ChangeNotifier { Map get categories => Map.from(jsonDecode(prefs?.getString('categories') ?? '{}')); - set categories(Map cats) { + void setCategories(Map cats, {AppsProvider? appsProvider}) { + if (appsProvider != null) { + List changedApps = appsProvider.apps.values + .map((a) { + var n1 = a.app.categories.length; + a.app.categories.removeWhere((c) => cats.keys.contains(c)); + return n1 > a.app.categories.length ? a.app : null; + }) + .where((element) => element != null) + .map((e) => e as App) + .toList(); + if (changedApps.isNotEmpty) { + appsProvider.saveApps(changedApps, + attemptToCorrectInstallStatus: false); + } + } prefs?.setString('categories', jsonEncode(cats)); notifyListeners(); } diff --git a/pubspec.yaml b/pubspec.yaml index 0f6c57f..0cd7b91 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.11.18+140 # When changing this, update the tag in main() accordingly +version: 0.11.19+141 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 4cfe6af0446c69d53a23a93ec38cded5e9324dea Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 31 Mar 2023 15:39:52 -0400 Subject: [PATCH 107/600] Bugfix for prev. commit --- lib/providers/settings_provider.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 0373857..7c3dcff 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -167,7 +167,7 @@ class SettingsProvider with ChangeNotifier { List changedApps = appsProvider.apps.values .map((a) { var n1 = a.app.categories.length; - a.app.categories.removeWhere((c) => cats.keys.contains(c)); + a.app.categories.removeWhere((c) => !cats.keys.contains(c)); return n1 > a.app.categories.length ? a.app : null; }) .where((element) => element != null) From abf7be222d21e35f3637ec13f62b58cabd5d4d1a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 1 Apr 2023 00:24:16 -0400 Subject: [PATCH 108/600] Bugfix: App pinning not working (#410) --- lib/main.dart | 2 +- lib/pages/apps.dart | 14 ++++++-------- pubspec.lock | 34 +++++++++++++++++----------------- pubspec.yaml | 2 +- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 5cfcf56..d252dc0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.19'; +const String currentVersion = '0.11.20'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index f8e04d5..84b77c9 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -735,14 +735,12 @@ class AppsPageState extends State { } pinSelectedApps() { - () { - var pinStatus = selectedApps.where((element) => element.pinned).isEmpty; - appsProvider.saveApps(selectedApps.map((e) { - e.pinned = pinStatus; - return e; - }).toList()); - Navigator.of(context).pop(); - }; + var pinStatus = selectedApps.where((element) => element.pinned).isEmpty; + appsProvider.saveApps(selectedApps.map((e) { + e.pinned = pinStatus; + return e; + }).toList()); + Navigator.of(context).pop(); } resetSelectedAppsInstallStatuses() { diff --git a/pubspec.lock b/pubspec.lock index b58e952..6510e6f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -337,10 +337,10 @@ packages: dependency: transitive description: name: markdown - sha256: b3c60dee8c2af50ad0e6e90cceba98e47718a6ee0a7a6772c77846a0cc21f78b + sha256: d95a9d12954aafc97f984ca29baaa7690ed4d9ec4140a23ad40580bcdb6c87f5 url: "https://pub.dev" source: hosted - version: "7.0.1" + version: "7.0.2" matcher: dependency: transitive description: @@ -553,34 +553,34 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "78528fd87d0d08ffd3e69551173c026e8eacc7b7079c82eb6a77413957b7e394" + sha256: "858aaa72d8f61637d64e776aca82e1c67e6d9ee07979123c5d17115031c1b13b" url: "https://pub.dev" source: hosted - version: "2.0.20" + version: "2.1.0" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: ad423a80fe7b4e48b50d6111b3ea1027af0e959e49d485712e134863d9c1c521 + sha256: "8304d8a1f7d21a429f91dee552792249362b68a331ac5c3c1caf370f658873f6" url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.1.0" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "1e755f8583229f185cfca61b1d80fb2344c9d660e1c69ede5450d8f478fa5310" + sha256: cf2a42fb20148502022861f71698db12d937c7459345a1bdaa88fc91a91b3603 url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.0" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "3a59ed10890a8409ad0faad7bb2957dab4b92b8fbe553257b05d30ed8af2c707" + sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.0" shared_preferences_platform_interface: dependency: transitive description: @@ -593,18 +593,18 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "0dc2633f215a3d4aa3184c9b2c5766f4711e4e5a6b256e62aafee41f89f1bfb8" + sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5" url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.1.0" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "71bcd669bb9cdb6b39f22c4a7728b6d49e934f6cba73157ffa5a54f1eed67436" + sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.0" sky_engine: dependency: transitive description: flutter @@ -790,10 +790,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "34f83c2f0f64c75ad75c77a2ccfc8d2e531afbe8ad41af1fd787d6d33336aa90" + sha256: "9e223788e1954087dac30d813dc151f8e12f09f1139f116ce20b5658893f3627" url: "https://pub.dev" source: hosted - version: "3.4.3" + version: "3.4.4" webview_flutter_platform_interface: dependency: transitive description: @@ -835,5 +835,5 @@ packages: source: hosted version: "6.2.2" sdks: - dart: ">=2.18.2 <3.0.0" + dart: ">=2.19.0 <3.0.0" flutter: ">=3.4.0-17.0.pre" diff --git a/pubspec.yaml b/pubspec.yaml index 0cd7b91..a58ed97 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.11.19+141 # When changing this, update the tag in main() accordingly +version: 0.11.20+142 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From d52660235b1dab47136f0c85be4b89b2227793ef Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 1 Apr 2023 00:42:44 -0400 Subject: [PATCH 109/600] Attempt to workaround export bug (#385) --- lib/main.dart | 2 +- lib/providers/apps_provider.dart | 18 ++++++++++++------ pubspec.yaml | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index d252dc0..e01a503 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.20'; +const String currentVersion = '0.11.21'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index e901fd5..28a0fc1 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -848,12 +848,6 @@ class AppsProvider with ChangeNotifier { } Future exportApps() async { - Directory? exportDir = Directory('/storage/emulated/0/Download'); - String path = 'Downloads'; // TODO: See if hardcoding this can be avoided - if (!exportDir.existsSync()) { - exportDir = await getExternalStorageDirectory(); - path = exportDir!.path; - } if ((await DeviceInfoPlugin().androidInfo).version.sdkInt <= 29) { if (await Permission.storage.isDenied) { await Permission.storage.request(); @@ -862,6 +856,18 @@ class AppsProvider with ChangeNotifier { throw ObtainiumError(tr('storagePermissionDenied')); } } + Directory? exportDir = Directory('/storage/emulated/0/Download'); + String path = 'Downloads'; // TODO: See if hardcoding this can be avoided + var downloadsAccessible = false; + try { + downloadsAccessible = exportDir.existsSync(); + } catch (e) { + logs.add('Error accessing Downloads (will use fallback): $e'); + } + if (!downloadsAccessible) { + exportDir = await getExternalStorageDirectory(); + path = exportDir!.path; + } File export = File( '${exportDir.path}/${tr('obtainiumExportHyphenatedLowercase')}-${DateTime.now().millisecondsSinceEpoch}.json'); export.writeAsStringSync( diff --git a/pubspec.yaml b/pubspec.yaml index a58ed97..75372bd 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.11.20+142 # When changing this, update the tag in main() accordingly +version: 0.11.21+143 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 9fe8a200ef726467e0a9968eefe89ff99e2dcbcb Mon Sep 17 00:00:00 2001 From: gidano Date: Sat, 1 Apr 2023 14:55:56 +0200 Subject: [PATCH 110/600] Done --- assets/translations/hu.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 638a74a..9e280eb 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -219,7 +219,7 @@ "importFromURLsInFile": "Importálás fájlban található URL-ből (mint pl. OPML)", "versionDetection": "Verzió érzékelés", "standardVersionDetection": "Alapért. verzió érzékelés", - "groupByCategory": "Group by Category", + "groupByCategory": "Csoportosítás Kategória alapján", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From 682026ed0a2c4aadf566597c9f0e92c9ccded8f7 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 2 Apr 2023 18:14:43 -0400 Subject: [PATCH 111/600] Added a source filter to the Apps page --- lib/main.dart | 2 +- lib/pages/apps.dart | 30 +++++++++++++++++++++++++++--- pubspec.yaml | 2 +- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index e01a503..b9f36b6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.21'; +const String currentVersion = '0.11.22'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 84b77c9..733e8b2 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -56,6 +56,7 @@ class AppsPageState extends State { Widget build(BuildContext context) { var appsProvider = context.watch(); var settingsProvider = context.watch(); + var sourceProvider = SourceProvider(); var listedApps = appsProvider.apps.values.toList(); var currentFilterIsUpdatesOnly = filter.isIdenticalTo(updatesOnlyFilter, settingsProvider); @@ -110,6 +111,11 @@ class AppsPageState extends State { .isEmpty) { return false; } + if (filter.sourceFilter.isNotEmpty && + sourceProvider.getSource(app.app.url).runtimeType.toString() != + filter.sourceFilter) { + return false; + } return true; }).toList(); @@ -892,6 +898,19 @@ class AppsPageState extends State { GeneratedFormSwitch('nonInstalledApps', label: tr('nonInstalledApps'), defaultValue: vals['nonInstalledApps']) + ], + [ + GeneratedFormDropdown( + 'sourceFilter', + label: tr('appSource'), + defaultValue: filter.sourceFilter, + [ + MapEntry('', tr('none')), + ...sourceProvider.sources + .map((e) => + MapEntry(e.runtimeType.toString(), e.name)) + .toList() + ]) ] ], additionalWidgets: [ @@ -1015,20 +1034,23 @@ class AppsFilter { late bool includeUptodate; late bool includeNonInstalled; late Set categoryFilter; + late String sourceFilter; AppsFilter( {this.nameFilter = '', this.authorFilter = '', this.includeUptodate = true, this.includeNonInstalled = true, - this.categoryFilter = const {}}); + this.categoryFilter = const {}, + this.sourceFilter = ''}); Map toFormValuesMap() { return { 'appName': nameFilter, 'author': authorFilter, 'upToDateApps': includeUptodate, - 'nonInstalledApps': includeNonInstalled + 'nonInstalledApps': includeNonInstalled, + 'sourceFilter': sourceFilter }; } @@ -1037,6 +1059,7 @@ class AppsFilter { authorFilter = values['author']!; includeUptodate = values['upToDateApps']; includeNonInstalled = values['nonInstalledApps']; + sourceFilter = values['sourceFilter']; } bool isIdenticalTo(AppsFilter other, SettingsProvider settingsProvider) => @@ -1044,5 +1067,6 @@ class AppsFilter { nameFilter.trim() == other.nameFilter.trim() && includeUptodate == other.includeUptodate && includeNonInstalled == other.includeNonInstalled && - settingsProvider.setEqual(categoryFilter, other.categoryFilter); + settingsProvider.setEqual(categoryFilter, other.categoryFilter) && + sourceFilter.trim() == other.sourceFilter.trim(); } diff --git a/pubspec.yaml b/pubspec.yaml index 75372bd..13d0b38 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.11.21+143 # When changing this, update the tag in main() accordingly +version: 0.11.22+144 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From e6b05d50b95f0e7ab70299c474850c36c6219762 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 4 Apr 2023 19:59:35 -0400 Subject: [PATCH 112/600] Scrolling bugfix #392, custom name #420, search archive label #421 --- lib/app_sources/github.dart | 8 +++++--- lib/pages/add_app.dart | 16 ++++++++-------- lib/pages/app.dart | 2 +- lib/providers/apps_provider.dart | 3 +++ lib/providers/source_provider.dart | 13 +++++++------ 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 9506453..39fbf2f 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -185,9 +185,11 @@ class GitHub extends AppSource { Map urlsWithDescriptions = {}; for (var e in (jsonDecode(res.body)['items'] as List)) { urlsWithDescriptions.addAll({ - e['html_url'] as String: e['description'] != null - ? e['description'] as String - : tr('noDescription') + e['html_url'] as String: + ((e['archived'] == true ? '[ARCHIVED] ' : '') + + (e['description'] != null + ? e['description'] as String + : tr('noDescription'))) }); } return urlsWithDescriptions; diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 64d7f3c..f4f6c0e 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -334,11 +334,10 @@ class _AddAppPageState extends State { ], ); - Widget getSourcesListWidget() => Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ + Widget getSourcesListWidget() => Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ const SizedBox( height: 48, ), @@ -365,16 +364,17 @@ class _AddAppPageState extends State { fontStyle: FontStyle.italic), ))) .toList() - ])); + ]); return Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, - body: CustomScrollView(slivers: [ + body: CustomScrollView(shrinkWrap: true, slivers: [ CustomAppBar(title: tr('addApp')), - SliverFillRemaining( + SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.all(16), child: Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ getUrlInputRow(), diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 3e015de..3f54294 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -147,7 +147,7 @@ class _AppPageState extends State { height: 25, ), Text( - app?.installedInfo?.name ?? app?.app.name ?? tr('app'), + app?.app.name ?? tr('app'), textAlign: TextAlign.center, style: Theme.of(context).textTheme.displayLarge, ), diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 28a0fc1..4815129 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -670,6 +670,9 @@ class AppsProvider with ChangeNotifier { for (var app in apps) { AppInfo? info = await getInstalledInfo(app.id); app.name = info?.name ?? app.name; + if (app.additionalSettings['appName']?.toString().isNotEmpty == true) { + app.name = app.additionalSettings['appName'].toString().trim(); + } if (attemptToCorrectInstallStatus) { app = getCorrectedInstallStatusAppIfPossible(app, info) ?? app; } diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index be18176..1239eef 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -278,7 +278,8 @@ class AppSource { return regExValidator(value); } ]) - ] + ], + [GeneratedFormTextField('appName', label: tr('appName'), required: false)] ]; // Previous 2 variables combined into one at runtime for convenient usage @@ -427,8 +428,10 @@ class SourceProvider { throw NoAPKError(); } String apkVersion = apk.version.replaceAll('/', '-'); - var name = currentApp?.name.trim() ?? - apk.names.name[0].toUpperCase() + apk.names.name.substring(1); + var name = currentApp != null ? currentApp.name.trim() : ''; + name = name.isNotEmpty + ? name + : apk.names.name[0].toUpperCase() + apk.names.name.substring(1); return App( currentApp?.id ?? source.tryInferringAppId(standardUrl, @@ -436,9 +439,7 @@ class SourceProvider { generateTempID(standardUrl, additionalSettings), standardUrl, apk.names.author[0].toUpperCase() + apk.names.author.substring(1), - name.trim().isNotEmpty - ? name - : apk.names.name[0].toUpperCase() + apk.names.name.substring(1), + name, currentApp?.installedVersion, apkVersion, apk.apkUrls, From d557746965d395db61d6e76c113e2145f37f4f66 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 4 Apr 2023 20:00:36 -0400 Subject: [PATCH 113/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index b9f36b6..7f2241b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.22'; +const String currentVersion = '0.11.23'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 13d0b38..ed83e2f 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.11.22+144 # When changing this, update the tag in main() accordingly +version: 0.11.23+145 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 782d055bc3c6411f2798c3bacddabf256e03b044 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 4 Apr 2023 20:21:24 -0400 Subject: [PATCH 114/600] Added cloudflare.f-droid.org support --- lib/app_sources/fdroid.dart | 13 ++++++++----- lib/providers/source_provider.dart | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 3c2bba8..f0279fe 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -14,12 +14,14 @@ class FDroid extends AppSource { @override String standardizeURL(String url) { RegExp standardUrlRegExB = - RegExp('^https?://$host/+[^/]+/+packages/+[^/]+'); + RegExp('^https?://(cloudflare\\.)?$host/+[^/]+/+packages/+[^/]+'); RegExpMatch? match = standardUrlRegExB.firstMatch(url.toLowerCase()); if (match != null) { - url = 'https://$host/packages/${Uri.parse(url).pathSegments.last}'; + url = + 'https://${Uri.parse(url.substring(0, match.end)).host}/packages/${Uri.parse(url).pathSegments.last}'; } - RegExp standardUrlRegExA = RegExp('^https?://$host/+packages/+[^/]+'); + RegExp standardUrlRegExA = + RegExp('^https?://(cloudflare\\.)?$host/+packages/+[^/]+'); match = standardUrlRegExA.firstMatch(url.toLowerCase()); if (match == null) { throw InvalidURLError(name); @@ -61,9 +63,10 @@ class FDroid extends AppSource { Map additionalSettings, ) async { String? appId = tryInferringAppId(standardUrl); + String host = Uri.parse(standardUrl).host; return getAPKUrlsFromFDroidPackagesAPIResponse( - await get(Uri.parse('https://f-droid.org/api/v1/packages/$appId')), - 'https://f-droid.org/repo/$appId', + await get(Uri.parse('https://$host/api/v1/packages/$appId')), + 'https://$host/repo/$appId', standardUrl); } } diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 1239eef..be09d43 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -363,7 +363,7 @@ class SourceProvider { url = preStandardizeUrl(url); AppSource? source; for (var s in sources.where((element) => element.host != null)) { - if (url.contains('://${s.host}')) { + if (RegExp('://(.+\\.)?${s.host}').hasMatch(url)) { source = s; break; } From ed120016d96c57a9b41dec53e260c3e98bc13518 Mon Sep 17 00:00:00 2001 From: HRTK92 Date: Wed, 5 Apr 2023 10:32:56 +0900 Subject: [PATCH 115/600] Add long-press URL copy and snackbar message --- assets/translations/de.json | 3 ++- assets/translations/en.json | 3 ++- assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 3 ++- assets/translations/zh.json | 3 ++- lib/pages/app.dart | 6 ++++++ 9 files changed, 18 insertions(+), 4 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 0662300..95d0bab 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -207,6 +207,7 @@ "addCategory": "Kategorie hinzufügen", "label": "Bezeichnung", "language": "Sprache", + "copiedToClipboard": "Copied to Clipboard", "storagePermissionDenied": "Speicherberechtigung verweigert", "selectedCategorizeWarning": "Dadurch werden alle bestehenden Kategorieeinstellungen für die ausgewählten Apps ersetzt.", "filterAPKsByRegEx": "APKs nach regulärem Ausdruck filtern", @@ -269,4 +270,4 @@ "one": "{} und 1 weitere Anwendung wurden aktualisiert.", "other": "{} und {} weitere Anwendungen wurden aktualisiert." } -} \ No newline at end of file +} diff --git a/assets/translations/en.json b/assets/translations/en.json index 9296a27..379b45c 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -207,6 +207,7 @@ "addCategory": "Add Category", "label": "Label", "language": "Language", + "copiedToClipboard": "Copied to Clipboard", "storagePermissionDenied": "Storage permission denied", "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", "filterAPKsByRegEx": "Filter APKs by Regular Expression", @@ -269,4 +270,4 @@ "one": "{} and 1 more app were updated.", "other": "{} and {} more apps were updated." } -} \ No newline at end of file +} diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 969d2b1..2aebffb 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -207,6 +207,7 @@ "addCategory": "اضافه کردن دسته", "label": "برچسب", "language": "زبان", + "copiedToClipboard": "Copied to Clipboard", "storagePermissionDenied": "مجوز ذخیره سازی رد شد", "selectedCategorizeWarning": "این جایگزین تنظیمات دسته بندی موجود برای برنامه های انتخابی می شود.", "filterAPKsByRegEx": "فایل‌های APK را با نظم فیلتر کنید", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index d159d88..2912ab1 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -207,6 +207,7 @@ "addCategory": "Ajouter une catégorie", "label": "Étiquette", "language": "Langue", + "copiedToClipboard": "Copied to Clipboard", "storagePermissionDenied": "Autorisation de stockage refusée", "selectedCategorizeWarning": "Cela remplacera tous les paramètres de catégorie existants pour les applications sélectionnées.", "filterAPKsByRegEx": "Filtrer les APK par expression régulière", diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 9e280eb..40f7f59 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -206,6 +206,7 @@ "addCategory": "Új kategória", "label": "Címke", "language": "Nyelv", + "copiedToClipboard": "Copied to Clipboard", "storagePermissionDenied": "Tárhely engedély megtagadva", "selectedCategorizeWarning": "Ez felváltja a kiválasztott alkalmazások meglévő kategória-beállításait.", "filterAPKsByRegEx": "Az APK-k szűrése reguláris kifejezéssel", diff --git a/assets/translations/it.json b/assets/translations/it.json index c3e15cc..85ea697 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -207,6 +207,7 @@ "addCategory": "Aggiungi categoria", "label": "Etichetta", "language": "Lingua", + "copiedToClipboard": "Copied to Clipboard", "storagePermissionDenied": "Accesso ai file non autorizzato", "selectedCategorizeWarning": "Ciò sostituirà le impostazioni di categoria esistenti per le App selezionate.", "filterAPKsByRegEx": "Filtra file APK con espressioni regolari", diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 40cd428..04806a4 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -207,6 +207,7 @@ "addCategory": "カテゴリを追加", "label": "ラベル", "language": "言語", + "copiedToClipboard": "クリップボードにコピーしました", "storagePermissionDenied": "ストレージ権限が拒否されました", "selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。", "filterAPKsByRegEx": "正規表現でAPKを絞り込む", @@ -269,4 +270,4 @@ "one": "{} とさらに {} 個のアプリがアップデートされました", "other": "{} とさらに {} 個のアプリがアップデートされました" } -} \ No newline at end of file +} diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 466ed23..0aba1e6 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -208,6 +208,7 @@ "addCategory": "添加类别", "label": "标签", "language": "语言", + "copiedToClipboard": "Copied to Clipboard", "storagePermissionDenied": "存储权限已被拒绝", "selectedCategorizeWarning": "这将取代所选应用程序的任何现有类别", "filterAPKsByRegEx": "Filter APKs by Regular Expression", @@ -269,4 +270,4 @@ "one": "{} 和 {} 更多应用已被安装", "other": "{} 和 {} 更多应用已被安装" } -} \ No newline at end of file +} diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 3f54294..867e3f1 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -61,6 +61,12 @@ class _AppPageState extends State { mode: LaunchMode.externalApplication); } }, + onLongPress: () { + Clipboard.setData(ClipboardData(text: app?.app.url ?? '')); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(tr('copiedToClipboard')), + )); + }, child: Text( app?.app.url ?? '', textAlign: TextAlign.center, From f33a26d4f412a93977d82befedf954f11d6c5c9f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 4 Apr 2023 21:45:57 -0400 Subject: [PATCH 116/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 7f2241b..b30c939 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.23'; +const String currentVersion = '0.11.24'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index ed83e2f..e0b862b 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.11.23+145 # When changing this, update the tag in main() accordingly +version: 0.11.24+146 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 202ce4f0d5bd4b29843d9d579bcc797922cb7272 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 5 Apr 2023 18:50:19 -0400 Subject: [PATCH 117/600] Store APK names with URLs (#432) --- lib/app_sources/codeberg.dart | 7 ++++--- lib/app_sources/fdroid.dart | 2 +- lib/app_sources/fdroidrepo.dart | 3 ++- lib/app_sources/github.dart | 4 +++- lib/app_sources/gitlab.dart | 3 ++- lib/app_sources/html.dart | 3 ++- lib/app_sources/mullvad.dart | 2 +- lib/app_sources/neutroncode.dart | 2 +- lib/app_sources/signal.dart | 3 ++- lib/app_sources/sourceforge.dart | 2 +- lib/app_sources/steammobile.dart | 3 ++- lib/app_sources/telegramapp.dart | 3 ++- lib/app_sources/vlc.dart | 3 ++- lib/app_sources/whatsapp.dart | 4 ++-- lib/main.dart | 2 +- lib/providers/apps_provider.dart | 29 ++++++++++++++--------------- lib/providers/source_provider.dart | 29 ++++++++++++++++++++++------- pubspec.yaml | 2 +- 18 files changed, 65 insertions(+), 41 deletions(-) diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index 1d181bc..32ecad0 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -68,7 +68,7 @@ class Codeberg extends AppSource { if (res.statusCode == 200) { var releases = jsonDecode(res.body) as List; - List getReleaseAPKUrls(dynamic release) => + List> getReleaseAPKUrls(dynamic release) => (release['assets'] as List?) ?.map((e) { return e['name'] != null && e['browser_download_url'] != null @@ -77,7 +77,6 @@ class Codeberg extends AppSource { : const MapEntry('', ''); }) .where((element) => element.key.toLowerCase().endsWith('.apk')) - .map((e) => e.value) .toList() ?? []; @@ -119,7 +118,9 @@ class Codeberg extends AppSource { throw NoVersionError(); } var changeLog = targetRelease['body'].toString(); - return APKDetails(version, targetRelease['apkUrls'] as List, + return APKDetails( + version, + targetRelease['apkUrls'] as List>, getAppNames(standardUrl), releaseDate: releaseDate, changeLog: changeLog.isEmpty ? null : changeLog); diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index f0279fe..3d87419 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -50,7 +50,7 @@ class FDroid extends AppSource { .where((element) => element['versionName'] == latestVersion) .map((e) => '${apkUrlPrefix}_${e['versionCode']}.apk') .toList(); - return APKDetails(latestVersion, apkUrls, + return APKDetails(latestVersion, getApkUrlsFromUrls(apkUrls), AppNames(name, Uri.parse(standardUrl).pathSegments.last)); } else { throw getObtainiumHttpError(res); diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index 11e8e01..8523257 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -80,7 +80,8 @@ class FDroidRepo extends AppSource { element.querySelector('apkname') != null) .map((e) => '$standardUrl/${e.querySelector('apkname')!.innerHtml}') .toList(); - return APKDetails(latestVersion, apkUrls, AppNames(authorName, appName), + return APKDetails(latestVersion, getApkUrlsFromUrls(apkUrls), + AppNames(authorName, appName), releaseDate: releaseDate); } else { throw getObtainiumHttpError(res); diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 39fbf2f..a7d8a0e 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -161,7 +161,9 @@ class GitHub extends AppSource { throw NoVersionError(); } var changeLog = targetRelease['body'].toString(); - return APKDetails(version, targetRelease['apkUrls'] as List, + return APKDetails( + version, + getApkUrlsFromUrls(targetRelease['apkUrls'] as List), getAppNames(standardUrl), releaseDate: releaseDate, changeLog: changeLog.isEmpty ? null : changeLog); diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index 428568e..7d813d7 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -60,7 +60,8 @@ class GitLab extends AppSource { if (version == null) { throw NoVersionError(); } - return APKDetails(version, apkUrls, GitHub().getAppNames(standardUrl), + return APKDetails(version, getApkUrlsFromUrls(apkUrls), + GitHub().getAppNames(standardUrl), releaseDate: releaseDate); } else { throw getObtainiumHttpError(res); diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 5d44b98..bf4203e 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -42,7 +42,8 @@ class HTML extends AppSource { ? '${uri.origin}/$e' : '${uri.origin}/${uri.path}/$e') .toList(); - return APKDetails(version, apkUrls, AppNames(uri.host, tr('app'))); + return APKDetails( + version, getApkUrlsFromUrls(apkUrls), AppNames(uri.host, tr('app'))); } else { throw getObtainiumHttpError(res); } diff --git a/lib/app_sources/mullvad.dart b/lib/app_sources/mullvad.dart index 763befd..3f43def 100644 --- a/lib/app_sources/mullvad.dart +++ b/lib/app_sources/mullvad.dart @@ -58,7 +58,7 @@ class Mullvad extends AppSource { } return APKDetails( versions[0], - ['https://mullvad.net/download/app/apk/latest'], + getApkUrlsFromUrls(['https://mullvad.net/download/app/apk/latest']), AppNames(name, 'Mullvad-VPN'), changeLog: changeLog); } else { diff --git a/lib/app_sources/neutroncode.dart b/lib/app_sources/neutroncode.dart index b5e499a..881cc31 100644 --- a/lib/app_sources/neutroncode.dart +++ b/lib/app_sources/neutroncode.dart @@ -98,7 +98,7 @@ class NeutronCode extends AppSource { ? (customDateParse(dateStringOriginal)) : null; var changeLogElements = http.querySelectorAll('.pd-fdesc p'); - return APKDetails(version, [apkUrl], + return APKDetails(version, getApkUrlsFromUrls([apkUrl]), AppNames(runtimeType.toString(), name ?? standardUrl.split('/').last), releaseDate: dateString != null ? DateTime.parse(dateString) : null, changeLog: changeLogElements.isNotEmpty diff --git a/lib/app_sources/signal.dart b/lib/app_sources/signal.dart index 38af04a..4258d0c 100644 --- a/lib/app_sources/signal.dart +++ b/lib/app_sources/signal.dart @@ -28,7 +28,8 @@ class Signal extends AppSource { if (version == null) { throw NoVersionError(); } - return APKDetails(version, apkUrls, AppNames(name, 'Signal')); + return APKDetails( + version, getApkUrlsFromUrls(apkUrls), AppNames(name, 'Signal')); } else { throw getObtainiumHttpError(res); } diff --git a/lib/app_sources/sourceforge.dart b/lib/app_sources/sourceforge.dart index ed484a6..11aec8e 100644 --- a/lib/app_sources/sourceforge.dart +++ b/lib/app_sources/sourceforge.dart @@ -50,7 +50,7 @@ class SourceForge extends AppSource { .toList(); return APKDetails( version, - apkUrlList, + getApkUrlsFromUrls(apkUrlList), AppNames( name, standardUrl.substring(standardUrl.lastIndexOf('/') + 1))); } else { diff --git a/lib/app_sources/steammobile.dart b/lib/app_sources/steammobile.dart index db6def3..5478a8f 100644 --- a/lib/app_sources/steammobile.dart +++ b/lib/app_sources/steammobile.dart @@ -53,7 +53,8 @@ class SteamMobile extends AppSource { var version = links[0].substring( versionMatch.start + apkNamePrefix.length + 2, versionMatch.end - 4); var apkUrls = [links[0]]; - return APKDetails(version, apkUrls, AppNames(name, apks[apkNamePrefix]!)); + return APKDetails(version, getApkUrlsFromUrls(apkUrls), + AppNames(name, apks[apkNamePrefix]!)); } else { throw getObtainiumHttpError(res); } diff --git a/lib/app_sources/telegramapp.dart b/lib/app_sources/telegramapp.dart index c152ed9..dd59e50 100644 --- a/lib/app_sources/telegramapp.dart +++ b/lib/app_sources/telegramapp.dart @@ -32,7 +32,8 @@ class TelegramApp extends AppSource { throw NoVersionError(); } String? apkUrl = 'https://telegram.org/dl/android/apk'; - return APKDetails(version, [apkUrl], AppNames('Telegram', 'Telegram')); + return APKDetails(version, getApkUrlsFromUrls([apkUrl]), + AppNames('Telegram', 'Telegram')); } else { throw getObtainiumHttpError(res); } diff --git a/lib/app_sources/vlc.dart b/lib/app_sources/vlc.dart index e4678d7..56adf8d 100644 --- a/lib/app_sources/vlc.dart +++ b/lib/app_sources/vlc.dart @@ -54,7 +54,8 @@ class VLC extends AppSource { throw getObtainiumHttpError(res2); } - return APKDetails(version, apkUrls, AppNames('VideoLAN', 'VLC')); + return APKDetails( + version, getApkUrlsFromUrls(apkUrls), AppNames('VideoLAN', 'VLC')); } else { throw getObtainiumHttpError(res); } diff --git a/lib/app_sources/whatsapp.dart b/lib/app_sources/whatsapp.dart index 6d08549..9512158 100644 --- a/lib/app_sources/whatsapp.dart +++ b/lib/app_sources/whatsapp.dart @@ -64,9 +64,9 @@ class WhatsApp extends AppSource { vLines[0].substring(versionMatch.start, versionMatch.end); return APKDetails( version, - [ + getApkUrlsFromUrls([ 'https://www.whatsapp.com/android?v=$version&=thisIsaPlaceholder&a=realURLPrefetchedAtDownloadTime' - ], + ]), AppNames('Meta', 'WhatsApp')); } else { throw getObtainiumHttpError(res); diff --git a/lib/main.dart b/lib/main.dart index b30c939..db412df 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.24'; +const String currentVersion = '0.11.25'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 4815129..31f5b22 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -169,7 +169,7 @@ class AppsProvider with ChangeNotifier { '${app.id}-${app.latestVersion}-${app.preferredApkIndex}.apk'; String downloadUrl = await SourceProvider() .getSource(app.url) - .apkUrlPrefetchModifier(app.apkUrls[app.preferredApkIndex]); + .apkUrlPrefetchModifier(app.apkUrls[app.preferredApkIndex].value); var notif = DownloadNotification(app.name, 100); notificationsProvider?.cancel(notif.id); int? prevProg; @@ -296,9 +296,10 @@ class AppsProvider with ChangeNotifier { await intent.launch(); } - Future confirmApkUrl(App app, BuildContext? context) async { + Future?> confirmApkUrl( + App app, BuildContext? context) async { // If the App has more than one APK, the user should pick one (if context provided) - String? apkUrl = app.apkUrls[app.preferredApkIndex]; + MapEntry? apkUrl = app.apkUrls[app.preferredApkIndex]; // get device supported architecture List archs = (await DeviceInfoPlugin().androidInfo).supportedAbis; @@ -321,14 +322,14 @@ class AppsProvider with ChangeNotifier { // If the picked APK comes from an origin different from the source, get user confirmation (if context provided) if (apkUrl != null && - getHost(apkUrl) != getHost(app.url) && + 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!); + sourceUrl: app.url, apkUrl: apkUrl!.value); }) != true) { apkUrl = null; @@ -353,7 +354,7 @@ class AppsProvider with ChangeNotifier { if (apps[id] == null) { throw ObtainiumError(tr('appNotFound')); } - String? apkUrl; + MapEntry? apkUrl; var trackOnly = apps[id]!.app.additionalSettings['trackOnly'] == true; if (!trackOnly) { apkUrl = await confirmApkUrl(apps[id]!.app, context); @@ -923,7 +924,7 @@ class APKPicker extends StatefulWidget { const APKPicker({super.key, required this.app, this.initVal, this.archs}); final App app; - final String? initVal; + final MapEntry? initVal; final List? archs; @override @@ -931,7 +932,7 @@ class APKPicker extends StatefulWidget { } class _APKPickerState extends State { - String? apkUrl; + MapEntry? apkUrl; @override Widget build(BuildContext context) { @@ -944,15 +945,13 @@ class _APKPickerState extends State { const SizedBox(height: 16), ...widget.app.apkUrls.map( (u) => RadioListTile( - title: Text(Uri.parse(u) - .pathSegments - .where((element) => element.isNotEmpty) - .last), - value: u, - groupValue: apkUrl, + title: Text(u.key), + value: u.value, + groupValue: apkUrl!.value, onChanged: (String? val) { setState(() { - apkUrl = val; + apkUrl = + widget.app.apkUrls.where((e) => e.value == val).first; }); }), ), diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index be09d43..6e3430c 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -34,7 +34,7 @@ class AppNames { class APKDetails { late String version; - late List apkUrls; + late List> apkUrls; late AppNames names; late DateTime? releaseDate; late String? changeLog; @@ -50,7 +50,7 @@ class App { late String name; String? installedVersion; late String latestVersion; - List apkUrls = []; + List> apkUrls = []; late int preferredApkIndex; late Map additionalSettings; late DateTime? lastUpdateCheck; @@ -134,6 +134,18 @@ class App { if (preferredApkIndex < 0) { preferredApkIndex = 0; } + // apkUrls can either be old list or new named list apkUrls + List> apkUrls = []; + if (json['apkUrls'] != null) { + var apkUrlJson = jsonDecode(json['apkUrls']); + try { + apkUrls = getApkUrlsFromUrls(List.from(apkUrlJson)); + } catch (e) { + apkUrls = List.from(apkUrlJson) + .map((e) => MapEntry(e[0] as String, e[1] as String)) + .toList(); + } + } return App( json['id'] as String, json['url'] as String, @@ -143,9 +155,7 @@ class App { ? null : json['installedVersion'] as String, json['latestVersion'] as String, - json['apkUrls'] == null - ? [] - : List.from(jsonDecode(json['apkUrls'])), + apkUrls, preferredApkIndex, additionalSettings, json['lastUpdateCheck'] == null @@ -173,7 +183,7 @@ class App { 'name': name, 'installedVersion': installedVersion, 'latestVersion': latestVersion, - 'apkUrls': jsonEncode(apkUrls), + 'apkUrls': jsonEncode(apkUrls.map((e) => [e.key, e.value]).toList()), 'preferredApkIndex': preferredApkIndex, 'additionalSettings': jsonEncode(additionalSettings), 'lastUpdateCheck': lastUpdateCheck?.microsecondsSinceEpoch, @@ -225,6 +235,11 @@ Map getDefaultValuesFromFormItems( .reduce((value, element) => [...value, ...element])); } +getApkUrlsFromUrls(List urls) => urls + .map((e) => + MapEntry(e.split('/').where((el) => el.trim().isNotEmpty).last, e)) + .toList(); + class AppSource { String? host; late String name; @@ -422,7 +437,7 @@ class SourceProvider { if (additionalSettings['apkFilterRegEx'] != null) { var reg = RegExp(additionalSettings['apkFilterRegEx']); apk.apkUrls = - apk.apkUrls.where((element) => reg.hasMatch(element)).toList(); + apk.apkUrls.where((element) => reg.hasMatch(element.key)).toList(); } if (apk.apkUrls.isEmpty && !trackOnly) { throw NoAPKError(); diff --git a/pubspec.yaml b/pubspec.yaml index e0b862b..f080bd2 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.11.24+146 # When changing this, update the tag in main() accordingly +version: 0.11.25+147 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 0804e680b2f3bd36c552936db55a48cca03d5460 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 6 Apr 2023 22:37:24 -0400 Subject: [PATCH 118/600] Added simple APK try auto-select by CPU arch #436 Plus minor form switch UI fixes (overflow, spacing) --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/zh.json | 1 + lib/components/generated_form.dart | 5 ++++- lib/main.dart | 2 +- lib/providers/source_provider.dart | 23 +++++++++++++++++++++++ pubspec.yaml | 2 +- 12 files changed, 37 insertions(+), 3 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 95d0bab..e0caa02 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -222,6 +222,7 @@ "versionDetection": "Versionserkennung", "standardVersionDetection": "Standardversionserkennung", "groupByCategory": "Group by Category", + "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", "removeAppQuestion": { "one": "App entfernen?", "other": "App entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 379b45c..bdafd9b 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -222,6 +222,7 @@ "versionDetection": "Version Detection", "standardVersionDetection": "Standard version detection", "groupByCategory": "Group by Category", + "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 2aebffb..f0b9401 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -222,6 +222,7 @@ "versionDetection": "تشخیص نسخه", "standardVersionDetection": "تشخیص نسخه استاندارد", "groupByCategory": "Group by Category", + "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 2912ab1..b363c4f 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -222,6 +222,7 @@ "versionDetection": "Détection des versions", "standardVersionDetection": "Détection de version standard", "groupByCategory": "Group by Category", + "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 40f7f59..5fd5ec5 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -221,6 +221,7 @@ "versionDetection": "Verzió érzékelés", "standardVersionDetection": "Alapért. verzió érzékelés", "groupByCategory": "Csoportosítás Kategória alapján", + "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", "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 85ea697..4a619f6 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -222,6 +222,7 @@ "versionDetection": "Rilevamento di versione", "standardVersionDetection": "Rilevamento di versione standard", "groupByCategory": "Group by Category", + "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 04806a4..eee03d3 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -222,6 +222,7 @@ "versionDetection": "バージョン検出", "standardVersionDetection": "標準のバージョン検出", "groupByCategory": "Group by Category", + "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 0aba1e6..b1a18bc 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -222,6 +222,7 @@ "versionDetection": "Version Detection", "standardVersionDetection": "Standard version detection", "groupByCategory": "Group by Category", + "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", "removeAppQuestion": { "one": "删除应用?", "other": "删除应用?" diff --git a/lib/components/generated_form.dart b/lib/components/generated_form.dart index 3f892c8..8ab4149 100644 --- a/lib/components/generated_form.dart +++ b/lib/components/generated_form.dart @@ -267,7 +267,10 @@ class _GeneratedFormState extends State { formInputs[r][e] = Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(widget.items[r][e].label), + Flexible(child: Text(widget.items[r][e].label)), + const SizedBox( + width: 8, + ), Switch( value: values[widget.items[r][e].key], onChanged: (value) { diff --git a/lib/main.dart b/lib/main.dart index db412df..016eb3a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.25'; +const String currentVersion = '0.11.26'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 6e3430c..181d423 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -3,6 +3,7 @@ import 'dart:convert'; +import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:html/dom.dart'; import 'package:http/http.dart'; @@ -146,6 +147,11 @@ class App { .toList(); } } + // Arch based APK filter option should be disabled if it previously did not exist + if (json['additionalSettings'] != null && + jsonDecode(json['additionalSettings'])['autoApkFilterByArch'] == null) { + additionalSettings['autoApkFilterByArch'] = false; + } return App( json['id'] as String, json['url'] as String, @@ -294,6 +300,10 @@ class AppSource { } ]) ], + [ + GeneratedFormSwitch('autoApkFilterByArch', + label: tr('autoApkFilterByArch'), defaultValue: true) + ], [GeneratedFormTextField('appName', label: tr('appName'), required: false)] ]; @@ -442,6 +452,19 @@ class SourceProvider { if (apk.apkUrls.isEmpty && !trackOnly) { throw NoAPKError(); } + if (apk.apkUrls.length > 1 && + additionalSettings['autoApkFilterByArch'] == true) { + var abis = (await DeviceInfoPlugin().androidInfo).supportedAbis; + for (var abi in abis) { + var urls2 = apk.apkUrls + .where((element) => RegExp('.*$abi.*').hasMatch(element.key)) + .toList(); + if (urls2.isNotEmpty && urls2.length < apk.apkUrls.length) { + apk.apkUrls = urls2; + break; + } + } + } String apkVersion = apk.version.replaceAll('/', '-'); var name = currentApp != null ? currentApp.name.trim() : ''; name = name.isNotEmpty diff --git a/pubspec.yaml b/pubspec.yaml index f080bd2..cd39266 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.11.25+147 # When changing this, update the tag in main() accordingly +version: 0.11.26+148 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 8f75ddd43fa0dcef28a9c3511f39450be869f192 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 6 Apr 2023 22:59:40 -0400 Subject: [PATCH 119/600] Better download file naming (reduces conflicts) --- lib/main.dart | 2 +- lib/providers/apps_provider.dart | 5 ++--- pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 016eb3a..eeb10de 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.26'; +const String currentVersion = '0.11.27'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 31f5b22..f24dbd9 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -165,11 +165,10 @@ class AppsProvider with ChangeNotifier { notifyListeners(); } try { - var fileName = - '${app.id}-${app.latestVersion}-${app.preferredApkIndex}.apk'; String downloadUrl = await SourceProvider() .getSource(app.url) .apkUrlPrefetchModifier(app.apkUrls[app.preferredApkIndex].value); + var fileName = '${app.id}-${downloadUrl.hashCode}.apk'; var notif = DownloadNotification(app.name, 100); notificationsProvider?.cancel(notif.id); int? prevProg; @@ -205,7 +204,7 @@ class AppsProvider with ChangeNotifier { var originalAppId = app.id; app.id = newInfo.packageName; downloadedFile = downloadedFile.renameSync( - '${downloadedFile.parent.path}/${app.id}-${app.latestVersion}-${app.preferredApkIndex}.apk'); + '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.apk'); if (apps[originalAppId] != null) { await removeApps([originalAppId]); await saveApps([app]); diff --git a/pubspec.yaml b/pubspec.yaml index cd39266..d9a9f6c 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.11.26+148 # When changing this, update the tag in main() accordingly +version: 0.11.27+149 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 334ac8d3d661a27d79dc046b1f62fbe0fbeacc60 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 7 Apr 2023 01:54:14 -0400 Subject: [PATCH 120/600] Use app deep copy in places to avoid bugs --- lib/main.dart | 2 +- lib/pages/app.dart | 2 +- lib/pages/apps.dart | 63 +++++++++++++++------------- lib/providers/apps_provider.dart | 7 +++- lib/providers/settings_provider.dart | 3 +- lib/providers/source_provider.dart | 16 +++++++ pubspec.yaml | 2 +- 7 files changed, 62 insertions(+), 33 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index eeb10de..c64b04f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.27'; +const String currentVersion = '0.11.28'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 867e3f1..bd9e510 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -38,7 +38,7 @@ class _AppPageState extends State { bool areDownloadsRunning = appsProvider.areDownloadsRunning(); var sourceProvider = SourceProvider(); - AppInMemory? app = appsProvider.apps[widget.appId]; + AppInMemory? app = appsProvider.apps[widget.appId]?.deepCopy(); var source = app != null ? sourceProvider.getSource(app.app.url) : null; if (!areDownloadsRunning && prevApp == null && app != null) { prevApp = app; diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 733e8b2..201df76 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -29,13 +29,13 @@ class AppsPageState extends State { final AppsFilter neutralFilter = AppsFilter(); var updatesOnlyFilter = AppsFilter(includeUptodate: false, includeNonInstalled: false); - Set selectedApps = {}; + Set selectedAppIds = {}; DateTime? refreshingSince; clearSelected() { - if (selectedApps.isNotEmpty) { + if (selectedAppIds.isNotEmpty) { setState(() { - selectedApps.clear(); + selectedAppIds.clear(); }); return true; } @@ -43,10 +43,10 @@ class AppsPageState extends State { } selectThese(List apps) { - if (selectedApps.isEmpty) { + if (selectedAppIds.isEmpty) { setState(() { for (var a in apps) { - selectedApps.add(a); + selectedAppIds.add(a.id); } }); } @@ -57,20 +57,20 @@ class AppsPageState extends State { var appsProvider = context.watch(); var settingsProvider = context.watch(); var sourceProvider = SourceProvider(); - var listedApps = appsProvider.apps.values.toList(); + var listedApps = appsProvider.getAppValues().toList(); var currentFilterIsUpdatesOnly = filter.isIdenticalTo(updatesOnlyFilter, settingsProvider); - selectedApps = selectedApps - .where((element) => listedApps.map((e) => e.app).contains(element)) + selectedAppIds = selectedAppIds + .where((element) => listedApps.map((e) => e.app.id).contains(element)) .toSet(); toggleAppSelected(App app) { setState(() { - if (selectedApps.contains(app)) { - selectedApps.remove(app); + if (selectedAppIds.map((e) => e).contains(app.id)) { + selectedAppIds.removeWhere((a) => a == app.id); } else { - selectedApps.add(app); + selectedAppIds.add(app.id); } }); } @@ -143,15 +143,15 @@ class AppsPageState extends State { var existingUpdates = appsProvider.findExistingUpdates(installedOnly: true); var existingUpdateIdsAllOrSelected = existingUpdates - .where((element) => selectedApps.isEmpty + .where((element) => selectedAppIds.isEmpty ? listedApps.where((a) => a.app.id == element).isNotEmpty - : selectedApps.map((e) => e.id).contains(element)) + : selectedAppIds.map((e) => e).contains(element)) .toList(); var newInstallIdsAllOrSelected = appsProvider .findExistingUpdates(nonInstalledOnly: true) - .where((element) => selectedApps.isEmpty + .where((element) => selectedAppIds.isEmpty ? listedApps.where((a) => a.app.id == element).isNotEmpty - : selectedApps.map((e) => e.id).contains(element)) + : selectedAppIds.map((e) => e).contains(element)) .toList(); List trackOnlyUpdateIdsAllOrSelected = []; @@ -212,6 +212,11 @@ class AppsPageState extends State { : -1; }); + Set selectedApps = listedApps + .map((e) => e.app) + .where((a) => selectedAppIds.contains(a.id)) + .toSet(); + showChangeLogDialog( String? changesUrl, AppSource appSource, String changeLog, int index) { showDialog( @@ -288,7 +293,8 @@ class AppsPageState extends State { if (refreshingSince != null) SliverToBoxAdapter( child: LinearProgressIndicator( - value: appsProvider.apps.values + value: appsProvider + .getAppValues() .where((element) => !(element.app.lastUpdateCheck ?.isBefore(refreshingSince!) ?? true)) @@ -467,7 +473,8 @@ class AppsPageState extends State { .colorScheme .primary .withOpacity(listedApps[index].app.pinned ? 0.2 : 0.1), - selected: selectedApps.contains(listedApps[index].app), + selected: + selectedAppIds.map((e) => e).contains(listedApps[index].app.id), onLongPress: () { toggleAppSelected(listedApps[index].app); }, @@ -497,7 +504,7 @@ class AppsPageState extends State { ])) : trailingRow, onTap: () { - if (selectedApps.isNotEmpty) { + if (selectedAppIds.isNotEmpty) { toggleAppSelected(listedApps[index].app); } else { Navigator.push( @@ -534,7 +541,7 @@ class AppsPageState extends State { } getSelectAllButton() { - return selectedApps.isEmpty + return selectedAppIds.isEmpty ? TextButton.icon( style: const ButtonStyle(visualDensity: VisualDensity.compact), onPressed: () { @@ -548,17 +555,17 @@ class AppsPageState extends State { : TextButton.icon( style: const ButtonStyle(visualDensity: VisualDensity.compact), onPressed: () { - selectedApps.isEmpty + selectedAppIds.isEmpty ? selectThese(listedApps.map((e) => e.app).toList()) : clearSelected(); }, icon: Icon( - selectedApps.isEmpty + selectedAppIds.isEmpty ? Icons.select_all_outlined : Icons.deselect_outlined, color: Theme.of(context).colorScheme.primary, ), - label: Text(selectedApps.length.toString())); + label: Text(selectedAppIds.length.toString())); } getMassObtainFunction() { @@ -706,7 +713,7 @@ class AppsPageState extends State { builder: (BuildContext ctx) { return AlertDialog( title: Text(tr('markXSelectedAppsAsUpdated', - args: [selectedApps.length.toString()])), + args: [selectedAppIds.length.toString()])), content: Text( tr('onlyWorksWithNonVersionDetectApps'), style: const TextStyle( @@ -760,7 +767,7 @@ class AppsPageState extends State { items: const [], initValid: true, message: tr('installStatusOfXWillBeResetExplanation', - args: [plural('app', selectedApps.length)]), + args: [plural('app', selectedAppIds.length)]), ); }); if (values != null) { @@ -836,7 +843,7 @@ class AppsPageState extends State { children: [ IconButton( visualDensity: VisualDensity.compact, - onPressed: selectedApps.isEmpty + onPressed: selectedAppIds.isEmpty ? null : () { appsProvider.removeAppsWithModal( @@ -848,7 +855,7 @@ class AppsPageState extends State { IconButton( visualDensity: VisualDensity.compact, onPressed: getMassObtainFunction(), - tooltip: selectedApps.isEmpty + tooltip: selectedAppIds.isEmpty ? tr('installUpdateApps') : tr('installUpdateSelectedApps'), icon: const Icon( @@ -856,13 +863,13 @@ class AppsPageState extends State { )), IconButton( visualDensity: VisualDensity.compact, - onPressed: selectedApps.isEmpty ? null : launchCategorizeDialog(), + onPressed: selectedAppIds.isEmpty ? null : launchCategorizeDialog(), tooltip: tr('categorize'), icon: const Icon(Icons.category_outlined), ), IconButton( visualDensity: VisualDensity.compact, - onPressed: selectedApps.isEmpty ? null : showMoreOptionsDialog, + onPressed: selectedAppIds.isEmpty ? null : showMoreOptionsDialog, tooltip: tr('more'), icon: const Icon(Icons.more_horiz), ), diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index f24dbd9..13fa426 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -34,6 +34,8 @@ class AppInMemory { AppInfo? installedInfo; AppInMemory(this.app, this.downloadProgress, this.installedInfo); + AppInMemory deepCopy() => + AppInMemory(app.deepCopy(), downloadProgress, installedInfo); } class DownloadedApk { @@ -97,6 +99,8 @@ class AppsProvider with ChangeNotifier { late Stream? foregroundStream; late StreamSubscription? foregroundSubscription; + Iterable getAppValues() => apps.values.map((a) => a.deepCopy()); + AppsProvider() { // Subscribe to changes in the app foreground status foregroundStream = FGBGEvents.stream.asBroadcastStream(); @@ -667,7 +671,8 @@ class AppsProvider with ChangeNotifier { bool onlyIfExists = true}) async { attemptToCorrectInstallStatus = attemptToCorrectInstallStatus && (await doesInstalledAppsPluginWork()); - for (var app in apps) { + for (var a in apps) { + var app = a.deepCopy(); AppInfo? info = await getInstalledInfo(app.id); app.name = info?.name ?? app.name; if (app.additionalSettings['appName']?.toString().isNotEmpty == true) { diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 7c3dcff..541b2e4 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -164,7 +164,8 @@ class SettingsProvider with ChangeNotifier { void setCategories(Map cats, {AppsProvider? appsProvider}) { if (appsProvider != null) { - List changedApps = appsProvider.apps.values + List changedApps = appsProvider + .getAppValues() .map((a) { var n1 = a.app.categories.length; a.app.categories.removeWhere((c) => !cats.keys.contains(c)); diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 181d423..5e8f595 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -80,6 +80,22 @@ class App { return 'ID: $id URL: $url INSTALLED: $installedVersion LATEST: $latestVersion APK: $apkUrls PREFERREDAPK: $preferredApkIndex ADDITIONALSETTINGS: ${additionalSettings.toString()} LASTCHECK: ${lastUpdateCheck.toString()} PINNED $pinned'; } + App deepCopy() => App( + id, + url, + author, + name, + installedVersion, + latestVersion, + apkUrls, + preferredApkIndex, + Map.from(additionalSettings), + lastUpdateCheck, + pinned, + categories: categories, + changeLog: changeLog, + releaseDate: releaseDate); + factory App.fromJson(Map json) { var source = SourceProvider().getSource(json['url']); var formItems = source.combinedAppSpecificSettingFormItems diff --git a/pubspec.yaml b/pubspec.yaml index d9a9f6c..160c2da 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.11.27+149 # When changing this, update the tag in main() accordingly +version: 0.11.28+150 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From d597d569e205ac5d4807dff292e26bc347e5b648 Mon Sep 17 00:00:00 2001 From: atilluF <110931720+atilluF@users.noreply.github.com> Date: Fri, 7 Apr 2023 13:19:12 +0200 Subject: [PATCH 121/600] Update it.json --- assets/translations/it.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/it.json b/assets/translations/it.json index 4a619f6..77649d8 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -207,7 +207,7 @@ "addCategory": "Aggiungi categoria", "label": "Etichetta", "language": "Lingua", - "copiedToClipboard": "Copied to Clipboard", + "copiedToClipboard": "Copiato negli appunti", "storagePermissionDenied": "Accesso ai file non autorizzato", "selectedCategorizeWarning": "Ciò sostituirà le impostazioni di categoria esistenti per le App selezionate.", "filterAPKsByRegEx": "Filtra file APK con espressioni regolari", @@ -221,8 +221,8 @@ "importFromURLsInFile": "Importa da URL in file (come OPML)", "versionDetection": "Rilevamento di versione", "standardVersionDetection": "Rilevamento di versione standard", - "groupByCategory": "Group by Category", - "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", + "groupByCategory": "Raggruppa per categoria", + "autoApkFilterByArch": "Tenta di filtrare gli APK in base all'architettura della CPU, se possibile", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" From f144ffdded6e3c1b618c78de6d412d252eab3026 Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Sat, 8 Apr 2023 00:03:31 +0900 Subject: [PATCH 122/600] Update ja.json --- assets/translations/ja.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index eee03d3..e7d5b5b 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -221,8 +221,8 @@ "importFromURLsInFile": "ファイル(OPMLなど)内のURLからインポート", "versionDetection": "バージョン検出", "standardVersionDetection": "標準のバージョン検出", - "groupByCategory": "Group by Category", - "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", + "groupByCategory": "カテゴリ別にグループ化する", + "autoApkFilterByArch": "可能であれば,CPUアーキテクチャによるAPKのフィルタリングを試みる", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" From 46a00836df7b8818a8c08546cb90a8bc4e03ab76 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 7 Apr 2023 22:10:55 -0400 Subject: [PATCH 123/600] Bugfix: GitHub/Codeberg fallback + no-prerel fail --- lib/app_sources/codeberg.dart | 5 +++-- lib/app_sources/github.dart | 5 +++-- lib/main.dart | 2 +- pubspec.yaml | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index 32ecad0..5787485 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -81,10 +81,11 @@ class Codeberg extends AppSource { []; dynamic targetRelease; - + var prerrelsSkipped = 0; for (int i = 0; i < releases.length; i++) { - if (!fallbackToOlderReleases && i > 0) break; + if (!fallbackToOlderReleases && i > prerrelsSkipped) break; if (!includePrereleases && releases[i]['prerelease'] == true) { + prerrelsSkipped++; continue; } if (releases[i]['draft'] == true) { diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index a7d8a0e..4741fd4 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -127,10 +127,11 @@ class GitHub extends AppSource { []; dynamic targetRelease; - + var prerrelsSkipped = 0; for (int i = 0; i < releases.length; i++) { - if (!fallbackToOlderReleases && i > 0) break; + if (!fallbackToOlderReleases && i > prerrelsSkipped) break; if (!includePrereleases && releases[i]['prerelease'] == true) { + prerrelsSkipped++; continue; } var nameToFilter = releases[i]['name'] as String?; diff --git a/lib/main.dart b/lib/main.dart index c64b04f..3ce2b61 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.28'; +const String currentVersion = '0.11.29'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 160c2da..9c5f555 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.11.28+150 # When changing this, update the tag in main() accordingly +version: 0.11.29+151 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 1c2980d1ac541898f76de5bfae6b99519e7c12ad Mon Sep 17 00:00:00 2001 From: gidano Date: Sun, 9 Apr 2023 08:57:12 +0200 Subject: [PATCH 124/600] Updated hu.json --- assets/translations/hu.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 5fd5ec5..dccb7dd 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -221,7 +221,7 @@ "versionDetection": "Verzió érzékelés", "standardVersionDetection": "Alapért. verzió érzékelés", "groupByCategory": "Csoportosítás Kategória alapján", - "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", + "autoApkFilterByArch": "Ha lehetséges, próbálja CPU architektúra szerint szűrni az APK-kat", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From d274b9a42875f0c1616061b45e31eb82d6c32bdc Mon Sep 17 00:00:00 2001 From: Mehdee <85278288+mehdijahann@users.noreply.github.com> Date: Mon, 10 Apr 2023 16:54:29 +0200 Subject: [PATCH 125/600] Update fa.json --- assets/translations/fa.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/fa.json b/assets/translations/fa.json index f0b9401..c68514d 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -207,7 +207,7 @@ "addCategory": "اضافه کردن دسته", "label": "برچسب", "language": "زبان", - "copiedToClipboard": "Copied to Clipboard", + "copiedToClipboard": "در کلیپ بورد کپی شد", "storagePermissionDenied": "مجوز ذخیره سازی رد شد", "selectedCategorizeWarning": "این جایگزین تنظیمات دسته بندی موجود برای برنامه های انتخابی می شود.", "filterAPKsByRegEx": "فایل‌های APK را با نظم فیلتر کنید", @@ -221,8 +221,8 @@ "importFromURLsInFile": "وارد کردن از آدرس های اینترنتی موجود در فایل (مانند OPML)", "versionDetection": "تشخیص نسخه", "standardVersionDetection": "تشخیص نسخه استاندارد", - "groupByCategory": "Group by Category", - "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", + "groupByCategory": "گروه بر اساس دسته", + "autoApkFilterByArch": "در صورت امکان سعی کنید APKها را بر اساس معماری CPU فیلتر کنید", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" From 36b8ef6782845a3b9c752ef7c0eacaec4fe2ddb8 Mon Sep 17 00:00:00 2001 From: Markus <82206269+markus-gitdev@users.noreply.github.com> Date: Tue, 11 Apr 2023 13:10:03 +0200 Subject: [PATCH 126/600] Update de.json Translations for: - groupByCategory - autoApkFilterByArch --- assets/translations/de.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index e0caa02..1fbf1c8 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -221,8 +221,8 @@ "importFromURLsInFile": "Importieren von URLs aus Datei ( z.B. OPML)", "versionDetection": "Versionserkennung", "standardVersionDetection": "Standardversionserkennung", - "groupByCategory": "Group by Category", - "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", + "groupByCategory": "Nach Kategorie gruppieren", + "autoApkFilterByArch": "Nach Möglichkeit versuchen, APKs nach CPU-Architektur zu filtern", "removeAppQuestion": { "one": "App entfernen?", "other": "App entfernen?" From 6275cbf1146e6b811f3aea97a2f0304269c80dfb Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 12 Apr 2023 14:50:54 -0400 Subject: [PATCH 127/600] HTML Source - handle relative URLs in literal .html pages --- lib/app_sources/html.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index bf4203e..92ddc9d 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -40,7 +40,9 @@ class HTML extends AppSource { ? e : e.startsWith('/') ? '${uri.origin}/$e' - : '${uri.origin}/${uri.path}/$e') + : uri.path.endsWith('.html') || uri.path.endsWith('.php') + ? '${uri.origin}/${uri.path.split('/').sublist(0, uri.path.split('/').length - 1).join('/')}/$e' + : '${uri.origin}/${uri.path}/$e') .toList(); return APKDetails( version, getApkUrlsFromUrls(apkUrls), AppNames(uri.host, tr('app'))); From 0704dfe2ee0be9dca04c74a629fd1b64c9972c78 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 12 Apr 2023 15:17:08 -0400 Subject: [PATCH 128/600] Fixed relative link handling in HTML source --- lib/app_sources/html.dart | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 92ddc9d..92178bf 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -34,16 +34,20 @@ class HTML extends AppSource { var rel = links.last; var apkName = rel.split('/').last; var version = apkName.substring(0, apkName.length - 4); - List apkUrls = [rel] - .map((e) => e.toLowerCase().startsWith('http://') || - e.toLowerCase().startsWith('https://') - ? e - : e.startsWith('/') - ? '${uri.origin}/$e' - : uri.path.endsWith('.html') || uri.path.endsWith('.php') - ? '${uri.origin}/${uri.path.split('/').sublist(0, uri.path.split('/').length - 1).join('/')}/$e' - : '${uri.origin}/${uri.path}/$e') - .toList(); + List apkUrls = [rel].map((e) { + try { + Uri.parse(e).origin; + return e; + } catch (err) { + // is relative + } + var currPathSegments = uri.path.split('/'); + if (e.startsWith('/') || currPathSegments.isEmpty) { + return '${uri.origin}/$e'; + } else { + return '${uri.origin}/${currPathSegments.sublist(0, currPathSegments.length - 1).join('/')}/$e'; + } + }).toList(); return APKDetails( version, getApkUrlsFromUrls(apkUrls), AppNames(uri.host, tr('app'))); } else { From 7ea75325bb2124d4da0a9a3945bf0c199f43a56d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 12 Apr 2023 15:36:17 -0400 Subject: [PATCH 129/600] App name overrides more consistent (#450) --- lib/pages/app.dart | 4 ++-- lib/pages/apps.dart | 12 ++++-------- lib/providers/apps_provider.dart | 15 +++++++-------- lib/providers/notifications_provider.dart | 8 ++++---- lib/providers/source_provider.dart | 9 +++++++++ 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index bd9e510..815b6dc 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -153,7 +153,7 @@ class _AppPageState extends State { height: 25, ), Text( - app?.app.name ?? tr('app'), + app?.name ?? tr('app'), textAlign: TextAlign.center, style: Theme.of(context).textTheme.displayLarge, ), @@ -386,7 +386,7 @@ class _AppPageState extends State { scrollable: true, content: getInfoColumn(), title: Text( - '${app.app.name} ${tr('byX', args: [ + '${app.name} ${tr('byX', args: [ app.app.author ])}'), actions: [ diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 201df76..be6cd50 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -94,8 +94,7 @@ class AppsPageState extends State { .toList(); for (var t in nameTokens) { - var name = app.installedInfo?.name ?? app.app.name; - if (!name.toLowerCase().contains(t.toLowerCase())) { + if (!app.name.toLowerCase().contains(t.toLowerCase())) { return false; } } @@ -120,13 +119,11 @@ class AppsPageState extends State { }).toList(); listedApps.sort((a, b) { - var nameA = a.installedInfo?.name ?? a.app.name; - var nameB = b.installedInfo?.name ?? b.app.name; int result = 0; if (settingsProvider.sortColumn == SortColumnSettings.authorName) { - result = (a.app.author + nameA).compareTo(b.app.author + nameB); + result = (a.app.author + a.name).compareTo(b.app.author + b.name); } else if (settingsProvider.sortColumn == SortColumnSettings.nameAuthor) { - result = (nameA + a.app.author).compareTo(nameB + b.app.author); + result = (a.name + a.app.author).compareTo(b.name + b.app.author); } else if (settingsProvider.sortColumn == SortColumnSettings.releaseDate) { result = (a.app.releaseDate)?.compareTo( @@ -481,8 +478,7 @@ class AppsPageState extends State { leading: getAppIcon(index), title: Text( maxLines: 1, - listedApps[index].installedInfo?.name ?? - listedApps[index].app.name, + listedApps[index].name, style: TextStyle( overflow: TextOverflow.ellipsis, fontWeight: listedApps[index].app.pinned diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 13fa426..22e08cc 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -36,6 +36,8 @@ class AppInMemory { AppInMemory(this.app, this.downloadProgress, this.installedInfo); AppInMemory deepCopy() => AppInMemory(app.deepCopy(), downloadProgress, installedInfo); + + String get name => app.overrideName ?? installedInfo?.name ?? app.finalName; } class DownloadedApk { @@ -163,7 +165,7 @@ class AppsProvider with ChangeNotifier { Future downloadApp(App app, BuildContext? context) async { NotificationsProvider? notificationsProvider = context?.read(); - var notifId = DownloadNotification(app.name, 0).id; + var notifId = DownloadNotification(app.finalName, 0).id; if (apps[app.id] != null) { apps[app.id]!.downloadProgress = 0; notifyListeners(); @@ -173,7 +175,7 @@ class AppsProvider with ChangeNotifier { .getSource(app.url) .apkUrlPrefetchModifier(app.apkUrls[app.preferredApkIndex].value); var fileName = '${app.id}-${downloadUrl.hashCode}.apk'; - var notif = DownloadNotification(app.name, 100); + var notif = DownloadNotification(app.finalName, 100); notificationsProvider?.cancel(notif.id); int? prevProg; File downloadedFile = @@ -183,7 +185,7 @@ class AppsProvider with ChangeNotifier { apps[app.id]!.downloadProgress = progress; notifyListeners(); } - notif = DownloadNotification(app.name, prog ?? 100); + notif = DownloadNotification(app.finalName, prog ?? 100); if (prog != null && prevProg != prog) { notificationsProvider?.notify(notif); } @@ -641,7 +643,7 @@ class AppsProvider with ChangeNotifier { sp.getSource(newApps[i].url); apps[newApps[i].id] = AppInMemory(newApps[i], null, info); } catch (e) { - errors.add([newApps[i].id, newApps[i].name, e.toString()]); + errors.add([newApps[i].id, newApps[i].finalName, e.toString()]); } } if (errors.isNotEmpty) { @@ -675,9 +677,6 @@ class AppsProvider with ChangeNotifier { var app = a.deepCopy(); AppInfo? info = await getInstalledInfo(app.id); app.name = info?.name ?? app.name; - if (app.additionalSettings['appName']?.toString().isNotEmpty == true) { - app.name = app.additionalSettings['appName'].toString().trim(); - } if (attemptToCorrectInstallStatus) { app = getCorrectedInstallStatusAppIfPossible(app, info) ?? app; } @@ -945,7 +944,7 @@ class _APKPickerState extends State { scrollable: true, title: Text(tr('pickAnAPK')), content: Column(children: [ - Text(tr('appHasMoreThanOnePackage', args: [widget.app.name])), + Text(tr('appHasMoreThanOnePackage', args: [widget.app.finalName])), const SizedBox(height: 16), ...widget.app.apkUrls.map( (u) => RadioListTile( diff --git a/lib/providers/notifications_provider.dart b/lib/providers/notifications_provider.dart index b68a669..f48b09a 100644 --- a/lib/providers/notifications_provider.dart +++ b/lib/providers/notifications_provider.dart @@ -34,9 +34,9 @@ class UpdateNotification extends ObtainiumNotification { message = updates.isEmpty ? tr('noNewUpdates') : updates.length == 1 - ? tr('xHasAnUpdate', args: [updates[0].name]) + ? tr('xHasAnUpdate', args: [updates[0].finalName]) : plural('xAndNMoreUpdatesAvailable', updates.length - 1, - args: [updates[0].name, (updates.length - 1).toString()]); + args: [updates[0].finalName, (updates.length - 1).toString()]); } } @@ -46,9 +46,9 @@ class SilentUpdateNotification extends ObtainiumNotification { tr('appsUpdatedNotifDescription'), Importance.defaultImportance) { message = updates.length == 1 ? tr('xWasUpdatedToY', - args: [updates[0].name, updates[0].latestVersion]) + args: [updates[0].finalName, updates[0].latestVersion]) : plural('xAndNMoreUpdatesInstalled', updates.length - 1, - args: [updates[0].name, (updates.length - 1).toString()]); + args: [updates[0].finalName, (updates.length - 1).toString()]); } } diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 5e8f595..24449d4 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -80,6 +80,15 @@ class App { return 'ID: $id URL: $url INSTALLED: $installedVersion LATEST: $latestVersion APK: $apkUrls PREFERREDAPK: $preferredApkIndex ADDITIONALSETTINGS: ${additionalSettings.toString()} LASTCHECK: ${lastUpdateCheck.toString()} PINNED $pinned'; } + String? get overrideName => + additionalSettings['appName']?.toString().trim().isNotEmpty == true + ? additionalSettings['appName'] + : null; + + String get finalName { + return overrideName ?? name; + } + App deepCopy() => App( id, url, From df242b91ad3ae51ede57898027236aa8371e25ad Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 12 Apr 2023 15:39:32 -0400 Subject: [PATCH 130/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 64 +++++++++++++++++++++++++-------------------------- pubspec.yaml | 2 +- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 3ce2b61..d11d07d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.29'; +const String currentVersion = '0.11.30'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 6510e6f..2bc0b23 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: "direct main" description: name: android_alarm_manager_plus - sha256: "8647cc5f9339f3955a2bd9ec40e0f10c3a80049f31f80b3ffdd87e07bb73fce2" + sha256: f6d0347734fa2ea716349a5a3e16ffdc1800ca64e5640112896d128c6815c178 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" android_intent_plus: dependency: "direct main" description: name: android_intent_plus - sha256: "54810cb33945c2c10742cd746ea994822c115e9dbe189919bc63cb436e45a6af" + sha256: "6bcdcd20461ac7a0c785f6298cdda96ad275d5bcbc1ecf28829cbe03ec6690be" url: "https://pub.dev" source: hosted - version: "3.1.6" + version: "3.1.7" animations: dependency: "direct main" description: @@ -117,10 +117,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "1d6e5a61674ba3a68fb048a7c7b4ff4bebfed8d7379dbe8f2b718231be9a7c95" + sha256: "435383ca05f212760b0a70426b5a90354fe6bd65992b3a5e27ab6ede74c02f5c" url: "https://pub.dev" source: hosted - version: "8.1.0" + version: "8.2.0" device_info_plus_platform_interface: dependency: transitive description: @@ -133,10 +133,10 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: c4a508284b14ec4dda5adba2c28b2cdd34fbae1afead7e8c52cad87d51c5405b + sha256: bbebb1b7ebed819e0ec83d4abdc2a8482d934f6a85289ffc1c6acf7589fa2aad url: "https://pub.dev" source: hosted - version: "1.6.2" + version: "1.6.3" easy_localization: dependency: "direct main" description: @@ -181,10 +181,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: d8e9ca7e5d1983365c277f12c21b4362df6cf659c99af146ad4d04eb33033013 + sha256: dd328189f2f4ccea042bb5b382d5e981691cc74b5a3429b9317bff2b19704489 url: "https://pub.dev" source: hosted - version: "5.2.6" + version: "5.2.8" flutter: dependency: "direct main" description: flutter @@ -425,10 +425,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: "818b2dc38b0f178e0ea3f7cf3b28146faab11375985d815942a68eee11c2d0f7" + sha256: ad4c4d011830462633f03eb34445a45345673dfd4faf1ab0b4735fbd93b19183 url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" path_provider_linux: dependency: transitive description: @@ -537,18 +537,18 @@ packages: dependency: "direct main" description: name: share_plus - sha256: "8c6892037b1824e2d7e8f59d54b3105932899008642e6372e5079c6939b4b625" + sha256: "692261968a494e47323dcc8bc66d8d52e81bc27cb4b808e4e8d7e8079d4cc01a" url: "https://pub.dev" source: hosted - version: "6.3.1" + version: "6.3.2" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface - sha256: "82ddd4ab9260c295e6e39612d4ff00390b9a7a21f1bb1da771e2f232d80ab8a1" + sha256: "0c6e61471bd71b04a138b8b588fa388e66d8b005e6f2deda63371c5c505a0981" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.1" shared_preferences: dependency: "direct main" description: @@ -569,10 +569,10 @@ packages: dependency: transitive description: name: shared_preferences_foundation - sha256: cf2a42fb20148502022861f71698db12d937c7459345a1bdaa88fc91a91b3603 + sha256: "0c1c16c56c9708aa9c361541a6f0e5cc6fc12a3232d866a687a7b7db30032b07" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" shared_preferences_linux: dependency: transitive description: @@ -710,18 +710,18 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: dd729390aa936bf1bdf5cd1bc7468ff340263f80a2c4f569416507667de8e3c8 + sha256: a52628068d282d01a07cd86e6ba99e497aa45ce8c91159015b2416907d78e411 url: "https://pub.dev" source: hosted - version: "6.0.26" + version: "6.0.27" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "3dedc66ca3c0bef9e6a93c0999aee102556a450afcc1b7bcfeace7a424927d92" + sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" url: "https://pub.dev" source: hosted - version: "6.1.3" + version: "6.1.4" url_launcher_linux: dependency: transitive description: @@ -734,10 +734,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: "0ef2b4f97942a16523e51256b799e9aa1843da6c60c55eefbfa9dbc2dcb8331a" + sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.0.5" url_launcher_platform_interface: dependency: transitive description: @@ -790,34 +790,34 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "9e223788e1954087dac30d813dc151f8e12f09f1139f116ce20b5658893f3627" + sha256: "5906c9aa8c88ed372b2ad3c88c942790b4fb16f73fdd1c0647b4d747d9cf5b3f" url: "https://pub.dev" source: hosted - version: "3.4.4" + version: "3.4.5" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "1939c39e2150fb4d30fd3cc59a891a49fed9935db53007df633ed83581b6117b" + sha256: "6341f92977609be71391f4d4dcd64bfaa8ac657af1dfb2e231b5c1724e8c6c36" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.0" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - sha256: d601aba11ad8d4481e17a34a76fa1d30dee92dcbbe2c58b0df3120e9453099c7 + sha256: "9a78d963cce191dd6a9df547301fc5c008bf3dae95a323ec281fff1284e0a037" url: "https://pub.dev" source: hosted - version: "3.2.3" + version: "3.2.4" win32: dependency: transitive description: name: win32 - sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 + sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4 url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "3.1.4" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9c5f555..129c962 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.11.29+151 # When changing this, update the tag in main() accordingly +version: 0.11.30+152 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 6a1275e9e421f93c28390348fba25aafad120fcd Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 12 Apr 2023 15:46:48 -0400 Subject: [PATCH 131/600] Sort no longer case-sensitive (#450) --- lib/pages/apps.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index be6cd50..44d16a1 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -121,9 +121,11 @@ class AppsPageState extends State { listedApps.sort((a, b) { int result = 0; if (settingsProvider.sortColumn == SortColumnSettings.authorName) { - result = (a.app.author + a.name).compareTo(b.app.author + b.name); + result = ((a.app.author + a.name).toLowerCase()) + .compareTo((b.app.author + b.name).toLowerCase()); } else if (settingsProvider.sortColumn == SortColumnSettings.nameAuthor) { - result = (a.name + a.app.author).compareTo(b.name + b.app.author); + result = ((a.name + a.app.author).toLowerCase()) + .compareTo((b.name + b.app.author).toLowerCase()); } else if (settingsProvider.sortColumn == SortColumnSettings.releaseDate) { result = (a.app.releaseDate)?.compareTo( @@ -203,7 +205,7 @@ class AppsPageState extends State { var listedCategories = getListedCategories(); listedCategories.sort((a, b) { return a != null && b != null - ? a.compareTo(b) + ? a.toLowerCase().compareTo(b.toLowerCase()) : a == null ? 1 : -1; From 3b28143a4e18022c9db6db2e71ffe2352fbdc96d Mon Sep 17 00:00:00 2001 From: Bnyro Date: Thu, 13 Apr 2023 18:19:24 +0200 Subject: [PATCH 132/600] Add an amoled black theme --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/zh.json | 1 + lib/main.dart | 8 ++++++++ lib/pages/settings.dart | 11 +++++++++++ lib/providers/settings_provider.dart | 9 +++++++++ 11 files changed, 36 insertions(+) diff --git a/assets/translations/de.json b/assets/translations/de.json index 1fbf1c8..705eb22 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -122,6 +122,7 @@ "followSystem": "System folgen", "obtainium": "Obtainium", "materialYou": "Material You", + "useBlackTheme": "Use pure black dark theme", "appSortBy": "App sortieren nach", "authorName": "Autor/Name", "nameAuthor": "Name/Autor", diff --git a/assets/translations/en.json b/assets/translations/en.json index bdafd9b..a9b074d 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -122,6 +122,7 @@ "followSystem": "Follow System", "obtainium": "Obtainium", "materialYou": "Material You", + "useBlackTheme": "Use pure black dark theme", "appSortBy": "App Sort By", "authorName": "Author/Name", "nameAuthor": "Name/Author", diff --git a/assets/translations/fa.json b/assets/translations/fa.json index c68514d..dbf4123 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -122,6 +122,7 @@ "followSystem": "هماهنگ با سیستم", "obtainium": "Obtainium", "materialYou": "Material You", + "useBlackTheme": "Use pure black dark theme", "appSortBy": "مرتب سازی برنامه بر اساس", "authorName": "سازنده/اسم", "nameAuthor": "اسم/سازنده", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index b363c4f..4e7a5ea 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -122,6 +122,7 @@ "followSystem": "Suivre le système", "obtainium": "Obtainium", "materialYou": "Material You", + "useBlackTheme": "Use pure black dark theme", "appSortBy": "Applications triées par", "authorName": "Auteur/Nom", "nameAuthor": "Nom/Auteur", diff --git a/assets/translations/hu.json b/assets/translations/hu.json index dccb7dd..527d924 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -122,6 +122,7 @@ "followSystem": "Rendszer szerint", "obtainium": "Obtainium", "materialYou": "Material You", + "useBlackTheme": "Use pure black dark theme", "appSortBy": "App rendezés...", "authorName": "Szerző/Név", "nameAuthor": "Név/Szerző", diff --git a/assets/translations/it.json b/assets/translations/it.json index 77649d8..b3ef7ec 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -122,6 +122,7 @@ "followSystem": "Segui sistema", "obtainium": "Obtainium", "materialYou": "Material You", + "useBlackTheme": "Use pure black dark theme", "appSortBy": "App ordinate per", "authorName": "Autore/Nome", "nameAuthor": "Nome/Autore", diff --git a/assets/translations/ja.json b/assets/translations/ja.json index e7d5b5b..ea5f56e 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -122,6 +122,7 @@ "followSystem": "システムに従う", "obtainium": "Obtainium", "materialYou": "Material You", + "useBlackTheme": "Use pure black dark theme", "appSortBy": "アプリの並び方", "authorName": "作者名/アプリ名", "nameAuthor": "アプリ名/作者名", diff --git a/assets/translations/zh.json b/assets/translations/zh.json index b1a18bc..b89922e 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -123,6 +123,7 @@ "followSystem": "跟随系统", "obtainium": "Obtainium", "materialYou": "Material You", + "useBlackTheme": "Use pure black dark theme", "appSortBy": "排列方式", "authorName": "作者 / 名字", "nameAuthor": "名字 / 作者", diff --git a/lib/main.dart b/lib/main.dart index d11d07d..53756f4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -263,6 +263,14 @@ class _ObtainiumState extends State { darkColorScheme = ColorScheme.fromSeed( seedColor: defaultThemeColour, brightness: Brightness.dark); } + + // set the background and surface colors to pure black in the amoled theme + if (settingsProvider.useBlackTheme) { + darkColorScheme = darkColorScheme + .copyWith(background: Colors.black, surface: Colors.black) + .harmonized(); + } + return MaterialApp( title: 'Obtainium', localizationsDelegates: context.localizationDelegates, diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 7fde4f6..2c4aeb0 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -224,6 +224,17 @@ class _SettingsPageState extends State { ), themeDropdown, height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(tr('useBlackTheme')), + Switch( + value: settingsProvider.useBlackTheme, + onChanged: (value) { + settingsProvider.useBlackTheme = value; + }) + ], + ), colourDropdown, height16, Row( diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 541b2e4..7fe5693 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -64,6 +64,15 @@ class SettingsProvider with ChangeNotifier { notifyListeners(); } + bool get useBlackTheme { + return prefs?.getBool('useBlackTheme') ?? false; + } + + set useBlackTheme(bool useBlackTheme) { + prefs?.setBool('useBlackTheme', useBlackTheme); + notifyListeners(); + } + int get updateInterval { var min = prefs?.getInt('updateInterval') ?? 360; if (!updateIntervals.contains(min)) { From ce8aeff3425776bf35fce87ec41a46965f06078b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 13 Apr 2023 23:06:08 -0400 Subject: [PATCH 133/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 16 ++++++++-------- pubspec.yaml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 53756f4..9382420 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.30'; +const String currentVersion = '0.11.31'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 2bc0b23..115934a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -181,10 +181,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: dd328189f2f4ccea042bb5b382d5e981691cc74b5a3429b9317bff2b19704489 + sha256: dcde5ad1a0cebcf3715ea3f24d0db1888bf77027a26c77d7779e8ef63b8ade62 url: "https://pub.dev" source: hosted - version: "5.2.8" + version: "5.2.9" flutter: dependency: "direct main" description: flutter @@ -561,10 +561,10 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "8304d8a1f7d21a429f91dee552792249362b68a331ac5c3c1caf370f658873f6" + sha256: "1bc5d734b109c327b922b0891b41fc51483ccbd53c0d19952b7e230349a5d90b" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" shared_preferences_foundation: dependency: transitive description: @@ -790,10 +790,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "5906c9aa8c88ed372b2ad3c88c942790b4fb16f73fdd1c0647b4d747d9cf5b3f" + sha256: bdd3ddbeaf341c75620e153d22b6f4f6c4a342fe4439ed3a10db74dd82e65d1c url: "https://pub.dev" source: hosted - version: "3.4.5" + version: "3.5.1" webview_flutter_platform_interface: dependency: transitive description: @@ -806,10 +806,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "9a78d963cce191dd6a9df547301fc5c008bf3dae95a323ec281fff1284e0a037" + sha256: "2ef3f65fd49061c18e4d837a411308f2850417f2d0a7c11aad2c3857bee12c18" url: "https://pub.dev" source: hosted - version: "3.2.4" + version: "3.3.0" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 129c962..1cf3391 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.11.30+152 # When changing this, update the tag in main() accordingly +version: 0.11.31+153 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 666941350e5ed4ec042f735a793d3219c68e226f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 15 Apr 2023 14:28:00 -0400 Subject: [PATCH 134/600] APK name bugfix --- lib/providers/source_provider.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 24449d4..da871cd 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -266,10 +266,12 @@ Map getDefaultValuesFromFormItems( .reduce((value, element) => [...value, ...element])); } -getApkUrlsFromUrls(List urls) => urls - .map((e) => - MapEntry(e.split('/').where((el) => el.trim().isNotEmpty).last, e)) - .toList(); +List> getApkUrlsFromUrls(List urls) => + urls.map((e) { + var segments = e.split('/').where((el) => el.trim().isNotEmpty); + var apkSegs = segments.where((s) => s.toLowerCase().endsWith('.apk')); + return MapEntry(apkSegs.isNotEmpty ? apkSegs.last : segments.last, e); + }).toList(); class AppSource { String? host; From 1090f15508da6951967eba441be1a4c7f6dc23d4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 15 Apr 2023 14:34:14 -0400 Subject: [PATCH 135/600] Sourceforge bugfix --- lib/app_sources/sourceforge.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app_sources/sourceforge.dart b/lib/app_sources/sourceforge.dart index 11aec8e..88017dd 100644 --- a/lib/app_sources/sourceforge.dart +++ b/lib/app_sources/sourceforge.dart @@ -31,7 +31,7 @@ class SourceForge extends AppSource { getVersion(String url) { try { var tokens = url.split('/'); - return tokens[tokens.length - 3]; + return tokens[tokens.length - 2]; } catch (e) { return null; } From ad250c30e4ab3cb645693f406919bba610858744 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 15 Apr 2023 14:41:38 -0400 Subject: [PATCH 136/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 9382420..32043e1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.31'; +const String currentVersion = '0.11.32'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 1cf3391..59b8686 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.11.31+153 # When changing this, update the tag in main() accordingly +version: 0.11.32+154 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 9e4ac397d8516b57218fe90ab13838f327ae6ca1 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 15 Apr 2023 15:18:32 -0400 Subject: [PATCH 137/600] Sourceforge apk url extraction bugfix --- lib/app_sources/sourceforge.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/app_sources/sourceforge.dart b/lib/app_sources/sourceforge.dart index 88017dd..e7b9ec5 100644 --- a/lib/app_sources/sourceforge.dart +++ b/lib/app_sources/sourceforge.dart @@ -31,7 +31,8 @@ class SourceForge extends AppSource { getVersion(String url) { try { var tokens = url.split('/'); - return tokens[tokens.length - 2]; + var fi = tokens.indexOf('files'); + return tokens[tokens[fi + 2] == 'download' ? fi - 1 : fi + 1]; } catch (e) { return null; } From 1b2a9a39e301713ff73be8dc02cc17bd3058747a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 19 Apr 2023 02:05:31 -0400 Subject: [PATCH 138/600] Fix "reset install status" button being disabled --- lib/pages/apps.dart | 46 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 44d16a1..8d56aea 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -754,30 +754,28 @@ class AppsPageState extends State { Navigator.of(context).pop(); } - resetSelectedAppsInstallStatuses() { - () async { - try { - var values = await showDialog( - context: context, - builder: (BuildContext ctx) { - return GeneratedFormModal( - title: tr('resetInstallStatusForSelectedAppsQuestion'), - items: const [], - initValid: true, - message: tr('installStatusOfXWillBeResetExplanation', - args: [plural('app', selectedAppIds.length)]), - ); - }); - if (values != null) { - appsProvider.saveApps(selectedApps.map((e) { - e.installedVersion = null; - return e; - }).toList()); - } - } finally { - Navigator.of(context).pop(); + resetSelectedAppsInstallStatuses() async { + try { + var values = await showDialog( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: tr('resetInstallStatusForSelectedAppsQuestion'), + items: const [], + initValid: true, + message: tr('installStatusOfXWillBeResetExplanation', + args: [plural('app', selectedAppIds.length)]), + ); + }); + if (values != null) { + appsProvider.saveApps(selectedApps.map((e) { + e.installedVersion = null; + return e; + }).toList()); } - }; + } finally { + Navigator.of(context).pop(); + } } showMoreOptionsDialog() { @@ -825,7 +823,7 @@ class AppsPageState extends State { icon: const Icon(Icons.share), ), IconButton( - onPressed: resetSelectedAppsInstallStatuses(), + onPressed: resetSelectedAppsInstallStatuses, tooltip: tr('resetInstallStatus'), icon: const Icon(Icons.restore_page_outlined), ), From 934f237e34eab35526ed8fd41cfa43a07009ce6e Mon Sep 17 00:00:00 2001 From: Markus <82206269+markus-gitdev@users.noreply.github.com> Date: Wed, 19 Apr 2023 12:04:51 +0200 Subject: [PATCH 139/600] Update de.json Correction of "removeAppQuestion" --- assets/translations/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 705eb22..8d7eee6 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -226,7 +226,7 @@ "autoApkFilterByArch": "Nach Möglichkeit versuchen, APKs nach CPU-Architektur zu filtern", "removeAppQuestion": { "one": "App entfernen?", - "other": "App entfernen?" + "other": "Apps entfernen?" }, "tooManyRequestsTryAgainInMinutes": { "one": "Zu viele Anfragen (Rate begrenzt) - versuchen Sie es in {} Minute erneut", From 78141998f48a45c31048ade1b07f5aafe33dc1dd Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 21 Apr 2023 15:54:17 -0400 Subject: [PATCH 140/600] Attempt additional fix for #201 --- lib/pages/add_app.dart | 3 ++- lib/providers/apps_provider.dart | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index f4f6c0e..27d37c2 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -127,7 +127,8 @@ class _AddAppPageState extends State { if (apkUrl == null) { throw ObtainiumError(tr('cancelled')); } - app.preferredApkIndex = app.apkUrls.indexOf(apkUrl); + app.preferredApkIndex = + app.apkUrls.map((e) => e.value).toList().indexOf(apkUrl.value); // ignore: use_build_context_synchronously var downloadedApk = await appsProvider.downloadApp( app, globalNavigatorKey.currentContext); diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 22e08cc..aa6719b 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -304,7 +304,8 @@ class AppsProvider with ChangeNotifier { Future?> confirmApkUrl( App app, BuildContext? context) async { // If the App has more than one APK, the user should pick one (if context provided) - MapEntry? apkUrl = app.apkUrls[app.preferredApkIndex]; + MapEntry? apkUrl = + app.apkUrls[app.preferredApkIndex >= 0 ? app.preferredApkIndex : 0]; // get device supported architecture List archs = (await DeviceInfoPlugin().androidInfo).supportedAbis; @@ -365,8 +366,13 @@ class AppsProvider with ChangeNotifier { apkUrl = await confirmApkUrl(apps[id]!.app, context); } if (apkUrl != null) { - int urlInd = apps[id]!.app.apkUrls.indexOf(apkUrl); - if (urlInd != apps[id]!.app.preferredApkIndex) { + int urlInd = apps[id]! + .app + .apkUrls + .map((e) => e.value) + .toList() + .indexOf(apkUrl.value); + if (urlInd >= 0 && urlInd != apps[id]!.app.preferredApkIndex) { apps[id]!.app.preferredApkIndex = urlInd; await saveApps([apps[id]!.app]); } From 9f2db4e4e7fbae7f8617063e687ff9cce255bfc9 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 22 Apr 2023 21:40:15 -0400 Subject: [PATCH 141/600] App page 'reset install status' button shows if appropriate --- lib/pages/app.dart | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 815b6dc..2b40cdd 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -268,9 +268,7 @@ class _AppPageState extends State { }).toList(); return GeneratedFormModal( - title: tr('additionalOptions'), - items: items, - ); + title: tr('additionalOptions'), items: items); }); } @@ -307,6 +305,15 @@ class _AppPageState extends State { } } + getResetInstallStatusButton() => TextButton( + onPressed: app?.app == null + ? null + : () { + app!.app.installedVersion = null; + appsProvider.saveApps([app.app]); + }, + child: Text(tr('resetInstallStatus'))); + getInstallOrUpdateButton() => TextButton( onPressed: (app?.app.installedVersion == null || app?.app.installedVersion != app?.app.latestVersion) && @@ -402,7 +409,13 @@ class _AppPageState extends State { icon: const Icon(Icons.more_horiz), tooltip: tr('more')), const SizedBox(width: 16.0), - Expanded(child: getInstallOrUpdateButton()), + Expanded( + child: !isVersionDetectionStandard && + app?.app.installedVersion != null && + app?.app.installedVersion == + app?.app.latestVersion + ? getResetInstallStatusButton() + : getInstallOrUpdateButton()), const SizedBox(width: 16.0), Expanded( child: TextButton( From 3e732a4317ffbcb8add22b983bbb4f3de7f74b63 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 22 Apr 2023 22:42:59 -0400 Subject: [PATCH 142/600] Sort GitHub releases by date, remove codeberg redundancy --- lib/app_sources/codeberg.dart | 100 ++++------------------------------ lib/app_sources/github.dart | 91 +++++++++++++++++++++++-------- 2 files changed, 79 insertions(+), 112 deletions(-) diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index 5787485..dc71fd6 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:http/http.dart'; +import 'package:obtainium/app_sources/github.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -35,6 +36,8 @@ class Codeberg extends AppSource { canSearch = true; } + var gh = GitHub(); + @override String standardizeURL(String url) { RegExp standardUrlRegEx = RegExp('^https?://$host/[^/]+/[^/]+'); @@ -54,80 +57,10 @@ class Codeberg extends AppSource { String standardUrl, Map additionalSettings, ) async { - bool includePrereleases = additionalSettings['includePrereleases'] == true; - bool fallbackToOlderReleases = - additionalSettings['fallbackToOlderReleases'] == true; - String? regexFilter = - (additionalSettings['filterReleaseTitlesByRegEx'] as String?) - ?.isNotEmpty == - true - ? additionalSettings['filterReleaseTitlesByRegEx'] - : null; - Response res = await get(Uri.parse( - 'https://$host/api/v1/repos${standardUrl.substring('https://$host'.length)}/releases?per_page=100')); - if (res.statusCode == 200) { - var releases = jsonDecode(res.body) as List; - - List> getReleaseAPKUrls(dynamic release) => - (release['assets'] as List?) - ?.map((e) { - return e['name'] != null && e['browser_download_url'] != null - ? MapEntry(e['name'] as String, - e['browser_download_url'] as String) - : const MapEntry('', ''); - }) - .where((element) => element.key.toLowerCase().endsWith('.apk')) - .toList() ?? - []; - - dynamic targetRelease; - var prerrelsSkipped = 0; - for (int i = 0; i < releases.length; i++) { - if (!fallbackToOlderReleases && i > prerrelsSkipped) break; - if (!includePrereleases && releases[i]['prerelease'] == true) { - prerrelsSkipped++; - continue; - } - if (releases[i]['draft'] == true) { - // Draft releases not supported - } - var nameToFilter = releases[i]['name'] as String?; - if (nameToFilter == null || nameToFilter.trim().isEmpty) { - // Some leave titles empty so tag is used - nameToFilter = releases[i]['tag_name'] as String; - } - if (regexFilter != null && - !RegExp(regexFilter).hasMatch(nameToFilter.trim())) { - continue; - } - var apkUrls = getReleaseAPKUrls(releases[i]); - if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) { - continue; - } - targetRelease = releases[i]; - targetRelease['apkUrls'] = apkUrls; - break; - } - if (targetRelease == null) { - throw NoReleasesError(); - } - String? version = targetRelease['tag_name']; - DateTime? releaseDate = targetRelease['published_at'] != null - ? DateTime.parse(targetRelease['published_at']) - : null; - if (version == null) { - throw NoVersionError(); - } - var changeLog = targetRelease['body'].toString(); - return APKDetails( - version, - targetRelease['apkUrls'] as List>, - getAppNames(standardUrl), - releaseDate: releaseDate, - changeLog: changeLog.isEmpty ? null : changeLog); - } else { - throw getObtainiumHttpError(res); - } + return gh.getLatestAPKDetailsCommon( + 'https://$host/api/v1/repos${standardUrl.substring('https://$host'.length)}/releases?per_page=100', + standardUrl, + additionalSettings); } AppNames getAppNames(String standardUrl) { @@ -138,20 +71,9 @@ class Codeberg extends AppSource { @override Future> search(String query) async { - Response res = await get(Uri.parse( - 'https://$host/api/v1/repos/search?q=${Uri.encodeQueryComponent(query)}&limit=100')); - if (res.statusCode == 200) { - Map urlsWithDescriptions = {}; - for (var e in (jsonDecode(res.body)['data'] as List)) { - urlsWithDescriptions.addAll({ - e['html_url'] as String: e['description'] != null - ? e['description'] as String - : tr('noDescription') - }); - } - return urlsWithDescriptions; - } else { - throw getObtainiumHttpError(res); - } + return gh.searchCommon( + query, + 'https://$host/api/v1/repos/search?q=${Uri.encodeQueryComponent(query)}&limit=100', + 'data'); } } diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 4741fd4..5b6f2cf 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -96,11 +96,9 @@ class GitHub extends AppSource { String? changeLogPageFromStandardUrl(String standardUrl) => '$standardUrl/releases'; - @override - Future getLatestAPKDetails( - String standardUrl, - Map additionalSettings, - ) async { + Future getLatestAPKDetailsCommon(String requestUrl, + String standardUrl, Map additionalSettings, + {Function(Response)? onHttpErrorCode}) async { bool includePrereleases = additionalSettings['includePrereleases'] == true; bool fallbackToOlderReleases = additionalSettings['fallbackToOlderReleases'] == true; @@ -110,22 +108,40 @@ class GitHub extends AppSource { true ? additionalSettings['filterReleaseTitlesByRegEx'] : null; - Response res = await get(Uri.parse( - 'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/releases?per_page=100')); + Response res = await get(Uri.parse(requestUrl)); if (res.statusCode == 200) { var releases = jsonDecode(res.body) as List; - List getReleaseAPKUrls(dynamic release) => + List> getReleaseAPKUrls(dynamic release) => (release['assets'] as List?) ?.map((e) { - return e['browser_download_url'] != null - ? e['browser_download_url'] as String - : ''; + return e['name'] != null && e['browser_download_url'] != null + ? MapEntry(e['name'] as String, + e['browser_download_url'] as String) + : const MapEntry('', ''); }) - .where((element) => element.toLowerCase().endsWith('.apk')) + .where((element) => element.key.toLowerCase().endsWith('.apk')) .toList() ?? []; + DateTime? getReleaseDateFromRelease(dynamic rel) => + rel?['published_at'] != null + ? DateTime.parse(rel['published_at']) + : null; + releases.sort((a, b) { + // See #478 + if (a == b) { + return 0; + } else if (a == null) { + return -1; + } else if (b == null) { + return 1; + } else { + return getReleaseDateFromRelease(a)! + .compareTo(getReleaseDateFromRelease(b)!); + } + }); + releases = releases.reversed.toList(); dynamic targetRelease; var prerrelsSkipped = 0; for (int i = 0; i < releases.length; i++) { @@ -134,6 +150,10 @@ class GitHub extends AppSource { prerrelsSkipped++; continue; } + if (releases[i]['draft'] == true) { + // Draft releases not supported + continue; + } var nameToFilter = releases[i]['name'] as String?; if (nameToFilter == null || nameToFilter.trim().isEmpty) { // Some leave titles empty so tag is used @@ -155,38 +175,51 @@ class GitHub extends AppSource { throw NoReleasesError(); } String? version = targetRelease['tag_name']; - DateTime? releaseDate = targetRelease['published_at'] != null - ? DateTime.parse(targetRelease['published_at']) - : null; + DateTime? releaseDate = getReleaseDateFromRelease(targetRelease); if (version == null) { throw NoVersionError(); } var changeLog = targetRelease['body'].toString(); return APKDetails( version, - getApkUrlsFromUrls(targetRelease['apkUrls'] as List), + targetRelease['apkUrls'] as List>, getAppNames(standardUrl), releaseDate: releaseDate, changeLog: changeLog.isEmpty ? null : changeLog); } else { - rateLimitErrorCheck(res); + if (onHttpErrorCode != null) { + onHttpErrorCode(res); + } throw getObtainiumHttpError(res); } } + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + return getLatestAPKDetailsCommon( + 'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/releases?per_page=100', + standardUrl, + additionalSettings, onHttpErrorCode: (Response res) { + rateLimitErrorCheck(res); + }); + } + AppNames getAppNames(String standardUrl) { String temp = standardUrl.substring(standardUrl.indexOf('://') + 3); List names = temp.substring(temp.indexOf('/') + 1).split('/'); return AppNames(names[0], names[1]); } - @override - Future> search(String query) async { - Response res = await get(Uri.parse( - 'https://${await getCredentialPrefixIfAny()}api.$host/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100')); + Future> searchCommon( + String query, String requestUrl, String rootProp, + {Function(Response)? onHttpErrorCode}) async { + Response res = await get(Uri.parse(requestUrl)); if (res.statusCode == 200) { Map urlsWithDescriptions = {}; - for (var e in (jsonDecode(res.body)['items'] as List)) { + for (var e in (jsonDecode(res.body)[rootProp] as List)) { urlsWithDescriptions.addAll({ e['html_url'] as String: ((e['archived'] == true ? '[ARCHIVED] ' : '') + @@ -197,11 +230,23 @@ class GitHub extends AppSource { } return urlsWithDescriptions; } else { - rateLimitErrorCheck(res); + if (onHttpErrorCode != null) { + onHttpErrorCode(res); + } throw getObtainiumHttpError(res); } } + @override + Future> search(String query) async { + return searchCommon( + query, + 'https://${await getCredentialPrefixIfAny()}api.$host/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100', + 'items', onHttpErrorCode: (Response res) { + rateLimitErrorCheck(res); + }); + } + rateLimitErrorCheck(Response res) { if (res.headers['x-ratelimit-remaining'] == '0') { throw RateLimitError( From be61220af40dca17449a8ab9b05b24d81018e64c Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 22 Apr 2023 22:57:54 -0400 Subject: [PATCH 143/600] Show version in changelog dialog (#482) --- lib/pages/apps.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 8d56aea..2629bc9 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -224,6 +224,7 @@ class AppsPageState extends State { return GeneratedFormModal( title: tr('changes'), items: const [], + message: listedApps[index].app.latestVersion, additionalWidgets: [ changesUrl != null ? GestureDetector( From de2b7fa7a13ac2e46c188c5e059d2dabe36d2836 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 22 Apr 2023 23:49:55 -0400 Subject: [PATCH 144/600] URL selection modal improvements (incl. #460) --- lib/pages/import_export.dart | 78 +++++++++++++++++++++--------- lib/providers/apps_provider.dart | 2 +- lib/providers/source_provider.dart | 7 ++- 3 files changed, 62 insertions(+), 25 deletions(-) diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index 3234919..d8fe3d2 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -506,7 +506,7 @@ class _UrlSelectionModalState extends State { widget.onlyOneSelectionAllowed ? tr('selectURL') : tr('selectURLs')), content: Column(children: [ ...urlWithDescriptionSelections.keys.map((urlWithD) { - select(bool? value) { + selectThis(bool? value) { setState(() { value ??= false; if (value! && widget.onlyOneSelectionAllowed) { @@ -517,11 +517,56 @@ class _UrlSelectionModalState extends State { }); } - return Row(children: [ + var urlLink = GestureDetector( + onTap: () { + launchUrlString(urlWithD.key, + mode: LaunchMode.externalApplication); + }, + child: Text( + Uri.parse(urlWithD.key).path.substring(1), + style: const TextStyle(decoration: TextDecoration.underline), + textAlign: TextAlign.start, + )); + + var descriptionText = Text( + urlWithD.value.length > 128 + ? '${urlWithD.value.substring(0, 128)}...' + : urlWithD.value, + style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 12), + ); + + var selectedUrlsWithDs = urlWithDescriptionSelections.entries + .where((e) => e.value) + .toList(); + + var singleSelectTile = ListTile( + title: urlLink, + subtitle: GestureDetector( + onTap: () { + setState(() { + selectOnlyOne(urlWithD.key); + }); + }, + child: descriptionText, + ), + leading: Radio( + value: urlWithD.key, + groupValue: selectedUrlsWithDs.isEmpty + ? null + : selectedUrlsWithDs.first.key.key, + onChanged: (value) { + setState(() { + selectOnlyOne(urlWithD.key); + }); + }, + ), + ); + + var multiSelectTile = Row(children: [ Checkbox( value: urlWithDescriptionSelections[urlWithD], onChanged: (value) { - select(value); + selectThis(value); }), const SizedBox( width: 8, @@ -534,28 +579,13 @@ class _UrlSelectionModalState extends State { const SizedBox( height: 8, ), - GestureDetector( - onTap: () { - launchUrlString(urlWithD.key, - mode: LaunchMode.externalApplication); - }, - child: Text( - Uri.parse(urlWithD.key).path.substring(1), - style: - const TextStyle(decoration: TextDecoration.underline), - textAlign: TextAlign.start, - )), + urlLink, GestureDetector( onTap: () { - select(!(urlWithDescriptionSelections[urlWithD] ?? false)); + selectThis( + !(urlWithDescriptionSelections[urlWithD] ?? false)); }, - child: Text( - urlWithD.value.length > 128 - ? '${urlWithD.value.substring(0, 128)}...' - : urlWithD.value, - style: const TextStyle( - fontStyle: FontStyle.italic, fontSize: 12), - ), + child: descriptionText, ), const SizedBox( height: 8, @@ -563,6 +593,10 @@ class _UrlSelectionModalState extends State { ], )) ]); + + return widget.onlyOneSelectionAllowed + ? singleSelectTile + : multiSelectTile; }) ]), actions: [ diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index aa6719b..a5b6154 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -913,7 +913,7 @@ class AppsProvider with ChangeNotifier { Future>> addAppsByURL(List urls) async { List results = await SourceProvider().getAppsByURLNaive(urls, - ignoreUrls: apps.values.map((e) => e.app.url).toList()); + alreadyAddedUrls: apps.values.map((e) => e.app.url).toList()); List pps = results[0]; Map errorsMap = results[1]; for (var app in pps) { diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index da871cd..8670216 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -519,11 +519,14 @@ class SourceProvider { // Returns errors in [results, errors] instead of throwing them Future> getAppsByURLNaive(List urls, - {List ignoreUrls = const []}) async { + {List alreadyAddedUrls = const []}) async { List apps = []; Map errors = {}; - for (var url in urls.where((element) => !ignoreUrls.contains(element))) { + for (var url in urls) { try { + if (alreadyAddedUrls.contains(url)) { + throw ObtainiumError(tr('appAlreadyAdded')); + } var source = getSource(url); apps.add(await getApp( source, From b406bb5c6ac9bfb2a8b6cca2323c3734e365cf1c Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Apr 2023 00:01:49 -0400 Subject: [PATCH 145/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 44 ++++++++++++++++++++++---------------------- pubspec.yaml | 4 ++-- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 32043e1..8b76e13 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.32'; +const String currentVersion = '0.11.33'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 115934a..71ed08d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -181,10 +181,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: dcde5ad1a0cebcf3715ea3f24d0db1888bf77027a26c77d7779e8ef63b8ade62 + sha256: b85eb92b175767fdaa0c543bf3b0d1f610fe966412ea72845fe5ba7801e763ff url: "https://pub.dev" source: hosted - version: "5.2.9" + version: "5.2.10" flutter: dependency: "direct main" description: flutter @@ -417,10 +417,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "019f18c9c10ae370b08dce1f3e3b73bc9f58e7f087bb5e921f06529438ac0ae7" + sha256: da97262be945a72270513700a92b39dd2f4a54dad55d061687e2e37a6390366a url: "https://pub.dev" source: hosted - version: "2.0.24" + version: "2.0.25" path_provider_foundation: dependency: transitive description: @@ -561,10 +561,10 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "1bc5d734b109c327b922b0891b41fc51483ccbd53c0d19952b7e230349a5d90b" + sha256: "7fa90471a6875d26ad78c7e4a675874b2043874586891128dc5899662c97db46" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" shared_preferences_foundation: dependency: transitive description: @@ -622,18 +622,18 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "500d6fec583d2c021f2d25a056d96654f910662c64f836cd2063167b8f1fa758" + sha256: e7dfb6482d5d02b661d0b2399efa72b98909e5aa7b8336e1fb37e226264ade00 url: "https://pub.dev" source: hosted - version: "2.2.6" + version: "2.2.7" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "963dad8c4aa2f814ce7d2d5b1da2f36f31bd1a439d8f27e3dc189bb9d26bc684" + sha256: "220831bf0bd5333ff2445eee35ec131553b804e6b5d47a4a37ca6f5eb66e282c" url: "https://pub.dev" source: hosted - version: "2.4.3" + version: "2.4.4" stack_trace: dependency: transitive description: @@ -662,10 +662,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "33b31b6beb98100bf9add464a36a8dd03eb10c7a8cf15aeec535e9b054aaf04b" + sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.1.0" term_glyph: dependency: transitive description: @@ -686,10 +686,10 @@ packages: dependency: transitive description: name: timezone - sha256: "24c8fcdd49a805d95777a39064862133ff816ebfffe0ceff110fb5960e557964" + sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0" url: "https://pub.dev" source: hosted - version: "0.9.1" + version: "0.9.2" typed_data: dependency: transitive description: @@ -782,34 +782,34 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: "47663d51a9061451aa3880a214ee9a65dcbb933b77bc44388e194279ab3ccaf6" + sha256: "1a37bdbaaf5fbe09ad8579ab09ecfd473284ce482f900b5aea27cf834386a567" url: "https://pub.dev" source: hosted - version: "4.0.7" + version: "4.2.0" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: bdd3ddbeaf341c75620e153d22b6f4f6c4a342fe4439ed3a10db74dd82e65d1c + sha256: "134ed5d36127b6f5865e86a82174886eae0b983dacd8df14b0448371debde755" url: "https://pub.dev" source: hosted - version: "3.5.1" + version: "3.6.0" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "6341f92977609be71391f4d4dcd64bfaa8ac657af1dfb2e231b5c1724e8c6c36" + sha256: "78715dc442b7849dbde74e92bb67de1cecf5addf95531c5fb474e72f5fe9a507" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "2ef3f65fd49061c18e4d837a411308f2850417f2d0a7c11aad2c3857bee12c18" + sha256: c94d242d8cbe1012c06ba7ac790c46d6e6b68723b7d34f8c74ed19f68d166f49 url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "3.4.0" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 59b8686..ea6682f 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.11.32+154 # When changing this, update the tag in main() accordingly +version: 0.11.33+155 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' @@ -49,7 +49,7 @@ dependencies: permission_handler: ^10.0.0 fluttertoast: ^8.0.9 device_info_plus: ^8.0.0 - file_picker: ^5.1.0 + file_picker: ^5.2.10 animations: ^2.0.4 install_plugin_v2: ^1.0.0 share_plus: ^6.0.1 From 283722319b554b0a284058f854ff1b88bc1d8825 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Apr 2023 00:53:03 -0400 Subject: [PATCH 146/600] More adaptive column spacing in apps list (#485) --- lib/pages/apps.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 2629bc9..6280c81 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -406,7 +406,8 @@ class AppsPageState extends State { children: [ Row(mainAxisSize: MainAxisSize.min, children: [ Container( - constraints: const BoxConstraints(maxWidth: 150), + constraints: BoxConstraints( + maxWidth: MediaQuery.of(context).size.width / 4), child: Text( getVersionText(index), overflow: TextOverflow.ellipsis, From e72b33ebf242b7c968d0e561dbbd64f950508cc6 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Apr 2023 01:19:31 -0400 Subject: [PATCH 147/600] Added fallback option to GitLab Source (#456) --- lib/app_sources/gitlab.dart | 84 ++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index 7d813d7..5b8db8c 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -3,10 +3,19 @@ import 'package:http/http.dart'; import 'package:obtainium/app_sources/github.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; +import 'package:obtainium/components/generated_form.dart'; +import 'package:easy_localization/easy_localization.dart'; class GitLab extends AppSource { GitLab() { host = 'gitlab.com'; + + additionalSourceAppSpecificSettingFormItems = [ + [ + GeneratedFormSwitch('fallbackToOlderReleases', + label: tr('fallbackToOlderReleases'), defaultValue: true) + ] + ]; } @override @@ -28,41 +37,58 @@ class GitLab extends AppSource { String standardUrl, Map additionalSettings, ) async { + bool fallbackToOlderReleases = + additionalSettings['fallbackToOlderReleases'] == true; Response res = await get(Uri.parse('$standardUrl/-/tags?format=atom')); if (res.statusCode == 200) { var standardUri = Uri.parse(standardUrl); var parsedHtml = parse(res.body); - var entry = parsedHtml.querySelector('entry'); - var entryContent = - parse(parseFragment(entry?.querySelector('content')!.innerHtml).text); - var apkUrls = [ - ...getLinksFromParsedHTML( - entryContent, - RegExp( - '^${standardUri.path.replaceAllMapped(RegExp(r'[.*+?^${}()|[\]\\]'), (x) { - return '\\${x[0]}'; - })}/uploads/[^/]+/[^/]+\\.apk\$', - caseSensitive: false), - standardUri.origin), - // GitLab releases may contain links to externally hosted APKs - ...getLinksFromParsedHTML(entryContent, - RegExp('/[^/]+\\.apk\$', caseSensitive: false), '') - .where((element) => Uri.parse(element).host != '') - .toList() - ]; + var apkDetailsList = parsedHtml.querySelectorAll('entry').map((entry) { + var entryContent = parse( + parseFragment(entry.querySelector('content')!.innerHtml).text); + var apkUrls = [ + ...getLinksFromParsedHTML( + entryContent, + RegExp( + '^${standardUri.path.replaceAllMapped(RegExp(r'[.*+?^${}()|[\]\\]'), (x) { + return '\\${x[0]}'; + })}/uploads/[^/]+/[^/]+\\.apk\$', + caseSensitive: false), + standardUri.origin), + // GitLab releases may contain links to externally hosted APKs + ...getLinksFromParsedHTML(entryContent, + RegExp('/[^/]+\\.apk\$', caseSensitive: false), '') + .where((element) => Uri.parse(element).host != '') + .toList() + ]; - var entryId = entry?.querySelector('id')?.innerHtml; - var version = - entryId == null ? null : Uri.parse(entryId).pathSegments.last; - var releaseDateString = entry?.querySelector('updated')?.innerHtml; - DateTime? releaseDate = - releaseDateString != null ? DateTime.parse(releaseDateString) : null; - if (version == null) { - throw NoVersionError(); + var entryId = entry.querySelector('id')?.innerHtml; + var version = + entryId == null ? null : Uri.parse(entryId).pathSegments.last; + var releaseDateString = entry.querySelector('updated')?.innerHtml; + DateTime? releaseDate = releaseDateString != null + ? DateTime.parse(releaseDateString) + : null; + if (version == null) { + throw NoVersionError(); + } + return APKDetails(version, getApkUrlsFromUrls(apkUrls), + GitHub().getAppNames(standardUrl), + releaseDate: releaseDate); + }); + if (apkDetailsList.isEmpty) { + throw NoReleasesError(); } - return APKDetails(version, getApkUrlsFromUrls(apkUrls), - GitHub().getAppNames(standardUrl), - releaseDate: releaseDate); + if (fallbackToOlderReleases) { + if (additionalSettings['trackOnly'] != true) { + apkDetailsList = + apkDetailsList.where((e) => e.apkUrls.isNotEmpty).toList(); + } + if (apkDetailsList.isEmpty) { + throw NoReleasesError(); + } + } + return apkDetailsList.first; } else { throw getObtainiumHttpError(res); } From 3c6e66ce127412399beef79d909f4071c4ec13bf Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Apr 2023 03:22:56 -0400 Subject: [PATCH 148/600] Fixed null error for imported Apps (#476) --- lib/main.dart | 2 +- lib/providers/apps_provider.dart | 5 +++-- pubspec.yaml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8b76e13..a3bb694 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.33'; +const String currentVersion = '0.11.34'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index a5b6154..02dd719 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -204,7 +204,8 @@ class AppsProvider with ChangeNotifier { // The former case should be handled (give the App its real ID), the latter is a security issue var newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); if (app.id != newInfo.packageName) { - if (apps[app.id] != null && !SourceProvider().isTempId(app)) { + var isTempId = SourceProvider().isTempId(app); + if (apps[app.id] != null && !isTempId) { throw IDChangedError(); } var originalAppId = app.id; @@ -213,7 +214,7 @@ class AppsProvider with ChangeNotifier { '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.apk'); if (apps[originalAppId] != null) { await removeApps([originalAppId]); - await saveApps([app]); + await saveApps([app], onlyIfExists: !isTempId); } } return DownloadedApk(app.id, downloadedFile); diff --git a/pubspec.yaml b/pubspec.yaml index ea6682f..03380ba 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.11.33+155 # When changing this, update the tag in main() accordingly +version: 0.11.34+156 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 396bf012c9ac60900a91cdb5aa4fe1d8e0f6309a Mon Sep 17 00:00:00 2001 From: gidano Date: Tue, 25 Apr 2023 15:55:30 +0200 Subject: [PATCH 149/600] Update hu.json --- assets/translations/hu.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 527d924..e10d709 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -122,7 +122,7 @@ "followSystem": "Rendszer szerint", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use pure black dark theme", + "useBlackTheme": "Használjon tiszta fekete sötét témát", "appSortBy": "App rendezés...", "authorName": "Szerző/Név", "nameAuthor": "Név/Szerző", @@ -207,7 +207,7 @@ "addCategory": "Új kategória", "label": "Címke", "language": "Nyelv", - "copiedToClipboard": "Copied to Clipboard", + "copiedToClipboard": "Másolva a vágólapra", "storagePermissionDenied": "Tárhely engedély megtagadva", "selectedCategorizeWarning": "Ez felváltja a kiválasztott alkalmazások meglévő kategória-beállításait.", "filterAPKsByRegEx": "Az APK-k szűrése reguláris kifejezéssel", From 28a996441c5c6aed4d26afa30e8b299d9fe5c7dd Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 28 Apr 2023 22:18:58 -0400 Subject: [PATCH 150/600] HTML Source Bugfix #288 --- lib/app_sources/html.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 92178bf..8067b26 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -41,9 +41,14 @@ class HTML extends AppSource { } catch (err) { // is relative } - var currPathSegments = uri.path.split('/'); + var currPathSegments = uri.path + .split('/') + .where((element) => element.trim().isNotEmpty) + .toList(); if (e.startsWith('/') || currPathSegments.isEmpty) { return '${uri.origin}/$e'; + } else if (e.split('/').length == 1) { + return '${uri.origin}/${currPathSegments.join('/')}/$e'; } else { return '${uri.origin}/${currPathSegments.sublist(0, currPathSegments.length - 1).join('/')}/$e'; } From 09c71e4e9f0eba8aaf39ab6ac34c5dc9f2b1d3ac Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 28 Apr 2023 22:22:55 -0400 Subject: [PATCH 151/600] Increase icon placeholder opacity (#490) --- lib/pages/apps.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 6280c81..fd1c5e0 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -364,7 +364,7 @@ class AppsPageState extends State { child: Image( image: const AssetImage( 'assets/graphics/icon_small.png'), - color: Colors.white.withOpacity(0.1), + color: Colors.white.withOpacity(0.3), colorBlendMode: BlendMode.modulate, gaplessPlayback: true, ), From e8ebf53626cf58bd4b273632fc17fee3581c39b5 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 28 Apr 2023 22:24:41 -0400 Subject: [PATCH 152/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 72 +++++++++++++++++++++++++-------------------------- pubspec.yaml | 4 +-- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a3bb694..3867379 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.34'; +const String currentVersion = '0.11.35'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 71ed08d..15a9746 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: "direct main" description: name: android_alarm_manager_plus - sha256: f6d0347734fa2ea716349a5a3e16ffdc1800ca64e5640112896d128c6815c178 + sha256: "88a8001851fdc9bd54fa4e30d0277bb900a50f3d86ff244da7f027400bf23ac0" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" android_intent_plus: dependency: "direct main" description: name: android_intent_plus - sha256: "6bcdcd20461ac7a0c785f6298cdda96ad275d5bcbc1ecf28829cbe03ec6690be" + sha256: "04cbc7c332a6f0bba88fed354de78813e9d24049c1800aaf10f449c7adc22603" url: "https://pub.dev" source: hosted - version: "3.1.7" + version: "3.1.9" animations: dependency: "direct main" description: @@ -117,10 +117,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "435383ca05f212760b0a70426b5a90354fe6bd65992b3a5e27ab6ede74c02f5c" + sha256: f52ab3b76b36ede4d135aab80194df8925b553686f0fa12226b4e2d658e45903 url: "https://pub.dev" source: hosted - version: "8.2.0" + version: "8.2.2" device_info_plus_platform_interface: dependency: transitive description: @@ -210,26 +210,26 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "293995f94e120c8afce768981bd1fa9c5d6de67c547568e3b42ae2defdcbb4a0" + sha256: "2876372952b65ca7f684e698eba22bda1cf581fa071dd30ba2f01900f507d0d1" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.0.0+1" flutter_local_notifications_linux: dependency: transitive description: name: flutter_local_notifications_linux - sha256: ccb08b93703aeedb58856e5637450bf3ffec899adb66dc325630b68994734b89 + sha256: "909bb95de05a2e793503a2437146285a2f600cd0b3f826e26b870a334d8586d7" url: "https://pub.dev" source: hosted - version: "3.0.0+1" + version: "4.0.0" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface - sha256: "5ec1feac5f7f7d9266759488bc5f76416152baba9aa1b26fe572246caa00d1ab" + sha256: "63235c42de5b6c99846969a27ad0209c401e6b77b0498939813725b5791c107c" url: "https://pub.dev" source: hosted - version: "6.0.0" + version: "7.0.0" flutter_localizations: dependency: transitive description: flutter @@ -247,10 +247,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: c224ac897bed083dabf11f238dd11a239809b446740be0c2044608c50029ffdf + sha256: "8ffe990dac54a4a5492747added38571a5ab474c8e5d196809ea08849c69b1bb" url: "https://pub.dev" source: hosted - version: "2.0.9" + version: "2.0.13" flutter_test: dependency: "direct dev" description: flutter @@ -417,10 +417,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: da97262be945a72270513700a92b39dd2f4a54dad55d061687e2e37a6390366a + sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" url: "https://pub.dev" source: hosted - version: "2.0.25" + version: "2.0.27" path_provider_foundation: dependency: transitive description: @@ -449,10 +449,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6 url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.1.6" permission_handler: dependency: "direct main" description: @@ -537,10 +537,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: "692261968a494e47323dcc8bc66d8d52e81bc27cb4b808e4e8d7e8079d4cc01a" + sha256: b1f15232d41e9701ab2f04181f21610c36c83a12ae426b79b4bd011c567934b1 url: "https://pub.dev" source: hosted - version: "6.3.2" + version: "6.3.4" share_plus_platform_interface: dependency: transitive description: @@ -561,10 +561,10 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "7fa90471a6875d26ad78c7e4a675874b2043874586891128dc5899662c97db46" + sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" shared_preferences_foundation: dependency: transitive description: @@ -622,18 +622,18 @@ packages: dependency: "direct main" description: name: sqflite - sha256: e7dfb6482d5d02b661d0b2399efa72b98909e5aa7b8336e1fb37e226264ade00 + sha256: "8453780d1f703ead201a39673deb93decf85d543f359f750e2afc4908b55533f" url: "https://pub.dev" source: hosted - version: "2.2.7" + version: "2.2.8" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "220831bf0bd5333ff2445eee35ec131553b804e6b5d47a4a37ca6f5eb66e282c" + sha256: e77abf6ff961d69dfef41daccbb66b51e9983cdd5cb35bf30733598057401555 url: "https://pub.dev" source: hosted - version: "2.4.4" + version: "2.4.5" stack_trace: dependency: transitive description: @@ -710,10 +710,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: a52628068d282d01a07cd86e6ba99e497aa45ce8c91159015b2416907d78e411 + sha256: "22f8db4a72be26e9e3a4aa3f194b1f7afbc76d20ec141f84be1d787db2155cbd" url: "https://pub.dev" source: hosted - version: "6.0.27" + version: "6.0.31" url_launcher_ios: dependency: transitive description: @@ -726,10 +726,10 @@ packages: dependency: transitive description: name: url_launcher_linux - sha256: "206fb8334a700ef7754d6a9ed119e7349bc830448098f21a69bf1b4ed038cabc" + sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.0.5" url_launcher_macos: dependency: transitive description: @@ -758,10 +758,10 @@ packages: dependency: transitive description: name: url_launcher_windows - sha256: a83ba3607a507758669cfafb03f9de09bf6e6280c14d9b9cb18f013e406dcacd + sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" uuid: dependency: transitive description: @@ -790,10 +790,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "134ed5d36127b6f5865e86a82174886eae0b983dacd8df14b0448371debde755" + sha256: d6cf18cd6c809c5a9294cd99707a21986aac4e08c87e1916ce2590315fb55d3a url: "https://pub.dev" source: hosted - version: "3.6.0" + version: "3.6.2" webview_flutter_platform_interface: dependency: transitive description: @@ -822,10 +822,10 @@ packages: dependency: transitive description: name: xdg_directories - sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 url: "https://pub.dev" source: hosted - version: "0.2.0+3" + version: "1.0.0" xml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 03380ba..346901f 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.11.34+156 # When changing this, update the tag in main() accordingly +version: 0.11.35+157 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' @@ -38,7 +38,7 @@ dependencies: cupertino_icons: ^1.0.5 path_provider: ^2.0.11 flutter_fgbg: ^0.2.0 # Try removing reliance on this - flutter_local_notifications: ^13.0.0 + flutter_local_notifications: ^14.0.0+1 provider: ^6.0.3 http: ^0.13.5 webview_flutter: ^4.0.0 From 4a07cf99519c43d5ea9ba41263276ac4a4b5a0d3 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 28 Apr 2023 22:45:38 -0400 Subject: [PATCH 153/600] Show "Reset Install Status" button on track-only apps --- lib/main.dart | 2 +- lib/pages/app.dart | 7 +++++-- pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 3867379..0939e5e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.35'; +const String currentVersion = '0.11.36'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 2b40cdd..f105470 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -312,7 +312,10 @@ class _AppPageState extends State { app!.app.installedVersion = null; appsProvider.saveApps([app.app]); }, - child: Text(tr('resetInstallStatus'))); + child: Text( + tr('resetInstallStatus'), + textAlign: TextAlign.center, + )); getInstallOrUpdateButton() => TextButton( onPressed: (app?.app.installedVersion == null || @@ -410,7 +413,7 @@ class _AppPageState extends State { tooltip: tr('more')), const SizedBox(width: 16.0), Expanded( - child: !isVersionDetectionStandard && + child: (!isVersionDetectionStandard || trackOnly) && app?.app.installedVersion != null && app?.app.installedVersion == app?.app.latestVersion diff --git a/pubspec.yaml b/pubspec.yaml index 346901f..9fd310d 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.11.35+157 # When changing this, update the tag in main() accordingly +version: 0.11.36+158 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 86b7f6fef34713e851bce6eb220d54921c85847f Mon Sep 17 00:00:00 2001 From: Matsuri Date: Sat, 29 Apr 2023 22:10:00 +0800 Subject: [PATCH 154/600] Update zh.json - Overhaul Simplified Chinese translation - Add a missing string ("onlyWorksWithNonVersionDetectApps") - Remove an invalid string ("onlyAppliesToInstalledAndOutdatedApps") --- assets/translations/zh.json | 292 ++++++++++++++++++------------------ 1 file changed, 146 insertions(+), 146 deletions(-) diff --git a/assets/translations/zh.json b/assets/translations/zh.json index b89922e..b7a1780 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -1,106 +1,105 @@ { - "invalidURLForSource": "不是一个有效的 {} URL", - "noReleaseFound": "找不到合适的更新", - "noVersionFound": "无法确定更新版本", - "urlMatchesNoSource": "URL 与已知来源不符", - "cantInstallOlderVersion": "无法安装旧版应用程序", - "appIdMismatch": "下载的软件包名与现有的应用程序包名不一致", - "functionNotImplemented": "该类没有实现此功能", + "invalidURLForSource": "无效的 {} URL", + "noReleaseFound": "找不到合适的发行版", + "noVersionFound": "无法确定发行版本号", + "urlMatchesNoSource": "URL 与已知的来源不符", + "cantInstallOlderVersion": "无法安装旧版本的应用", + "appIdMismatch": "所下载 APK 的应用 ID 与现有应用不一致", + "functionNotImplemented": "该类未实现此功能", "placeholder": "占位符", "someErrors": "出现了一些错误", "unexpectedError": "意外错误", "ok": "好的", "and": "和", - "startedBgUpdateTask": "开始后台检查更新任务", - "bgUpdateIgnoreAfterIs": "下次后台更新检查 {}", - "startedActualBGUpdateCheck": "后台检查更新已开始", - "bgUpdateTaskFinished": "后台检查更新已完成", - "firstRun": "这是你第一次运行 Obtainium", - "settingUpdateCheckIntervalTo": "设置检查更新间隔为 {}", - "githubPATLabel": "GitHub 个人访问令牌 (提高 API 限制)", - "githubPATHint": "个人访问令牌必须为: username:token 形式", + "startedBgUpdateTask": "后台更新检查任务已启动", + "bgUpdateIgnoreAfterIs": "后台更新检查间隔为 {}", + "startedActualBGUpdateCheck": "开始后台更新检查", + "bgUpdateTaskFinished": "后台更新检查任务已完成", + "firstRun": "这是 Obtainium 首次启动", + "settingUpdateCheckIntervalTo": "更新检查间隔设置为 {}", + "githubPATLabel": "GitHub 个人访问令牌(提升 API 请求限额)", + "githubPATHint": "个人访问令牌必须为“username:token”的格式", "githubPATFormat": "username:token", "githubPATLinkText": "关于 GitHub 个人访问令牌", - "includePrereleases": "包含预发布版", - "fallbackToOlderReleases": "回退到旧版", - "filterReleaseTitlesByRegEx": "使用正则以过滤发布标题", - "invalidRegEx": "表达式无效", + "includePrereleases": "包含预发行版", + "fallbackToOlderReleases": "将旧发行版作为备选", + "filterReleaseTitlesByRegEx": "使用正则表达式筛选发行标题", + "invalidRegEx": "无效的正则表达式", "noDescription": "无描述", "cancel": "取消", "continue": "继续", - "requiredInBrackets": "(必须)", - "dropdownNoOptsError": "错误:下拉菜单必须至少有一个选项", - "colour": "颜色", + "requiredInBrackets": "(必填)", + "dropdownNoOptsError": "错误:下拉菜单必须包含至少一个选项", + "colour": "配色", "githubStarredRepos": "GitHub 已星标仓库", "uname": "用户名", - "wrongArgNum": "提供了错误的参数数量", - "xIsTrackOnly": "{} 仅追踪", - "source": "源码", - "app": "应用程序", - "appsFromSourceAreTrackOnly": "来自此来源的应用为仅追踪", - "youPickedTrackOnly": "你已选择仅追踪选项", - "trackOnlyAppDescription": "该应用程序将被跟踪更新,但 Obtainium 无法下载或安装它", + "wrongArgNum": "参数数量错误", + "xIsTrackOnly": "{} 为“仅追踪”模式", + "source": "源代码", + "app": "应用", + "appsFromSourceAreTrackOnly": "此来源的应用为“仅追踪”模式。", + "youPickedTrackOnly": "您选择了“仅追踪”。", + "trackOnlyAppDescription": "该应用的更新会被追踪,但 Obtainium 无法下载或安装它。", "cancelled": "已取消", - "appAlreadyAdded": "此应用程序已被添加", - "alreadyUpToDateQuestion": "应用已是最新?", + "appAlreadyAdded": "此应用已经添加", + "alreadyUpToDateQuestion": "应用是否已经为最新版本?", "addApp": "添加应用", - "appSourceURL": "应用来源 URL", + "appSourceURL": "来源 URL", "error": "错误", "add": "添加", - "searchSomeSourcesLabel": "搜索 (仅部分来源)", + "searchSomeSourcesLabel": "搜索(仅部分来源)", "search": "搜索", "additionalOptsFor": "{} 的更多选项", - "supportedSourcesBelow": "受支持的来源:", - "trackOnlyInBrackets": "(仅追踪)", - "searchableInBrackets": "(可被搜索)", - "appsString": "应用程序", - "noApps": "无应用程序", - "noAppsForFilter": "没有应用可被过滤", - "byX": "来自 {}", - "percentProgress": "进度: {}%", - "pleaseWait": "请等待...", + "supportedSourcesBelow": "支持的来源:", + "trackOnlyInBrackets": "(仅追踪)", + "searchableInBrackets": "(可搜索)", + "appsString": "应用列表", + "noApps": "无应用", + "noAppsForFilter": "没有符合条件的应用", + "byX": "作者:{}", + "percentProgress": "进度:{}%", + "pleaseWait": "请稍候", "updateAvailable": "更新可用", - "estimateInBracketsShort": "(预计.)", + "estimateInBracketsShort": "(预计)", "notInstalled": "未安装", - "estimateInBrackets": "(预计)", + "estimateInBrackets": "(预计)", "selectAll": "全选", "deselectN": "取消选择 {}", - "xWillBeRemovedButRemainInstalled": "{} 将被从 Obtainium 中删除,但仍安装在设备上。", - "removeSelectedAppsQuestion": "删除已选择的应用程序吗?", - "removeSelectedApps": "删除已选择的应用程序", + "xWillBeRemovedButRemainInstalled": "{} 将从 Obtainium 中删除,但仍安装在您的设备中。", + "removeSelectedAppsQuestion": "是否删除选中的应用?", + "removeSelectedApps": "删除选中的应用", "updateX": "更新 {}", "installX": "安装 {}", - "markXTrackOnlyAsUpdated": "将仅追踪编辑为已更新", + "markXTrackOnlyAsUpdated": "将 {}\n(仅追踪)\n标记为已更新", "changeX": "更改 {}", - "installUpdateApps": "安装/更新应用程序", - "installUpdateSelectedApps": "安装/更新已选择的应用程序", - "onlyAppliesToInstalledAndOutdatedApps": "'只适用于已安装但已过时的应用程序", - "markXSelectedAppsAsUpdated": "将已选择的 {} 个应用程序标记为已更新?", + "installUpdateApps": "安装/更新应用", + "installUpdateSelectedApps": "安装/更新选中的应用", + "markXSelectedAppsAsUpdated": "是否将选中的 {} 个应用标记为已更新?", "no": "不要", "yes": "好的", - "markSelectedAppsUpdated": "标记已选择的应用程序为已更新", + "markSelectedAppsUpdated": "将选中的应用标记为已更新", "pinToTop": "置顶", "unpinFromTop": "取消置顶", - "resetInstallStatusForSelectedAppsQuestion": "为已选择的应用程序重置安装状态吗?", - "installStatusOfXWillBeResetExplanation": "当 Obtainium 中显示的应用程序版本由于更新失败或其他问题而不正确时,这将有助于重置任何选定应用程序的安装状态。", - "shareSelectedAppURLs": "分享已选择的应用程序 URL", + "resetInstallStatusForSelectedAppsQuestion": "是否重置选中应用的安装状态?", + "installStatusOfXWillBeResetExplanation": "选中应用的安装状态将会被重置。\n\n当更新安装失败或其他问题导致 Obtainium 中的应用版本显示错误时,可以尝试通过此方法解决。", + "shareSelectedAppURLs": "分享选中应用的 URL", "resetInstallStatus": "重置安装状态", "more": "更多", - "removeOutdatedFilter": "删除过时的应用程序过滤器", - "showOutdatedOnly": "只显示过时的应用程序", - "filter": "过滤器", - "filterActive": "过滤器 *", - "filterApps": "过滤应用", + "removeOutdatedFilter": "删除失效的应用筛选", + "showOutdatedOnly": "只显示待更新应用", + "filter": "筛选", + "filterActive": "筛选 *", + "filterApps": "筛选应用", "appName": "应用名称", "author": "作者", - "upToDateApps": "已更新的应用程序", - "nonInstalledApps": "未安装的应用程序", + "upToDateApps": "无需更新的应用", + "nonInstalledApps": "未安装的应用", "importExport": "导入/导出", "settings": "设置", - "exportedTo": "导出到 {}", + "exportedTo": "已导出至 {}", "obtainiumExport": "Obtainium 导出", - "invalidInput": "无效输入", - "importedX": "已导出到 {}", + "invalidInput": "无效的输入", + "importedX": "已导入 {}", "obtainiumImport": "Obtainium 导入", "importFromURLList": "从 URL 列表导入", "searchQuery": "搜索查询", @@ -109,13 +108,13 @@ "searchX": "搜索 {}", "noResults": "无结果", "importX": "导入 {}", - "importedAppsIdDisclaimer": "导入的应用程序可能显示为未安装。要解决这个问题,请通过 Obtainium 重新安装它们。", + "importedAppsIdDisclaimer": "导入的应用可能错误地显示为“未安装”。\n请通过 Obtainium 重新安装这些应用来解决此问题。", "importErrors": "导入错误", - "importedXOfYApps": "{} 中的 {} 个应用已导入", - "followingURLsHadErrors": "以下 URL 有错误:", + "importedXOfYApps": "已导入 {} 中的 {} 个应用。", + "followingURLsHadErrors": "下列 URL 存在错误:", "okay": "好的", - "selectURL": "已选择的 URL", - "selectURLs": "已选择的 URL", + "selectURL": "选择 URL", + "selectURLs": "选择 URL", "pick": "选择", "theme": "主题", "dark": "深色", @@ -123,68 +122,68 @@ "followSystem": "跟随系统", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use pure black dark theme", - "appSortBy": "排列方式", - "authorName": "作者 / 名字", - "nameAuthor": "名字 / 作者", - "asAdded": "添加顺序", - "appSortOrder": "排列顺序", + "useBlackTheme": "使用纯黑深色主题", + "appSortBy": "排序依据", + "authorName": "作者 / 应用名称", + "nameAuthor": "应用名称 / 作者", + "asAdded": "添加次序", + "appSortOrder": "顺序", "ascending": "升序", "descending": "降序", "bgUpdateCheckInterval": "后台更新检查间隔", "neverManualOnly": "手动", "appearance": "外观", - "showWebInAppView": "在应用来源页显示网页", - "pinUpdates": "需更新的应用置顶", - "updates": "检查间隔", - "sourceSpecific": "Github 访问令牌", + "showWebInAppView": "在应用详情页显示来源网页", + "pinUpdates": "将待更新应用置顶", + "updates": "更新", + "sourceSpecific": "来源相关", "appSource": "源代码", "noLogs": "无日志", - "appLogs": "应用日志", + "appLogs": "日志", "close": "关闭", "share": "分享", "appNotFound": "未找到应用", "obtainiumExportHyphenatedLowercase": "obtainium-导出", - "pickAnAPK": "选择一个安装包", + "pickAnAPK": "选择一个 APK 文件", "appHasMoreThanOnePackage": "{} 有多个架构可用:", - "deviceSupportsXArch": "你的设备支持 {} 架构", - "deviceSupportsFollowingArchs": "你的设备支持以下架构:", + "deviceSupportsXArch": "您的设备支持 {} 架构。", + "deviceSupportsFollowingArchs": "您的设备支持下列架构:", "warning": "警告", - "sourceIsXButPackageFromYPrompt": "此应用来源是 '{}' 但更新包来自 '{}'。 继续吗?", + "sourceIsXButPackageFromYPrompt": "此应用的来源是“{}”,但 APK 文件来自“{}”。是否继续?", "updatesAvailable": "更新可用", - "updatesAvailableNotifDescription": "通知 Obtainium 所跟踪应用程序的更新", - "noNewUpdates": "你的应用已是最新。", - "xHasAnUpdate": "{} 有更新啦", + "updatesAvailableNotifDescription": "Obtainium 追踪的应用有更新时发出通知", + "noNewUpdates": "全部应用已是最新。", + "xHasAnUpdate": "{} 可以更新了。", "appsUpdated": "应用已更新", - "appsUpdatedNotifDescription": "通知在后台安装应用程序的更新", - "xWasUpdatedToY": "{} 已更新到 {}.", + "appsUpdatedNotifDescription": "当应用在后台安装更新时发出通知", + "xWasUpdatedToY": "{} 已更新至 {}。", "errorCheckingUpdates": "检查更新出错", - "errorCheckingUpdatesNotifDescription": "当后台更新检查失败时显示的通知", + "errorCheckingUpdatesNotifDescription": "当后台检查更新失败时显示的通知", "appsRemoved": "应用已删除", - "appsRemovedNotifDescription": "通知由于加载应用程序时出错而被删除", - "xWasRemovedDueToErrorY": "{} 已因以下错误被删除: {}", + "appsRemovedNotifDescription": "当应用因加载出错而被删除时发出通知", + "xWasRemovedDueToErrorY": "{} 由于以下错误被删除:{}", "completeAppInstallation": "完成应用安装", - "obtainiumMustBeOpenToInstallApps": "Obtainium 需要被启动以安装更新", - "completeAppInstallationNotifDescription": "需要返回 Obtainium,以完成应用程序的安装。", - "checkingForUpdates": "检查更新中", - "checkingForUpdatesNotifDescription": "检查更新时出现的瞬时通知", - "pleaseAllowInstallPerm": "请允许 Obtainium 安装应用程序", + "obtainiumMustBeOpenToInstallApps": "必须启动 Obtainium 才能安装应用", + "completeAppInstallationNotifDescription": "提示返回 Obtainium 以完成应用的安装", + "checkingForUpdates": "正在检查更新", + "checkingForUpdatesNotifDescription": "检查更新时短暂显示的通知", + "pleaseAllowInstallPerm": "请授予 Obtainium 安装应用的权限", "trackOnly": "仅追踪", "errorWithHttpStatusCode": "错误 {}", - "versionCorrectionDisabled": "禁用版本更正(插件似乎未起作用)", + "versionCorrectionDisabled": "禁用版本号更正(插件似乎未起作用)", "unknown": "未知", "none": "无", "never": "从不", - "latestVersionX": "最新: {}", - "installedVersionX": "已安装: {}", - "lastUpdateCheckX": "最后检查: {}", + "latestVersionX": "最新版本:{}", + "installedVersionX": "当前版本:{}", + "lastUpdateCheckX": "上次更新检查:{}", "remove": "删除", - "yesMarkUpdated": "'是的,标为已更新", + "yesMarkUpdated": "是的,标记为已更新", "fdroid": "F-Droid", "appIdOrName": "应用 ID 或名称", - "appWithIdOrNameNotFound": "没有发现具有此 ID 或名称的应用", - "reposHaveMultipleApps": "来源可能包含多个应用", - "fdroidThirdPartyRepo": "F-Droid 第三方源", + "appWithIdOrNameNotFound": "未找到符合此 ID 或名称的应用", + "reposHaveMultipleApps": "存储库中可能包含多个应用", + "fdroidThirdPartyRepo": "F-Droid 第三方存储库", "steam": "Steam", "steamMobile": "Steam Mobile", "steamChat": "Steam Chat", @@ -193,52 +192,53 @@ "update": "更新", "markUpdated": "标记为已更新", "additionalOptions": "附加选项", - "disableVersionDetection": "关闭版本检测", - "noVersionDetectionExplanation": "此选项应只用于版本检测不能工作的应用程序", - "downloadingX": "下载中 {}", - "downloadNotifDescription": "通知用户下载进度", - "noAPKFound": "未找到安装包", - "noVersionDetection": "无版本检测", - "categorize": "归档", - "categories": "归档", + "disableVersionDetection": "禁用版本检测", + "noVersionDetectionExplanation": "此选项应该仅用于无法进行版本检测的应用。", + "downloadingX": "正在下载 {}", + "downloadNotifDescription": "提示应用的下载进度", + "noAPKFound": "未找到 APK 文件", + "noVersionDetection": "禁用版本检测", + "categorize": "分类", + "categories": "类别", "category": "类别", "noCategory": "无类别", "noCategories": "无类别", - "deleteCategoriesQuestion": "删除所有类别?", - "categoryDeleteWarning": "所有被删除类别的应用程序将被设置为无类别", + "deleteCategoriesQuestion": "是否删除选中的类别?", + "categoryDeleteWarning": "被删除类别下的应用将恢复为未分类状态。", "addCategory": "添加类别", "label": "标签", "language": "语言", - "copiedToClipboard": "Copied to Clipboard", - "storagePermissionDenied": "存储权限已被拒绝", - "selectedCategorizeWarning": "这将取代所选应用程序的任何现有类别", - "filterAPKsByRegEx": "Filter APKs by Regular Expression", - "removeFromObtainium": "Remove from Obtainium", - "uninstallFromDevice": "Uninstall from Device", - "releaseDateAsVersion": "Use Release Date as Version", - "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", - "changes": "Changes", - "releaseDate": "Release Date", - "importFromURLsInFile": "Import from URLs in File (like OPML)", - "versionDetection": "Version Detection", - "standardVersionDetection": "Standard version detection", - "groupByCategory": "Group by Category", - "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", + "copiedToClipboard": "已复制至剪贴板", + "storagePermissionDenied": "已拒绝授予存储权限", + "selectedCategorizeWarning": "这将覆盖选中应用当前的类别设置。", + "filterAPKsByRegEx": "使用正则表达式筛选 APK 文件", + "removeFromObtainium": "从 Obtainium 中删除", + "uninstallFromDevice": "从设备中卸载", + "onlyWorksWithNonVersionDetectApps": "仅适用于禁用版本检测的应用。", + "releaseDateAsVersion": "将发行日期作为版本号", + "releaseDateAsVersionExplanation": "此选项应该仅用于无法进行版本检测但能够获取发行日期的应用。", + "changes": "更新日志", + "releaseDate": "发行日期", + "importFromURLsInFile": "从文件中的 URL 导入(如 OPML)", + "versionDetection": "版本检测", + "standardVersionDetection": "常规版本检测", + "groupByCategory": "按类别分组显示", + "autoApkFilterByArch": "如果可能,尝试按 CPU 架构筛选 APK 文件", "removeAppQuestion": { - "one": "删除应用?", - "other": "删除应用?" + "one": "是否删除应用?", + "other": "是否删除应用?" }, "tooManyRequestsTryAgainInMinutes": { - "one": "请求过多 (API 限制) - 在 {} 分钟后重试", - "other": "请求过多 (API 限制) - 在 {} 分钟后重试" + "one": "API 请求过于频繁(速率限制)- 在 {} 分钟后重试", + "other": "API 请求过于频繁(速率限制)- 在 {} 分钟后重试" }, "bgUpdateGotErrorRetryInMinutes": { - "one": "后台更新检查遇到了 {} 问题, 将在 {} 分钟后重试", - "other": "后台更新检查遇到了 {} 问题, 将在 {} 分钟后重试" + "one": "后台更新检查遇到了“{}”问题,预定于 {} 分钟后重试", + "other": "后台更新检查遇到了“{}”问题,预定于 {} 分钟后重试" }, "bgCheckFoundUpdatesWillNotifyIfNeeded": { - "one": "后台更新检查找到了 {} 个更新 - 将通知用户", - "other": "后台更新检查找到了 {} 个更新 - 将通知用户" + "one": "后台检查发现 {} 个应用更新 - 如有需要将发出通知", + "other": "后台检查发现 {} 个应用更新 - 如有需要将发出通知" }, "apps": { "one": "{} 个应用", @@ -261,15 +261,15 @@ "other": "{} 天" }, "clearedNLogsBeforeXAfterY": { - "one": "清除了 {n} 个日志 (清除前 = {before}, 清除后 = {after})", - "other": "清除了 {n} 个日志 (清除前 = {before}, 清除后 = {after})" + "one": "清除了 {n} 个日志({before} 之前,{after} 之后)", + "other": "清除了 {n} 个日志({before} 之前,{after} 之后)" }, "xAndNMoreUpdatesAvailable": { - "one": "{} 和 {} 更多应用已被更新", - "other": "{} 和 {} 更多应用已被更新" + "one": "{} 和另外 1 个应用可以更新了。", + "other": "{} 和另外 {} 个应用可以更新了。" }, "xAndNMoreUpdatesInstalled": { - "one": "{} 和 {} 更多应用已被安装", - "other": "{} 和 {} 更多应用已被安装" + "one": "{} 和另外 1 个应用已更新。", + "other": "{} 和另外 {} 个应用已更新。" } } From 392554123b38e7fda5eacbba7e5a59519e284841 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 29 Apr 2023 23:50:12 -0400 Subject: [PATCH 155/600] Added an (experimental) Source override option for URLs that work with an existing Source but use a custom host (#271, #393) (#502) --- README.md | 1 - assets/translations/de.json | 2 +- assets/translations/en.json | 3 +- assets/translations/fa.json | 2 +- assets/translations/fr.json | 2 +- assets/translations/hu.json | 2 +- assets/translations/it.json | 2 +- assets/translations/ja.json | 2 +- assets/translations/zh.json | 2 +- lib/app_sources/apkmirror.dart | 2 +- lib/app_sources/codeberg.dart | 2 +- lib/app_sources/fdroid.dart | 7 +- lib/app_sources/fdroidrepo.dart | 11 -- lib/app_sources/github.dart | 2 +- lib/app_sources/gitlab.dart | 2 +- lib/app_sources/html.dart | 2 +- lib/app_sources/izzyondroid.dart | 2 +- lib/app_sources/mullvad.dart | 2 +- lib/app_sources/neutroncode.dart | 2 +- lib/app_sources/signal.dart | 2 +- lib/app_sources/sourceforge.dart | 2 +- lib/app_sources/steammobile.dart | 2 +- lib/app_sources/telegramapp.dart | 2 +- lib/app_sources/vlc.dart | 2 +- lib/app_sources/whatsapp.dart | 2 +- lib/main.dart | 2 +- lib/pages/add_app.dart | 69 +++++++- lib/pages/app.dart | 5 +- lib/pages/apps.dart | 11 +- lib/providers/apps_provider.dart | 7 +- lib/providers/source_provider.dart | 268 ++++++++++++++++++----------- pubspec.yaml | 2 +- 32 files changed, 270 insertions(+), 158 deletions(-) diff --git a/README.md b/README.md index 107e70f..0b30e18 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,6 @@ Currently supported App sources: - [SourceForge](https://sourceforge.net/) - [APKMirror](https://apkmirror.com/) (Track-Only) - Third Party F-Droid Repos - - Any URLs ending with `/fdroid/`, where `` can be anything - most often `repo` - [Steam](https://store.steampowered.com/mobile) - [Telegram App](https://telegram.org) - [VLC](https://www.videolan.org/vlc/download-android.html) diff --git a/assets/translations/de.json b/assets/translations/de.json index 8d7eee6..c89f6db 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -179,7 +179,7 @@ "lastUpdateCheckX": "Letzte Aktualisierungsprüfung: {}", "remove": "Entfernen", "yesMarkUpdated": "Ja, als aktualisiert markieren", - "fdroid": "F-Droid", + "fdroid": "F-Droid Official", "appIdOrName": "App ID oder Name", "appWithIdOrNameNotFound": "Es wurde keine App mit dieser ID oder diesem Namen gefunden", "reposHaveMultipleApps": "Repos können mehrere Apps enthalten", diff --git a/assets/translations/en.json b/assets/translations/en.json index a9b074d..8654d1d 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -179,7 +179,7 @@ "lastUpdateCheckX": "Last Update Check: {}", "remove": "Remove", "yesMarkUpdated": "Yes, Mark as Updated", - "fdroid": "F-Droid", + "fdroid": "F-Droid Official", "appIdOrName": "App ID or Name", "appWithIdOrNameNotFound": "No App was found with that ID or Name", "reposHaveMultipleApps": "Repos may contain multiple Apps", @@ -224,6 +224,7 @@ "standardVersionDetection": "Standard version detection", "groupByCategory": "Group by Category", "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", + "overrideSource": "Override Source", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index dbf4123..6aeee69 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -179,7 +179,7 @@ "lastUpdateCheckX": "بررسی آخرین به‌روزرسانی: {}", "remove": "حذف", "yesMarkUpdated": "بله، علامت گذاری به عنوان به روز شده", - "fdroid": "F-Droid", + "fdroid": "F-Droid Official", "appIdOrName": "شناسه یا نام برنامه", "appWithIdOrNameNotFound": "هیچ برنامه ای با آن شناسه یا نام یافت نشد", "reposHaveMultipleApps": "مخازن ممکن است شامل چندین برنامه باشد", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 4e7a5ea..95a73ee 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -179,7 +179,7 @@ "lastUpdateCheckX": "Vérification de la dernière mise à jour : {}", "remove": "Retirer", "yesMarkUpdated": "Oui, marquer comme mis à jour", - "fdroid": "F-Droid", + "fdroid": "F-Droid Official", "appIdOrName": "ID ou nom de l'application", "appWithIdOrNameNotFound": "Aucune application n'a été trouvée avec cet identifiant ou ce nom", "reposHaveMultipleApps": "Les dépôts peuvent contenir plusieurs applications", diff --git a/assets/translations/hu.json b/assets/translations/hu.json index e10d709..30b3418 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -179,7 +179,7 @@ "lastUpdateCheckX": "Frissítés ellenőrizve: {}", "remove": "Eltávolítás", "yesMarkUpdated": "Igen, megjelölés frissítettként", - "fdroid": "F-Droid", + "fdroid": "F-Droid Official", "appIdOrName": "App ID vagy név", "appWithIdOrNameNotFound": "Nem található app ezzel az azonosítóval vagy névvel", "reposHaveMultipleApps": "A repók több alkalmazást is tartalmazhatnak", diff --git a/assets/translations/it.json b/assets/translations/it.json index b3ef7ec..e212184 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -179,7 +179,7 @@ "lastUpdateCheckX": "Ultimo controllo degli aggiornamenti: {}", "remove": "Rimuovi", "yesMarkUpdated": "Sì, contrassegna come aggiornato", - "fdroid": "F-Droid", + "fdroid": "F-Droid Official", "appIdOrName": "ID o nome dell'App", "appWithIdOrNameNotFound": "Non è stata trovata alcuna App con quell'ID o nome", "reposHaveMultipleApps": "I repository possono contenere più App", diff --git a/assets/translations/ja.json b/assets/translations/ja.json index ea5f56e..2de9a3c 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -179,7 +179,7 @@ "lastUpdateCheckX": "最終アップデート確認: {}", "remove": "削除", "yesMarkUpdated": "はい、アップデート済みとしてマークします", - "fdroid": "F-Droid", + "fdroid": "F-Droid Official", "appIdOrName": "アプリのIDまたは名前", "appWithIdOrNameNotFound": "そのIDや名前を持つアプリは見つかりませんでした", "reposHaveMultipleApps": "リポジトリには複数のアプリが含まれることがあります", diff --git a/assets/translations/zh.json b/assets/translations/zh.json index b7a1780..4a555a9 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -179,7 +179,7 @@ "lastUpdateCheckX": "上次更新检查:{}", "remove": "删除", "yesMarkUpdated": "是的,标记为已更新", - "fdroid": "F-Droid", + "fdroid": "F-Droid Official", "appIdOrName": "应用 ID 或名称", "appWithIdOrNameNotFound": "未找到符合此 ID 或名称的应用", "reposHaveMultipleApps": "存储库中可能包含多个应用", diff --git a/lib/app_sources/apkmirror.dart b/lib/app_sources/apkmirror.dart index 6905023..396e599 100644 --- a/lib/app_sources/apkmirror.dart +++ b/lib/app_sources/apkmirror.dart @@ -31,7 +31,7 @@ class APKMirror extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { RegExp standardUrlRegEx = RegExp('^https?://$host/apk/[^/]+/[^/]+'); RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); if (match == null) { diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index dc71fd6..382c7f9 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -39,7 +39,7 @@ class Codeberg extends AppSource { var gh = GitHub(); @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { RegExp standardUrlRegEx = RegExp('^https?://$host/[^/]+/[^/]+'); RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); if (match == null) { diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 3d87419..c9c84e6 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -12,16 +12,15 @@ class FDroid extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { RegExp standardUrlRegExB = - RegExp('^https?://(cloudflare\\.)?$host/+[^/]+/+packages/+[^/]+'); + RegExp('^https?://$host/+[^/]+/+packages/+[^/]+'); RegExpMatch? match = standardUrlRegExB.firstMatch(url.toLowerCase()); if (match != null) { url = 'https://${Uri.parse(url.substring(0, match.end)).host}/packages/${Uri.parse(url).pathSegments.last}'; } - RegExp standardUrlRegExA = - RegExp('^https?://(cloudflare\\.)?$host/+packages/+[^/]+'); + RegExp standardUrlRegExA = RegExp('^https?://$host/+packages/+[^/]+'); match = standardUrlRegExA.firstMatch(url.toLowerCase()); if (match == null) { throw InvalidURLError(name); diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index 8523257..33c8edf 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -19,17 +19,6 @@ class FDroidRepo extends AppSource { ]; } - @override - String standardizeURL(String url) { - RegExp standardUrlRegExp = - RegExp('^https?://.+/fdroid/([^/]+(/|\\?)|[^/]+\$)'); - RegExpMatch? match = standardUrlRegExp.firstMatch(url.toLowerCase()); - if (match == null) { - throw InvalidURLError(name); - } - return url.substring(0, match.end); - } - @override Future getLatestAPKDetails( String standardUrl, diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 5b6f2cf..55e1d8b 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -75,7 +75,7 @@ class GitHub extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { RegExp standardUrlRegEx = RegExp('^https?://$host/[^/]+/[^/]+'); RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); if (match == null) { diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index 5b8db8c..150cb04 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -19,7 +19,7 @@ class GitLab extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { RegExp standardUrlRegEx = RegExp('^https?://$host/[^/]+/[^/]+'); RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); if (match == null) { diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 8067b26..ece1796 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -6,7 +6,7 @@ import 'package:obtainium/providers/source_provider.dart'; class HTML extends AppSource { @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { return url; } diff --git a/lib/app_sources/izzyondroid.dart b/lib/app_sources/izzyondroid.dart index a3f388c..0fbceb9 100644 --- a/lib/app_sources/izzyondroid.dart +++ b/lib/app_sources/izzyondroid.dart @@ -9,7 +9,7 @@ class IzzyOnDroid extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { RegExp standardUrlRegEx = RegExp('^https?://$host/repo/apk/[^/]+'); RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); if (match == null) { diff --git a/lib/app_sources/mullvad.dart b/lib/app_sources/mullvad.dart index 3f43def..64ef092 100644 --- a/lib/app_sources/mullvad.dart +++ b/lib/app_sources/mullvad.dart @@ -10,7 +10,7 @@ class Mullvad extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { RegExp standardUrlRegEx = RegExp('^https?://$host'); RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); if (match == null) { diff --git a/lib/app_sources/neutroncode.dart b/lib/app_sources/neutroncode.dart index 881cc31..45374a9 100644 --- a/lib/app_sources/neutroncode.dart +++ b/lib/app_sources/neutroncode.dart @@ -9,7 +9,7 @@ class NeutronCode extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { RegExp standardUrlRegEx = RegExp('^https?://$host/downloads/file/[^/]+'); RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); if (match == null) { diff --git a/lib/app_sources/signal.dart b/lib/app_sources/signal.dart index 4258d0c..40d6953 100644 --- a/lib/app_sources/signal.dart +++ b/lib/app_sources/signal.dart @@ -9,7 +9,7 @@ class Signal extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { return 'https://$host'; } diff --git a/lib/app_sources/sourceforge.dart b/lib/app_sources/sourceforge.dart index e7b9ec5..2d976ea 100644 --- a/lib/app_sources/sourceforge.dart +++ b/lib/app_sources/sourceforge.dart @@ -9,7 +9,7 @@ class SourceForge extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { RegExp standardUrlRegEx = RegExp('^https?://$host/projects/[^/]+'); RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); if (match == null) { diff --git a/lib/app_sources/steammobile.dart b/lib/app_sources/steammobile.dart index 5478a8f..305c89a 100644 --- a/lib/app_sources/steammobile.dart +++ b/lib/app_sources/steammobile.dart @@ -20,7 +20,7 @@ class SteamMobile extends AppSource { final apks = {'steam': tr('steamMobile'), 'steam-chat-app': tr('steamChat')}; @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { return 'https://$host'; } diff --git a/lib/app_sources/telegramapp.dart b/lib/app_sources/telegramapp.dart index dd59e50..3c02156 100644 --- a/lib/app_sources/telegramapp.dart +++ b/lib/app_sources/telegramapp.dart @@ -11,7 +11,7 @@ class TelegramApp extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { return 'https://$host'; } diff --git a/lib/app_sources/vlc.dart b/lib/app_sources/vlc.dart index 56adf8d..b105068 100644 --- a/lib/app_sources/vlc.dart +++ b/lib/app_sources/vlc.dart @@ -10,7 +10,7 @@ class VLC extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { return 'https://$host'; } diff --git a/lib/app_sources/whatsapp.dart b/lib/app_sources/whatsapp.dart index 9512158..85deb84 100644 --- a/lib/app_sources/whatsapp.dart +++ b/lib/app_sources/whatsapp.dart @@ -9,7 +9,7 @@ class WhatsApp extends AppSource { } @override - String standardizeURL(String url) { + String sourceSpecificStandardizeURL(String url) { return 'https://$host'; } diff --git a/lib/main.dart b/lib/main.dart index 0939e5e..e17f836 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.11.36'; +const String currentVersion = '0.12.0'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 27d37c2..625e5dd 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_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/app_sources/html.dart'; import 'package:obtainium/components/custom_app_bar.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/components/generated_form_modal.dart'; @@ -28,6 +29,7 @@ class _AddAppPageState extends State { String userInput = ''; String searchQuery = ''; + String? pickedSourceOverride; AppSource? pickedSource; Map additionalSettings = {}; bool additionalSettingsValid = true; @@ -49,8 +51,13 @@ class _AddAppPageState extends State { if (isSearch) { searchnum++; } - var source = valid ? sourceProvider.getSource(userInput) : null; - if (pickedSource.runtimeType != source.runtimeType) { + var prevHost = pickedSource?.host; + var source = valid + ? sourceProvider.getSource(userInput, + overrideSource: pickedSourceOverride) + : null; + if (pickedSource.runtimeType != source.runtimeType || + (prevHost != null && prevHost != source?.host)) { pickedSource = source; additionalSettings = source != null ? getDefaultValuesFromFormItems( @@ -115,7 +122,8 @@ class _AddAppPageState extends State { var trackOnly = pickedSource!.enforceTrackOnly || userPickedTrackOnly; app = await sourceProvider.getApp( pickedSource!, userInput, additionalSettings, - trackOnlyOverride: trackOnly); + trackOnlyOverride: trackOnly, + overrideSource: pickedSourceOverride); if (!trackOnly) { await settingsProvider.getInstallPermission(); } @@ -173,9 +181,9 @@ class _AddAppPageState extends State { (value) { try { sourceProvider - .getSource(value ?? '') - .standardizeURL( - preStandardizeUrl(value ?? '')); + .getSource(value ?? '', + overrideSource: pickedSourceOverride) + .standardizeUrl(value ?? ''); } catch (e) { return e is String ? e @@ -260,6 +268,48 @@ class _AddAppPageState extends State { } } + Widget getHTMLSourceOverrideDropdown() => Column(children: [ + Row( + children: [ + Expanded( + child: GeneratedForm( + items: [ + [ + GeneratedFormDropdown( + 'overrideSource', + defaultValue: HTML().runtimeType.toString(), + [ + ...sourceProvider.sources.map( + (s) => MapEntry(s.runtimeType.toString(), s.name)) + ], + label: tr('overrideSource')) + ] + ], + onValueChanges: (values, valid, isBuilding) { + fn() { + pickedSourceOverride = (values['overrideSource'] == null || + values['overrideSource'] == '') + ? null + : values['overrideSource']; + } + + if (!isBuilding) { + setState(() { + fn(); + }); + } else { + fn(); + } + changeUserInput(userInput, valid, isBuilding); + }, + )) + ], + ), + const SizedBox( + height: 25, + ), + ]); + bool shouldShowSearchBar() => sourceProvider.sources.where((e) => e.canSearch).isNotEmpty && pickedSource == null && @@ -309,6 +359,10 @@ class _AddAppPageState extends State { const SizedBox( height: 16, ), + if (pickedSourceOverride != null || + pickedSource.runtimeType.toString() == + HTML().runtimeType.toString()) + getHTMLSourceOverrideDropdown(), GeneratedForm( key: Key(pickedSource.runtimeType.toString()), items: pickedSource!.combinedAppSpecificSettingFormItems, @@ -379,6 +433,9 @@ class _AddAppPageState extends State { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ getUrlInputRow(), + const SizedBox( + height: 16, + ), if (shouldShowSearchBar()) const SizedBox( height: 16, diff --git a/lib/pages/app.dart b/lib/pages/app.dart index f105470..3e4c3aa 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -39,7 +39,10 @@ class _AppPageState extends State { var sourceProvider = SourceProvider(); AppInMemory? app = appsProvider.apps[widget.appId]?.deepCopy(); - var source = app != null ? sourceProvider.getSource(app.app.url) : null; + var source = app != null + ? sourceProvider.getSource(app.app.url, + overrideSource: app.app.overrideSource) + : null; if (!areDownloadsRunning && prevApp == null && app != null) { prevApp = app; getUpdate(app.app.id); diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index fd1c5e0..e00dae2 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -111,7 +111,11 @@ class AppsPageState extends State { return false; } if (filter.sourceFilter.isNotEmpty && - sourceProvider.getSource(app.app.url).runtimeType.toString() != + sourceProvider + .getSource(app.app.url, + overrideSource: app.app.overrideSource) + .runtimeType + .toString() != filter.sourceFilter) { return false; } @@ -306,8 +310,9 @@ class AppsPageState extends State { } getChangeLogFn(int appIndex) { - AppSource appSource = - SourceProvider().getSource(listedApps[appIndex].app.url); + AppSource appSource = SourceProvider().getSource( + listedApps[appIndex].app.url, + overrideSource: listedApps[appIndex].app.overrideSource); String? changesUrl = appSource.changeLogPageFromStandardUrl(listedApps[appIndex].app.url); String? changeLog = listedApps[appIndex].app.changeLog; diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 02dd719..46d57c4 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -172,7 +172,7 @@ class AppsProvider with ChangeNotifier { } try { String downloadUrl = await SourceProvider() - .getSource(app.url) + .getSource(app.url, overrideSource: app.overrideSource) .apkUrlPrefetchModifier(app.apkUrls[app.preferredApkIndex].value); var fileName = '${app.id}-${downloadUrl.hashCode}.apk'; var notif = DownloadNotification(app.finalName, 100); @@ -647,7 +647,7 @@ class AppsProvider with ChangeNotifier { for (int i = 0; i < newApps.length; i++) { var info = await getInstalledInfo(newApps[i].id); try { - sp.getSource(newApps[i].url); + sp.getSource(newApps[i].url, overrideSource: newApps[i].overrideSource); apps[newApps[i].id] = AppInMemory(newApps[i], null, info); } catch (e) { errors.add([newApps[i].id, newApps[i].finalName, e.toString()]); @@ -787,7 +787,8 @@ class AppsProvider with ChangeNotifier { App? currentApp = apps[appId]!.app; SourceProvider sourceProvider = SourceProvider(); App newApp = await sourceProvider.getApp( - sourceProvider.getSource(currentApp.url), + sourceProvider.getSource(currentApp.url, + overrideSource: currentApp.overrideSource), currentApp.url, currentApp.additionalSettings, currentApp: currentApp); diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 8670216..367e559 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -44,6 +44,106 @@ class APKDetails { {this.releaseDate, this.changeLog}); } +stringMapListTo2DList(List> mapList) => + mapList.map((e) => [e.key, e.value]).toList(); + +assumed2DlistToStringMapList(List arr) => + arr.map((e) => MapEntry(e[0] as String, e[1] as String)).toList(); + +// App JSON schema has changed multiple times over the many versions of Obtainium +// This function takes an App JSON and modifies it if needed to conform to the latest (current) version +appJSONCompatibilityModifiers(Map json) { + var source = SourceProvider() + .getSource(json['url'], overrideSource: json['overrideSource']); + var formItems = source.combinedAppSpecificSettingFormItems + .reduce((value, element) => [...value, ...element]); + Map additionalSettings = + getDefaultValuesFromFormItems([formItems]); + if (json['additionalSettings'] != null) { + additionalSettings.addEntries( + Map.from(jsonDecode(json['additionalSettings'])) + .entries); + } + // If needed, migrate old-style additionalData to newer-style additionalSettings (V1) + if (json['additionalData'] != null) { + List temp = List.from(jsonDecode(json['additionalData'])); + temp.asMap().forEach((i, value) { + if (i < formItems.length) { + if (formItems[i] is GeneratedFormSwitch) { + additionalSettings[formItems[i].key] = value == 'true'; + } else { + additionalSettings[formItems[i].key] = value; + } + } + }); + additionalSettings['trackOnly'] = + json['trackOnly'] == 'true' || json['trackOnly'] == true; + additionalSettings['noVersionDetection'] = + json['noVersionDetection'] == 'true' || json['trackOnly'] == true; + } + // Convert bool style version detection options to dropdown style + if (additionalSettings['noVersionDetection'] == true) { + additionalSettings['versionDetection'] = 'noVersionDetection'; + if (additionalSettings['releaseDateAsVersion'] == true) { + additionalSettings['versionDetection'] = 'releaseDateAsVersion'; + additionalSettings.remove('releaseDateAsVersion'); + } + if (additionalSettings['noVersionDetection'] != null) { + additionalSettings.remove('noVersionDetection'); + } + if (additionalSettings['releaseDateAsVersion'] != null) { + additionalSettings.remove('releaseDateAsVersion'); + } + } + // Ensure additionalSettings are correctly typed + for (var item in formItems) { + if (additionalSettings[item.key] != null) { + additionalSettings[item.key] = + item.ensureType(additionalSettings[item.key]); + } + } + int preferredApkIndex = + json['preferredApkIndex'] == null ? 0 : json['preferredApkIndex'] as int; + if (preferredApkIndex < 0) { + preferredApkIndex = 0; + } + json['preferredApkIndex'] = preferredApkIndex; + // apkUrls can either be old list or new named list apkUrls + List> apkUrls = []; + if (json['apkUrls'] != null) { + var apkUrlJson = jsonDecode(json['apkUrls']); + try { + apkUrls = getApkUrlsFromUrls(List.from(apkUrlJson)); + } catch (e) { + apkUrls = assumed2DlistToStringMapList(List.from(apkUrlJson)); + apkUrls = List.from(apkUrlJson) + .map((e) => MapEntry(e[0] as String, e[1] as String)) + .toList(); + } + json['apkUrls'] = jsonEncode(stringMapListTo2DList(apkUrls)); + } + // Arch based APK filter option should be disabled if it previously did not exist + if (additionalSettings['autoApkFilterByArch'] == null) { + additionalSettings['autoApkFilterByArch'] = false; + } + json['additionalSettings'] = jsonEncode(additionalSettings); + // F-Droid no longer needs cloudflare exception since override can be used - migrate apps appropriately + // This allows us to reverse the changes made for issue #418 (support cloudflare.f-droid) + // While not causing problems for existing apps from that source that were added in a previous version + var overrideSourceWasUndefined = !json.keys.contains('overrideSource'); + if ((json['url'] as String).startsWith('https://cloudflare.f-droid.org')) { + json['overrideSource'] = FDroid().runtimeType.toString(); + } else if (overrideSourceWasUndefined) { + // Similar to above, but for third-party F-Droid repos + RegExpMatch? match = RegExp('^https?://.+/fdroid/([^/]+(/|\\?)|[^/]+\$)') + .firstMatch(json['url'] as String); + if (match != null) { + json['overrideSource'] = FDroidRepo().runtimeType.toString(); + } + } + return json; +} + class App { late String id; late String url; @@ -59,6 +159,7 @@ class App { List categories; late DateTime? releaseDate; late String? changeLog; + late String? overrideSource; App( this.id, this.url, @@ -73,7 +174,8 @@ class App { this.pinned, {this.categories = const [], this.releaseDate, - this.changeLog}); + this.changeLog, + this.overrideSource}); @override String toString() { @@ -103,80 +205,11 @@ class App { pinned, categories: categories, changeLog: changeLog, - releaseDate: releaseDate); + releaseDate: releaseDate, + overrideSource: overrideSource); factory App.fromJson(Map json) { - var source = SourceProvider().getSource(json['url']); - var formItems = source.combinedAppSpecificSettingFormItems - .reduce((value, element) => [...value, ...element]); - Map additionalSettings = - getDefaultValuesFromFormItems([formItems]); - if (json['additionalSettings'] != null) { - additionalSettings.addEntries( - Map.from(jsonDecode(json['additionalSettings'])) - .entries); - } - // If needed, migrate old-style additionalData to newer-style additionalSettings (V1) - if (json['additionalData'] != null) { - List temp = List.from(jsonDecode(json['additionalData'])); - temp.asMap().forEach((i, value) { - if (i < formItems.length) { - if (formItems[i] is GeneratedFormSwitch) { - additionalSettings[formItems[i].key] = value == 'true'; - } else { - additionalSettings[formItems[i].key] = value; - } - } - }); - additionalSettings['trackOnly'] = - json['trackOnly'] == 'true' || json['trackOnly'] == true; - additionalSettings['noVersionDetection'] = - json['noVersionDetection'] == 'true' || json['trackOnly'] == true; - } - // Convert bool style version detection options to dropdown style - if (additionalSettings['noVersionDetection'] == true) { - additionalSettings['versionDetection'] = 'noVersionDetection'; - if (additionalSettings['releaseDateAsVersion'] == true) { - additionalSettings['versionDetection'] = 'releaseDateAsVersion'; - additionalSettings.remove('releaseDateAsVersion'); - } - if (additionalSettings['noVersionDetection'] != null) { - additionalSettings.remove('noVersionDetection'); - } - if (additionalSettings['releaseDateAsVersion'] != null) { - additionalSettings.remove('releaseDateAsVersion'); - } - } - // Ensure additionalSettings are correctly typed - for (var item in formItems) { - if (additionalSettings[item.key] != null) { - additionalSettings[item.key] = - item.ensureType(additionalSettings[item.key]); - } - } - int preferredApkIndex = json['preferredApkIndex'] == null - ? 0 - : json['preferredApkIndex'] as int; - if (preferredApkIndex < 0) { - preferredApkIndex = 0; - } - // apkUrls can either be old list or new named list apkUrls - List> apkUrls = []; - if (json['apkUrls'] != null) { - var apkUrlJson = jsonDecode(json['apkUrls']); - try { - apkUrls = getApkUrlsFromUrls(List.from(apkUrlJson)); - } catch (e) { - apkUrls = List.from(apkUrlJson) - .map((e) => MapEntry(e[0] as String, e[1] as String)) - .toList(); - } - } - // Arch based APK filter option should be disabled if it previously did not exist - if (json['additionalSettings'] != null && - jsonDecode(json['additionalSettings'])['autoApkFilterByArch'] == null) { - additionalSettings['autoApkFilterByArch'] = false; - } + json = appJSONCompatibilityModifiers(json); return App( json['id'] as String, json['url'] as String, @@ -186,9 +219,9 @@ class App { ? null : json['installedVersion'] as String, json['latestVersion'] as String, - apkUrls, - preferredApkIndex, - additionalSettings, + assumed2DlistToStringMapList(jsonDecode(json['apkUrls'])), + json['preferredApkIndex'] as int, + jsonDecode(json['additionalSettings']) as Map, json['lastUpdateCheck'] == null ? null : DateTime.fromMicrosecondsSinceEpoch(json['lastUpdateCheck']), @@ -204,7 +237,8 @@ class App { ? null : DateTime.fromMicrosecondsSinceEpoch(json['releaseDate']), changeLog: - json['changeLog'] == null ? null : json['changeLog'] as String); + json['changeLog'] == null ? null : json['changeLog'] as String, + overrideSource: json['overrideSource']); } Map toJson() => { @@ -214,14 +248,15 @@ class App { 'name': name, 'installedVersion': installedVersion, 'latestVersion': latestVersion, - 'apkUrls': jsonEncode(apkUrls.map((e) => [e.key, e.value]).toList()), + 'apkUrls': jsonEncode(stringMapListTo2DList(apkUrls)), 'preferredApkIndex': preferredApkIndex, 'additionalSettings': jsonEncode(additionalSettings), 'lastUpdateCheck': lastUpdateCheck?.microsecondsSinceEpoch, 'pinned': pinned, 'categories': categories, 'releaseDate': releaseDate?.microsecondsSinceEpoch, - 'changeLog': changeLog + 'changeLog': changeLog, + 'overrideSource': overrideSource }; } @@ -273,8 +308,9 @@ List> getApkUrlsFromUrls(List urls) => return MapEntry(apkSegs.isNotEmpty ? apkSegs.last : segments.last, e); }).toList(); -class AppSource { +abstract class AppSource { String? host; + bool hostChanged = false; late String name; bool enforceTrackOnly = false; bool changeLogIfAnyIsMarkDown = true; @@ -283,7 +319,15 @@ class AppSource { name = runtimeType.toString(); } - String standardizeURL(String url) { + String standardizeUrl(String url) { + url = preStandardizeUrl(url); + if (!hostChanged) { + url = sourceSpecificStandardizeURL(url); + } + return url; + } + + String sourceSpecificStandardizeURL(String url) { throw NotImplementedError(); } @@ -389,33 +433,44 @@ regExValidator(String? value) { class SourceProvider { // Add more source classes here so they are available via the service - List sources = [ - GitHub(), - GitLab(), - Codeberg(), - FDroid(), - IzzyOnDroid(), - FDroidRepo(), - SourceForge(), - APKMirror(), - Mullvad(), - Signal(), - VLC(), - // WhatsApp(), // As of 2023-03-20 this is unusable as the version on the webpage is months out of date - TelegramApp(), - SteamMobile(), - NeutronCode(), - HTML() // This should ALWAYS be the last option as they are tried in order - ]; + List get sources => [ + GitHub(), + GitLab(), + Codeberg(), + FDroid(), + IzzyOnDroid(), + FDroidRepo(), + SourceForge(), + APKMirror(), + Mullvad(), + Signal(), + VLC(), + // WhatsApp(), // As of 2023-03-20 this is unusable as the version on the webpage is months out of date + TelegramApp(), + SteamMobile(), + NeutronCode(), + HTML() // This should ALWAYS be the last option as they are tried in order + ]; // Add more mass url source classes here so they are available via the service List massUrlSources = [GitHubStars()]; - AppSource getSource(String url) { + AppSource getSource(String url, {String? overrideSource}) { url = preStandardizeUrl(url); + if (overrideSource != null) { + var srcs = + sources.where((e) => e.runtimeType.toString() == overrideSource); + if (srcs.isEmpty) { + throw UnsupportedURLError(); + } + var res = srcs.first; + res.host = Uri.parse(url).host; + res.hostChanged = true; + return srcs.first; + } AppSource? source; for (var s in sources.where((element) => element.host != null)) { - if (RegExp('://(.+\\.)?${s.host}').hasMatch(url)) { + if (RegExp('://${s.host}').hasMatch(url)) { source = s; break; } @@ -423,7 +478,7 @@ class SourceProvider { if (source == null) { for (var s in sources.where((element) => element.host == null)) { try { - s.standardizeURL(url); + s.sourceSpecificStandardizeURL(url); source = s; break; } catch (e) { @@ -459,12 +514,14 @@ class SourceProvider { Future getApp( AppSource source, String url, Map additionalSettings, - {App? currentApp, bool trackOnlyOverride = false}) async { + {App? currentApp, + bool trackOnlyOverride = false, + String? overrideSource}) async { if (trackOnlyOverride || source.enforceTrackOnly) { additionalSettings['trackOnly'] = true; } var trackOnly = additionalSettings['trackOnly'] == true; - String standardUrl = source.standardizeURL(preStandardizeUrl(url)); + String standardUrl = source.standardizeUrl(url); APKDetails apk = await source.getLatestAPKDetails(standardUrl, additionalSettings); if (additionalSettings['versionDetection'] == 'releaseDateAsVersion' && @@ -514,7 +571,8 @@ class SourceProvider { currentApp?.pinned ?? false, categories: currentApp?.categories ?? const [], releaseDate: apk.releaseDate, - changeLog: apk.changeLog); + changeLog: apk.changeLog, + overrideSource: overrideSource ?? currentApp?.overrideSource); } // Returns errors in [results, errors] instead of throwing them diff --git a/pubspec.yaml b/pubspec.yaml index 9fd310d..e62f283 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.11.36+158 # When changing this, update the tag in main() accordingly +version: 0.12.0+159 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 81f66683d2ac721079a019d32988fed35eac3fb1 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 00:02:23 -0400 Subject: [PATCH 156/600] 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 157/600] 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 158/600] 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' From 8b123acdcd303f48861cc251f7fb7498caf3802a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 02:23:53 -0400 Subject: [PATCH 159/600] Switched to synchronous install plugin --- README.md | 1 - android/app/src/main/AndroidManifest.xml | 14 +++ android/app/src/main/res/xml/file_paths.xml | 1 + lib/custom_errors.dart | 6 + lib/main.dart | 2 +- lib/providers/apps_provider.dart | 122 ++++++++------------ pubspec.lock | 17 +-- pubspec.yaml | 7 +- 8 files changed, 81 insertions(+), 89 deletions(-) diff --git a/README.md b/README.md index 0b30e18..57ba978 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,6 @@ Currently supported App sources: height="80">](https://apt.izzysoft.de/fdroid/index/apk/dev.imranr.obtainium) ## Limitations -- App installs happen asynchronously and the success/failure of an install cannot be determined directly. This results in install statuses and versions sometimes being out of sync with the OS until the next launch or until the problem is manually corrected. - Auto (unattended) updates are unsupported due to a lack of any capable Flutter plugin. - For some sources, data is gathered using Web scraping and can easily break due to changes in website design. In such cases, more reliable methods may be unavailable. diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 8b78ce2..35f7597 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -25,6 +25,11 @@ + + + @@ -46,9 +51,18 @@ + + + + diff --git a/android/app/src/main/res/xml/file_paths.xml b/android/app/src/main/res/xml/file_paths.xml index 670a26f..d0973ae 100644 --- a/android/app/src/main/res/xml/file_paths.xml +++ b/android/app/src/main/res/xml/file_paths.xml @@ -2,4 +2,5 @@ + \ No newline at end of file diff --git a/lib/custom_errors.dart b/lib/custom_errors.dart index a049170..99970ea 100644 --- a/lib/custom_errors.dart +++ b/lib/custom_errors.dart @@ -1,3 +1,4 @@ +import 'package:android_package_installer/android_package_installer.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:obtainium/providers/logs_provider.dart'; @@ -44,6 +45,11 @@ class DowngradeError extends ObtainiumError { DowngradeError() : super(tr('cantInstallOlderVersion')); } +class InstallError extends ObtainiumError { + InstallError(int code) + : super(PackageInstallerStatus.byCode(code).name.substring(7)); +} + class IDChangedError extends ObtainiumError { IDChangedError() : super(tr('appIdMismatch')); } diff --git a/lib/main.dart b/lib/main.dart index e17f836..8b4973e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.12.0'; +const String currentVersion = '0.12.1'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index aff7412..f5738f7 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -6,11 +6,11 @@ import 'dart:convert'; import 'dart:io'; import 'package:android_intent_plus/flag.dart'; +import 'package:android_package_installer/android_package_installer.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:install_plugin_v2/install_plugin_v2.dart'; import 'package:installed_apps/app_info.dart'; import 'package:installed_apps/installed_apps.dart'; import 'package:obtainium/components/generated_form.dart'; @@ -268,7 +268,8 @@ class AppsProvider with ChangeNotifier { // So we only know that the install prompt was shown, but the user could still cancel w/o us knowing // If appropriate criteria are met, the update (never a fresh install) happens silently in the background // But even then, we don't know if it actually succeeded - Future installApk(DownloadedApk file) async { + Future installApk(DownloadedApk file, {bool silent = false}) async { + // TODO: Use 'silent' when/if ever possible var newInfo = await PackageArchiveInfo.fromPath(file.file.path); AppInfo? appInfo; try { @@ -281,16 +282,15 @@ class AppsProvider with ChangeNotifier { !(await canDowngradeApps())) { throw DowngradeError(); } - await InstallPlugin.installApk(file.file.path, obtainiumId); - if (file.appId == obtainiumId) { - // Obtainium prompt should be lowest - await Future.delayed(const Duration(milliseconds: 500)); + int? code = + await AndroidPackageInstaller.installApk(apkFilePath: file.file.path); + if (code != null && code != 0 && code != 3) { + throw InstallError(code); + } else if (code == 0) { + apps[file.appId]!.app.installedVersion = + apps[file.appId]!.app.latestVersion; } - apps[file.appId]!.app.installedVersion = - apps[file.appId]!.app.latestVersion; - // Don't correct install status as installation may not be done yet - await saveApps([apps[file.appId]!.app], - attemptToCorrectInstallStatus: false); + await saveApps([apps[file.appId]!.app]); } void uninstallApp(String appId) async { @@ -395,76 +395,44 @@ class AppsProvider with ChangeNotifier { a.installedVersion = a.latestVersion; return a; }).toList()); - // Download APKs for all Apps to be installed + + // Prepare to download+install Apps MultiAppMultiError errors = MultiAppMultiError(); - List downloadedFiles = - await Future.wait(appsToInstall.map((id) async { + List installedIds = []; + + // Move Obtainium to the end of the line (let all other apps update first) + String? temp; + appsToInstall.removeWhere((element) { + bool res = element == obtainiumId || element == obtainiumTempId; + if (res) { + temp = element; + } + return res; + }); + if (temp != null) { + appsToInstall = [...appsToInstall, temp!]; + } + + for (var id in appsToInstall) { try { - return await downloadApp(apps[id]!.app, context); + // ignore: use_build_context_synchronously + var downloadedFile = await downloadApp(apps[id]!.app, context); + bool willBeSilent = + await canInstallSilently(apps[downloadedFile.appId]!.app); + willBeSilent = false; // TODO: Remove this when silent updates work + if (!(await settingsProvider?.getInstallPermission(enforce: false) ?? + true)) { + throw ObtainiumError(tr('cancelled')); + } + if (!willBeSilent && context != null) { + // ignore: use_build_context_synchronously + await waitForUserToReturnToForeground(context); + } + await installApk(downloadedFile, silent: willBeSilent); + installedIds.add(id); } catch (e) { errors.add(id, e.toString()); } - return null; - })); - downloadedFiles = - downloadedFiles.where((element) => element != null).toList(); - // Separate the Apps to install into silent and regular lists - List silentUpdates = []; - List regularInstalls = []; - for (var f in downloadedFiles) { - bool willBeSilent = await canInstallSilently(apps[f!.appId]!.app); - if (willBeSilent) { - silentUpdates.add(f); - } else { - regularInstalls.add(f); - } - } - - // Move everything to the regular install list (since silent updates don't currently work) - // TODO: Remove this when silent updates work - regularInstalls.addAll(silentUpdates); - - // If Obtainium is being installed, it should be the last one - List moveObtainiumToStart(List items) { - DownloadedApk? temp; - items.removeWhere((element) { - bool res = - element.appId == obtainiumId || element.appId == obtainiumTempId; - if (res) { - temp = element; - } - return res; - }); - if (temp != null) { - items = [temp!, ...items]; - } - return items; - } - - 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 - // } - - // Do regular installs - if (regularInstalls.isNotEmpty && context != null) { - // ignore: use_build_context_synchronously - await waitForUserToReturnToForeground(context); - for (var i in regularInstalls) { - try { - await installApk(i); - } catch (e) { - errors.add(i.appId, e.toString()); - } - } } if (errors.content.isNotEmpty) { @@ -473,7 +441,7 @@ class AppsProvider with ChangeNotifier { NotificationsProvider().cancel(UpdateNotification([]).id); - return downloadedFiles.map((e) => e!.appId).toList(); + return installedIds; } Future getAppsDir() async { diff --git a/pubspec.lock b/pubspec.lock index 15a9746..a3fbae7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -17,6 +17,15 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.9" + android_package_installer: + dependency: "direct main" + description: + path: "." + ref: main + resolved-ref: f09c79eee5be3c60b04760143eb954a13fdd07f1 + url: "https://github.com/ImranR98/android_package_installer" + source: git + version: "0.0.1" animations: dependency: "direct main" description: @@ -293,14 +302,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" - install_plugin_v2: - dependency: "direct main" - description: - name: install_plugin_v2 - sha256: d6b014637e7a53839e9c5a254f9fd9bb8866392c6db1f16184ce17818cc2d979 - url: "https://pub.dev" - source: hosted - version: "1.0.0" installed_apps: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index e817d41..008567c 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+160 # When changing this, update the tag in main() accordingly +version: 0.12.1+161 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' @@ -51,7 +51,10 @@ dependencies: device_info_plus: ^8.0.0 file_picker: ^5.2.10 animations: ^2.0.4 - install_plugin_v2: ^1.0.0 + android_package_installer: + git: + url: https://github.com/ImranR98/android_package_installer + ref: main share_plus: ^6.0.1 installed_apps: ^1.3.1 package_archive_info: ^0.1.0 From 08586870fb287215ea8fbcda480fd3ebf6edaae6 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 02:28:14 -0400 Subject: [PATCH 160/600] Tweak use of attemptToCorrectInstallStatus --- lib/providers/apps_provider.dart | 2 +- lib/providers/settings_provider.dart | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index f5738f7..4173ee2 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -730,7 +730,7 @@ class AppsProvider with ChangeNotifier { apps[i].installedVersion = null; } } - await saveApps(apps, attemptToCorrectInstallStatus: false); + await saveApps(apps, attemptToCorrectInstallStatus: !remove); } if (remove) { await removeApps(apps.map((e) => e.id).toList()); diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 6c08d5f..872a083 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -206,8 +206,7 @@ class SettingsProvider with ChangeNotifier { .map((e) => e as App) .toList(); if (changedApps.isNotEmpty) { - appsProvider.saveApps(changedApps, - attemptToCorrectInstallStatus: false); + appsProvider.saveApps(changedApps); } } prefs?.setString('categories', jsonEncode(cats)); From 7c592756fe9c32b5fc23413c3db266bd8ed2b295 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 02:47:53 -0400 Subject: [PATCH 161/600] Smarter APK caching (#459) --- lib/providers/apps_provider.dart | 36 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 4173ee2..4dd7668 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -113,21 +113,20 @@ class AppsProvider with ChangeNotifier { () async { // Load Apps into memory (in background, this is done later instead of in the constructor) await loadApps(); - // Delete existing APKs - (await getExternalStorageDirectory()) - ?.listSync() - .where((element) => - element.path.endsWith('.apk') || - element.path.endsWith('.apk.part')) - .forEach((apk) { - apk.delete(); + // Delete any partial APKs + (await getExternalCacheDirectories()) + ?.first + .listSync() + .where((element) => element.path.endsWith('.apk.part')) + .forEach((partialApk) { + partialApk.delete(); }); }(); } downloadFile(String url, String fileName, Function? onProgress, {bool useExisting = true}) async { - var destDir = (await getExternalStorageDirectory())!.path; + var destDir = (await getExternalCacheDirectories())!.first.path; StreamedResponse response = await Client().send(Request('GET', Uri.parse(url))); File downloadedFile = File('$destDir/$fileName'); @@ -191,15 +190,6 @@ class AppsProvider with ChangeNotifier { } prevProg = prog; }); - // Delete older versions of the APK if any - for (var file in downloadedFile.parent.listSync()) { - var fn = file.path.split('/').last; - if (fn.startsWith('${app.id}-') && - fn.endsWith('.apk') && - fn != fileName) { - file.delete(); - } - } // If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed // The former case should be handled (give the App its real ID), the latter is a security issue var newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); @@ -217,6 +207,15 @@ class AppsProvider with ChangeNotifier { await saveApps([app], onlyIfExists: !isTempId); } } + // Delete older versions of the APK if any + for (var file in downloadedFile.parent.listSync()) { + var fn = file.path.split('/').last; + if (fn.startsWith('${app.id}-') && + fn.endsWith('.apk') && + fn != fileName) { + file.delete(); + } + } return DownloadedApk(app.id, downloadedFile); } finally { notificationsProvider?.cancel(notifId); @@ -289,6 +288,7 @@ class AppsProvider with ChangeNotifier { } else if (code == 0) { apps[file.appId]!.app.installedVersion = apps[file.appId]!.app.latestVersion; + file.file.delete(); } await saveApps([apps[file.appId]!.app]); } From 9469d561447d9e653e49d2f3de8f6b35e6a85ba0 Mon Sep 17 00:00:00 2001 From: PhoDit Date: Sun, 30 Apr 2023 11:37:07 +0200 Subject: [PATCH 162/600] Spanish translations --- assets/translations/es.json | 279 ++++++++++++++++++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 assets/translations/es.json diff --git a/assets/translations/es.json b/assets/translations/es.json new file mode 100644 index 0000000..1f80bac --- /dev/null +++ b/assets/translations/es.json @@ -0,0 +1,279 @@ +{ + "invalidURLForSource": "URL de la aplicación {} no válida", + "noReleaseFound": "No se ha podido encontrar una versión válida", + "noVersionFound": "No se ha podido determinar la versión de la publicación", + "urlMatchesNoSource": "La URL no coincide con ninguna fuente conocida", + "cantInstallOlderVersion": "No se puede instalar una versión previa de la aplicación", + "appIdMismatch": "La ID del paquete descargado no coincide con la ID de la aplicación instalada", + "functionNotImplemented": "Esta clase no ha implementado esta función", + "placeholder": "Espacio reservado", + "someErrors": "Han ocurrido algunos errores", + "unexpectedError": "Error Inesperado", + "ok": "Correcto", + "and": "y", + "startedBgUpdateTask": "Empezada la tarea de comprobación de actualizaciones en segundo plano", + "bgUpdateIgnoreAfterIs": "El parámetro ignoreAfter de la actualización en segundo plano es {}", + "startedActualBGUpdateCheck": "Ha comenzado la comprobación de actualizaciones en segundo plano", + "bgUpdateTaskFinished": "Ha finalizado la comprobación de actualizaciones en segundo plano", + "firstRun": "Esta es la primera ejecución de Obtainium", + "settingUpdateCheckIntervalTo": "Cambiando intervalo de actualización a {}", + "githubPATLabel": "Token de Acceso Personal de GitHub (Reduce tiempos de espera)", + "githubPATHint": "El TAP debe tener este formato: nombre_de_usuario:token", + "githubPATFormat": "nombre_de_usuario:token", + "githubPATLinkText": "Sobre los TAP de GitHub", + "includePrereleases": "Incluir versiones preliminares", + "fallbackToOlderReleases": "Retorceder a versiones previas", + "filterReleaseTitlesByRegEx": "Filtra Títulos de Versiones mediantes Expresiones Regulares", + "invalidRegEx": "Expresión regular inválida", + "noDescription": "Sin descripción", + "cancel": "Cancelar", + "continue": "Continuar", + "requiredInBrackets": "(Requerido)", + "dropdownNoOptsError": "ERROR: EL DESPLEGABLE DEBE TENER AL MENOS UNA OPCIÓN", + "colour": "Color", + "githubStarredRepos": "Repositorios favoritos de GitHub", + "uname": "Nombre de usuario", + "wrongArgNum": "Número de argumentos provistos inválido", + "xIsTrackOnly": "{} es de 'Solo Seguimiento'", + "source": "Origen", + "app": "Aplicación", + "appsFromSourceAreTrackOnly": "Las aplicaciones de este origen son de 'Solo Seguimiento'.", + "youPickedTrackOnly": "Debes seleccionar la opción de 'Solo Seguimiento'.", + "trackOnlyAppDescription": "Se monitorizará la aplicación en busca de actualizaciones, pero Obtainium no será capaz de descargarla o acutalizarla.", + "cancelled": "Cancelado", + "appAlreadyAdded": "Aplicación ya añadida", + "alreadyUpToDateQuestion": "¿Aplicación ya actualizada?", + "addApp": "Añadir Aplicación", + "appSourceURL": "URL de Origen de la Aplicación", + "error": "Error", + "add": "Añadir", + "searchSomeSourcesLabel": "Buscar (Solo Algunas Fuentes)", + "search": "Buscar", + "additionalOptsFor": "Opciones Adicionales para {}", + "supportedSourcesBelow": "Fuentes Soportadas:", + "trackOnlyInBrackets": "(Solo Seguimiento)", + "searchableInBrackets": "(Soporta Búsquedas)", + "appsString": "Aplicaciones", + "noApps": "Sin Aplicaciones", + "noAppsForFilter": "Sin Aplicaciones para Filtrar", + "byX": "Por {}", + "percentProgress": "Progreso: {}%", + "pleaseWait": "Por favor, espere", + "updateAvailable": "Actualización Disponible", + "estimateInBracketsShort": "(Aprox.)", + "notInstalled": "No Instalado", + "estimateInBrackets": "(Aproximado)", + "selectAll": "Seleccionar Todo", + "deselectN": "Deseleccionar {}", + "xWillBeRemovedButRemainInstalled": "{} será borrada de Obtainium pero continuará instalada en el dispositivo.", + "removeSelectedAppsQuestion": "¿Borrar aplicaciones seleccionadas?", + "removeSelectedApps": "Borrar Aplicaciones Seleccionadas", + "updateX": "Actualizar {}", + "installX": "Instalar {}", + "markXTrackOnlyAsUpdated": "Marcar {}\n(Solo Seguimient)\ncomo Actualizada", + "changeX": "Cambiar {}", + "installUpdateApps": "Instalar/Actualizar Aplicaciones", + "installUpdateSelectedApps": "Instalar/Actualizar Aplicaciones Seleccionadas", + "markXSelectedAppsAsUpdated": "¿Marcar {} Aplicaciones Seleccionadas como Actualizadas?", + "no": "No", + "yes": "Sí", + "markSelectedAppsUpdated": "Marcar Aplicaciones Seleccionadas como Actualizadas", + "pinToTop": "Fijar arriba", + "unpinFromTop": "Desfijar de arriba", + "resetInstallStatusForSelectedAppsQuestion": "¿Restuarar Estado de Instalación para las Aplicaciones Seleccionadas?", + "installStatusOfXWillBeResetExplanation": "El estado de instalación de las aplicaciones seleccionadas será restaurado.\n\nEsto puede ser de utilidad cuando la versión de la aplicación mostrada en Obtainium es incorrecta por actualizaciones fallidas u otros motivos.", + "shareSelectedAppURLs": "Compartir URLs de las Aplicaciones Seleccionadas", + "resetInstallStatus": "Restaurar Estado de Instalación", + "more": "Más", + "removeOutdatedFilter": "Elimiar Filtro de Aplicaciones Desactualizado", + "showOutdatedOnly": "Mostrar solo Aplicaciones Desactualizadas", + "filter": "Filtrar", + "filterActive": "Filtrar *", + "filterApps": "Filtrar Actualizaciones", + "appName": "Nombre de la Aplicación", + "author": "Autor", + "upToDateApps": "Aplicaciones Actualizadas", + "nonInstalledApps": "Aplicaciones No Instaladas", + "importExport": "Importar/Exportar", + "settings": "Ajustes", + "exportedTo": "Exportado a {}", + "obtainiumExport": "Exportar Obtainium", + "invalidInput": "Input incorrecto", + "importedX": "Importado {}", + "obtainiumImport": "Importar Obtainium", + "importFromURLList": "Importar desde lista de URLs", + "searchQuery": "Consulta de Búsqueda", + "appURLList": "Lista de URLs de Aplicaciones", + "line": "Línea", + "searchX": "Buscar {}", + "noResults": "Resultados no encontrados", + "importX": "Importar {}", + "importedAppsIdDisclaimer": "Las Aplicaciones Importadas pueden mostrarse incorrectamente como \"No Instalada\".\nPara arreglar esto, reinstálalas a través de Obtainium.\nEsto no debería afectar a los datos de las aplicaciones.\n\nSolo afecta a las URLs y a los métodos de importación mediante terceros.", + "importErrors": "Import Errors", + "importedXOfYApps": "{} de {} Aplicaciones importadas.", + "followingURLsHadErrors": "Las siguientes URLs tuvieron problemas:", + "okay": "Correcto", + "selectURL": "Seleccionar URL", + "selectURLs": "Seleccionar URLs", + "pick": "Escoger", + "theme": "Tema", + "dark": "Oscuro", + "light": "Claro", + "followSystem": "Seguir al Sistema", + "obtainium": "Obtainium", + "materialYou": "Material You", + "useBlackTheme": "Usar tema oscuro con negros puros", + "appSortBy": "Ordenar Aplicaciones Por", + "authorName": "Autor/Nombre", + "nameAuthor": "Nombre/Autor", + "asAdded": "Según se Añadieron", + "appSortOrder": "Orden de Clasificación de Aplicaciones", + "ascending": "Ascendente", + "descending": "Descendente", + "bgUpdateCheckInterval": "Intervalo de Comprobación de Actualizaciones en Segundo Plano", + "neverManualOnly": "Nunca - Solo Manual", + "appearance": "Apariencia", + "showWebInAppView": "Mostrar Vista de la Web de Origen", + "pinUpdates": "Fijar Actualizaciones en la Parte Superior de la Vista de Aplicaciones", + "updates": "Actualizaciones", + "sourceSpecific": "Fuente Específica", + "appSource": "Fuente de la Aplicación", + "noLogs": "Sin Logs", + "appLogs": "Logs de la Aplicación", + "close": "Cerrar", + "share": "Compartir", + "appNotFound": "Aplicación no encontrada", + "obtainiumExportHyphenatedLowercase": "obtainium-export", + "pickAnAPK": "Elige una APK", + "appHasMoreThanOnePackage": "{} tiene más de un paquete:", + "deviceSupportsXArch": "Tu dispositivo soporta las siguientes arquitecturas de procesador: {}.", + "deviceSupportsFollowingArchs": "Tu dispositivo soporta las siguientes arquitecturas de procesador:", + "warning": "Aviso", + "sourceIsXButPackageFromYPrompt": "La fuente de la aplicación es '{}' pero el paquete de la actualización viene de '{}'. ¿Desea continuar?", + "updatesAvailable": "Actualizaciones Disponibles", + "updatesAvailableNotifDescription": "Notifica al usuario de que hay actualizaciones para una o más aplicaciones monitorizadas por Obtainium", + "noNewUpdates": "No hay nuevas actualizaciones.", + "xHasAnUpdate": "{} tiene una actualización.", + "appsUpdated": "Aplicaciones Actualizadas", + "appsUpdatedNotifDescription": "Notifica al usuario de que una o más aplicaciones han sido actualizadas en segundo plano", + "xWasUpdatedToY": "{} ha sido actualizada a {}.", + "errorCheckingUpdates": "Error Buscando Actualizaciones", + "errorCheckingUpdatesNotifDescription": "Una notificación que muestra cuándo la comprobación de actualizaciones en segundo plano falla", + "appsRemoved": "Aplicaciones Eliminadas", + "appsRemovedNotifDescription": "Notifica al usuario que una o más aplicaciones fueron eliminadas por problemas al cargarlas", + "xWasRemovedDueToErrorY": "{} ha sido eliminada por: {}", + "completeAppInstallation": "Instalación Completa de la Aplicación", + "obtainiumMustBeOpenToInstallApps": "Obtainium debe estar abierta para instalar aplicaciones", + "completeAppInstallationNotifDescription": "Pide al usuario volver a Obtainium para teminar de instalar una aplicación", + "checkingForUpdates": "Buscando Actualizaciones", + "checkingForUpdatesNotifDescription": "Notificación temporal que aparece al buscar actualizaciones", + "pleaseAllowInstallPerm": "Por favor, permite a Obtainium instalar aplicaciones", + "trackOnly": "Solo Seguimiento", + "errorWithHttpStatusCode": "Error {}", + "versionCorrectionDisabled": "Corrección de versiones desactivada (el plugin parece no funcionar)", + "unknown": "Desconocido", + "none": "Ninguno", + "never": "Nunca", + "latestVersionX": "Última Versión: {}", + "installedVersionX": "Versión Instalada: {}", + "lastUpdateCheckX": "Última Comprobación: {}", + "remove": "Eliminar", + "yesMarkUpdated": "Sí, Marcar como Actualizada", + "fdroid": "Repositorio oficial de F-Droid", + "appIdOrName": "ID o Nombre de la Aplicación", + "appWithIdOrNameNotFound": "No se han encontrado aplicaciones con esa ID o nombre", + "reposHaveMultipleApps": "Los repositorios pueden contener varias aplicaciones", + "fdroidThirdPartyRepo": "Rpositorios de terceros de F-Droid", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Chat", + "install": "Instalar", + "markInstalled": "Marcar como Instalda", + "update": "Actualizar", + "markUpdated": "Marcar como Actualizada", + "additionalOptions": "Opciones Adicionales", + "disableVersionDetection": "Descativar Detección de Versiones", + "noVersionDetectionExplanation": "Esta opción solo se debe usar en aplicaciones en las que la deteción de versiones pueda no funcionar correctamente.", + "downloadingX": "Descargando {}", + "downloadNotifDescription": "Notifica al usuario de progreso de descarga de una aplicación", + "noAPKFound": "APK no encontrada", + "noVersionDetection": "Sin detección de versiones", + "categorize": "Catogorizar", + "categories": "Categorías", + "category": "Categoría", + "noCategory": "Sin Categoría", + "noCategories": "Sin Categorías", + "deleteCategoriesQuestion": "¿Borrar Categorías?", + "categoryDeleteWarning": "Todas las aplicaciones en las categorías borradas serán margadas como 'Sin Categoría'.", + "addCategory": "Añadir Categoría", + "label": "Nombre", + "language": "Idioma", + "copiedToClipboard": "Copiado al Portapapeles", + "storagePermissionDenied": "Permiso de Almacenamiento rechazado", + "selectedCategorizeWarning": "Esto reemplazará cualquier ajuste de categoría para las aplicaicones seleccionadas.", + "filterAPKsByRegEx": "Filtrar APKs mediante Expresiones Regulares", + "removeFromObtainium": "Eliminar de Obtainium", + "uninstallFromDevice": "Desinstalar del Dispositivo", + "onlyWorksWithNonVersionDetectApps": "Solo funciona para aplicaciones con la detección de versiones desactivada.", + "releaseDateAsVersion": "Usar Fecha de Publicación como Versión", + "releaseDateAsVersionExplanation": "Esta opción solo se debería usar con aplicaciones en las que la detección de versiones no funciona pero hay disponible una fecha de publicación.", + "changes": "Cambios", + "releaseDate": "Fecha de Publicación", + "importFromURLsInFile": "Importar de URls en un Archivo (como OPML)", + "versionDetection": "Detección de Versiones", + "standardVersionDetection": "Detección de versiones estándar", + "groupByCategory": "Agrupar por Categoría", + "autoApkFilterByArch": "Tratar de filtrar las APKs mediante arquitecturas de procesador si es posible", + "overrideSource": "Sobrescribir Fuente", + "dontShowAgain": "No mostrar de nuevo", + "dontShowTrackOnlyWarnings": "No mostrar avisos de 'Solo Seguimiento'", + "dontShowAPKOriginWarnings": "No mostrar avisos de las fuentes de las APks", + "removeAppQuestion": { + "one": "¿Eliminar Aplicación?", + "other": "¿Eliminar Aplicaciones?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Muchas peticiones (limitado) - prueba de nuevo en {} minuto", + "other": "Muchas peticiones (limitado) - prueba de nuevo en {} minutos" + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "La comprobación de actualizaciones en segundo plano se ha encontrado un {}, se volverá a probar en {} minuto", + "other": "La comprobación de actualizaciones en segundo plano se ha encontrado un {}, se volverá a probar en {} minutos" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "La comprobación de actualizaciones en segundo plano ha encontrado {} actualización - se notificará al usuario si es necesario", + "other": "La comprobación de actualizaciones en segundo plano ha encontrado {} actualizaciones - se notificará al usuario si es necesario" + }, + "apps": { + "one": "{} Aplicación", + "other": "{} Aplicaciones" + }, + "url": { + "one": "{} URL", + "other": "{} URLs" + }, + "minute": { + "one": "{} Minuto", + "other": "{} Minutos" + }, + "hour": { + "one": "{} Hora", + "other": "{} Horas" + }, + "day": { + "one": "{} Día", + "other": "{} Días" + }, + "clearedNLogsBeforeXAfterY": { + "one": "Borrado {n} log (previo a = {before}, posterior a = {after})", + "other": "Borrados {n} logs (previos a = {before}, posteriores a = {after})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "{} y 1 aplicación más tiene actualizaciones.", + "other": "{} y {} aplicaciones más tiene actualizaciones." + }, + "xAndNMoreUpdatesInstalled": { + "one": "{} y 1 aplicación más han sido actualizadas.", + "other": "{} y {} aplicaciones más han sido actualizadas." + } +} From 73d04b15648d7dc31c78afcf153a095753a6a243 Mon Sep 17 00:00:00 2001 From: gidano Date: Sun, 30 Apr 2023 16:09:15 +0200 Subject: [PATCH 163/600] Update hu.json --- assets/translations/hu.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 0355e37..f1ed8d2 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -223,10 +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", + "overrideSource": "Forrás felülbírálása", + "dontShowAgain": "Ne mutassa ezt újra", + "dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést", + "dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From 03b592521c46a4e9a8053519eb9af165f6c03797 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 15:39:21 -0400 Subject: [PATCH 164/600] Fixed link sorting for HTML Source --- lib/app_sources/html.dart | 63 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index ece1796..c4c039f 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -10,6 +10,66 @@ class HTML extends AppSource { return url; } + int compareAlphaNumeric(String a, String b) { + List aParts = _splitAlphaNumeric(a); + List bParts = _splitAlphaNumeric(b); + + for (int i = 0; i < aParts.length && i < bParts.length; i++) { + String aPart = aParts[i]; + String bPart = bParts[i]; + + bool aIsNumber = _isNumeric(aPart); + bool bIsNumber = _isNumeric(bPart); + + if (aIsNumber && bIsNumber) { + int aNumber = int.parse(aPart); + int bNumber = int.parse(bPart); + int cmp = aNumber.compareTo(bNumber); + if (cmp != 0) { + return cmp; + } + } else if (!aIsNumber && !bIsNumber) { + int cmp = aPart.compareTo(bPart); + if (cmp != 0) { + return cmp; + } + } else { + // Alphanumeric strings come before numeric strings + return aIsNumber ? 1 : -1; + } + } + + return aParts.length.compareTo(bParts.length); + } + + List _splitAlphaNumeric(String s) { + List parts = []; + StringBuffer sb = StringBuffer(); + + bool isNumeric = _isNumeric(s[0]); + sb.write(s[0]); + + for (int i = 1; i < s.length; i++) { + bool currentIsNumeric = _isNumeric(s[i]); + if (currentIsNumeric == isNumeric) { + sb.write(s[i]); + } else { + parts.add(sb.toString()); + sb.clear(); + sb.write(s[i]); + isNumeric = currentIsNumeric; + } + } + + parts.add(sb.toString()); + + return parts; + } + + bool _isNumeric(String s) { + return s.codeUnitAt(0) >= 48 && s.codeUnitAt(0) <= 57; + } + @override Future getLatestAPKDetails( String standardUrl, @@ -23,7 +83,8 @@ class HTML extends AppSource { .map((element) => element.attributes['href'] ?? '') .where((element) => element.toLowerCase().endsWith('.apk')) .toList(); - links.sort((a, b) => a.split('/').last.compareTo(b.split('/').last)); + links.sort( + (a, b) => compareAlphaNumeric(a.split('/').last, b.split('/').last)); if (additionalSettings['apkFilterRegEx'] != null) { var reg = RegExp(additionalSettings['apkFilterRegEx']); links = links.where((element) => reg.hasMatch(element)).toList(); From 36273fe02df9fd8dcb6f18c61cfd22e8f538ad41 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 15:49:25 -0400 Subject: [PATCH 165/600] Switch to apps tab after app added (#508) --- lib/pages/home.dart | 58 +++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/lib/pages/home.dart b/lib/pages/home.dart index d233297..a830b1a 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -6,6 +6,8 @@ import 'package:obtainium/pages/add_app.dart'; import 'package:obtainium/pages/apps.dart'; import 'package:obtainium/pages/import_export.dart'; import 'package:obtainium/pages/settings.dart'; +import 'package:obtainium/providers/apps_provider.dart'; +import 'package:provider/provider.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @@ -24,6 +26,7 @@ class NavigationPageItem { class _HomePageState extends State { List selectedIndexHistory = []; + int prevAppCount = -1; List pages = [ NavigationPageItem(tr('appsString'), Icons.apps, @@ -36,6 +39,39 @@ class _HomePageState extends State { @override Widget build(BuildContext context) { + AppsProvider appsProvider = context.watch(); + + switchToPage(int index) async { + if (index == 0) { + while ((pages[0].widget.key as GlobalKey).currentState != + null) { + // Avoid duplicate GlobalKey error + await Future.delayed(const Duration(microseconds: 1)); + } + setState(() { + selectedIndexHistory.clear(); + }); + } else if (selectedIndexHistory.isEmpty || + (selectedIndexHistory.isNotEmpty && + selectedIndexHistory.last != index)) { + setState(() { + int existingInd = selectedIndexHistory.indexOf(index); + if (existingInd >= 0) { + selectedIndexHistory.removeAt(existingInd); + } + selectedIndexHistory.add(index); + }); + } + } + + if (prevAppCount >= 0 && + appsProvider.apps.length > prevAppCount && + selectedIndexHistory.isNotEmpty && + selectedIndexHistory.last == 1) { + switchToPage(0); + } + prevAppCount = appsProvider.apps.length; + return WillPopScope( child: Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, @@ -65,27 +101,7 @@ class _HomePageState extends State { .toList(), onDestinationSelected: (int index) async { HapticFeedback.selectionClick(); - if (index == 0) { - while ((pages[0].widget.key as GlobalKey) - .currentState != - null) { - // Avoid duplicate GlobalKey error - await Future.delayed(const Duration(microseconds: 1)); - } - setState(() { - selectedIndexHistory.clear(); - }); - } else if (selectedIndexHistory.isEmpty || - (selectedIndexHistory.isNotEmpty && - selectedIndexHistory.last != index)) { - setState(() { - int existingInd = selectedIndexHistory.indexOf(index); - if (existingInd >= 0) { - selectedIndexHistory.removeAt(existingInd); - } - selectedIndexHistory.add(index); - }); - } + await switchToPage(index); }, selectedIndex: selectedIndexHistory.isEmpty ? 0 : selectedIndexHistory.last, From 76e316422c818e776fbb2412959fc5f381da1005 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 16:28:09 -0400 Subject: [PATCH 166/600] Added Jenkins Source (#514) --- lib/app_sources/jenkins.dart | 66 ++++++++++++++++++++++++++++++ lib/providers/source_provider.dart | 2 + 2 files changed, 68 insertions(+) create mode 100644 lib/app_sources/jenkins.dart diff --git a/lib/app_sources/jenkins.dart b/lib/app_sources/jenkins.dart new file mode 100644 index 0000000..a695b68 --- /dev/null +++ b/lib/app_sources/jenkins.dart @@ -0,0 +1,66 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class Jenkins extends AppSource { + @override + String trimJobUrl(String url) { + RegExp standardUrlRegEx = RegExp('.*/job/[^/]+'); + RegExpMatch? match = standardUrlRegEx.firstMatch(url); + if (match == null) { + throw InvalidURLError(name); + } + return url.substring(0, match.end); + } + + @override + String? changeLogPageFromStandardUrl(String standardUrl) => + '$standardUrl/-/releases'; + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + standardUrl = trimJobUrl(standardUrl); + Response res = + await get(Uri.parse('$standardUrl/lastSuccessfulBuild/api/json')); + if (res.statusCode == 200) { + var json = jsonDecode(res.body); + var releaseDate = json['timestamp'] == null + ? null + : DateTime.fromMillisecondsSinceEpoch(json['timestamp'] as int); + var version = + json['number'] == null ? null : (json['number'] as int).toString(); + if (version == null) { + throw NoVersionError(); + } + var apkUrls = (json['artifacts'] as List) + .map((e) { + var path = (e['relativePath'] as String?); + if (path != null && path.isNotEmpty) { + path = '$standardUrl/lastSuccessfulBuild/artifact/$path'; + } + return path == null + ? const MapEntry('', '') + : MapEntry( + (e['fileName'] ?? e['relativePath']) as String, path); + }) + .where((url) => + url.value.isNotEmpty && url.key.toLowerCase().endsWith('.apk')) + .toList(); + if (apkUrls.isEmpty) { + throw NoAPKError(); + } + return APKDetails( + version, + apkUrls, + releaseDate: releaseDate, + AppNames(Uri.parse(standardUrl).host, standardUrl.split('/').last)); + } else { + throw getObtainiumHttpError(res); + } + } +} diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 2606a37..211e87f 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -15,6 +15,7 @@ import 'package:obtainium/app_sources/github.dart'; import 'package:obtainium/app_sources/gitlab.dart'; import 'package:obtainium/app_sources/izzyondroid.dart'; import 'package:obtainium/app_sources/html.dart'; +import 'package:obtainium/app_sources/jenkins.dart'; import 'package:obtainium/app_sources/mullvad.dart'; import 'package:obtainium/app_sources/neutroncode.dart'; import 'package:obtainium/app_sources/signal.dart'; @@ -440,6 +441,7 @@ class SourceProvider { FDroid(), IzzyOnDroid(), FDroidRepo(), + Jenkins(), SourceForge(), APKMirror(), Mullvad(), From 779de58f74fb766ab8b787b52e6e93c8f875211a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 17:00:00 -0400 Subject: [PATCH 167/600] Jenkins uses release dates only + APK delete bugfix --- lib/app_sources/jenkins.dart | 4 ++++ lib/pages/add_app.dart | 4 +++- lib/providers/apps_provider.dart | 2 +- lib/providers/source_provider.dart | 18 +++++++++++++++++- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/app_sources/jenkins.dart b/lib/app_sources/jenkins.dart index a695b68..366b76d 100644 --- a/lib/app_sources/jenkins.dart +++ b/lib/app_sources/jenkins.dart @@ -5,6 +5,10 @@ import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; class Jenkins extends AppSource { + Jenkins() { + overrideVersionDetectionFormDefault('releaseDateAsVersion', true); + } + @override String trimJobUrl(String url) { RegExp standardUrlRegEx = RegExp('.*/job/[^/]+'); diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 768f7e7..a81eb9c 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -166,7 +166,9 @@ class _AddAppPageState extends State { if (appsProvider.apps.containsKey(app.id)) { throw ObtainiumError(tr('appAlreadyAdded')); } - if (app.additionalSettings['trackOnly'] == true) { + if (app.additionalSettings['trackOnly'] == true || + app.additionalSettings['versionDetection'] != + 'standardVersionDetection') { app.installedVersion = app.latestVersion; } app.categories = pickedCategories; diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 4dd7668..9cc445c 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -212,7 +212,7 @@ class AppsProvider with ChangeNotifier { var fn = file.path.split('/').last; if (fn.startsWith('${app.id}-') && fn.endsWith('.apk') && - fn != fileName) { + fn != downloadedFile.path.split('/').last) { file.delete(); } } diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 211e87f..e27cdd8 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -320,6 +320,22 @@ abstract class AppSource { name = runtimeType.toString(); } + overrideVersionDetectionFormDefault(String vd, bool disableStandard) { + additionalAppSpecificSourceAgnosticSettingFormItems = + additionalAppSpecificSourceAgnosticSettingFormItems.map((e) { + return e.map((e2) { + if (e2.key == 'versionDetection') { + var item = e2 as GeneratedFormDropdown; + item.defaultValue = vd; + if (disableStandard) { + item.disabledOptKeys = ['standardVersionDetection']; + } + } + return e2; + }).toList(); + }).toList(); + } + String standardizeUrl(String url) { url = preStandardizeUrl(url); if (!hostChanged) { @@ -342,7 +358,7 @@ abstract class AppSource { []; // Some additional data may be needed for Apps regardless of Source - final List> + List> additionalAppSpecificSourceAgnosticSettingFormItems = [ [ GeneratedFormSwitch( From 9f5f1174ba8ca2780b1ce2958f62fa822d82711f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 17:02:33 -0400 Subject: [PATCH 168/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8b4973e..1c7caa6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.12.1'; +const String currentVersion = '0.12.2'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 008567c..89e6ec6 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.1+161 # When changing this, update the tag in main() accordingly +version: 0.12.2+162 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From f8b326529fbd761414748c5c2e75dfcca8c24854 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 30 Apr 2023 17:03:54 -0400 Subject: [PATCH 169/600] Add Jenkins to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 57ba978..b21d416 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Currently supported App sources: - [SourceForge](https://sourceforge.net/) - [APKMirror](https://apkmirror.com/) (Track-Only) - Third Party F-Droid Repos +- Jenkins Jobs - [Steam](https://store.steampowered.com/mobile) - [Telegram App](https://telegram.org) - [VLC](https://www.videolan.org/vlc/download-android.html) From 0a751cf545f7dddd17190940af388a5adb06655d Mon Sep 17 00:00:00 2001 From: Markus <82206269+markus-gitdev@users.noreply.github.com> Date: Mon, 1 May 2023 13:58:46 +0200 Subject: [PATCH 170/600] Update de.json Correction of "changeX". New translations for: - "overrideSource" - "dontShowAgain" - "dontShowTrackOnlyWarnings" - "dontShowAPKOriginWarnings" --- assets/translations/de.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index f1d1f68..1406cf1 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -71,7 +71,7 @@ "updateX": "Aktualisiere {}", "installX": "Installiere {}", "markXTrackOnlyAsUpdated": "Markiere {}\n(Nur Nachverfolgen)\nals aktualisiert", - "changeX": "Ändern {}", + "changeX": "Ändere {}", "installUpdateApps": "Apps installieren/aktualisieren", "installUpdateSelectedApps": "Ausgewählte Apps installieren/aktualisieren", "markXSelectedAppsAsUpdated": "Markiere {} ausgewählte Apps als aktuell?", @@ -224,10 +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", + "overrideSource": "Quelle überschreiben", + "dontShowAgain": "Nicht noch einmal zeigen", + "dontShowTrackOnlyWarnings": "Warnung für 'Nur Nachverfolgen' nicht anzeigen", + "dontShowAPKOriginWarnings": "Warnung für APK-Herkunft nicht anzeigen", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" From d6366a145eeb561b8468a31281eace764d9f9fba Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Tue, 2 May 2023 13:38:22 +0900 Subject: [PATCH 171/600] Update ja.json --- assets/translations/ja.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 262fffe..f7cbab3 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -122,7 +122,7 @@ "followSystem": "システムに従う", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use pure black dark theme", + "useBlackTheme": "ピュアブラックダークテーマを使用する", "appSortBy": "アプリの並び方", "authorName": "作者名/アプリ名", "nameAuthor": "アプリ名/作者名", @@ -224,10 +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", + "overrideSource": "ソースの上書き", + "dontShowAgain": "二度と表示しない", + "dontShowTrackOnlyWarnings": "「追跡のみ」の警告を表示しない", + "dontShowAPKOriginWarnings": "APK Originの警告を表示しない", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" From 0404449842da317b1c85360da1062fde4e25a029 Mon Sep 17 00:00:00 2001 From: Mehdee <85278288+mehdijahann@users.noreply.github.com> Date: Wed, 3 May 2023 09:03:55 +0800 Subject: [PATCH 172/600] Update fa.json --- assets/translations/fa.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 7b48c7d..64f6989 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -122,7 +122,7 @@ "followSystem": "هماهنگ با سیستم", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use pure black dark theme", + "useBlackTheme": "استفاده از تم تیره سیاه خالص", "appSortBy": "مرتب سازی برنامه بر اساس", "authorName": "سازنده/اسم", "nameAuthor": "اسم/سازنده", @@ -224,10 +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", + "overrideSource": "نادیده گرفتن منبع", + "dontShowAgain": "دوباره این را نشان نده", + "dontShowTrackOnlyWarnings": "هشدار "فقط ردیابی" را نشان ندهید", + "dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" From be9c671a5679b49029d9d8805353d457f88f0b22 Mon Sep 17 00:00:00 2001 From: Mehdee <85278288+mehdijahann@users.noreply.github.com> Date: Wed, 3 May 2023 09:06:44 +0800 Subject: [PATCH 173/600] Update fa.json --- assets/translations/fa.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 64f6989..d0ba5c5 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -226,7 +226,7 @@ "autoApkFilterByArch": "در صورت امکان سعی کنید APKها را بر اساس معماری CPU فیلتر کنید", "overrideSource": "نادیده گرفتن منبع", "dontShowAgain": "دوباره این را نشان نده", - "dontShowTrackOnlyWarnings": "هشدار "فقط ردیابی" را نشان ندهید", + "dontShowTrackOnlyWarnings": "هشدار 'فقط ردیابی' را نشان ندهید", "dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید", "removeAppQuestion": { "one": "برنامه حذف شود؟", From e1980f4de205a847ce2b588a5b72236e9144b3b8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 3 May 2023 17:49:50 -0400 Subject: [PATCH 174/600] SourceForge URL flexibility (#525) --- lib/app_sources/sourceforge.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/app_sources/sourceforge.dart b/lib/app_sources/sourceforge.dart index 2d976ea..ee2f22b 100644 --- a/lib/app_sources/sourceforge.dart +++ b/lib/app_sources/sourceforge.dart @@ -10,8 +10,14 @@ class SourceForge extends AppSource { @override String sourceSpecificStandardizeURL(String url) { - RegExp standardUrlRegEx = RegExp('^https?://$host/projects/[^/]+'); - RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); + RegExp standardUrlRegExB = RegExp('^https?://$host/p/[^/]+'); + RegExpMatch? match = standardUrlRegExB.firstMatch(url.toLowerCase()); + if (match != null) { + url = + 'https://${Uri.parse(url.substring(0, match.end)).host}/projects/${url.substring(Uri.parse(url.substring(0, match.end)).host.length + '/projects/'.length + 1)}'; + } + RegExp standardUrlRegExA = RegExp('^https?://$host/projects/[^/]+'); + match = standardUrlRegExA.firstMatch(url.toLowerCase()); if (match == null) { throw InvalidURLError(name); } From cbec486ad17f12e6f7442922c61a88810feea09e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 3 May 2023 18:00:24 -0400 Subject: [PATCH 175/600] Add language names and enable Spanish --- lib/main.dart | 25 +++++++++++++------------ lib/pages/settings.dart | 4 ++-- lib/providers/settings_provider.dart | 4 ++-- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 1c7caa6..6fa333f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -27,15 +27,16 @@ const String currentReleaseTag = const int bgUpdateCheckAlarmId = 666; -const supportedLocales = [ - Locale('en'), - Locale('zh'), - Locale('it'), - Locale('ja'), - Locale('hu'), - Locale('de'), - Locale('fa'), - Locale('fr') +List> supportedLocales = const [ + MapEntry(Locale('en'), 'English'), + MapEntry(Locale('zh'), '汉语'), + MapEntry(Locale('it'), 'Italiano'), + MapEntry(Locale('ja'), '日本語'), + MapEntry(Locale('hu'), 'Magyar'), + MapEntry(Locale('de'), 'Deutsch'), + MapEntry(Locale('fa'), 'فارسی'), + MapEntry(Locale('fr'), 'Français'), + MapEntry(Locale('es'), 'Español'), ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; @@ -52,7 +53,7 @@ Future loadTranslations() async { saveLocale: true, forceLocale: forceLocale != null ? Locale(forceLocale) : null, fallbackLocale: fallbackLocale, - supportedLocales: supportedLocales, + supportedLocales: supportedLocales.map((e) => e.key).toList(), assetLoader: const RootBundleAssetLoader(), useOnlyLangCode: true, useFallbackTranslations: true, @@ -171,7 +172,7 @@ void main() async { Provider(create: (context) => LogsProvider()) ], child: EasyLocalization( - supportedLocales: supportedLocales, + supportedLocales: supportedLocales.map((e) => e.key).toList(), path: localeDir, fallbackLocale: fallbackLocale, useOnlyLangCode: true, @@ -221,7 +222,7 @@ class _ObtainiumState extends State { ], onlyIfExists: false); } if (!supportedLocales - .map((e) => e.languageCode) + .map((e) => e.key.languageCode) .contains(context.locale.languageCode) || settingsProvider.forcedLocale == null && context.deviceLocale.languageCode != diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index a3808e8..988fe85 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -144,8 +144,8 @@ class _SettingsPageState extends State { child: Text(tr('followSystem')), ), ...supportedLocales.map((e) => DropdownMenuItem( - value: e.toLanguageTag(), - child: Text(e.toLanguageTag().toUpperCase()), + value: e.key.toLanguageTag(), + child: Text(e.value), )) ], onChanged: (value) { diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 872a083..2f03dfb 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -216,7 +216,7 @@ class SettingsProvider with ChangeNotifier { String? get forcedLocale { var fl = prefs?.getString('forcedLocale'); return supportedLocales - .where((element) => element.toLanguageTag() == fl) + .where((element) => element.key.toLanguageTag() == fl) .isNotEmpty ? fl : null; @@ -226,7 +226,7 @@ class SettingsProvider with ChangeNotifier { if (fl == null) { prefs?.remove('forcedLocale'); } else if (supportedLocales - .where((element) => element.toLanguageTag() == fl) + .where((element) => element.key.toLanguageTag() == fl) .isNotEmpty) { prefs?.setString('forcedLocale', fl); } From 1f9c2c16999ae76dddf140e534b25fd6b4993f05 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 3 May 2023 18:00:57 -0400 Subject: [PATCH 176/600] Update packages, increment version --- pubspec.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index a3fbae7..0a80259 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -38,10 +38,10 @@ packages: dependency: transitive description: name: args - sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" + sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" async: dependency: transitive description: @@ -282,18 +282,18 @@ packages: dependency: "direct main" description: name: html - sha256: "79d498e6d6761925a34ee5ea8fa6dfef38607781d2fa91e37523474282af55cb" + sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8" url: "https://pub.dev" source: hosted - version: "0.15.2" + version: "0.15.3" http: dependency: "direct main" description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "0.13.6" http_parser: dependency: transitive description: @@ -338,10 +338,10 @@ packages: dependency: transitive description: name: markdown - sha256: d95a9d12954aafc97f984ca29baaa7690ed4d9ec4140a23ad40580bcdb6c87f5 + sha256: "8e332924094383133cee218b676871f42db2514f1f6ac617b6cf6152a7faab8e" url: "https://pub.dev" source: hosted - version: "7.0.2" + version: "7.1.0" matcher: dependency: transitive description: @@ -791,10 +791,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: d6cf18cd6c809c5a9294cd99707a21986aac4e08c87e1916ce2590315fb55d3a + sha256: "1acea8def62592123e2fbbca164ed8681a98a890bdcbb88f916d5b4a22687759" url: "https://pub.dev" source: hosted - version: "3.6.2" + version: "3.7.0" webview_flutter_platform_interface: dependency: transitive description: @@ -807,10 +807,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: c94d242d8cbe1012c06ba7ac790c46d6e6b68723b7d34f8c74ed19f68d166f49 + sha256: "61f33512810bf1ee9ac89761a4b02663ff64e8227b7dc80654642acd660fd49d" url: "https://pub.dev" source: hosted - version: "3.4.0" + version: "3.4.2" win32: dependency: transitive description: From 9ec345761e8ab24025b99293fca387919cdafbe2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 3 May 2023 18:01:47 -0400 Subject: [PATCH 177/600] Actually increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 6fa333f..056f3cc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.12.2'; +const String currentVersion = '0.12.3'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 89e6ec6..1826128 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.2+162 # When changing this, update the tag in main() accordingly +version: 0.12.3+163 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 639fc20fcb0c28bc51408b5d56d2fe017cbf3ab4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 3 May 2023 18:40:34 -0400 Subject: [PATCH 178/600] Added F-Droid search (#526) + search UI improvements --- lib/app_sources/codeberg.dart | 2 +- lib/app_sources/fdroid.dart | 30 +++++++++++++++++++++++++++ lib/app_sources/github.dart | 18 +++++++++------- lib/mass_app_sources/githubstars.dart | 18 +++++++++------- lib/pages/add_app.dart | 2 +- lib/pages/import_export.dart | 30 +++++++++++++++++++-------- lib/providers/source_provider.dart | 4 ++-- 7 files changed, 76 insertions(+), 28 deletions(-) diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index 382c7f9..a45d620 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -70,7 +70,7 @@ class Codeberg extends AppSource { } @override - Future> search(String query) async { + Future>> search(String query) async { return gh.searchCommon( query, 'https://$host/api/v1/repos/search?q=${Uri.encodeQueryComponent(query)}&limit=100', diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index c9c84e6..318a983 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; +import 'package:html/parser.dart'; import 'package:http/http.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -9,6 +10,7 @@ class FDroid extends AppSource { FDroid() { host = 'f-droid.org'; name = tr('fdroid'); + canSearch = true; } @override @@ -68,4 +70,32 @@ class FDroid extends AppSource { 'https://$host/repo/$appId', standardUrl); } + + @override + Future>> search(String query) async { + Response res = await get(Uri.parse('https://search.$host/?q=$query')); + if (res.statusCode == 200) { + Map> urlsWithDescriptions = {}; + parse(res.body).querySelectorAll('.package-header').forEach((e) { + String? url = e.attributes['href']; + if (url != null) { + try { + standardizeUrl(url); + } catch (e) { + url = null; + } + } + if (url != null) { + urlsWithDescriptions[url] = [ + e.querySelector('.package-name')?.text.trim() ?? '', + e.querySelector('.package-summary')?.text.trim() ?? + tr('noDescription') + ]; + } + }); + return urlsWithDescriptions; + } else { + throw getObtainiumHttpError(res); + } + } } diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 55e1d8b..e6b67ae 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -213,19 +213,21 @@ class GitHub extends AppSource { return AppNames(names[0], names[1]); } - Future> searchCommon( + Future>> searchCommon( String query, String requestUrl, String rootProp, {Function(Response)? onHttpErrorCode}) async { Response res = await get(Uri.parse(requestUrl)); if (res.statusCode == 200) { - Map urlsWithDescriptions = {}; + Map> urlsWithDescriptions = {}; for (var e in (jsonDecode(res.body)[rootProp] as List)) { urlsWithDescriptions.addAll({ - e['html_url'] as String: - ((e['archived'] == true ? '[ARCHIVED] ' : '') + - (e['description'] != null - ? e['description'] as String - : tr('noDescription'))) + e['html_url'] as String: [ + e['full_name'] as String, + ((e['archived'] == true ? '[ARCHIVED] ' : '') + + (e['description'] != null + ? e['description'] as String + : tr('noDescription'))) + ] }); } return urlsWithDescriptions; @@ -238,7 +240,7 @@ class GitHub extends AppSource { } @override - Future> search(String query) async { + Future>> search(String query) async { return searchCommon( query, 'https://${await getCredentialPrefixIfAny()}api.$host/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100', diff --git a/lib/mass_app_sources/githubstars.dart b/lib/mass_app_sources/githubstars.dart index d8ca40e..5a086f1 100644 --- a/lib/mass_app_sources/githubstars.dart +++ b/lib/mass_app_sources/githubstars.dart @@ -13,17 +13,20 @@ class GitHubStars implements MassAppUrlSource { @override late List requiredArgs = [tr('uname')]; - Future> getOnePageOfUserStarredUrlsWithDescriptions( + Future>> getOnePageOfUserStarredUrlsWithDescriptions( String username, int page) async { Response res = await get(Uri.parse( 'https://${await GitHub().getCredentialPrefixIfAny()}api.github.com/users/$username/starred?per_page=100&page=$page')); if (res.statusCode == 200) { - Map urlsWithDescriptions = {}; + Map> urlsWithDescriptions = {}; for (var e in (jsonDecode(res.body) as List)) { urlsWithDescriptions.addAll({ - e['html_url'] as String: e['description'] != null - ? e['description'] as String - : tr('noDescription') + e['html_url'] as String: [ + e['full_name'] as String, + e['description'] != null + ? e['description'] as String + : tr('noDescription') + ] }); } return urlsWithDescriptions; @@ -35,11 +38,12 @@ class GitHubStars implements MassAppUrlSource { } @override - Future> getUrlsWithDescriptions(List args) async { + Future>> getUrlsWithDescriptions( + List args) async { if (args.length != requiredArgs.length) { throw ObtainiumError(tr('wrongArgNum')); } - Map urlsWithDescriptions = {}; + Map> urlsWithDescriptions = {}; var page = 1; while (true) { var pageUrls = diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index a81eb9c..b0654c3 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -254,7 +254,7 @@ class _AddAppPageState extends State { // .then((results) async { // Interleave results instead of simple reduce - Map res = {}; + Map> res = {}; var si = 0; var done = false; while (!done) { diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index d8fe3d2..7a896c9 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -470,7 +470,7 @@ class UrlSelectionModal extends StatefulWidget { this.selectedByDefault = true, this.onlyOneSelectionAllowed = false}); - Map urlsWithDescriptions; + Map> urlsWithDescriptions; bool selectedByDefault; bool onlyOneSelectionAllowed; @@ -479,7 +479,7 @@ class UrlSelectionModal extends StatefulWidget { } class _UrlSelectionModalState extends State { - Map, bool> urlWithDescriptionSelections = {}; + Map>, bool> urlWithDescriptionSelections = {}; @override void initState() { super.initState(); @@ -522,16 +522,28 @@ class _UrlSelectionModalState extends State { launchUrlString(urlWithD.key, mode: LaunchMode.externalApplication); }, - child: Text( - Uri.parse(urlWithD.key).path.substring(1), - style: const TextStyle(decoration: TextDecoration.underline), - textAlign: TextAlign.start, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + urlWithD.value[0], + style: const TextStyle( + decoration: TextDecoration.underline, + fontWeight: FontWeight.bold), + textAlign: TextAlign.start, + ), + Text( + Uri.parse(urlWithD.key).host, + style: const TextStyle( + decoration: TextDecoration.underline, fontSize: 12), + ) + ], )); var descriptionText = Text( - urlWithD.value.length > 128 - ? '${urlWithD.value.substring(0, 128)}...' - : urlWithD.value, + urlWithD.value[1].length > 128 + ? '${urlWithD.value[1].substring(0, 128)}...' + : urlWithD.value[1], style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 12), ); diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index e27cdd8..556c294 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -415,7 +415,7 @@ abstract class AppSource { } bool canSearch = false; - Future> search(String query) { + Future>> search(String query) { throw NotImplementedError(); } @@ -433,7 +433,7 @@ ObtainiumError getObtainiumHttpError(Response res) { abstract class MassAppUrlSource { late String name; late List requiredArgs; - Future> getUrlsWithDescriptions(List args); + Future>> getUrlsWithDescriptions(List args); } regExValidator(String? value) { From fb9e66332df81a8f27a7bdcb69e7c2da2bb26dd0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 5 May 2023 22:35:32 -0400 Subject: [PATCH 179/600] APKPure, SourceHut, Bugfixes --- lib/app_sources/apkcombo.dart | 116 ++++++++++++++++++++ lib/app_sources/apkmirror.dart | 2 +- lib/app_sources/apkpure.dart | 69 ++++++++++++ lib/app_sources/codeberg.dart | 1 + lib/app_sources/fdroid.dart | 4 +- lib/app_sources/fdroidrepo.dart | 3 +- lib/app_sources/github.dart | 5 +- lib/app_sources/gitlab.dart | 3 +- lib/app_sources/html.dart | 170 +++++++++++++++-------------- lib/app_sources/izzyondroid.dart | 4 +- lib/app_sources/jenkins.dart | 6 +- lib/app_sources/mullvad.dart | 2 +- lib/app_sources/neutroncode.dart | 2 +- lib/app_sources/signal.dart | 2 +- lib/app_sources/sourceforge.dart | 3 +- lib/app_sources/sourcehut.dart | 101 +++++++++++++++++ lib/app_sources/steammobile.dart | 2 +- lib/app_sources/telegramapp.dart | 2 +- lib/app_sources/vlc.dart | 6 +- lib/app_sources/whatsapp.dart | 16 +-- lib/pages/add_app.dart | 6 +- lib/providers/apps_provider.dart | 20 ++-- lib/providers/source_provider.dart | 22 +++- 23 files changed, 445 insertions(+), 122 deletions(-) create mode 100644 lib/app_sources/apkcombo.dart create mode 100644 lib/app_sources/apkpure.dart create mode 100644 lib/app_sources/sourcehut.dart diff --git a/lib/app_sources/apkcombo.dart b/lib/app_sources/apkcombo.dart new file mode 100644 index 0000000..6c5dfa6 --- /dev/null +++ b/lib/app_sources/apkcombo.dart @@ -0,0 +1,116 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:html/parser.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class APKCombo extends AppSource { + APKCombo() { + host = 'apkcombo.com'; + } + + @override + String sourceSpecificStandardizeURL(String url) { + RegExp standardUrlRegEx = RegExp('^https?://$host/+[^/]+/+[^/]+'); + var match = standardUrlRegEx.firstMatch(url.toLowerCase()); + if (match == null) { + throw InvalidURLError(name); + } + return url.substring(0, match.end); + } + + @override + String? tryInferringAppId(String standardUrl, + {Map additionalSettings = const {}}) { + return Uri.parse(standardUrl).pathSegments.last; + } + + @override + Map get requestHeaders => { + "User-Agent": "curl/8.0.1", + "Accept": "*/*", + "Connection": "keep-alive", + "Host": "$host" + }; + + Future>> getApkUrls(String standardUrl) async { + var res = await sourceRequest('$standardUrl/download/apk'); + if (res.statusCode != 200) { + throw getObtainiumHttpError(res); + } + var html = parse(res.body); + return html + .querySelectorAll('#variants-tab > div > ul > li') + .map((e) { + String? arch = e + .querySelector('code') + ?.text + .trim() + .replaceAll(',', '') + .replaceAll(':', '-') + .replaceAll(' ', '-'); + return e.querySelectorAll('a').map((e) { + String? url = e.attributes['href']; + if (url != null && + !Uri.parse(url).path.toLowerCase().endsWith('.apk')) { + url = null; + } + String verCode = + e.querySelector('.info .header .vercode')?.text.trim() ?? ''; + return MapEntry( + arch != null ? '$arch-$verCode.apk' : '', url ?? ''); + }).toList(); + }) + .reduce((value, element) => [...value, ...element]) + .where((element) => element.value.isNotEmpty) + .toList(); + } + + @override + Future apkUrlPrefetchModifier( + String apkUrl, String standardUrl) async { + var freshURLs = await getApkUrls(standardUrl); + var path2Match = Uri.parse(apkUrl).path; + for (var url in freshURLs) { + if (Uri.parse(url.value).path == path2Match) { + return url.value; + } + } + throw NoAPKError(); + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + String appId = tryInferringAppId(standardUrl)!; + String host = Uri.parse(standardUrl).host; + var preres = await sourceRequest(standardUrl); + if (preres.statusCode != 200) { + throw getObtainiumHttpError(preres); + } + var res = parse(preres.body); + String? version = res.querySelector('div.version')?.text.trim(); + if (version == null) { + throw NoVersionError(); + } + String appName = res.querySelector('div.app_name')?.text.trim() ?? appId; + String author = res.querySelector('div.author')?.text.trim() ?? appName; + List infoArray = res + .querySelectorAll('div.information-table > .item > div.value') + .map((e) => e.text.trim()) + .toList(); + DateTime? releaseDate; + if (infoArray.length >= 2) { + try { + releaseDate = DateFormat('MMMM d, yyyy').parse(infoArray[1]); + } catch (e) { + // ignore + } + } + return APKDetails( + version, await getApkUrls(standardUrl), AppNames(author, appName), + releaseDate: releaseDate); + } +} diff --git a/lib/app_sources/apkmirror.dart b/lib/app_sources/apkmirror.dart index 396e599..2265cc7 100644 --- a/lib/app_sources/apkmirror.dart +++ b/lib/app_sources/apkmirror.dart @@ -57,7 +57,7 @@ class APKMirror extends AppSource { true ? additionalSettings['filterReleaseTitlesByRegEx'] : null; - Response res = await get(Uri.parse('$standardUrl/feed')); + Response res = await sourceRequest('$standardUrl/feed'); if (res.statusCode == 200) { var items = parse(res.body).querySelectorAll('item'); dynamic targetRelease; diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart new file mode 100644 index 0000000..437ae4c --- /dev/null +++ b/lib/app_sources/apkpure.dart @@ -0,0 +1,69 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:html/parser.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class APKPure extends AppSource { + APKPure() { + host = 'apkpure.com'; + } + + @override + String sourceSpecificStandardizeURL(String url) { + RegExp standardUrlRegExB = RegExp('^https?://m.$host/+[^/]+/+[^/]+'); + RegExpMatch? match = standardUrlRegExB.firstMatch(url.toLowerCase()); + if (match != null) { + url = 'https://$host/${Uri.parse(url).path}'; + } + RegExp standardUrlRegExA = RegExp('^https?://$host/+[^/]+/+[^/]+'); + match = standardUrlRegExA.firstMatch(url.toLowerCase()); + if (match == null) { + throw InvalidURLError(name); + } + return url.substring(0, match.end); + } + + @override + String? tryInferringAppId(String standardUrl, + {Map additionalSettings = const {}}) { + return Uri.parse(standardUrl).pathSegments.last; + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + String appId = tryInferringAppId(standardUrl)!; + String host = Uri.parse(standardUrl).host; + var res = await sourceRequest('$standardUrl/download'); + if (res.statusCode == 200) { + var html = parse(res.body); + String? version = html.querySelector('span.info-sdk span')?.text.trim(); + if (version == null) { + throw NoVersionError(); + } + String? dateString = + html.querySelector('span.info-other span.date')?.text.trim(); + DateTime? releaseDate = dateString != null + ? DateFormat('MMMM d, yyyy').parse(dateString) + : null; + List> apkUrls = [ + MapEntry('$appId.apk', 'https://d.$host/b/APK/$appId?version=latest') + ]; + String author = html + .querySelector('span.info-sdk') + ?.text + .trim() + .substring(version.length + 4) ?? + Uri.parse(standardUrl).pathSegments.reversed.last; + String appName = + html.querySelector('h1.info-title')?.text.trim() ?? appId; + return APKDetails(version, apkUrls, AppNames(author, appName), + releaseDate: releaseDate); + } else { + throw getObtainiumHttpError(res); + } + } +} diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index a45d620..d50332d 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -9,6 +9,7 @@ import 'package:obtainium/providers/source_provider.dart'; class Codeberg extends AppSource { Codeberg() { host = 'codeberg.org'; + overrideEligible = true; additionalSourceSpecificSettingFormItems = []; diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 318a983..88b4f5e 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -66,14 +66,14 @@ class FDroid extends AppSource { String? appId = tryInferringAppId(standardUrl); String host = Uri.parse(standardUrl).host; return getAPKUrlsFromFDroidPackagesAPIResponse( - await get(Uri.parse('https://$host/api/v1/packages/$appId')), + await sourceRequest('https://$host/api/v1/packages/$appId'), 'https://$host/repo/$appId', standardUrl); } @override Future>> search(String query) async { - Response res = await get(Uri.parse('https://search.$host/?q=$query')); + Response res = await sourceRequest('https://search.$host/?q=$query'); if (res.statusCode == 200) { Map> urlsWithDescriptions = {}; parse(res.body).querySelectorAll('.package-header').forEach((e) { diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index 33c8edf..184e139 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -8,6 +8,7 @@ import 'package:obtainium/providers/source_provider.dart'; class FDroidRepo extends AppSource { FDroidRepo() { name = tr('fdroidThirdPartyRepo'); + overrideEligible = true; additionalSourceAppSpecificSettingFormItems = [ [ @@ -28,7 +29,7 @@ class FDroidRepo extends AppSource { if (appIdOrName == null) { throw NoReleasesError(); } - var res = await get(Uri.parse('$standardUrl/index.xml')); + var res = await sourceRequest('$standardUrl/index.xml'); if (res.statusCode == 200) { var body = parse(res.body); var foundApps = body.querySelectorAll('application').where((element) { diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index e6b67ae..a9a76c3 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -11,6 +11,7 @@ import 'package:url_launcher/url_launcher_string.dart'; class GitHub extends AppSource { GitHub() { host = 'github.com'; + overrideEligible = true; additionalSourceSpecificSettingFormItems = [ GeneratedFormTextField('github-creds', @@ -108,7 +109,7 @@ class GitHub extends AppSource { true ? additionalSettings['filterReleaseTitlesByRegEx'] : null; - Response res = await get(Uri.parse(requestUrl)); + Response res = await sourceRequest(requestUrl); if (res.statusCode == 200) { var releases = jsonDecode(res.body) as List; @@ -216,7 +217,7 @@ class GitHub extends AppSource { Future>> searchCommon( String query, String requestUrl, String rootProp, {Function(Response)? onHttpErrorCode}) async { - Response res = await get(Uri.parse(requestUrl)); + Response res = await sourceRequest(requestUrl); if (res.statusCode == 200) { Map> urlsWithDescriptions = {}; for (var e in (jsonDecode(res.body)[rootProp] as List)) { diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index 150cb04..07f8369 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -9,6 +9,7 @@ import 'package:easy_localization/easy_localization.dart'; class GitLab extends AppSource { GitLab() { host = 'gitlab.com'; + overrideEligible = true; additionalSourceAppSpecificSettingFormItems = [ [ @@ -39,7 +40,7 @@ class GitLab extends AppSource { ) async { bool fallbackToOlderReleases = additionalSettings['fallbackToOlderReleases'] == true; - Response res = await get(Uri.parse('$standardUrl/-/tags?format=atom')); + Response res = await sourceRequest('$standardUrl/-/tags?format=atom'); if (res.statusCode == 200) { var standardUri = Uri.parse(standardUrl); var parsedHtml = parse(res.body); diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index c4c039f..d9ec173 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -4,84 +4,109 @@ import 'package:http/http.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; +String ensureAbsoluteUrl(String ambiguousUrl, Uri referenceAbsoluteUrl) { + try { + Uri.parse(ambiguousUrl).origin; + return ambiguousUrl; + } catch (err) { + // is relative + } + var currPathSegments = referenceAbsoluteUrl.path + .split('/') + .where((element) => element.trim().isNotEmpty) + .toList(); + if (ambiguousUrl.startsWith('/') || currPathSegments.isEmpty) { + return '${referenceAbsoluteUrl.origin}/$ambiguousUrl'; + } else if (ambiguousUrl.split('/').length == 1) { + return '${referenceAbsoluteUrl.origin}/${currPathSegments.join('/')}/$ambiguousUrl'; + } else { + return '${referenceAbsoluteUrl.origin}/${currPathSegments.sublist(0, currPathSegments.length - 1).join('/')}/$ambiguousUrl'; + } +} + +int compareAlphaNumeric(String a, String b) { + List aParts = _splitAlphaNumeric(a); + List bParts = _splitAlphaNumeric(b); + + for (int i = 0; i < aParts.length && i < bParts.length; i++) { + String aPart = aParts[i]; + String bPart = bParts[i]; + + bool aIsNumber = _isNumeric(aPart); + bool bIsNumber = _isNumeric(bPart); + + if (aIsNumber && bIsNumber) { + int aNumber = int.parse(aPart); + int bNumber = int.parse(bPart); + int cmp = aNumber.compareTo(bNumber); + if (cmp != 0) { + return cmp; + } + } else if (!aIsNumber && !bIsNumber) { + int cmp = aPart.compareTo(bPart); + if (cmp != 0) { + return cmp; + } + } else { + // Alphanumeric strings come before numeric strings + return aIsNumber ? 1 : -1; + } + } + + return aParts.length.compareTo(bParts.length); +} + +List _splitAlphaNumeric(String s) { + List parts = []; + StringBuffer sb = StringBuffer(); + + bool isNumeric = _isNumeric(s[0]); + sb.write(s[0]); + + for (int i = 1; i < s.length; i++) { + bool currentIsNumeric = _isNumeric(s[i]); + if (currentIsNumeric == isNumeric) { + sb.write(s[i]); + } else { + parts.add(sb.toString()); + sb.clear(); + sb.write(s[i]); + isNumeric = currentIsNumeric; + } + } + + parts.add(sb.toString()); + + return parts; +} + +bool _isNumeric(String s) { + return s.codeUnitAt(0) >= 48 && s.codeUnitAt(0) <= 57; +} + class HTML extends AppSource { + HTML() { + overrideEligible = true; + } + @override String sourceSpecificStandardizeURL(String url) { return url; } - int compareAlphaNumeric(String a, String b) { - List aParts = _splitAlphaNumeric(a); - List bParts = _splitAlphaNumeric(b); - - for (int i = 0; i < aParts.length && i < bParts.length; i++) { - String aPart = aParts[i]; - String bPart = bParts[i]; - - bool aIsNumber = _isNumeric(aPart); - bool bIsNumber = _isNumeric(bPart); - - if (aIsNumber && bIsNumber) { - int aNumber = int.parse(aPart); - int bNumber = int.parse(bPart); - int cmp = aNumber.compareTo(bNumber); - if (cmp != 0) { - return cmp; - } - } else if (!aIsNumber && !bIsNumber) { - int cmp = aPart.compareTo(bPart); - if (cmp != 0) { - return cmp; - } - } else { - // Alphanumeric strings come before numeric strings - return aIsNumber ? 1 : -1; - } - } - - return aParts.length.compareTo(bParts.length); - } - - List _splitAlphaNumeric(String s) { - List parts = []; - StringBuffer sb = StringBuffer(); - - bool isNumeric = _isNumeric(s[0]); - sb.write(s[0]); - - for (int i = 1; i < s.length; i++) { - bool currentIsNumeric = _isNumeric(s[i]); - if (currentIsNumeric == isNumeric) { - sb.write(s[i]); - } else { - parts.add(sb.toString()); - sb.clear(); - sb.write(s[i]); - isNumeric = currentIsNumeric; - } - } - - parts.add(sb.toString()); - - return parts; - } - - bool _isNumeric(String s) { - return s.codeUnitAt(0) >= 48 && s.codeUnitAt(0) <= 57; - } - @override Future getLatestAPKDetails( String standardUrl, Map additionalSettings, ) async { var uri = Uri.parse(standardUrl); - Response res = await get(uri); + Response res = await sourceRequest(standardUrl); if (res.statusCode == 200) { List links = parse(res.body) .querySelectorAll('a') .map((element) => element.attributes['href'] ?? '') - .where((element) => element.toLowerCase().endsWith('.apk')) + .where((element) => + Uri.parse(element).path.toLowerCase().endsWith('.apk')) .toList(); links.sort( (a, b) => compareAlphaNumeric(a.split('/').last, b.split('/').last)); @@ -95,25 +120,8 @@ class HTML extends AppSource { var rel = links.last; var apkName = rel.split('/').last; var version = apkName.substring(0, apkName.length - 4); - List apkUrls = [rel].map((e) { - try { - Uri.parse(e).origin; - return e; - } catch (err) { - // is relative - } - var currPathSegments = uri.path - .split('/') - .where((element) => element.trim().isNotEmpty) - .toList(); - if (e.startsWith('/') || currPathSegments.isEmpty) { - return '${uri.origin}/$e'; - } else if (e.split('/').length == 1) { - return '${uri.origin}/${currPathSegments.join('/')}/$e'; - } else { - return '${uri.origin}/${currPathSegments.sublist(0, currPathSegments.length - 1).join('/')}/$e'; - } - }).toList(); + List apkUrls = + [rel].map((e) => ensureAbsoluteUrl(e, uri)).toList(); return APKDetails( version, getApkUrlsFromUrls(apkUrls), AppNames(uri.host, tr('app'))); } else { diff --git a/lib/app_sources/izzyondroid.dart b/lib/app_sources/izzyondroid.dart index 0fbceb9..cdab17a 100644 --- a/lib/app_sources/izzyondroid.dart +++ b/lib/app_sources/izzyondroid.dart @@ -31,8 +31,8 @@ class IzzyOnDroid extends AppSource { ) async { String? appId = tryInferringAppId(standardUrl); return FDroid().getAPKUrlsFromFDroidPackagesAPIResponse( - await get( - Uri.parse('https://apt.izzysoft.de/fdroid/api/v1/packages/$appId')), + await sourceRequest( + 'https://apt.izzysoft.de/fdroid/api/v1/packages/$appId'), 'https://android.izzysoft.de/frepo/$appId', standardUrl); } diff --git a/lib/app_sources/jenkins.dart b/lib/app_sources/jenkins.dart index 366b76d..804b3fb 100644 --- a/lib/app_sources/jenkins.dart +++ b/lib/app_sources/jenkins.dart @@ -6,6 +6,7 @@ import 'package:obtainium/providers/source_provider.dart'; class Jenkins extends AppSource { Jenkins() { + overrideEligible = true; overrideVersionDetectionFormDefault('releaseDateAsVersion', true); } @@ -30,7 +31,7 @@ class Jenkins extends AppSource { ) async { standardUrl = trimJobUrl(standardUrl); Response res = - await get(Uri.parse('$standardUrl/lastSuccessfulBuild/api/json')); + await sourceRequest('$standardUrl/lastSuccessfulBuild/api/json'); if (res.statusCode == 200) { var json = jsonDecode(res.body); var releaseDate = json['timestamp'] == null @@ -55,9 +56,6 @@ class Jenkins extends AppSource { .where((url) => url.value.isNotEmpty && url.key.toLowerCase().endsWith('.apk')) .toList(); - if (apkUrls.isEmpty) { - throw NoAPKError(); - } return APKDetails( version, apkUrls, diff --git a/lib/app_sources/mullvad.dart b/lib/app_sources/mullvad.dart index 64ef092..4e15d2f 100644 --- a/lib/app_sources/mullvad.dart +++ b/lib/app_sources/mullvad.dart @@ -28,7 +28,7 @@ class Mullvad extends AppSource { String standardUrl, Map additionalSettings, ) async { - Response res = await get(Uri.parse('$standardUrl/en/download/android')); + Response res = await sourceRequest('$standardUrl/en/download/android'); if (res.statusCode == 200) { var versions = parse(res.body) .querySelectorAll('p') diff --git a/lib/app_sources/neutroncode.dart b/lib/app_sources/neutroncode.dart index 45374a9..4fbec3c 100644 --- a/lib/app_sources/neutroncode.dart +++ b/lib/app_sources/neutroncode.dart @@ -78,7 +78,7 @@ class NeutronCode extends AppSource { String standardUrl, Map additionalSettings, ) async { - Response res = await get(Uri.parse(standardUrl)); + Response res = await sourceRequest(standardUrl); if (res.statusCode == 200) { var http = parse(res.body); var name = http.querySelector('.pd-title')?.innerHtml; diff --git a/lib/app_sources/signal.dart b/lib/app_sources/signal.dart index 40d6953..f7bda25 100644 --- a/lib/app_sources/signal.dart +++ b/lib/app_sources/signal.dart @@ -19,7 +19,7 @@ class Signal extends AppSource { Map additionalSettings, ) async { Response res = - await get(Uri.parse('https://updates.$host/android/latest.json')); + await sourceRequest('https://updates.$host/android/latest.json'); if (res.statusCode == 200) { var json = jsonDecode(res.body); String? apkUrl = json['url']; diff --git a/lib/app_sources/sourceforge.dart b/lib/app_sources/sourceforge.dart index ee2f22b..794eef1 100644 --- a/lib/app_sources/sourceforge.dart +++ b/lib/app_sources/sourceforge.dart @@ -6,6 +6,7 @@ import 'package:obtainium/providers/source_provider.dart'; class SourceForge extends AppSource { SourceForge() { host = 'sourceforge.net'; + overrideEligible = true; } @override @@ -29,7 +30,7 @@ class SourceForge extends AppSource { String standardUrl, Map additionalSettings, ) async { - Response res = await get(Uri.parse('$standardUrl/rss?path=/')); + Response res = await sourceRequest('$standardUrl/rss?path=/'); if (res.statusCode == 200) { var parsedHtml = parse(res.body); var allDownloadLinks = diff --git a/lib/app_sources/sourcehut.dart b/lib/app_sources/sourcehut.dart new file mode 100644 index 0000000..b85758f --- /dev/null +++ b/lib/app_sources/sourcehut.dart @@ -0,0 +1,101 @@ +import 'package:html/parser.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/app_sources/github.dart'; +import 'package:obtainium/app_sources/html.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; +import 'package:obtainium/components/generated_form.dart'; +import 'package:easy_localization/easy_localization.dart'; + +class SourceHut extends AppSource { + SourceHut() { + host = 'git.sr.ht'; + overrideEligible = true; + + additionalSourceAppSpecificSettingFormItems = [ + [ + GeneratedFormSwitch('fallbackToOlderReleases', + label: tr('fallbackToOlderReleases'), defaultValue: true) + ] + ]; + } + + @override + String sourceSpecificStandardizeURL(String url) { + RegExp standardUrlRegEx = RegExp('^https?://$host/[^/]+/[^/]+'); + RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); + if (match == null) { + throw InvalidURLError(name); + } + return url.substring(0, match.end); + } + + @override + String? changeLogPageFromStandardUrl(String standardUrl) => standardUrl; + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + Uri standardUri = Uri.parse(standardUrl); + String appName = standardUri.pathSegments.last; + bool fallbackToOlderReleases = + additionalSettings['fallbackToOlderReleases'] == true; + Response res = await sourceRequest('$standardUrl/refs/rss.xml'); + if (res.statusCode == 200) { + var parsedHtml = parse(res.body); + List apkDetailsList = []; + int ind = 0; + + for (var entry in parsedHtml.querySelectorAll('item').sublist(0, 6)) { + // Limit 5 for speed + if (!fallbackToOlderReleases && ind > 0) { + break; + } + String? version = entry.querySelector('title')?.text.trim(); + if (version == null) { + throw NoVersionError(); + } + String? releaseDateString = entry.querySelector('pubDate')?.innerHtml; + var link = entry.querySelector('link'); + String releasePage = '$standardUrl/refs/$version'; + DateTime? releaseDate = releaseDateString != null + ? DateFormat('EEE, dd MMM yyyy HH:mm:ss Z').parse(releaseDateString) + : null; + var res2 = await sourceRequest(releasePage); + List> apkUrls = []; + if (res2.statusCode == 200) { + apkUrls = getApkUrlsFromUrls(parse(res2.body) + .querySelectorAll('a') + .map((e) => e.attributes['href'] ?? '') + .where((e) => e.toLowerCase().endsWith('.apk')) + .map((e) => ensureAbsoluteUrl(e, standardUri)) + .toList()); + } + apkDetailsList.add(APKDetails( + version, + apkUrls, + AppNames(entry.querySelector('author')?.innerHtml.trim() ?? appName, + appName), + releaseDate: releaseDate)); + ind++; + } + if (apkDetailsList.isEmpty) { + throw NoReleasesError(); + } + if (fallbackToOlderReleases) { + if (additionalSettings['trackOnly'] != true) { + apkDetailsList = + apkDetailsList.where((e) => e.apkUrls.isNotEmpty).toList(); + } + if (apkDetailsList.isEmpty) { + throw NoReleasesError(); + } + } + return apkDetailsList.first; + } else { + throw getObtainiumHttpError(res); + } + } +} diff --git a/lib/app_sources/steammobile.dart b/lib/app_sources/steammobile.dart index 305c89a..65c518b 100644 --- a/lib/app_sources/steammobile.dart +++ b/lib/app_sources/steammobile.dart @@ -29,7 +29,7 @@ class SteamMobile extends AppSource { String standardUrl, Map additionalSettings, ) async { - Response res = await get(Uri.parse('https://$host/mobile')); + Response res = await sourceRequest('https://$host/mobile'); if (res.statusCode == 200) { var apkNamePrefix = additionalSettings['app'] as String?; if (apkNamePrefix == null) { diff --git a/lib/app_sources/telegramapp.dart b/lib/app_sources/telegramapp.dart index 3c02156..44042e0 100644 --- a/lib/app_sources/telegramapp.dart +++ b/lib/app_sources/telegramapp.dart @@ -20,7 +20,7 @@ class TelegramApp extends AppSource { String standardUrl, Map additionalSettings, ) async { - Response res = await get(Uri.parse('https://t.me/s/TAndroidAPK')); + Response res = await sourceRequest('https://t.me/s/TAndroidAPK'); if (res.statusCode == 200) { var http = parse(res.body); var messages = diff --git a/lib/app_sources/vlc.dart b/lib/app_sources/vlc.dart index b105068..06ad878 100644 --- a/lib/app_sources/vlc.dart +++ b/lib/app_sources/vlc.dart @@ -19,8 +19,8 @@ class VLC extends AppSource { String standardUrl, Map additionalSettings, ) async { - Response res = await get( - Uri.parse('https://www.videolan.org/vlc/download-android.html')); + Response res = await sourceRequest( + 'https://www.videolan.org/vlc/download-android.html'); if (res.statusCode == 200) { var dwUrlBase = 'get.videolan.org/vlc-android'; var dwLinks = parse(res.body) @@ -38,7 +38,7 @@ class VLC extends AppSource { throw NoVersionError(); } String? targetUrl = 'https://$dwUrlBase/$version/'; - Response res2 = await get(Uri.parse(targetUrl)); + Response res2 = await sourceRequest(targetUrl); String mirrorDwBase = 'https://plug-mirror.rcac.purdue.edu/vlc/vlc-android/$version/'; List apkUrls = []; diff --git a/lib/app_sources/whatsapp.dart b/lib/app_sources/whatsapp.dart index 85deb84..f17d8a0 100644 --- a/lib/app_sources/whatsapp.dart +++ b/lib/app_sources/whatsapp.dart @@ -14,21 +14,21 @@ class WhatsApp extends AppSource { } @override - Future apkUrlPrefetchModifier(String apkUrl) async { - Response res = await get(Uri.parse('https://www.whatsapp.com/android')); + Future apkUrlPrefetchModifier( + String apkUrl, String standardUrl) async { + Response res = await sourceRequest('https://www.whatsapp.com/android'); if (res.statusCode == 200) { var targetLinks = parse(res.body) .querySelectorAll('a') - .map((e) => e.attributes['href']) - .where((e) => e != null) + .map((e) => e.attributes['href'] ?? '') + .where((e) => e.isNotEmpty) .where((e) => - e!.contains('scontent.whatsapp.net') && - e.contains('WhatsApp.apk')) + e.contains('content.whatsapp.net') && e.contains('WhatsApp.apk')) .toList(); if (targetLinks.isEmpty) { throw NoAPKError(); } - return targetLinks[0]!; + return targetLinks[0]; } else { throw getObtainiumHttpError(res); } @@ -39,7 +39,7 @@ class WhatsApp extends AppSource { String standardUrl, Map additionalSettings, ) async { - Response res = await get(Uri.parse('https://www.whatsapp.com/android')); + Response res = await sourceRequest('https://www.whatsapp.com/android'); if (res.statusCode == 200) { var targetElements = parse(res.body) .querySelectorAll('p') diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index b0654c3..3cef280 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -302,8 +302,10 @@ class _AddAppPageState extends State { 'overrideSource', defaultValue: HTML().runtimeType.toString(), [ - ...sourceProvider.sources.map( - (s) => MapEntry(s.runtimeType.toString(), s.name)) + ...sourceProvider.sources + .where((s) => s.overrideEligible) + .map((s) => + MapEntry(s.runtimeType.toString(), s.name)) ], label: tr('overrideSource')) ] diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 9cc445c..e4f611c 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -125,10 +125,13 @@ class AppsProvider with ChangeNotifier { } downloadFile(String url, String fileName, Function? onProgress, - {bool useExisting = true}) async { + {bool useExisting = true, Map? headers}) async { var destDir = (await getExternalCacheDirectories())!.first.path; - StreamedResponse response = - await Client().send(Request('GET', Uri.parse(url))); + var req = Request('GET', Uri.parse(url)); + if (headers != null) { + req.headers.addAll(headers); + } + StreamedResponse response = await Client().send(req); File downloadedFile = File('$destDir/$fileName'); if (!(downloadedFile.existsSync() && useExisting)) { File tempDownloadedFile = File('${downloadedFile.path}.part'); @@ -170,15 +173,16 @@ class AppsProvider with ChangeNotifier { notifyListeners(); } try { - String downloadUrl = await SourceProvider() - .getSource(app.url, overrideSource: app.overrideSource) - .apkUrlPrefetchModifier(app.apkUrls[app.preferredApkIndex].value); + AppSource source = SourceProvider() + .getSource(app.url, overrideSource: app.overrideSource); + String downloadUrl = await source.apkUrlPrefetchModifier( + app.apkUrls[app.preferredApkIndex].value, app.url); var fileName = '${app.id}-${downloadUrl.hashCode}.apk'; var notif = DownloadNotification(app.finalName, 100); notificationsProvider?.cancel(notif.id); int? prevProg; - File downloadedFile = - await downloadFile(downloadUrl, fileName, (double? progress) { + File downloadedFile = await downloadFile(downloadUrl, fileName, + headers: source.requestHeaders, (double? progress) { int? prog = progress?.ceil(); if (apps[app.id] != null) { apps[app.id]!.downloadProgress = progress; diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 556c294..f498496 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -7,7 +7,9 @@ import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:html/dom.dart'; import 'package:http/http.dart'; +import 'package:obtainium/app_sources/apkcombo.dart'; import 'package:obtainium/app_sources/apkmirror.dart'; +import 'package:obtainium/app_sources/apkpure.dart'; import 'package:obtainium/app_sources/codeberg.dart'; import 'package:obtainium/app_sources/fdroid.dart'; import 'package:obtainium/app_sources/fdroidrepo.dart'; @@ -20,6 +22,7 @@ import 'package:obtainium/app_sources/mullvad.dart'; import 'package:obtainium/app_sources/neutroncode.dart'; import 'package:obtainium/app_sources/signal.dart'; import 'package:obtainium/app_sources/sourceforge.dart'; +import 'package:obtainium/app_sources/sourcehut.dart'; import 'package:obtainium/app_sources/steammobile.dart'; import 'package:obtainium/app_sources/telegramapp.dart'; import 'package:obtainium/app_sources/vlc.dart'; @@ -315,6 +318,7 @@ abstract class AppSource { late String name; bool enforceTrackOnly = false; bool changeLogIfAnyIsMarkDown = true; + bool overrideEligible = false; AppSource() { name = runtimeType.toString(); @@ -344,6 +348,18 @@ abstract class AppSource { return url; } + Map? get requestHeaders => null; + + Future sourceRequest(String url) async { + if (requestHeaders != null) { + var req = Request('GET', Uri.parse(url)); + req.headers.addAll(requestHeaders!); + return Response.fromStream(await Client().send(req)); + } else { + return get(Uri.parse(url)); + } + } + String sourceSpecificStandardizeURL(String url) { throw NotImplementedError(); } @@ -410,7 +426,8 @@ abstract class AppSource { return null; } - Future apkUrlPrefetchModifier(String apkUrl) async { + Future apkUrlPrefetchModifier( + String apkUrl, String standardUrl) async { return apkUrl; } @@ -459,7 +476,10 @@ class SourceProvider { FDroidRepo(), Jenkins(), SourceForge(), + SourceHut(), APKMirror(), + APKPure(), + // APKCombo(), // Can't get past their scraping blocking yet (get 403 Forbidden) Mullvad(), Signal(), VLC(), From 30c89fe3850db494263cc1f251f1b7b92140d668 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 5 May 2023 23:08:34 -0400 Subject: [PATCH 180/600] Option to move non-installed apps to bottom (#264) --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/zh.json | 1 + lib/pages/apps.dart | 12 +++++++++++ lib/pages/settings.dart | 30 ++++++++++++++++++++++------ lib/providers/settings_provider.dart | 9 +++++++++ 12 files changed, 54 insertions(+), 6 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 1406cf1..6510dd8 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -228,6 +228,7 @@ "dontShowAgain": "Nicht noch einmal zeigen", "dontShowTrackOnlyWarnings": "Warnung für 'Nur Nachverfolgen' nicht anzeigen", "dontShowAPKOriginWarnings": "Warnung für APK-Herkunft nicht anzeigen", + "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 58878ff..606f66f 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -228,6 +228,7 @@ "dontShowAgain": "Don't show this again", "dontShowTrackOnlyWarnings": "Don't Show 'Track-Only' Warnings", "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", + "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 1f80bac..3d8f1ad 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -228,6 +228,7 @@ "dontShowAgain": "No mostrar de nuevo", "dontShowTrackOnlyWarnings": "No mostrar avisos de 'Solo Seguimiento'", "dontShowAPKOriginWarnings": "No mostrar avisos de las fuentes de las APks", + "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index d0ba5c5..33da610 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -228,6 +228,7 @@ "dontShowAgain": "دوباره این را نشان نده", "dontShowTrackOnlyWarnings": "هشدار 'فقط ردیابی' را نشان ندهید", "dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید", + "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 27dbd45..1840c8a 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -228,6 +228,7 @@ "dontShowAgain": "Don't show this again", "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", + "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index f1ed8d2..26de38e 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -227,6 +227,7 @@ "dontShowAgain": "Ne mutassa ezt újra", "dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést", "dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket", + "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", "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 1b122d5..0e49191 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -228,6 +228,7 @@ "dontShowAgain": "Don't show this again", "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", + "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index f7cbab3..7f5bf32 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -228,6 +228,7 @@ "dontShowAgain": "二度と表示しない", "dontShowTrackOnlyWarnings": "「追跡のみ」の警告を表示しない", "dontShowAPKOriginWarnings": "APK Originの警告を表示しない", + "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index a430229..91ca57d 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -228,6 +228,7 @@ "dontShowAgain": "Don't show this again", "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", + "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index c240676..6a0a947 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -185,6 +185,18 @@ class AppsPageState extends State { listedApps = [...temp, ...listedApps]; } + if (settingsProvider.buryNonInstalled) { + var temp = []; + listedApps = listedApps.where((sa) { + if (sa.app.installedVersion == null) { + temp.add(sa); + return false; + } + return true; + }).toList(); + listedApps = [...listedApps, ...temp]; + } + var tempPinned = []; var tempNotPinned = []; for (var a in listedApps) { diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 988fe85..224a076 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -227,7 +227,7 @@ class _SettingsPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(tr('useBlackTheme')), + Flexible(child: Text(tr('useBlackTheme'))), Switch( value: settingsProvider.useBlackTheme, onChanged: (value) { @@ -254,7 +254,7 @@ class _SettingsPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(tr('showWebInAppView')), + Flexible(child: Text(tr('showWebInAppView'))), Switch( value: settingsProvider.showAppWebpage, onChanged: (value) { @@ -266,7 +266,7 @@ class _SettingsPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(tr('pinUpdates')), + Flexible(child: Text(tr('pinUpdates'))), Switch( value: settingsProvider.pinUpdates, onChanged: (value) { @@ -278,7 +278,21 @@ class _SettingsPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(tr('groupByCategory')), + Flexible( + child: Text( + tr('moveNonInstalledAppsToBottom'))), + Switch( + value: settingsProvider.buryNonInstalled, + onChanged: (value) { + settingsProvider.buryNonInstalled = value; + }) + ], + ), + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible(child: Text(tr('groupByCategory'))), Switch( value: settingsProvider.groupByCategory, onChanged: (value) { @@ -290,7 +304,9 @@ class _SettingsPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(tr('dontShowTrackOnlyWarnings')), + Flexible( + child: + Text(tr('dontShowTrackOnlyWarnings'))), Switch( value: settingsProvider.hideTrackOnlyWarning, @@ -304,7 +320,9 @@ class _SettingsPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(tr('dontShowAPKOriginWarnings')), + Flexible( + child: + Text(tr('dontShowAPKOriginWarnings'))), Switch( value: settingsProvider.hideAPKOriginWarning, diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 2f03dfb..162d7f9 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -154,6 +154,15 @@ class SettingsProvider with ChangeNotifier { notifyListeners(); } + bool get buryNonInstalled { + return prefs?.getBool('buryNonInstalled') ?? false; + } + + set buryNonInstalled(bool show) { + prefs?.setBool('buryNonInstalled', show); + notifyListeners(); + } + bool get groupByCategory { return prefs?.getBool('groupByCategory') ?? false; } From 8ca5964d31d74e21727fd52a13206c534dcf53ae Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 5 May 2023 23:09:40 -0400 Subject: [PATCH 181/600] Updated README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b21d416..d65389a 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ Currently supported App sources: - [Mullvad](https://mullvad.net/en/) - [Signal](https://signal.org/) - [SourceForge](https://sourceforge.net/) +- [SourceHut](https://git.sr.ht/) - [APKMirror](https://apkmirror.com/) (Track-Only) +- [APKPure](https://apkpure.com/) - Third Party F-Droid Repos - Jenkins Jobs - [Steam](https://store.steampowered.com/mobile) From b4642e16add024edc80ea0afc9008f576de3e507 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 6 May 2023 00:06:48 -0400 Subject: [PATCH 182/600] GitLab search (#422) + better settings UI --- assets/translations/de.json | 4 ++- assets/translations/en.json | 4 ++- assets/translations/es.json | 4 ++- 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/app_sources/fdroid.dart | 3 +- lib/app_sources/github.dart | 9 ++++-- lib/app_sources/gitlab.dart | 63 +++++++++++++++++++++++++++++++++++++ lib/custom_errors.dart | 5 +++ lib/pages/add_app.dart | 15 +++++++-- lib/pages/settings.dart | 45 +++++++++++++------------- 15 files changed, 138 insertions(+), 38 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 6510dd8..fb3135a 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -20,7 +20,6 @@ "githubPATLabel": "GitHub Personal Access Token (Erhöht das Ratenlimit)", "githubPATHint": "PAT muss in diesem Format sein: Benutzername:Token", "githubPATFormat": "Benutzername:Token", - "githubPATLinkText": "Über GitHub PATs", "includePrereleases": "Vorabversionen einbeziehen", "fallbackToOlderReleases": "Fallback auf ältere Versionen", "filterReleaseTitlesByRegEx": "Release-Titel nach regulärem Ausdruck\nfiltern", @@ -229,6 +228,9 @@ "dontShowTrackOnlyWarnings": "Warnung für 'Nur Nachverfolgen' nicht anzeigen", "dontShowAPKOriginWarnings": "Warnung für APK-Herkunft nicht anzeigen", "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "about": "About", + "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 606f66f..dd027a9 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -20,7 +20,6 @@ "githubPATLabel": "GitHub Personal Access Token (Increases Rate Limit)", "githubPATHint": "PAT must be in this format: username:token", "githubPATFormat": "username:token", - "githubPATLinkText": "About GitHub PATs", "includePrereleases": "Include prereleases", "fallbackToOlderReleases": "Fallback to older releases", "filterReleaseTitlesByRegEx": "Filter Release Titles by Regular Expression", @@ -229,6 +228,9 @@ "dontShowTrackOnlyWarnings": "Don't Show 'Track-Only' Warnings", "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "about": "About", + "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 3d8f1ad..d3fae41 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -20,7 +20,6 @@ "githubPATLabel": "Token de Acceso Personal de GitHub (Reduce tiempos de espera)", "githubPATHint": "El TAP debe tener este formato: nombre_de_usuario:token", "githubPATFormat": "nombre_de_usuario:token", - "githubPATLinkText": "Sobre los TAP de GitHub", "includePrereleases": "Incluir versiones preliminares", "fallbackToOlderReleases": "Retorceder a versiones previas", "filterReleaseTitlesByRegEx": "Filtra Títulos de Versiones mediantes Expresiones Regulares", @@ -229,6 +228,9 @@ "dontShowTrackOnlyWarnings": "No mostrar avisos de 'Solo Seguimiento'", "dontShowAPKOriginWarnings": "No mostrar avisos de las fuentes de las APks", "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "about": "About", + "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 33da610..36e25d4 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -20,7 +20,6 @@ "githubPATLabel": "توکن دسترسی شخصی گیت هاب(محدودیت نرخ را افزایش میدهد)", "githubPATHint": "PAT باید در این قالب باشد: username:token", "githubPATFormat": "username:token", - "githubPATLinkText": "درباره گیتهاب PATs", "includePrereleases": "شامل نسخه های اولیه", "fallbackToOlderReleases": "بازگشت به نسخه های قدیمی تر", "filterReleaseTitlesByRegEx": "عناوین انتشار را با بیان منظم فیلتر کنید", @@ -229,6 +228,9 @@ "dontShowTrackOnlyWarnings": "هشدار 'فقط ردیابی' را نشان ندهید", "dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید", "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "about": "About", + "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 1840c8a..4e29966 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -20,7 +20,6 @@ "githubPATLabel": "Jeton d'Accès Personnel GitHub (Augmente la limite de débit)", "githubPATHint": "Le JAP doit être dans ce format : username:token", "githubPATFormat": "username:token", - "githubPATLinkText": "À propos des JAP GitHub", "includePrereleases": "Inclure les avant-premières", "fallbackToOlderReleases": "Retour aux anciennes versions", "filterReleaseTitlesByRegEx": "Filtrer les titres de version par expression régulière", @@ -229,6 +228,9 @@ "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "about": "About", + "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 26de38e..85134f0 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -20,7 +20,6 @@ "githubPATLabel": "GitHub személyes hozzáférési token (megnöveli a díjkorlátot)", "githubPATHint": "A PAT-nak a következő formátumban kell lennie: felhasználónév:token", "githubPATFormat": "felhasználónév:token", - "githubPATLinkText": "A GitHub PAT-okról", "includePrereleases": "Tartalmazza az előzetes kiadásokat", "fallbackToOlderReleases": "Visszatérés a régebbi kiadásokhoz", "filterReleaseTitlesByRegEx": "A kiadás címeinek szűrése reguláris kifejezéssel", @@ -228,6 +227,9 @@ "dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést", "dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket", "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "about": "About", + "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "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 0e49191..728bce8 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -20,7 +20,6 @@ "githubPATLabel": "GitHub Personal Access Token (diminuisce limite di traffico)", "githubPATHint": "PAT deve seguire questo formato: username:token", "githubPATFormat": "username:token", - "githubPATLinkText": "Informazioni su GitHub PAT", "includePrereleases": "Includi prerelease", "fallbackToOlderReleases": "Ripiega su release precedenti", "filterReleaseTitlesByRegEx": "Filtra release con espressioni regolari", @@ -229,6 +228,9 @@ "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "about": "About", + "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 7f5bf32..02ee143 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -20,7 +20,6 @@ "githubPATLabel": "GitHub パーソナルアクセストークン (レート制限の引き上げ)", "githubPATHint": "PATは次の形式でなければなりません: ユーザー名:トークン", "githubPATFormat": "ユーザー名:トークン", - "githubPATLinkText": "GitHub PATsについて", "includePrereleases": "プレリリースを含む", "fallbackToOlderReleases": "旧リリースへのフォールバック", "filterReleaseTitlesByRegEx": "正規表現でリリースタイトルを絞り込む", @@ -229,6 +228,9 @@ "dontShowTrackOnlyWarnings": "「追跡のみ」の警告を表示しない", "dontShowAPKOriginWarnings": "APK Originの警告を表示しない", "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "about": "About", + "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 91ca57d..1cf5267 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -20,7 +20,6 @@ "githubPATLabel": "GitHub 个人访问令牌(提升 API 请求限额)", "githubPATHint": "个人访问令牌必须为“username:token”的格式", "githubPATFormat": "username:token", - "githubPATLinkText": "关于 GitHub 个人访问令牌", "includePrereleases": "包含预发行版", "fallbackToOlderReleases": "将旧发行版作为备选", "filterReleaseTitlesByRegEx": "使用正则表达式筛选发行标题", @@ -229,6 +228,9 @@ "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "about": "About", + "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 88b4f5e..28d45cc 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -73,7 +73,8 @@ class FDroid extends AppSource { @override Future>> search(String query) async { - Response res = await sourceRequest('https://search.$host/?q=$query'); + Response res = await sourceRequest( + 'https://search.$host/?q=${Uri.encodeQueryComponent(query)}'); if (res.statusCode == 200) { Map> urlsWithDescriptions = {}; parse(res.body).querySelectorAll('.package-header').forEach((e) { diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index a9a76c3..f67c36e 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -35,7 +35,7 @@ class GitHub extends AppSource { hint: tr('githubPATFormat'), belowWidgets: [ const SizedBox( - height: 8, + height: 4, ), GestureDetector( onTap: () { @@ -44,10 +44,13 @@ class GitHub extends AppSource { mode: LaunchMode.externalApplication); }, child: Text( - tr('githubPATLinkText'), + tr('about'), style: const TextStyle( decoration: TextDecoration.underline, fontSize: 12), - )) + )), + const SizedBox( + height: 4, + ), ]) ]; diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index 07f8369..ae65875 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -1,15 +1,47 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; import 'package:html/parser.dart'; import 'package:http/http.dart'; import 'package:obtainium/app_sources/github.dart'; import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/settings_provider.dart'; import 'package:obtainium/providers/source_provider.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:url_launcher/url_launcher_string.dart'; class GitLab extends AppSource { GitLab() { host = 'gitlab.com'; overrideEligible = true; + canSearch = true; + + additionalSourceSpecificSettingFormItems = [ + GeneratedFormTextField('gitlab-creds', + label: tr('gitlabPATLabel'), + password: true, + required: false, + belowWidgets: [ + const SizedBox( + height: 4, + ), + GestureDetector( + onTap: () { + launchUrlString( + 'https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token', + mode: LaunchMode.externalApplication); + }, + child: Text( + tr('about'), + style: const TextStyle( + decoration: TextDecoration.underline, fontSize: 12), + )), + const SizedBox( + height: 4, + ) + ]) + ]; additionalSourceAppSpecificSettingFormItems = [ [ @@ -29,6 +61,37 @@ class GitLab extends AppSource { return url.substring(0, match.end); } + Future getPATIfAny() async { + SettingsProvider settingsProvider = SettingsProvider(); + await settingsProvider.initializeSettings(); + String? creds = settingsProvider + .getSettingString(additionalSourceSpecificSettingFormItems[0].key); + return creds != null && creds.isNotEmpty ? creds : null; + } + + @override + Future>> search(String query) async { + String? PAT = await getPATIfAny(); + if (PAT == null) { + throw CredsNeededError(name); + } + var url = + 'https://$host/api/v4/search?private_token=$PAT&scope=projects&search=${Uri.encodeQueryComponent(query)}'; + var res = await sourceRequest(url); + if (res.statusCode != 200) { + throw getObtainiumHttpError(res); + } + var json = jsonDecode(res.body) as List; + Map> results = {}; + json.forEach((element) { + results['https://$host/${element['path_with_namespace']}'] = [ + element['name_with_namespace'], + element['description'] ?? tr('noDescription') + ]; + }); + return results; + } + @override String? changeLogPageFromStandardUrl(String standardUrl) => '$standardUrl/-/releases'; diff --git a/lib/custom_errors.dart b/lib/custom_errors.dart index 99970ea..8f535cf 100644 --- a/lib/custom_errors.dart +++ b/lib/custom_errors.dart @@ -25,6 +25,11 @@ class InvalidURLError extends ObtainiumError { : super(tr('invalidURLForSource', args: [sourceName])); } +class CredsNeededError extends ObtainiumError { + CredsNeededError(String sourceName) + : super(tr('requiresCredentialsInSettings', args: [sourceName])); +} + class NoReleasesError extends ObtainiumError { NoReleasesError() : super(tr('noReleaseFound')); } diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 3cef280..3f1886e 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -248,9 +248,18 @@ class _AddAppPageState extends State { searching = true; }); try { - var results = await Future.wait(sourceProvider.sources - .where((e) => e.canSearch) - .map((e) => e.search(searchQuery))); + var results = await Future.wait( + sourceProvider.sources.where((e) => e.canSearch).map((e) async { + try { + return await e.search(searchQuery); + } catch (err) { + if (err is! CredsNeededError) { + rethrow; + } else { + return >{}; + } + } + })); // .then((results) async { // Interleave results instead of simple reduce diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 224a076..65684cf 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -205,6 +205,10 @@ class _SettingsPageState extends State { height: 16, ); + const height32 = SizedBox( + height: 32, + ); + return Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, body: CustomScrollView(slivers: [ @@ -217,9 +221,26 @@ class _SettingsPageState extends State { : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text( + tr('updates'), + style: TextStyle( + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.primary), + ), + intervalDropdown, + height32, + Text( + tr('sourceSpecific'), + style: TextStyle( + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.primary), + ), + ...sourceSpecificFields, + height32, Text( tr('appearance'), style: TextStyle( + fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary), ), themeDropdown, @@ -332,31 +353,11 @@ class _SettingsPageState extends State { }) ], ), - const Divider( - height: 16, - ), - height16, - Text( - tr('updates'), - style: TextStyle( - color: Theme.of(context).colorScheme.primary), - ), - intervalDropdown, - const Divider( - height: 48, - ), - Text( - tr('sourceSpecific'), - style: TextStyle( - color: Theme.of(context).colorScheme.primary), - ), - ...sourceSpecificFields, - const Divider( - height: 48, - ), + height32, Text( tr('categories'), style: TextStyle( + fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary), ), height16, From 2e4fe89b85898c753506443b3012f5a526d78107 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 6 May 2023 00:12:25 -0400 Subject: [PATCH 183/600] APKPure bugfix, upgrade packages --- lib/app_sources/apkpure.dart | 2 +- pubspec.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index 437ae4c..ac9155b 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -47,7 +47,7 @@ class APKPure extends AppSource { String? dateString = html.querySelector('span.info-other span.date')?.text.trim(); DateTime? releaseDate = dateString != null - ? DateFormat('MMMM d, yyyy').parse(dateString) + ? DateFormat('MMM dd, yyyy').parse(dateString) : null; List> apkUrls = [ MapEntry('$appId.apk', 'https://d.$host/b/APK/$appId?version=latest') diff --git a/pubspec.lock b/pubspec.lock index 0a80259..fc6d56b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -94,10 +94,10 @@ packages: dependency: transitive description: name: crypto - sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" csslib: dependency: transitive description: @@ -256,10 +256,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "8ffe990dac54a4a5492747added38571a5ab474c8e5d196809ea08849c69b1bb" + sha256: "96af49aa6b57c10a312106ad6f71deed5a754029c24789bbf620ba784f0bd0b0" url: "https://pub.dev" source: hosted - version: "2.0.13" + version: "2.0.14" flutter_test: dependency: "direct dev" description: flutter @@ -623,10 +623,10 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "8453780d1f703ead201a39673deb93decf85d543f359f750e2afc4908b55533f" + sha256: acf091c6e55c50d00b30b8532b2dd23e393cf775861665ebd0f15cdd6ebfb079 url: "https://pub.dev" source: hosted - version: "2.2.8" + version: "2.2.8+1" sqflite_common: dependency: transitive description: From 12867634b663a212ed36c02c245a7cafca2f46d8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 6 May 2023 00:13:05 -0400 Subject: [PATCH 184/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 056f3cc..c7ca28b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.12.3'; +const String currentVersion = '0.13.0'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 1826128..d1197a8 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.3+163 # When changing this, update the tag in main() accordingly +version: 0.13.0+164 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From ee292146d128a00f6b6123a24df8c098245d052e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 6 May 2023 00:30:46 -0400 Subject: [PATCH 185/600] Better GitHub release sorting in some cases (#534) --- lib/app_sources/github.dart | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index f67c36e..c314d26 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -2,8 +2,10 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; +import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/apps_provider.dart'; import 'package:obtainium/providers/settings_provider.dart'; import 'package:obtainium/providers/source_provider.dart'; import 'package:url_launcher/url_launcher_string.dart'; @@ -133,7 +135,7 @@ class GitHub extends AppSource { ? DateTime.parse(rel['published_at']) : null; releases.sort((a, b) { - // See #478 + // See #478 and #534 if (a == b) { return 0; } else if (a == null) { @@ -141,8 +143,19 @@ class GitHub extends AppSource { } else if (b == null) { return 1; } else { - return getReleaseDateFromRelease(a)! - .compareTo(getReleaseDateFromRelease(b)!); + var stdFormats = findStandardFormatsForVersion(a['tag_name'], true) + .intersection(findStandardFormatsForVersion(b['tag_name'], true)); + if (stdFormats.isNotEmpty) { + var reg = RegExp(stdFormats.first); + var matchA = reg.firstMatch(a['tag_name']); + var matchB = reg.firstMatch(b['tag_name']); + return compareAlphaNumeric( + (a['tag_name'] as String).substring(matchA!.start, matchA.end), + (b['tag_name'] as String).substring(matchB!.start, matchB.end)); + } else { + return getReleaseDateFromRelease(a)! + .compareTo(getReleaseDateFromRelease(b)!); + } } }); releases = releases.reversed.toList(); From 3be5543df44de2f595acbd3b3f53bacb17fc531f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 6 May 2023 01:25:39 -0400 Subject: [PATCH 186/600] Slight UI improvement on Add App page --- lib/pages/add_app.dart | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 3f1886e..ee0b2e4 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -340,8 +340,8 @@ class _AddAppPageState extends State { ], ), const SizedBox( - height: 25, - ), + height: 16, + ) ]); bool shouldShowSearchBar() => @@ -383,20 +383,18 @@ class _AddAppPageState extends State { Widget getAdditionalOptsCol() => Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - const Divider( - height: 64, + const SizedBox( + height: 16, ), Text( tr('additionalOptsFor', args: [pickedSource?.name ?? tr('source')]), - style: TextStyle(color: Theme.of(context).colorScheme.primary)), + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontWeight: FontWeight.bold)), const SizedBox( height: 16, ), - if (pickedSourceOverride != null || - pickedSource.runtimeType.toString() == - HTML().runtimeType.toString()) - getHTMLSourceOverrideDropdown(), GeneratedForm( key: Key(pickedSource.runtimeType.toString()), items: pickedSource!.combinedAppSpecificSettingFormItems, @@ -470,11 +468,15 @@ class _AddAppPageState extends State { const SizedBox( height: 16, ), - if (shouldShowSearchBar()) - const SizedBox( - height: 16, - ), + if (pickedSourceOverride != null || + (pickedSource != null && + pickedSource.runtimeType.toString() == + HTML().runtimeType.toString())) + getHTMLSourceOverrideDropdown(), if (shouldShowSearchBar()) getSearchBarRow(), + const SizedBox( + height: 16, + ), if (pickedSource != null) getAdditionalOptsCol() else From b07f5dd6b60ba6b947f56ce0b76206853ef6aada Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 6 May 2023 01:37:51 -0400 Subject: [PATCH 187/600] APKPure Bugfix --- lib/app_sources/apkpure.dart | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index ac9155b..9f75f7d 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -46,9 +46,18 @@ class APKPure extends AppSource { } String? dateString = html.querySelector('span.info-other span.date')?.text.trim(); - DateTime? releaseDate = dateString != null - ? DateFormat('MMM dd, yyyy').parse(dateString) - : null; + DateTime? releaseDate; + try { + releaseDate = dateString != null + ? DateFormat('MMM dd, yyyy').parse(dateString) + : null; + releaseDate = dateString != null && releaseDate == null + ? DateFormat('MMMM dd, yyyy').parse(dateString) + : null; + } catch (err) { + // ignore + } + List> apkUrls = [ MapEntry('$appId.apk', 'https://d.$host/b/APK/$appId?version=latest') ]; From 89b61884f1521c09c1c1238fab7693f73f201bdb Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Sat, 6 May 2023 15:52:23 +0900 Subject: [PATCH 188/600] Update ja.json --- assets/translations/ja.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 02ee143..40b44a2 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -227,10 +227,10 @@ "dontShowAgain": "二度と表示しない", "dontShowTrackOnlyWarnings": "「追跡のみ」の警告を表示しない", "dontShowAPKOriginWarnings": "APK Originの警告を表示しない", - "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", - "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", - "about": "About", - "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", + "moveNonInstalledAppsToBottom": "未インストールのアプリをアプリ一覧の下部に移動させる", + "gitlabPATLabel": "GitLab パーソナルアクセストークン (検索を有効化する)", + "about": "概要", + "requiresCredentialsInSettings": "これには追加の認証が必要です (設定にて)", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" From cc3c4cc79f6ceb48f0cf5ee5bc9e9a5b161e3b5a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 6 May 2023 13:20:58 -0400 Subject: [PATCH 189/600] Add XAPK support (incomplete - OBB not copied) --- lib/app_sources/apkpure.dart | 4 +- lib/pages/add_app.dart | 11 ++- lib/providers/apps_provider.dart | 131 ++++++++++++++++++++++++------- pubspec.lock | 24 ++++++ pubspec.yaml | 1 + 5 files changed, 139 insertions(+), 32 deletions(-) diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index 9f75f7d..1ab017d 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -57,9 +57,9 @@ class APKPure extends AppSource { } catch (err) { // ignore } - + String type = html.querySelector('a.info-tag')?.text.trim() ?? 'APK'; List> apkUrls = [ - MapEntry('$appId.apk', 'https://d.$host/b/APK/$appId?version=latest') + MapEntry('$appId.apk', 'https://d.$host/b/$type/$appId?version=latest') ]; String author = html .querySelector('span.info-sdk') diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index ee0b2e4..bdb18e4 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -159,9 +159,16 @@ class _AddAppPageState extends State { app.preferredApkIndex = app.apkUrls.map((e) => e.value).toList().indexOf(apkUrl.value); // ignore: use_build_context_synchronously - var downloadedApk = await appsProvider.downloadApp( + var downloadedArtifact = await appsProvider.downloadApp( app, globalNavigatorKey.currentContext); - app.id = downloadedApk.appId; + DownloadedApk? downloadedFile; + DownloadedXApkDir? downloadedDir; + if (downloadedArtifact is DownloadedApk) { + downloadedFile = downloadedArtifact; + } else { + downloadedDir = downloadedArtifact as DownloadedXApkDir; + } + app.id = downloadedFile?.appId ?? downloadedDir!.appId; } if (appsProvider.apps.containsKey(app.id)) { throw ObtainiumError(tr('appAlreadyAdded')); diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index e4f611c..9691428 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -27,6 +27,7 @@ import 'package:flutter_fgbg/flutter_fgbg.dart'; import 'package:obtainium/providers/source_provider.dart'; import 'package:http/http.dart'; import 'package:android_intent_plus/android_intent.dart'; +import 'package:archive/archive.dart'; class AppInMemory { late App app; @@ -46,6 +47,13 @@ class DownloadedApk { DownloadedApk(this.appId, this.file); } +class DownloadedXApkDir { + String appId; + File file; + Directory extracted; + DownloadedXApkDir(this.appId, this.file, this.extracted); +} + List generateStandardVersionRegExStrings() { // TODO: Look into RegEx for non-Latin characters / non-Arabic numerals var basics = [ @@ -164,7 +172,27 @@ class AppsProvider with ChangeNotifier { return downloadedFile; } - Future downloadApp(App app, BuildContext? context) async { + handleAPKIDChange(App app, PackageArchiveInfo newInfo, File downloadedFile, + String downloadUrl) async { + // If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed + // The former case should be handled (give the App its real ID), the latter is a security issue + if (app.id != newInfo.packageName) { + var isTempId = SourceProvider().isTempId(app); + if (apps[app.id] != null && !isTempId) { + throw IDChangedError(); + } + var originalAppId = app.id; + app.id = newInfo.packageName; + downloadedFile = downloadedFile.renameSync( + '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.apk'); + if (apps[originalAppId] != null) { + await removeApps([originalAppId]); + await saveApps([app], onlyIfExists: !isTempId); + } + } + } + + Future downloadApp(App app, BuildContext? context) async { NotificationsProvider? notificationsProvider = context?.read(); var notifId = DownloadNotification(app.finalName, 0).id; @@ -194,33 +222,42 @@ class AppsProvider with ChangeNotifier { } prevProg = prog; }); - // If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed - // The former case should be handled (give the App its real ID), the latter is a security issue - var newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); - if (app.id != newInfo.packageName) { - var isTempId = SourceProvider().isTempId(app); - if (apps[app.id] != null && !isTempId) { - throw IDChangedError(); - } - var originalAppId = app.id; - app.id = newInfo.packageName; - downloadedFile = downloadedFile.renameSync( - '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.apk'); - if (apps[originalAppId] != null) { - await removeApps([originalAppId]); - await saveApps([app], onlyIfExists: !isTempId); - } + PackageArchiveInfo? newInfo; + try { + newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); + } catch (e) { + // Assume it's an XAPK + fileName = '${app.id}-${downloadUrl.hashCode}.xapk'; + String newPath = '${downloadedFile.parent.path}/$fileName'; + downloadedFile.renameSync(newPath); + downloadedFile = File(newPath); } - // Delete older versions of the APK if any + Directory? xapkDir; + if (newInfo == null) { + String xapkDirPath = '${downloadedFile.path}-dir'; + unzipFile(downloadedFile.path, '${downloadedFile.path}-dir'); + xapkDir = Directory(xapkDirPath); + var apks = xapkDir + .listSync() + .where((e) => e.path.toLowerCase().endsWith('.apk')) + .toList(); + newInfo = await PackageArchiveInfo.fromPath(apks.first.path); + } + await handleAPKIDChange(app, newInfo, downloadedFile, downloadUrl); + // Delete older versions of the file if any for (var file in downloadedFile.parent.listSync()) { var fn = file.path.split('/').last; if (fn.startsWith('${app.id}-') && - fn.endsWith('.apk') && + fn.toLowerCase().endsWith(xapkDir == null ? '.apk' : '.xapk') && fn != downloadedFile.path.split('/').last) { file.delete(); } } - return DownloadedApk(app.id, downloadedFile); + if (xapkDir != null) { + return DownloadedXApkDir(app.id, downloadedFile, xapkDir); + } else { + return DownloadedApk(app.id, downloadedFile); + } } finally { notificationsProvider?.cancel(notifId); if (apps[app.id] != null) { @@ -267,10 +304,37 @@ class AppsProvider with ChangeNotifier { } } - // Unfortunately this 'await' does not actually wait for the APK to finish installing - // So we only know that the install prompt was shown, but the user could still cancel w/o us knowing - // If appropriate criteria are met, the update (never a fresh install) happens silently in the background - // But even then, we don't know if it actually succeeded + void unzipFile(String filePath, String destinationPath) { + final bytes = File(filePath).readAsBytesSync(); + final archive = ZipDecoder().decodeBytes(bytes); + + for (final file in archive) { + final filename = '$destinationPath/${file.name}'; + if (file.isFile) { + final data = file.content as List; + File(filename) + ..createSync(recursive: true) + ..writeAsBytesSync(data); + } else { + Directory(filename).create(recursive: true); + } + } + } + + Future installXApkDir(DownloadedXApkDir dir, + {bool silent = false}) async { + try { + for (var apk in dir.extracted + .listSync() + .where((f) => f is File && f.path.toLowerCase().endsWith('.apk'))) { + await installApk(DownloadedApk(dir.appId, apk as File), silent: silent); + } + dir.file.delete(); + } finally { + dir.extracted.delete(recursive: true); + } + } + Future installApk(DownloadedApk file, {bool silent = false}) async { // TODO: Use 'silent' when/if ever possible var newInfo = await PackageArchiveInfo.fromPath(file.file.path); @@ -420,9 +484,16 @@ class AppsProvider with ChangeNotifier { for (var id in appsToInstall) { try { // ignore: use_build_context_synchronously - var downloadedFile = await downloadApp(apps[id]!.app, context); - bool willBeSilent = - await canInstallSilently(apps[downloadedFile.appId]!.app); + var downloadedArtifact = await downloadApp(apps[id]!.app, context); + DownloadedApk? downloadedFile; + DownloadedXApkDir? downloadedDir; + if (downloadedArtifact is DownloadedApk) { + downloadedFile = downloadedArtifact; + } else { + downloadedDir = downloadedArtifact as DownloadedXApkDir; + } + bool willBeSilent = await canInstallSilently( + apps[downloadedFile?.appId ?? downloadedDir!.appId]!.app); willBeSilent = false; // TODO: Remove this when silent updates work if (!(await settingsProvider?.getInstallPermission(enforce: false) ?? true)) { @@ -432,7 +503,11 @@ class AppsProvider with ChangeNotifier { // ignore: use_build_context_synchronously await waitForUserToReturnToForeground(context); } - await installApk(downloadedFile, silent: willBeSilent); + if (downloadedFile != null) { + await installApk(downloadedFile, silent: willBeSilent); + } else { + await installXApkDir(downloadedDir!, silent: willBeSilent); + } installedIds.add(id); } catch (e) { errors.add(id, e.toString()); diff --git a/pubspec.lock b/pubspec.lock index fc6d56b..c5513ac 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -34,6 +34,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.7" + archive: + dependency: "direct main" + description: + name: archive + sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + url: "https://pub.dev" + source: hosted + version: "3.3.7" args: dependency: transitive description: @@ -82,6 +90,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" cross_file: dependency: transitive description: @@ -518,6 +534,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" + source: hosted + version: "3.7.3" process: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d1197a8..36665bd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -63,6 +63,7 @@ dependencies: easy_localization: ^3.0.1 android_intent_plus: ^3.1.5 flutter_markdown: ^0.6.14 + archive: ^3.3.7 dev_dependencies: From d5f7eced8beb8b3af626293d49e15eb20e62a28b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 6 May 2023 13:28:41 -0400 Subject: [PATCH 190/600] UI tweaks --- lib/pages/apps.dart | 10 ++++++---- lib/providers/apps_provider.dart | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 6a0a947..f7a8159 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -515,10 +515,12 @@ class AppsPageState extends State { ? FontWeight.bold : FontWeight.normal)), trailing: listedApps[index].downloadProgress != null - ? Text(tr('percentProgress', args: [ - listedApps[index].downloadProgress?.toInt().toString() ?? - '100' - ])) + ? SizedBox( + width: 110, + child: Text(tr('percentProgress', args: [ + listedApps[index].downloadProgress?.toInt().toString() ?? + '100' + ]))) : trailingRow, onTap: () { if (selectedAppIds.isNotEmpty) { diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 9691428..3e6f5ea 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -809,7 +809,7 @@ class AppsProvider with ChangeNotifier { apps[i].installedVersion = null; } } - await saveApps(apps, attemptToCorrectInstallStatus: !remove); + await saveApps(apps, attemptToCorrectInstallStatus: false); } if (remove) { await removeApps(apps.map((e) => e.id).toList()); From cc268aeeda7c7351d27a0d94c434b9df31b915d4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 6 May 2023 14:25:17 -0400 Subject: [PATCH 191/600] "Check updates on start" toggle --- assets/translations/de.json | 3 +- assets/translations/en.json | 3 +- assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 3 +- assets/translations/hu.json | 1 + assets/translations/it.json | 3 +- assets/translations/ja.json | 1 + assets/translations/zh.json | 1 + lib/pages/apps.dart | 41 ++++++++++++++++++---------- lib/pages/settings.dart | 12 ++++++++ lib/providers/settings_provider.dart | 18 ++++++++++++ 12 files changed, 70 insertions(+), 18 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index fb3135a..5f53337 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -121,7 +121,7 @@ "followSystem": "System folgen", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use pure black dark theme", + "useBlackTheme": "Use Pure Black Dark Theme", "appSortBy": "App sortieren nach", "authorName": "Autor/Name", "nameAuthor": "Name/Autor", @@ -231,6 +231,7 @@ "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", + "checkOnStart": "Check Once on Start", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index dd027a9..eb59399 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -121,7 +121,7 @@ "followSystem": "Follow System", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use pure black dark theme", + "useBlackTheme": "Use Pure Black Dark Theme", "appSortBy": "App Sort By", "authorName": "Author/Name", "nameAuthor": "Name/Author", @@ -231,6 +231,7 @@ "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", + "checkOnStart": "Check Once on Start", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index d3fae41..c013d01 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -231,6 +231,7 @@ "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", + "checkOnStart": "Check Once on Start", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 36e25d4..5685c1e 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -231,6 +231,7 @@ "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", + "checkOnStart": "Check Once on Start", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 4e29966..90c060f 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -121,7 +121,7 @@ "followSystem": "Suivre le système", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use pure black dark theme", + "useBlackTheme": "Use Pure Black Dark Theme", "appSortBy": "Applications triées par", "authorName": "Auteur/Nom", "nameAuthor": "Nom/Auteur", @@ -231,6 +231,7 @@ "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", + "checkOnStart": "Check Once on Start", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 85134f0..c73ef70 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -230,6 +230,7 @@ "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", + "checkOnStart": "Check Once on Start", "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 728bce8..0cff11d 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -121,7 +121,7 @@ "followSystem": "Segui sistema", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use pure black dark theme", + "useBlackTheme": "Use Pure Black Dark Theme", "appSortBy": "App ordinate per", "authorName": "Autore/Nome", "nameAuthor": "Nome/Autore", @@ -231,6 +231,7 @@ "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", + "checkOnStart": "Check Once on Start", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 02ee143..621b831 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -231,6 +231,7 @@ "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", + "checkOnStart": "Check Once on Start", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 1cf5267..cd6f101 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -231,6 +231,7 @@ "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", + "checkOnStart": "Check Once on Start", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index f7a8159..5fcee6a 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -52,6 +52,9 @@ class AppsPageState extends State { } } + final GlobalKey _refreshIndicatorKey = + GlobalKey(); + @override Widget build(BuildContext context) { var appsProvider = context.watch(); @@ -61,6 +64,27 @@ class AppsPageState extends State { var currentFilterIsUpdatesOnly = filter.isIdenticalTo(updatesOnlyFilter, settingsProvider); + refresh() { + HapticFeedback.lightImpact(); + setState(() { + refreshingSince = DateTime.now(); + }); + return appsProvider.checkUpdates().catchError((e) { + showError(e, context); + }).whenComplete(() { + setState(() { + refreshingSince = null; + }); + }); + } + + if (!appsProvider.loadingApps && + appsProvider.apps.isNotEmpty && + settingsProvider.checkJustStarted() && + settingsProvider.checkOnStart) { + _refreshIndicatorKey.currentState?.show(); + } + selectedAppIds = selectedAppIds .where((element) => listedApps.map((e) => e.app.id).contains(element)) .toSet(); @@ -315,7 +339,7 @@ class AppsPageState extends State { ?.isBefore(refreshingSince!) ?? true)) .length / - appsProvider.apps.length, + (appsProvider.apps.isNotEmpty ? appsProvider.apps.length : 1), ), ) ]; @@ -1019,19 +1043,8 @@ class AppsPageState extends State { return Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, body: RefreshIndicator( - onRefresh: () { - HapticFeedback.lightImpact(); - setState(() { - refreshingSince = DateTime.now(); - }); - return appsProvider.checkUpdates().catchError((e) { - showError(e, context); - }).whenComplete(() { - setState(() { - refreshingSince = null; - }); - }); - }, + key: _refreshIndicatorKey, + onRefresh: refresh, child: CustomScrollView(slivers: [ CustomAppBar(title: tr('appsString')), ...getLoadingWidgets(), diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 65684cf..7827111 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -228,6 +228,18 @@ class _SettingsPageState extends State { color: Theme.of(context).colorScheme.primary), ), intervalDropdown, + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible(child: Text(tr('checkOnStart'))), + Switch( + value: settingsProvider.checkOnStart, + onChanged: (value) { + settingsProvider.checkOnStart = value; + }) + ], + ), height32, Text( tr('sourceSpecific'), diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 162d7f9..8ddfdf2 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -35,6 +35,7 @@ List updateIntervals = [15, 30, 60, 120, 180, 360, 720, 1440, 4320, 0] class SettingsProvider with ChangeNotifier { SharedPreferences? prefs; + bool justStarted = true; String sourceUrl = 'https://github.com/ImranR98/Obtainium'; @@ -92,6 +93,15 @@ class SettingsProvider with ChangeNotifier { notifyListeners(); } + bool get checkOnStart { + return prefs?.getBool('checkOnStart') ?? false; + } + + set checkOnStart(bool checkOnStart) { + prefs?.setBool('checkOnStart', checkOnStart); + notifyListeners(); + } + SortColumnSettings get sortColumn { return SortColumnSettings.values[ prefs?.getInt('sortColumn') ?? SortColumnSettings.nameAuthor.index]; @@ -120,6 +130,14 @@ class SettingsProvider with ChangeNotifier { return result; } + bool checkJustStarted() { + if (justStarted) { + justStarted = false; + return true; + } + return false; + } + Future getInstallPermission({bool enforce = false}) async { while (!(await Permission.requestInstallPackages.isGranted)) { // Explicit request as InstallPlugin request sometimes bugged From e1db024034a14169acb7c805aaf2d8c3a2854473 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 6 May 2023 14:40:14 -0400 Subject: [PATCH 192/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index c7ca28b..b9044c4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.0'; +const String currentVersion = '0.13.1'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 36665bd..5d786c4 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.13.0+164 # When changing this, update the tag in main() accordingly +version: 0.13.1+165 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 480467492aff7538f7d3081602e945933aa22896 Mon Sep 17 00:00:00 2001 From: Matsuri Date: Sun, 7 May 2023 22:00:02 +0800 Subject: [PATCH 193/600] Update zh.json - Translate new strings - Slight improvements Signed-off-by: Matsuri --- assets/translations/zh.json | 44 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/assets/translations/zh.json b/assets/translations/zh.json index cd6f101..f00d46b 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -33,7 +33,7 @@ "githubStarredRepos": "GitHub 已星标仓库", "uname": "用户名", "wrongArgNum": "参数数量错误", - "xIsTrackOnly": "{} 为“仅追踪”模式", + "xIsTrackOnly": "{}为“仅追踪”模式", "source": "源代码", "app": "应用", "appsFromSourceAreTrackOnly": "此来源的应用为“仅追踪”模式。", @@ -50,8 +50,8 @@ "search": "搜索", "additionalOptsFor": "{} 的更多选项", "supportedSourcesBelow": "支持的来源:", - "trackOnlyInBrackets": "(仅追踪)", - "searchableInBrackets": "(可搜索)", + "trackOnlyInBrackets": "(仅追踪)", + "searchableInBrackets": "(可搜索)", "appsString": "应用列表", "noApps": "无应用", "noAppsForFilter": "没有符合条件的应用", @@ -59,9 +59,9 @@ "percentProgress": "进度:{}%", "pleaseWait": "请稍候", "updateAvailable": "更新可用", - "estimateInBracketsShort": "(预计)", + "estimateInBracketsShort": "(推测)", "notInstalled": "未安装", - "estimateInBrackets": "(预计)", + "estimateInBrackets": "(推测)", "selectAll": "全选", "deselectN": "取消选择 {}", "xWillBeRemovedButRemainInstalled": "{} 将从 Obtainium 中删除,但仍安装在您的设备中。", @@ -74,8 +74,8 @@ "installUpdateApps": "安装/更新应用", "installUpdateSelectedApps": "安装/更新选中的应用", "markXSelectedAppsAsUpdated": "是否将选中的 {} 个应用标记为已更新?", - "no": "不要", - "yes": "好的", + "no": "否", + "yes": "是", "markSelectedAppsUpdated": "将选中的应用标记为已更新", "pinToTop": "置顶", "unpinFromTop": "取消置顶", @@ -142,7 +142,7 @@ "close": "关闭", "share": "分享", "appNotFound": "未找到应用", - "obtainiumExportHyphenatedLowercase": "obtainium-导出", + "obtainiumExportHyphenatedLowercase": "obtainium-export", "pickAnAPK": "选择一个 APK 文件", "appHasMoreThanOnePackage": "{} 有多个架构可用:", "deviceSupportsXArch": "您的设备支持 {} 架构。", @@ -172,13 +172,13 @@ "versionCorrectionDisabled": "禁用版本号更正(插件似乎未起作用)", "unknown": "未知", "none": "无", - "never": "从不", + "never": "从未", "latestVersionX": "最新版本:{}", "installedVersionX": "当前版本:{}", "lastUpdateCheckX": "上次更新检查:{}", "remove": "删除", - "yesMarkUpdated": "是的,标记为已更新", - "fdroid": "F-Droid Official", + "yesMarkUpdated": "是,标记为已更新", + "fdroid": "F-Droid 官方存储库", "appIdOrName": "应用 ID 或名称", "appWithIdOrNameNotFound": "未找到符合此 ID 或名称的应用", "reposHaveMultipleApps": "存储库中可能包含多个应用", @@ -193,7 +193,7 @@ "additionalOptions": "附加选项", "disableVersionDetection": "禁用版本检测", "noVersionDetectionExplanation": "此选项应该仅用于无法进行版本检测的应用。", - "downloadingX": "正在下载 {}", + "downloadingX": "正在下载{}", "downloadNotifDescription": "提示应用的下载进度", "noAPKFound": "未找到 APK 文件", "noVersionDetection": "禁用版本检测", @@ -222,16 +222,16 @@ "versionDetection": "版本检测", "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", - "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", - "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", - "about": "About", - "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", - "checkOnStart": "Check Once on Start", + "autoApkFilterByArch": "如果可能,尝试按设备支持的 CPU 架构筛选 APK 文件", + "overrideSource": "覆盖来源", + "dontShowAgain": "不再显示", + "dontShowTrackOnlyWarnings": "不显示“仅追踪”模式警告", + "dontShowAPKOriginWarnings": "不显示 APK 文件来源警告", + "moveNonInstalledAppsToBottom": "将未安装应用置底", + "gitlabPATLabel": "GitLab 个人访问令牌(用于搜索)", + "about": "相关文档", + "requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)", + "checkOnStart": "启动时进行一次检查", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" From 408bca8951e82c5659030156cfa81f84d69f05d4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 9 May 2023 00:37:06 -0400 Subject: [PATCH 194/600] XAPK bugfixes, HTML default User-Agent --- lib/app_sources/html.dart | 7 ++ lib/pages/app.dart | 4 +- lib/pages/apps.dart | 8 +- lib/providers/apps_provider.dart | 89 +++++++++++++++-------- lib/providers/notifications_provider.dart | 3 +- 5 files changed, 76 insertions(+), 35 deletions(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index d9ec173..c6ec9e2 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -89,6 +89,13 @@ class HTML extends AppSource { overrideEligible = true; } + @override + // TODO: implement requestHeaders choice, hardcoded for now + Map? get requestHeaders => { + "User-Agent": + "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0" + }; + @override String sourceSpecificStandardizeURL(String url) { return url; diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 8f851e5..b7585c8 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -444,7 +444,9 @@ class _AppPageState extends State { Padding( padding: const EdgeInsets.fromLTRB(0, 8, 0, 0), child: LinearProgressIndicator( - value: app!.downloadProgress! / 100)) + value: app!.downloadProgress! >= 0 + ? app.downloadProgress! / 100 + : null)) ], )); diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 5fcee6a..37fa60c 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -542,8 +542,12 @@ class AppsPageState extends State { ? SizedBox( width: 110, child: Text(tr('percentProgress', args: [ - listedApps[index].downloadProgress?.toInt().toString() ?? - '100' + listedApps[index].downloadProgress! >= 0 + ? listedApps[index] + .downloadProgress! + .toInt() + .toString() + : tr('pleaseWait') ]))) : trailingRow, onTap: () { diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 3e6f5ea..65eb1a3 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -132,15 +132,21 @@ class AppsProvider with ChangeNotifier { }(); } - downloadFile(String url, String fileName, Function? onProgress, + Future downloadFile( + String url, String fileNameNoExt, Function? onProgress, {bool useExisting = true, Map? headers}) async { var destDir = (await getExternalCacheDirectories())!.first.path; var req = Request('GET', Uri.parse(url)); if (headers != null) { req.headers.addAll(headers); } - StreamedResponse response = await Client().send(req); - File downloadedFile = File('$destDir/$fileName'); + var client = Client(); + StreamedResponse response = await client.send(req); + var ext = response.headers['content-disposition']!.split('.').last; + if (ext.endsWith('"') || ext.endsWith("other")) { + ext = ext.substring(0, ext.length - 1); + } + File downloadedFile = File('$destDir/$fileNameNoExt.$ext'); if (!(downloadedFile.existsSync() && useExisting)) { File tempDownloadedFile = File('${downloadedFile.path}.part'); if (tempDownloadedFile.existsSync()) { @@ -168,12 +174,14 @@ class AppsProvider with ChangeNotifier { throw response.reasonPhrase ?? tr('unexpectedError'); } tempDownloadedFile.renameSync(downloadedFile.path); + } else { + client.close(); } return downloadedFile; } - handleAPKIDChange(App app, PackageArchiveInfo newInfo, File downloadedFile, - String downloadUrl) async { + Future handleAPKIDChange(App app, PackageArchiveInfo newInfo, + File downloadedFile, String downloadUrl) async { // If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed // The former case should be handled (give the App its real ID), the latter is a security issue if (app.id != newInfo.packageName) { @@ -184,12 +192,13 @@ class AppsProvider with ChangeNotifier { var originalAppId = app.id; app.id = newInfo.packageName; downloadedFile = downloadedFile.renameSync( - '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.apk'); + '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.${downloadedFile.path.split('.').last}'); if (apps[originalAppId] != null) { await removeApps([originalAppId]); await saveApps([app], onlyIfExists: !isTempId); } } + return downloadedFile; } Future downloadApp(App app, BuildContext? context) async { @@ -205,11 +214,11 @@ class AppsProvider with ChangeNotifier { .getSource(app.url, overrideSource: app.overrideSource); String downloadUrl = await source.apkUrlPrefetchModifier( app.apkUrls[app.preferredApkIndex].value, app.url); - var fileName = '${app.id}-${downloadUrl.hashCode}.apk'; var notif = DownloadNotification(app.finalName, 100); notificationsProvider?.cancel(notif.id); int? prevProg; - File downloadedFile = await downloadFile(downloadUrl, fileName, + var fileNameNoExt = '${app.id}-${downloadUrl.hashCode}'; + var downloadedFile = await downloadFile(downloadUrl, fileNameNoExt, headers: source.requestHeaders, (double? progress) { int? prog = progress?.ceil(); if (apps[app.id] != null) { @@ -222,18 +231,20 @@ class AppsProvider with ChangeNotifier { } prevProg = prog; }); - PackageArchiveInfo? newInfo; - try { - newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); - } catch (e) { - // Assume it's an XAPK - fileName = '${app.id}-${downloadUrl.hashCode}.xapk'; - String newPath = '${downloadedFile.parent.path}/$fileName'; - downloadedFile.renameSync(newPath); - downloadedFile = File(newPath); + // Set to 90 for remaining steps, will make null in 'finally' + if (apps[app.id] != null) { + apps[app.id]!.downloadProgress = -1; + notifyListeners(); + notif = DownloadNotification(app.finalName, -1); + notificationsProvider?.notify(notif); } + PackageArchiveInfo? newInfo; + var isAPK = downloadedFile.path.toLowerCase().endsWith('.apk'); Directory? xapkDir; - if (newInfo == null) { + if (isAPK) { + newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); + } else { + // Assume XAPK String xapkDirPath = '${downloadedFile.path}-dir'; unzipFile(downloadedFile.path, '${downloadedFile.path}-dir'); xapkDir = Directory(xapkDirPath); @@ -243,20 +254,21 @@ class AppsProvider with ChangeNotifier { .toList(); newInfo = await PackageArchiveInfo.fromPath(apks.first.path); } - await handleAPKIDChange(app, newInfo, downloadedFile, downloadUrl); + downloadedFile = + await handleAPKIDChange(app, newInfo, downloadedFile, downloadUrl); // Delete older versions of the file if any for (var file in downloadedFile.parent.listSync()) { var fn = file.path.split('/').last; if (fn.startsWith('${app.id}-') && - fn.toLowerCase().endsWith(xapkDir == null ? '.apk' : '.xapk') && - fn != downloadedFile.path.split('/').last) { + FileSystemEntity.isFileSync(file.path) && + file.path != downloadedFile.path) { file.delete(); } } - if (xapkDir != null) { - return DownloadedXApkDir(app.id, downloadedFile, xapkDir); - } else { + if (isAPK) { return DownloadedApk(app.id, downloadedFile); + } else { + return DownloadedXApkDir(app.id, downloadedFile, xapkDir!); } } finally { notificationsProvider?.cancel(notifId); @@ -324,18 +336,23 @@ class AppsProvider with ChangeNotifier { Future installXApkDir(DownloadedXApkDir dir, {bool silent = false}) async { try { + var somethingInstalled = false; for (var apk in dir.extracted .listSync() .where((f) => f is File && f.path.toLowerCase().endsWith('.apk'))) { - await installApk(DownloadedApk(dir.appId, apk as File), silent: silent); + somethingInstalled = somethingInstalled || + await installApk(DownloadedApk(dir.appId, apk as File), + silent: silent); + } + if (somethingInstalled) { + dir.file.delete(); } - dir.file.delete(); } finally { dir.extracted.delete(recursive: true); } } - Future installApk(DownloadedApk file, {bool silent = false}) async { + Future installApk(DownloadedApk file, {bool silent = false}) async { // TODO: Use 'silent' when/if ever possible var newInfo = await PackageArchiveInfo.fromPath(file.file.path); AppInfo? appInfo; @@ -351,14 +368,17 @@ class AppsProvider with ChangeNotifier { } int? code = await AndroidPackageInstaller.installApk(apkFilePath: file.file.path); + bool installed = false; if (code != null && code != 0 && code != 3) { throw InstallError(code); } else if (code == 0) { + installed = true; apps[file.appId]!.app.installedVersion = apps[file.appId]!.app.latestVersion; file.file.delete(); } await saveApps([apps[file.appId]!.app]); + return installed; } void uninstallApp(String appId) async { @@ -503,10 +523,17 @@ class AppsProvider with ChangeNotifier { // ignore: use_build_context_synchronously await waitForUserToReturnToForeground(context); } - if (downloadedFile != null) { - await installApk(downloadedFile, silent: willBeSilent); - } else { - await installXApkDir(downloadedDir!, silent: willBeSilent); + apps[id]?.downloadProgress = -1; + notifyListeners(); + try { + if (downloadedFile != null) { + await installApk(downloadedFile, silent: willBeSilent); + } else { + await installXApkDir(downloadedDir!, silent: willBeSilent); + } + } finally { + apps[id]?.downloadProgress = null; + notifyListeners(); } installedIds.add(id); } catch (e) { diff --git a/lib/providers/notifications_provider.dart b/lib/providers/notifications_provider.dart index f48b09a..1f39cc8 100644 --- a/lib/providers/notifications_provider.dart +++ b/lib/providers/notifications_provider.dart @@ -167,7 +167,8 @@ class NotificationsProvider { progress: progPercent ?? 0, maxProgress: 100, showProgress: progPercent != null, - onlyAlertOnce: onlyAlertOnce))); + onlyAlertOnce: onlyAlertOnce, + indeterminate: progPercent != null && progPercent < 0))); } Future notify(ObtainiumNotification notif, From 65ab72ba901c90381d32829fdc4a944abf599f07 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 9 May 2023 00:40:39 -0400 Subject: [PATCH 195/600] Increment version --- lib/main.dart | 2 +- pubspec.lock | 20 ++++++++++---------- pubspec.yaml | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index b9044c4..900cd41 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.1'; +const String currentVersion = '0.13.2'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index c5513ac..32e6c98 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -426,10 +426,10 @@ packages: dependency: "direct main" description: name: path_provider - sha256: c7edf82217d4b2952b2129a61d3ad60f1075b9299e629e149a8d2e39c2e6aad4 + sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" url: "https://pub.dev" source: hosted - version: "2.0.14" + version: "2.0.15" path_provider_android: dependency: transitive description: @@ -442,10 +442,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: ad4c4d011830462633f03eb34445a45345673dfd4faf1ab0b4735fbd93b19183 + sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" path_provider_linux: dependency: transitive description: @@ -578,10 +578,10 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "858aaa72d8f61637d64e776aca82e1c67e6d9ee07979123c5d17115031c1b13b" + sha256: "16d3fb6b3692ad244a695c0183fca18cf81fd4b821664394a781de42386bf022" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" shared_preferences_android: dependency: transitive description: @@ -594,10 +594,10 @@ packages: dependency: transitive description: name: shared_preferences_foundation - sha256: "0c1c16c56c9708aa9c361541a6f0e5cc6fc12a3232d866a687a7b7db30032b07" + sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_linux: dependency: transitive description: @@ -647,10 +647,10 @@ packages: dependency: "direct main" description: name: sqflite - sha256: acf091c6e55c50d00b30b8532b2dd23e393cf775861665ebd0f15cdd6ebfb079 + sha256: "3a82c9a216b46b88617e3714dd74227eaca20c501c4abcc213e56db26b9caa00" url: "https://pub.dev" source: hosted - version: "2.2.8+1" + version: "2.2.8+2" sqflite_common: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5d786c4..730cb10 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.13.1+165 # When changing this, update the tag in main() accordingly +version: 0.13.2+166 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 59cfa242fb53f17dbe3bdc4ea8991a06d584fdf1 Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Wed, 10 May 2023 18:20:40 +0200 Subject: [PATCH 196/600] Update de.json translate newly added English text improved some German text --- assets/translations/de.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 5f53337..040f4cd 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -121,12 +121,12 @@ "followSystem": "System folgen", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use Pure Black Dark Theme", + "useBlackTheme": "Verwende Pure Black Dark Theme", "appSortBy": "App sortieren nach", "authorName": "Autor/Name", "nameAuthor": "Name/Autor", "asAdded": "Wie hinzugefügt", - "appSortOrder": "App Sortierung nach", + "appSortOrder": "App sortieren nach", "ascending": "Aufsteigend", "descending": "Absteigend", "bgUpdateCheckInterval": "Prüfintervall für Hintergrundaktualisierung", @@ -207,7 +207,7 @@ "addCategory": "Kategorie hinzufügen", "label": "Bezeichnung", "language": "Sprache", - "copiedToClipboard": "Copied to Clipboard", + "copiedToClipboard": "In die Zwischenablage kopiert", "storagePermissionDenied": "Speicherberechtigung verweigert", "selectedCategorizeWarning": "Dadurch werden alle bestehenden Kategorieeinstellungen für die ausgewählten Apps ersetzt.", "filterAPKsByRegEx": "APKs nach regulärem Ausdruck filtern", @@ -218,7 +218,7 @@ "releaseDateAsVersionExplanation": "Diese Option sollte nur für Apps verwendet werden, bei denen die Versionserkennung nicht korrekt funktioniert, aber ein Veröffentlichungsdatum verfügbar ist.", "changes": "Änderungen", "releaseDate": "Veröffentlichungsdatum", - "importFromURLsInFile": "Importieren von URLs aus Datei ( z.B. OPML)", + "importFromURLsInFile": "Importieren von URLs aus Datei (z. B. OPML)", "versionDetection": "Versionserkennung", "standardVersionDetection": "Standardversionserkennung", "groupByCategory": "Nach Kategorie gruppieren", @@ -227,11 +227,11 @@ "dontShowAgain": "Nicht noch einmal zeigen", "dontShowTrackOnlyWarnings": "Warnung für 'Nur Nachverfolgen' nicht anzeigen", "dontShowAPKOriginWarnings": "Warnung für APK-Herkunft nicht anzeigen", - "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", - "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", - "about": "About", - "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", - "checkOnStart": "Check Once on Start", + "moveNonInstalledAppsToBottom": "Nicht installierte Apps ans Ende der Apps Ansicht verschieben", + "gitlabPATLabel": "GitLab Personal Access Token (Aktiviert Suche)", + "about": "Über", + "requiresCredentialsInSettings": "Benötigt zusätzliche Anmeldedaten (in den Einstellungen)", + "checkOnStart": "Überprüfe einmalig beim Start", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" @@ -258,7 +258,7 @@ }, "minute": { "one": "{} Minute", - "other": "{} Minutes" + "other": "{} Minuten" }, "hour": { "one": "{} Stunde", From 0673e90dff29da8a1e8f330fc60fbc39e2f1977f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 12 May 2023 17:53:07 -0400 Subject: [PATCH 197/600] Better APK cleanup --- lib/providers/apps_provider.dart | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 65eb1a3..d15c5e3 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -122,10 +122,13 @@ class AppsProvider with ChangeNotifier { // Load Apps into memory (in background, this is done later instead of in the constructor) await loadApps(); // Delete any partial APKs + var cutoff = DateTime.now().subtract(const Duration(days: 7)); (await getExternalCacheDirectories()) ?.first .listSync() - .where((element) => element.path.endsWith('.apk.part')) + .where((element) => + element.path.endsWith('.part') || + element.statSync().modified.isBefore(cutoff)) .forEach((partialApk) { partialApk.delete(); }); @@ -786,11 +789,18 @@ class AppsProvider with ChangeNotifier { } Future removeApps(List appIds) async { + var apkFiles = (await getExternalCacheDirectories())?.first.listSync(); for (var appId in appIds) { File file = File('${(await getAppsDir()).path}/$appId.json'); if (file.existsSync()) { file.deleteSync(); } + apkFiles + ?.where( + (element) => element.path.split('/').last.startsWith('$appId-')) + .forEach((element) { + element.delete(); + }); if (apps.containsKey(appId)) { apps.remove(appId); } From b196715d6016a201ebba931163e0f2099d019d6c Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 12 May 2023 18:00:21 -0400 Subject: [PATCH 198/600] Search UI improvements --- lib/pages/add_app.dart | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index bdb18e4..ac85b10 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -283,6 +283,9 @@ class _AddAppPageState extends State { } si++; } + if (res.isEmpty) { + throw ObtainiumError(tr('noResults')); + } List? selectedUrls = res.isEmpty ? [] // ignore: use_build_context_synchronously @@ -377,13 +380,15 @@ class _AddAppPageState extends State { const SizedBox( width: 16, ), - ElevatedButton( - onPressed: searchQuery.isEmpty || doingSomething - ? null - : () { - runSearch(); - }, - child: Text(tr('search'))) + searching + ? const CircularProgressIndicator() + : ElevatedButton( + onPressed: searchQuery.isEmpty || doingSomething + ? null + : () { + runSearch(); + }, + child: Text(tr('search'))) ], ); From 431a01f2a5fd7055d17300b56c82dc437f1fdc87 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 13 May 2023 02:32:06 -0400 Subject: [PATCH 199/600] Fixed breaking bug for some sources (#561) --- lib/main.dart | 2 +- lib/providers/apps_provider.dart | 3 +- pubspec.lock | 118 +++++++++++++++++-------------- pubspec.yaml | 10 +-- 4 files changed, 71 insertions(+), 62 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 900cd41..98f12d9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.2'; +const String currentVersion = '0.13.3'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index d15c5e3..38f10fe 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -145,7 +145,8 @@ class AppsProvider with ChangeNotifier { } var client = Client(); StreamedResponse response = await client.send(req); - var ext = response.headers['content-disposition']!.split('.').last; + String ext = + response.headers['content-disposition']?.split('.').last ?? 'apk'; if (ext.endsWith('"') || ext.endsWith("other")) { ext = ext.substring(0, ext.length - 1); } diff --git a/pubspec.lock b/pubspec.lock index 32e6c98..d08183c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: "direct main" description: name: android_alarm_manager_plus - sha256: "88a8001851fdc9bd54fa4e30d0277bb900a50f3d86ff244da7f027400bf23ac0" + sha256: ed5fb34f8befc382fb4800b02aa86a34d279b911e1c05752f702d12fcfe26e0e url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "3.0.0" android_intent_plus: dependency: "direct main" description: name: android_intent_plus - sha256: "04cbc7c332a6f0bba88fed354de78813e9d24049c1800aaf10f449c7adc22603" + sha256: f79fbb8ccb64b5584d19caa9c3d15613bf21cfbd829a6ca7f089fb5dfd43f8aa url: "https://pub.dev" source: hosted - version: "3.1.9" + version: "4.0.0" android_package_installer: dependency: "direct main" description: @@ -54,10 +54,10 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.0" boolean_selector: dependency: transitive description: @@ -70,10 +70,10 @@ packages: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" clock: dependency: transitive description: @@ -86,10 +86,10 @@ packages: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.17.1" convert: dependency: transitive description: @@ -142,10 +142,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: f52ab3b76b36ede4d135aab80194df8925b553686f0fa12226b4e2d658e45903 + sha256: "9b1a0c32b2a503f8fe9f8764fac7b5fcd4f6bd35d8f49de5350bccf9e2a33b8a" url: "https://pub.dev" source: hosted - version: "8.2.2" + version: "9.0.0" device_info_plus_platform_interface: dependency: transitive description: @@ -166,10 +166,10 @@ packages: dependency: "direct main" description: name: easy_localization - sha256: "6a2e99fa0bfe5765bf4c6ca9b137d5de2c75593007178c5e4cd2ae985f870080" + sha256: f30e9b20ed4d1b890171c30241d9b9c43efe21fee55dee7bd68f94daf269ea75 url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2-dev.2" easy_logger: dependency: transitive description: @@ -190,10 +190,10 @@ packages: dependency: transitive description: name: ffi - sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" file: dependency: transitive description: @@ -206,10 +206,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: b85eb92b175767fdaa0c543bf3b0d1f610fe966412ea72845fe5ba7801e763ff + sha256: c7a8e25ca60e7f331b153b0cb3d405828f18d3e72a6fa1d9440c86556fffc877 url: "https://pub.dev" source: hosted - version: "5.2.10" + version: "5.3.0" flutter: dependency: "direct main" description: flutter @@ -235,26 +235,26 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "2876372952b65ca7f684e698eba22bda1cf581fa071dd30ba2f01900f507d0d1" + sha256: ee6ee56855aa920899b68586b538474d086c149932220b47b92502cbfb5ba5e5 url: "https://pub.dev" source: hosted - version: "14.0.0+1" + version: "14.0.0+2" flutter_local_notifications_linux: dependency: transitive description: name: flutter_local_notifications_linux - sha256: "909bb95de05a2e793503a2437146285a2f600cd0b3f826e26b870a334d8586d7" + sha256: "33f741ef47b5f63cc7f78fe75eeeac7e19f171ff3c3df054d84c1e38bedb6a03" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.0+1" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface - sha256: "63235c42de5b6c99846969a27ad0209c401e6b77b0498939813725b5791c107c" + sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef" url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.0+1" flutter_localizations: dependency: transitive description: flutter @@ -330,26 +330,26 @@ packages: dependency: transitive description: name: intl - sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 url: "https://pub.dev" source: hosted - version: "0.17.0" + version: "0.18.0" js: dependency: transitive description: name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.7" lints: dependency: transitive description: name: lints - sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + sha256: "6b0206b0bf4f04961fc5438198ccb3a885685cd67d4d4a32cc20ad7f8adbe015" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.0" markdown: dependency: transitive description: @@ -362,10 +362,10 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.13" + version: "0.12.15" material_color_utilities: dependency: transitive description: @@ -378,10 +378,10 @@ packages: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.9.1" mime: dependency: transitive description: @@ -418,10 +418,10 @@ packages: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.8.3" path_provider: dependency: "direct main" description: @@ -514,10 +514,10 @@ packages: dependency: transitive description: name: petitparser - sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.4.0" platform: dependency: transitive description: @@ -562,10 +562,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: b1f15232d41e9701ab2f04181f21610c36c83a12ae426b79b4bd011c567934b1 + sha256: "322a1ec9d9fe07e2e2252c098ce93d12dbd06133cc4c00ffe6a4ef505c295c17" url: "https://pub.dev" source: hosted - version: "6.3.4" + version: "7.0.0" share_plus_platform_interface: dependency: transitive description: @@ -703,10 +703,10 @@ packages: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.5.1" timezone: dependency: transitive description: @@ -719,26 +719,26 @@ packages: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" url_launcher: dependency: "direct main" description: name: url_launcher - sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" + sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 url: "https://pub.dev" source: hosted - version: "6.1.10" + version: "6.1.11" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "22f8db4a72be26e9e3a4aa3f194b1f7afbc76d20ec141f84be1d787db2155cbd" + sha256: "7aac14be5f4731b923cc697ae2d42043945076cd0dbb8806baecc92c1dc88891" url: "https://pub.dev" source: hosted - version: "6.0.31" + version: "6.0.33" url_launcher_ios: dependency: transitive description: @@ -831,18 +831,26 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "61f33512810bf1ee9ac89761a4b02663ff64e8227b7dc80654642acd660fd49d" + sha256: "4646bb68297803bdbb96d46853e8fcb560d6cb5e04153fa64581535767875dfe" url: "https://pub.dev" source: hosted - version: "3.4.2" + version: "3.4.3" win32: dependency: transitive description: name: win32 - sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4 + sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "4.1.4" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "1c52f994bdccb77103a6231ad4ea331a244dbcef5d1f37d8462f713143b0bfae" + url: "https://pub.dev" + source: hosted + version: "1.1.0" xdg_directories: dependency: transitive description: @@ -855,10 +863,10 @@ packages: dependency: transitive description: name: xml - sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.3.0" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=3.0.0-417 <4.0.0" flutter: ">=3.4.0-17.0.pre" diff --git a/pubspec.yaml b/pubspec.yaml index 730cb10..59ae74a 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.13.2+166 # When changing this, update the tag in main() accordingly +version: 0.13.3+167 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' @@ -48,20 +48,20 @@ dependencies: url_launcher: ^6.1.5 permission_handler: ^10.0.0 fluttertoast: ^8.0.9 - device_info_plus: ^8.0.0 + device_info_plus: ^9.0.0 file_picker: ^5.2.10 animations: ^2.0.4 android_package_installer: git: url: https://github.com/ImranR98/android_package_installer ref: main - share_plus: ^6.0.1 + share_plus: ^7.0.0 installed_apps: ^1.3.1 package_archive_info: ^0.1.0 - android_alarm_manager_plus: ^2.1.0 + android_alarm_manager_plus: ^3.0.0 sqflite: ^2.2.0+3 easy_localization: ^3.0.1 - android_intent_plus: ^3.1.5 + android_intent_plus: ^4.0.0 flutter_markdown: ^0.6.14 archive: ^3.3.7 From 7681e23de966b1ce9d54374595543778ce09d4c2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 13 May 2023 02:35:44 -0400 Subject: [PATCH 200/600] Flutter version - related change --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 58a8c74..713d7f6 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -26,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } From d212f13345917371cb5835ea7a3be28ddb8d6446 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 14 May 2023 12:29:37 -0400 Subject: [PATCH 201/600] Fixed code smells --- lib/app_sources/apkcombo.dart | 2 -- lib/app_sources/apkpure.dart | 1 - lib/app_sources/codeberg.dart | 2 -- lib/app_sources/fdroidrepo.dart | 1 - lib/app_sources/gitlab.dart | 4 ++-- lib/app_sources/izzyondroid.dart | 1 - lib/app_sources/jenkins.dart | 1 - lib/app_sources/sourcehut.dart | 2 -- lib/app_sources/vlc.dart | 1 - lib/pages/app.dart | 1 + lib/pages/apps.dart | 3 +++ lib/pages/import_export.dart | 4 ++-- lib/providers/source_provider.dart | 1 - 13 files changed, 8 insertions(+), 16 deletions(-) diff --git a/lib/app_sources/apkcombo.dart b/lib/app_sources/apkcombo.dart index 6c5dfa6..16e21c5 100644 --- a/lib/app_sources/apkcombo.dart +++ b/lib/app_sources/apkcombo.dart @@ -1,6 +1,5 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:html/parser.dart'; -import 'package:http/http.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -85,7 +84,6 @@ class APKCombo extends AppSource { Map additionalSettings, ) async { String appId = tryInferringAppId(standardUrl)!; - String host = Uri.parse(standardUrl).host; var preres = await sourceRequest(standardUrl); if (preres.statusCode != 200) { throw getObtainiumHttpError(preres); diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index 1ab017d..20028a4 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -1,6 +1,5 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:html/parser.dart'; -import 'package:http/http.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index d50332d..5938ec2 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -1,6 +1,4 @@ -import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; -import 'package:http/http.dart'; import 'package:obtainium/app_sources/github.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index 184e139..e19b34a 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -1,6 +1,5 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:html/parser.dart'; -import 'package:http/http.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index ae65875..f53f8af 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -83,12 +83,12 @@ class GitLab extends AppSource { } var json = jsonDecode(res.body) as List; Map> results = {}; - json.forEach((element) { + for (var element in json) { results['https://$host/${element['path_with_namespace']}'] = [ element['name_with_namespace'], element['description'] ?? tr('noDescription') ]; - }); + } return results; } diff --git a/lib/app_sources/izzyondroid.dart b/lib/app_sources/izzyondroid.dart index cdab17a..1773558 100644 --- a/lib/app_sources/izzyondroid.dart +++ b/lib/app_sources/izzyondroid.dart @@ -1,4 +1,3 @@ -import 'package:http/http.dart'; import 'package:obtainium/app_sources/fdroid.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; diff --git a/lib/app_sources/jenkins.dart b/lib/app_sources/jenkins.dart index 804b3fb..b628814 100644 --- a/lib/app_sources/jenkins.dart +++ b/lib/app_sources/jenkins.dart @@ -10,7 +10,6 @@ class Jenkins extends AppSource { overrideVersionDetectionFormDefault('releaseDateAsVersion', true); } - @override String trimJobUrl(String url) { RegExp standardUrlRegEx = RegExp('.*/job/[^/]+'); RegExpMatch? match = standardUrlRegEx.firstMatch(url); diff --git a/lib/app_sources/sourcehut.dart b/lib/app_sources/sourcehut.dart index b85758f..6277486 100644 --- a/lib/app_sources/sourcehut.dart +++ b/lib/app_sources/sourcehut.dart @@ -1,6 +1,5 @@ import 'package:html/parser.dart'; import 'package:http/http.dart'; -import 'package:obtainium/app_sources/github.dart'; import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -58,7 +57,6 @@ class SourceHut extends AppSource { throw NoVersionError(); } String? releaseDateString = entry.querySelector('pubDate')?.innerHtml; - var link = entry.querySelector('link'); String releasePage = '$standardUrl/refs/$version'; DateTime? releaseDate = releaseDateString != null ? DateFormat('EEE, dd MMM yyyy HH:mm:ss Z').parse(releaseDateString) diff --git a/lib/app_sources/vlc.dart b/lib/app_sources/vlc.dart index 06ad878..c531f26 100644 --- a/lib/app_sources/vlc.dart +++ b/lib/app_sources/vlc.dart @@ -1,6 +1,5 @@ import 'package:html/parser.dart'; import 'package:http/http.dart'; -import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; diff --git a/lib/pages/app.dart b/lib/pages/app.dart index b7585c8..3e2e993 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -32,6 +32,7 @@ class _AppPageState extends State { getUpdate(String id) { appsProvider.checkUpdate(id).catchError((e) { showError(e, context); + return null; }); } diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 37fa60c..72cdfbc 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -71,6 +71,7 @@ class AppsPageState extends State { }); return appsProvider.checkUpdates().catchError((e) { showError(e, context); + return []; }).whenComplete(() { setState(() { refreshingSince = null; @@ -379,6 +380,7 @@ class AppsPageState extends State { [listedApps[appIndex].app.id], globalNavigatorKey.currentContext).catchError((e) { showError(e, context); + return []; }); }, icon: Icon( @@ -681,6 +683,7 @@ class AppsPageState extends State { settingsProvider: settingsProvider) .catchError((e) { showError(e, context); + return []; }); } }); diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index 7a896c9..fd10f86 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -323,8 +323,8 @@ class _ImportExportPageState extends State { ], ), if (importInProgress) - Column( - children: const [ + const Column( + children: [ SizedBox( height: 14, ), diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index f498496..6fc9902 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -7,7 +7,6 @@ import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:html/dom.dart'; import 'package:http/http.dart'; -import 'package:obtainium/app_sources/apkcombo.dart'; import 'package:obtainium/app_sources/apkmirror.dart'; import 'package:obtainium/app_sources/apkpure.dart'; import 'package:obtainium/app_sources/codeberg.dart'; From 1606ad3442aa9c3a236094f0527ae58c256def71 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 14 May 2023 12:39:21 -0400 Subject: [PATCH 202/600] Fix potential date parse error in SoureHut --- lib/app_sources/sourcehut.dart | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/app_sources/sourcehut.dart b/lib/app_sources/sourcehut.dart index 6277486..756fadc 100644 --- a/lib/app_sources/sourcehut.dart +++ b/lib/app_sources/sourcehut.dart @@ -58,9 +58,18 @@ class SourceHut extends AppSource { } String? releaseDateString = entry.querySelector('pubDate')?.innerHtml; String releasePage = '$standardUrl/refs/$version'; - DateTime? releaseDate = releaseDateString != null - ? DateFormat('EEE, dd MMM yyyy HH:mm:ss Z').parse(releaseDateString) - : null; + DateTime? releaseDate; + try { + releaseDate = releaseDateString != null + ? DateFormat('E, dd MMM yyyy HH:mm:ss Z').parse(releaseDateString) + : null; + releaseDate = releaseDateString != null + ? DateFormat('EEE, dd MMM yyyy HH:mm:ss Z') + .parse(releaseDateString) + : null; + } catch (e) { + // ignore + } var res2 = await sourceRequest(releasePage); List> apkUrls = []; if (res2.statusCode == 200) { From eb0be196da0a9da53e26ddccd1c60ced73ce51af Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 14 May 2023 12:40:26 -0400 Subject: [PATCH 203/600] Fix 'Please Wait' message on Apps page --- lib/pages/apps.dart | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 72cdfbc..0aaa0ba 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -543,14 +543,14 @@ class AppsPageState extends State { trailing: listedApps[index].downloadProgress != null ? SizedBox( width: 110, - child: Text(tr('percentProgress', args: [ - listedApps[index].downloadProgress! >= 0 - ? listedApps[index] - .downloadProgress! - .toInt() - .toString() - : tr('pleaseWait') - ]))) + child: Text(listedApps[index].downloadProgress! >= 0 + ? tr('percentProgress', args: [ + listedApps[index] + .downloadProgress! + .toInt() + .toString() + ]) + : tr('pleaseWait'))) : trailingRow, onTap: () { if (selectedAppIds.isNotEmpty) { From e256ada2dc977fd960596203f225b9de8ad46c38 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 14 May 2023 12:53:40 -0400 Subject: [PATCH 204/600] Adjust Apps list trailing UI spacing and touch area --- lib/pages/apps.dart | 67 +++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 0aaa0ba..c06e3fe 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -443,37 +443,35 @@ class AppsPageState extends State { width: 10, ) : const SizedBox.shrink(), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Row(mainAxisSize: MainAxisSize.min, children: [ - Container( - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context).size.width / 4), - child: Text( - getVersionText(index), - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.end, - )), - ]), - Row( - mainAxisSize: MainAxisSize.min, + GestureDetector( + onTap: showChangesFn, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, children: [ - GestureDetector( - onTap: showChangesFn, - child: Text( + Row(mainAxisSize: MainAxisSize.min, children: [ + Container( + constraints: BoxConstraints( + maxWidth: MediaQuery.of(context).size.width / 4), + child: Text(getVersionText(index), + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.end)), + ]), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( getChangesButtonString(index, showChangesFn != null), style: TextStyle( fontStyle: FontStyle.italic, decoration: showChangesFn != null ? TextDecoration.underline : TextDecoration.none), - )) + ) + ], + ), ], - ), - ], - ) + )) ], ); @@ -542,15 +540,20 @@ class AppsPageState extends State { : FontWeight.normal)), trailing: listedApps[index].downloadProgress != null ? SizedBox( - width: 110, - child: Text(listedApps[index].downloadProgress! >= 0 - ? tr('percentProgress', args: [ - listedApps[index] - .downloadProgress! - .toInt() - .toString() - ]) - : tr('pleaseWait'))) + width: 90, + child: Text( + listedApps[index].downloadProgress! >= 0 + ? tr('percentProgress', args: [ + listedApps[index] + .downloadProgress! + .toInt() + .toString() + ]) + : tr('pleaseWait'), + textAlign: (listedApps[index].downloadProgress! >= 0) + ? TextAlign.start + : TextAlign.end, + )) : trailingRow, onTap: () { if (selectedAppIds.isNotEmpty) { From 96c92c8df93f86d08bde3dd575e150c75ecf6bc7 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 14 May 2023 13:25:09 -0400 Subject: [PATCH 205/600] Add 'tags-only' support (for Track-Only) to GitHub (and Codeberg) --- lib/app_sources/codeberg.dart | 8 +++---- lib/app_sources/github.dart | 44 ++++++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index 5938ec2..8b1e3d3 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -56,10 +56,10 @@ class Codeberg extends AppSource { String standardUrl, Map additionalSettings, ) async { - return gh.getLatestAPKDetailsCommon( - 'https://$host/api/v1/repos${standardUrl.substring('https://$host'.length)}/releases?per_page=100', - standardUrl, - additionalSettings); + return await gh.getLatestAPKDetailsCommon2(standardUrl, additionalSettings, + (bool useTagUrl) async { + return 'https://$host/api/v1/repos${standardUrl.substring('https://$host'.length)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100'; + }, null); } AppNames getAppNames(String standardUrl) { diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index c314d26..54c1242 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -143,15 +143,17 @@ class GitHub extends AppSource { } else if (b == null) { return 1; } else { - var stdFormats = findStandardFormatsForVersion(a['tag_name'], true) - .intersection(findStandardFormatsForVersion(b['tag_name'], true)); + var nameA = a['tag_name'] ?? a['name']; + var nameB = b['tag_name'] ?? b['name']; + var stdFormats = findStandardFormatsForVersion(nameA, true) + .intersection(findStandardFormatsForVersion(nameB, true)); if (stdFormats.isNotEmpty) { var reg = RegExp(stdFormats.first); - var matchA = reg.firstMatch(a['tag_name']); - var matchB = reg.firstMatch(b['tag_name']); + var matchA = reg.firstMatch(nameA); + var matchB = reg.firstMatch(nameB); return compareAlphaNumeric( - (a['tag_name'] as String).substring(matchA!.start, matchA.end), - (b['tag_name'] as String).substring(matchB!.start, matchB.end)); + (nameA as String).substring(matchA!.start, matchA.end), + (nameB as String).substring(matchB!.start, matchB.end)); } else { return getReleaseDateFromRelease(a)! .compareTo(getReleaseDateFromRelease(b)!); @@ -191,7 +193,7 @@ class GitHub extends AppSource { if (targetRelease == null) { throw NoReleasesError(); } - String? version = targetRelease['tag_name']; + String? version = targetRelease['tag_name'] ?? targetRelease['name']; DateTime? releaseDate = getReleaseDateFromRelease(targetRelease); if (version == null) { throw NoVersionError(); @@ -211,15 +213,35 @@ class GitHub extends AppSource { } } + getLatestAPKDetailsCommon2( + String standardUrl, + Map additionalSettings, + Future Function(bool) reqUrlGenerator, + dynamic Function(Response)? onHttpErrorCode) async { + try { + return await getLatestAPKDetailsCommon( + await reqUrlGenerator(false), standardUrl, additionalSettings, + onHttpErrorCode: onHttpErrorCode); + } catch (err) { + if (err is NoReleasesError && additionalSettings['trackOnly'] == true) { + return await getLatestAPKDetailsCommon( + await reqUrlGenerator(true), standardUrl, additionalSettings, + onHttpErrorCode: onHttpErrorCode); + } else { + rethrow; + } + } + } + @override Future getLatestAPKDetails( String standardUrl, Map additionalSettings, ) async { - return getLatestAPKDetailsCommon( - 'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/releases?per_page=100', - standardUrl, - additionalSettings, onHttpErrorCode: (Response res) { + return await getLatestAPKDetailsCommon2(standardUrl, additionalSettings, + (bool useTagUrl) async { + return 'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100'; + }, (Response res) { rateLimitErrorCheck(res); }); } From e33cc00266c2119c5dcae1fc575e515d7b90b7ff Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 14 May 2023 13:42:09 -0400 Subject: [PATCH 206/600] Make all sources override-eligible to account for subdomains --- lib/app_sources/codeberg.dart | 1 - lib/app_sources/fdroidrepo.dart | 1 - lib/app_sources/github.dart | 1 - lib/app_sources/gitlab.dart | 1 - lib/app_sources/html.dart | 4 ---- lib/app_sources/jenkins.dart | 1 - lib/app_sources/sourceforge.dart | 1 - lib/app_sources/sourcehut.dart | 1 - lib/pages/add_app.dart | 6 ++---- lib/providers/source_provider.dart | 1 - 10 files changed, 2 insertions(+), 16 deletions(-) diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index 8b1e3d3..f94cdb9 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -7,7 +7,6 @@ import 'package:obtainium/providers/source_provider.dart'; class Codeberg extends AppSource { Codeberg() { host = 'codeberg.org'; - overrideEligible = true; additionalSourceSpecificSettingFormItems = []; diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index e19b34a..9bf2931 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -7,7 +7,6 @@ import 'package:obtainium/providers/source_provider.dart'; class FDroidRepo extends AppSource { FDroidRepo() { name = tr('fdroidThirdPartyRepo'); - overrideEligible = true; additionalSourceAppSpecificSettingFormItems = [ [ diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 54c1242..a34bda2 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -13,7 +13,6 @@ import 'package:url_launcher/url_launcher_string.dart'; class GitHub extends AppSource { GitHub() { host = 'github.com'; - overrideEligible = true; additionalSourceSpecificSettingFormItems = [ GeneratedFormTextField('github-creds', diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index f53f8af..c6d8a63 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -14,7 +14,6 @@ import 'package:url_launcher/url_launcher_string.dart'; class GitLab extends AppSource { GitLab() { host = 'gitlab.com'; - overrideEligible = true; canSearch = true; additionalSourceSpecificSettingFormItems = [ diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index c6ec9e2..7b69ade 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -85,10 +85,6 @@ bool _isNumeric(String s) { } class HTML extends AppSource { - HTML() { - overrideEligible = true; - } - @override // TODO: implement requestHeaders choice, hardcoded for now Map? get requestHeaders => { diff --git a/lib/app_sources/jenkins.dart b/lib/app_sources/jenkins.dart index b628814..2aa8853 100644 --- a/lib/app_sources/jenkins.dart +++ b/lib/app_sources/jenkins.dart @@ -6,7 +6,6 @@ import 'package:obtainium/providers/source_provider.dart'; class Jenkins extends AppSource { Jenkins() { - overrideEligible = true; overrideVersionDetectionFormDefault('releaseDateAsVersion', true); } diff --git a/lib/app_sources/sourceforge.dart b/lib/app_sources/sourceforge.dart index 794eef1..3253926 100644 --- a/lib/app_sources/sourceforge.dart +++ b/lib/app_sources/sourceforge.dart @@ -6,7 +6,6 @@ import 'package:obtainium/providers/source_provider.dart'; class SourceForge extends AppSource { SourceForge() { host = 'sourceforge.net'; - overrideEligible = true; } @override diff --git a/lib/app_sources/sourcehut.dart b/lib/app_sources/sourcehut.dart index 756fadc..d74fd7c 100644 --- a/lib/app_sources/sourcehut.dart +++ b/lib/app_sources/sourcehut.dart @@ -9,7 +9,6 @@ import 'package:easy_localization/easy_localization.dart'; class SourceHut extends AppSource { SourceHut() { host = 'git.sr.ht'; - overrideEligible = true; additionalSourceAppSpecificSettingFormItems = [ [ diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index ac85b10..c439f30 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -321,10 +321,8 @@ class _AddAppPageState extends State { 'overrideSource', defaultValue: HTML().runtimeType.toString(), [ - ...sourceProvider.sources - .where((s) => s.overrideEligible) - .map((s) => - MapEntry(s.runtimeType.toString(), s.name)) + ...sourceProvider.sources.map( + (s) => MapEntry(s.runtimeType.toString(), s.name)) ], label: tr('overrideSource')) ] diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 6fc9902..d980e3c 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -317,7 +317,6 @@ abstract class AppSource { late String name; bool enforceTrackOnly = false; bool changeLogIfAnyIsMarkDown = true; - bool overrideEligible = false; AppSource() { name = runtimeType.toString(); From c6297ea449d41dbc866e41b84fd7f9a4e3f9bc9a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 14 May 2023 13:45:48 -0400 Subject: [PATCH 207/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 98f12d9..089c1fb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.3'; +const String currentVersion = '0.13.4'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 59ae74a..12cdeee 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.13.3+167 # When changing this, update the tag in main() accordingly +version: 0.13.4+168 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From eda5fec37c7c0be576b8ccde1e884fb04ce86e6a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 14 May 2023 13:57:01 -0400 Subject: [PATCH 208/600] Added App ID Filter --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/zh.json | 1 + lib/pages/apps.dart | 16 ++++++++++++++++ 10 files changed, 25 insertions(+) diff --git a/assets/translations/de.json b/assets/translations/de.json index 040f4cd..7499014 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -180,6 +180,7 @@ "yesMarkUpdated": "Ja, als aktualisiert markieren", "fdroid": "F-Droid Official", "appIdOrName": "App ID oder Name", + "appId": "App ID", "appWithIdOrNameNotFound": "Es wurde keine App mit dieser ID oder diesem Namen gefunden", "reposHaveMultipleApps": "Repos können mehrere Apps enthalten", "fdroidThirdPartyRepo": "F-Droid Third-Party Repo", diff --git a/assets/translations/en.json b/assets/translations/en.json index eb59399..1f543ac 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -180,6 +180,7 @@ "yesMarkUpdated": "Yes, Mark as Updated", "fdroid": "F-Droid Official", "appIdOrName": "App ID or Name", + "appId": "App ID", "appWithIdOrNameNotFound": "No App was found with that ID or Name", "reposHaveMultipleApps": "Repos may contain multiple Apps", "fdroidThirdPartyRepo": "F-Droid Third-Party Repo", diff --git a/assets/translations/es.json b/assets/translations/es.json index c013d01..d3b6500 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -180,6 +180,7 @@ "yesMarkUpdated": "Sí, Marcar como Actualizada", "fdroid": "Repositorio oficial de F-Droid", "appIdOrName": "ID o Nombre de la Aplicación", + "appId": "ID de la Aplicación", "appWithIdOrNameNotFound": "No se han encontrado aplicaciones con esa ID o nombre", "reposHaveMultipleApps": "Los repositorios pueden contener varias aplicaciones", "fdroidThirdPartyRepo": "Rpositorios de terceros de F-Droid", diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 5685c1e..d7eb778 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -180,6 +180,7 @@ "yesMarkUpdated": "بله، علامت گذاری به عنوان به روز شده", "fdroid": "F-Droid Official", "appIdOrName": "شناسه یا نام برنامه", + "appId": "App ID", "appWithIdOrNameNotFound": "هیچ برنامه ای با آن شناسه یا نام یافت نشد", "reposHaveMultipleApps": "مخازن ممکن است شامل چندین برنامه باشد", "fdroidThirdPartyRepo": "مخازن شخص ثالث F-Droid", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 90c060f..dfc8876 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -180,6 +180,7 @@ "yesMarkUpdated": "Oui, marquer comme mis à jour", "fdroid": "F-Droid Official", "appIdOrName": "ID ou nom de l'application", + "appId": "ID de l'application", "appWithIdOrNameNotFound": "Aucune application n'a été trouvée avec cet identifiant ou ce nom", "reposHaveMultipleApps": "Les dépôts peuvent contenir plusieurs applications", "fdroidThirdPartyRepo": "Dépôt tiers F-Droid", diff --git a/assets/translations/hu.json b/assets/translations/hu.json index c73ef70..a003fbc 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -180,6 +180,7 @@ "yesMarkUpdated": "Igen, megjelölés frissítettként", "fdroid": "F-Droid Official", "appIdOrName": "App ID vagy név", + "appId": "App ID", "appWithIdOrNameNotFound": "Nem található app ezzel az azonosítóval vagy névvel", "reposHaveMultipleApps": "A repók több alkalmazást is tartalmazhatnak", "fdroidThirdPartyRepo": "F-Droid Harmadik-fél Repo", diff --git a/assets/translations/it.json b/assets/translations/it.json index 0cff11d..53b20c6 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -180,6 +180,7 @@ "yesMarkUpdated": "Sì, contrassegna come aggiornato", "fdroid": "F-Droid Official", "appIdOrName": "ID o nome dell'App", + "appId": "ID dell'App", "appWithIdOrNameNotFound": "Non è stata trovata alcuna App con quell'ID o nome", "reposHaveMultipleApps": "I repository possono contenere più App", "fdroidThirdPartyRepo": "Repository F-Droid di terze parti", diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 47200fa..135a8ab 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -180,6 +180,7 @@ "yesMarkUpdated": "はい、アップデート済みとしてマークします", "fdroid": "F-Droid Official", "appIdOrName": "アプリのIDまたは名前", + "appId": "App ID", "appWithIdOrNameNotFound": "そのIDや名前を持つアプリは見つかりませんでした", "reposHaveMultipleApps": "リポジトリには複数のアプリが含まれることがあります", "fdroidThirdPartyRepo": "F-Droid サードパーティリポジトリ", diff --git a/assets/translations/zh.json b/assets/translations/zh.json index f00d46b..83c08b2 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -180,6 +180,7 @@ "yesMarkUpdated": "是,标记为已更新", "fdroid": "F-Droid 官方存储库", "appIdOrName": "应用 ID 或名称", + "appId": "App ID", "appWithIdOrNameNotFound": "未找到符合此 ID 或名称的应用", "reposHaveMultipleApps": "存储库中可能包含多个应用", "fdroidThirdPartyRepo": "F-Droid 第三方存储库", diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index c06e3fe..18fc509 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -129,6 +129,11 @@ class AppsPageState extends State { } } } + if (filter.idFilter.isNotEmpty) { + if (!app.app.id.contains(filter.idFilter)) { + return false; + } + } if (filter.categoryFilter.isNotEmpty && filter.categoryFilter .intersection(app.app.categories.toSet()) @@ -941,6 +946,12 @@ class AppsPageState extends State { required: false, defaultValue: vals['author']) ], + [ + GeneratedFormTextField('appId', + label: tr('appId'), + required: false, + defaultValue: vals['appId']) + ], [ GeneratedFormSwitch('upToDateApps', label: tr('upToDateApps'), @@ -1072,6 +1083,7 @@ class AppsPageState extends State { class AppsFilter { late String nameFilter; late String authorFilter; + late String idFilter; late bool includeUptodate; late bool includeNonInstalled; late Set categoryFilter; @@ -1080,6 +1092,7 @@ class AppsFilter { AppsFilter( {this.nameFilter = '', this.authorFilter = '', + this.idFilter = '', this.includeUptodate = true, this.includeNonInstalled = true, this.categoryFilter = const {}, @@ -1089,6 +1102,7 @@ class AppsFilter { return { 'appName': nameFilter, 'author': authorFilter, + 'appId': idFilter, 'upToDateApps': includeUptodate, 'nonInstalledApps': includeNonInstalled, 'sourceFilter': sourceFilter @@ -1098,6 +1112,7 @@ class AppsFilter { setFormValuesFromMap(Map values) { nameFilter = values['appName']!; authorFilter = values['author']!; + idFilter = values['appId']!; includeUptodate = values['upToDateApps']; includeNonInstalled = values['nonInstalledApps']; sourceFilter = values['sourceFilter']; @@ -1106,6 +1121,7 @@ class AppsFilter { bool isIdenticalTo(AppsFilter other, SettingsProvider settingsProvider) => authorFilter.trim() == other.authorFilter.trim() && nameFilter.trim() == other.nameFilter.trim() && + idFilter.trim() == other.idFilter.trim() && includeUptodate == other.includeUptodate && includeNonInstalled == other.includeNonInstalled && settingsProvider.setEqual(categoryFilter, other.categoryFilter) && From 03c2ce9a019cc1e457682f1702ed682b1dab11df Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 14 May 2023 14:18:31 -0400 Subject: [PATCH 209/600] Changes to bottom buttons UI on Apps page --- lib/pages/apps.dart | 134 ++++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 78 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 18fc509..9966f9c 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -61,8 +61,6 @@ class AppsPageState extends State { var settingsProvider = context.watch(); var sourceProvider = SourceProvider(); var listedApps = appsProvider.getAppValues().toList(); - var currentFilterIsUpdatesOnly = - filter.isIdenticalTo(updatesOnlyFilter, settingsProvider); refresh() { HapticFeedback.lightImpact(); @@ -887,44 +885,41 @@ class AppsPageState extends State { }); } - getMainBottomButtonsRow() { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - IconButton( + getMainBottomButtons() { + return [ + IconButton( visualDensity: VisualDensity.compact, - onPressed: selectedAppIds.isEmpty - ? null - : () { - appsProvider.removeAppsWithModal( - context, selectedApps.toList()); - }, - tooltip: tr('removeSelectedApps'), - icon: const Icon(Icons.delete_outline_outlined), - ), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: getMassObtainFunction(), - tooltip: selectedAppIds.isEmpty - ? tr('installUpdateApps') - : tr('installUpdateSelectedApps'), - icon: const Icon( - Icons.file_download_outlined, - )), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: selectedAppIds.isEmpty ? null : launchCategorizeDialog(), - tooltip: tr('categorize'), - icon: const Icon(Icons.category_outlined), - ), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: selectedAppIds.isEmpty ? null : showMoreOptionsDialog, - tooltip: tr('more'), - icon: const Icon(Icons.more_horiz), - ), - ], - ); + onPressed: getMassObtainFunction(), + tooltip: selectedAppIds.isEmpty + ? tr('installUpdateApps') + : tr('installUpdateSelectedApps'), + icon: const Icon( + Icons.file_download_outlined, + )), + IconButton( + visualDensity: VisualDensity.compact, + onPressed: selectedAppIds.isEmpty + ? null + : () { + appsProvider.removeAppsWithModal( + context, selectedApps.toList()); + }, + tooltip: tr('removeSelectedApps'), + icon: const Icon(Icons.delete_outline_outlined), + ), + IconButton( + visualDensity: VisualDensity.compact, + onPressed: selectedAppIds.isEmpty ? null : launchCategorizeDialog(), + tooltip: tr('categorize'), + icon: const Icon(Icons.category_outlined), + ), + IconButton( + visualDensity: VisualDensity.compact, + onPressed: selectedAppIds.isEmpty ? null : showMoreOptionsDialog, + tooltip: tr('more'), + icon: const Icon(Icons.more_horiz), + ), + ]; } showFilterDialog() async { @@ -997,50 +992,33 @@ class AppsPageState extends State { } getFilterButtonsRow() { + var isFilterOff = filter.isIdenticalTo(neutralFilter, settingsProvider); return Row( children: [ getSelectAllButton(), + IconButton( + color: Theme.of(context).colorScheme.primary, + style: const ButtonStyle(visualDensity: VisualDensity.compact), + tooltip: isFilterOff ? tr('filter') : tr('filterActive'), + onPressed: isFilterOff + ? showFilterDialog + : () { + setState(() { + filter = AppsFilter(); + }); + }, + icon: Icon(isFilterOff + ? Icons.filter_list_rounded + : Icons.filter_list_off_rounded)), + const SizedBox( + width: 10, + ), const VerticalDivider(), Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: getMainBottomButtonsRow())), - const VerticalDivider(), - IconButton( - visualDensity: VisualDensity.compact, - onPressed: () { - setState(() { - if (currentFilterIsUpdatesOnly) { - filter = AppsFilter(); - } else { - filter = updatesOnlyFilter; - } - }); - }, - tooltip: currentFilterIsUpdatesOnly - ? tr('removeOutdatedFilter') - : tr('showOutdatedOnly'), - icon: Icon( - currentFilterIsUpdatesOnly - ? Icons.update_disabled_rounded - : Icons.update_rounded, - color: Theme.of(context).colorScheme.primary, - ), - ), - TextButton.icon( - style: const ButtonStyle(visualDensity: VisualDensity.compact), - label: Text( - filter.isIdenticalTo(neutralFilter, settingsProvider) - ? tr('filter') - : tr('filterActive'), - style: TextStyle( - fontWeight: - filter.isIdenticalTo(neutralFilter, settingsProvider) - ? FontWeight.normal - : FontWeight.bold), - ), - onPressed: showFilterDialog, - icon: const Icon(Icons.filter_list_rounded)) + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: getMainBottomButtons(), + )), ], ); } From 4136734a608a2b000b54d4c9d89fdc79ed4e3150 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 22 May 2023 12:10:58 -0400 Subject: [PATCH 210/600] Skip App loading on return to foreground --- lib/pages/home.dart | 5 ++++- lib/providers/apps_provider.dart | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/pages/home.dart b/lib/pages/home.dart index a830b1a..1e74fcc 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -27,6 +27,7 @@ class NavigationPageItem { class _HomePageState extends State { List selectedIndexHistory = []; int prevAppCount = -1; + bool prevIsLoading = true; List pages = [ NavigationPageItem(tr('appsString'), Icons.apps, @@ -64,13 +65,15 @@ class _HomePageState extends State { } } - if (prevAppCount >= 0 && + if (!prevIsLoading && + prevAppCount >= 0 && appsProvider.apps.length > prevAppCount && selectedIndexHistory.isNotEmpty && selectedIndexHistory.last == 1) { switchToPage(0); } prevAppCount = appsProvider.apps.length; + prevIsLoading = appsProvider.loadingApps; return WillPopScope( child: Scaffold( diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 38f10fe..e585697 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -116,7 +116,7 @@ class AppsProvider with ChangeNotifier { foregroundStream = FGBGEvents.stream.asBroadcastStream(); foregroundSubscription = foregroundStream?.listen((event) async { isForeground = event == FGBGType.foreground; - if (isForeground) await loadApps(); + if (isForeground) await refreshInstallStatuses(); }); () async { // Load Apps into memory (in background, this is done later instead of in the constructor) @@ -747,6 +747,10 @@ class AppsProvider with ChangeNotifier { } loadingApps = false; notifyListeners(); + refreshInstallStatuses(); + } + + Future refreshInstallStatuses() async { if (await doesInstalledAppsPluginWork()) { List modifiedApps = []; for (var app in apps.values) { From 03fc6a530fac15a001e4e53aec0f64732c575698 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 22 May 2023 12:33:31 -0400 Subject: [PATCH 211/600] App load optimizations, dir delete bugfix --- lib/pages/apps.dart | 36 ++++++++--------- lib/providers/apps_provider.dart | 69 ++++++++++++++------------------ 2 files changed, 47 insertions(+), 58 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 9966f9c..173beb2 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -322,28 +322,28 @@ class AppsPageState extends State { getLoadingWidgets() { return [ - if (appsProvider.loadingApps || listedApps.isEmpty) + if (listedApps.isEmpty) SliverFillRemaining( child: Center( - child: appsProvider.loadingApps - ? const CircularProgressIndicator() - : Text( - appsProvider.apps.isEmpty - ? tr('noApps') - : tr('noAppsForFilter'), - style: Theme.of(context).textTheme.headlineMedium, - textAlign: TextAlign.center, - ))), - if (refreshingSince != null) + child: Text( + appsProvider.apps.isEmpty ? tr('noApps') : tr('noAppsForFilter'), + style: Theme.of(context).textTheme.headlineMedium, + textAlign: TextAlign.center, + ))), + if (refreshingSince != null || appsProvider.loadingApps) SliverToBoxAdapter( child: LinearProgressIndicator( - value: appsProvider - .getAppValues() - .where((element) => !(element.app.lastUpdateCheck - ?.isBefore(refreshingSince!) ?? - true)) - .length / - (appsProvider.apps.isNotEmpty ? appsProvider.apps.length : 1), + value: appsProvider.loadingApps + ? null + : appsProvider + .getAppValues() + .where((element) => !(element.app.lastUpdateCheck + ?.isBefore(refreshingSince!) ?? + true)) + .length / + (appsProvider.apps.isNotEmpty + ? appsProvider.apps.length + : 1), ), ) ]; diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index e585697..4d82bf4 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -130,7 +130,7 @@ class AppsProvider with ChangeNotifier { element.path.endsWith('.part') || element.statSync().modified.isBefore(cutoff)) .forEach((partialApk) { - partialApk.delete(); + partialApk.delete(recursive: true); }); }(); } @@ -154,7 +154,7 @@ class AppsProvider with ChangeNotifier { if (!(downloadedFile.existsSync() && useExisting)) { File tempDownloadedFile = File('${downloadedFile.path}.part'); if (tempDownloadedFile.existsSync()) { - tempDownloadedFile.deleteSync(); + tempDownloadedFile.deleteSync(recursive: true); } var length = response.contentLength; var received = 0; @@ -174,7 +174,7 @@ class AppsProvider with ChangeNotifier { onProgress(progress); } if (response.statusCode != 200) { - tempDownloadedFile.deleteSync(); + tempDownloadedFile.deleteSync(recursive: true); throw response.reasonPhrase ?? tr('unexpectedError'); } tempDownloadedFile.renameSync(downloadedFile.path); @@ -266,7 +266,7 @@ class AppsProvider with ChangeNotifier { if (fn.startsWith('${app.id}-') && FileSystemEntity.isFileSync(file.path) && file.path != downloadedFile.path) { - file.delete(); + file.delete(recursive: true); } } if (isAPK) { @@ -349,7 +349,7 @@ class AppsProvider with ChangeNotifier { silent: silent); } if (somethingInstalled) { - dir.file.delete(); + dir.file.delete(recursive: true); } } finally { dir.extracted.delete(recursive: true); @@ -379,7 +379,7 @@ class AppsProvider with ChangeNotifier { installed = true; apps[file.appId]!.app.installedVersion = apps[file.appId]!.app.latestVersion; - file.file.delete(); + file.file.delete(recursive: true); } await saveApps([apps[file.appId]!.app]); return installed; @@ -703,41 +703,30 @@ class AppsProvider with ChangeNotifier { } loadingApps = true; notifyListeners(); - List newApps = (await getAppsDir()) - .listSync() - .where((item) => item.path.toLowerCase().endsWith('.json')) - .map((e) { - try { - return App.fromJson(jsonDecode(File(e.path).readAsStringSync())); - } catch (err) { - if (err is FormatException) { - logs.add('Corrupt JSON when loading App (will be ignored): $e'); - e.renameSync('${e.path}.corrupt'); - return App( - '', '', '', '', '', '', [], 0, {}, DateTime.now(), false); - } else { - rethrow; - } - } - }) - .where((element) => element.id.isNotEmpty) - .toList(); - var idsToDelete = apps.values - .map((e) => e.app.id) - .toSet() - .difference(newApps.map((e) => e.id).toSet()); - for (var id in idsToDelete) { - apps.remove(id); - } var sp = SourceProvider(); List> errors = []; - for (int i = 0; i < newApps.length; i++) { - var info = await getInstalledInfo(newApps[i].id); + List newApps = (await getAppsDir()) + .listSync() + .where((item) => item.path.toLowerCase().endsWith('.json')) + .toList(); + for (var e in newApps) { try { - sp.getSource(newApps[i].url, overrideSource: newApps[i].overrideSource); - apps[newApps[i].id] = AppInMemory(newApps[i], null, info); - } catch (e) { - errors.add([newApps[i].id, newApps[i].finalName, e.toString()]); + var app = App.fromJson(jsonDecode(File(e.path).readAsStringSync())); + try { + var info = await getInstalledInfo(app.id); + sp.getSource(app.url, overrideSource: app.overrideSource); + apps[app.id] = AppInMemory(app, null, info); + notifyListeners(); + } catch (e) { + errors.add([app.id, app.finalName, e.toString()]); + } + } catch (err) { + if (err is FormatException) { + logs.add('Corrupt JSON when loading App (will be ignored): $e'); + e.renameSync('${e.path}.corrupt'); + } else { + rethrow; + } } } if (errors.isNotEmpty) { @@ -798,13 +787,13 @@ class AppsProvider with ChangeNotifier { for (var appId in appIds) { File file = File('${(await getAppsDir()).path}/$appId.json'); if (file.existsSync()) { - file.deleteSync(); + file.deleteSync(recursive: true); } apkFiles ?.where( (element) => element.path.split('/').last.startsWith('$appId-')) .forEach((element) { - element.delete(); + element.delete(recursive: true); }); if (apps.containsKey(appId)) { apps.remove(appId); From d24f2b4e6d98c2e39763d8b2b5c2bd52dbf5cafe Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 22 May 2023 13:02:18 -0400 Subject: [PATCH 212/600] Attempted fix for #549 APK stored in "ext storage" dir if cache dir not available --- lib/providers/apps_provider.dart | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 4d82bf4..9cc7b64 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -108,6 +108,7 @@ class AppsProvider with ChangeNotifier { bool isForeground = true; late Stream? foregroundStream; late StreamSubscription? foregroundSubscription; + late Directory APKDir; Iterable getAppValues() => apps.values.map((a) => a.deepCopy()); @@ -119,13 +120,21 @@ class AppsProvider with ChangeNotifier { if (isForeground) await refreshInstallStatuses(); }); () async { + var cacheDirs = await getExternalCacheDirectories(); + if (cacheDirs?.isNotEmpty ?? false) { + APKDir = cacheDirs!.first; + } else { + APKDir = + Directory('${(await getExternalStorageDirectory())!.path}/apks'); + if (!APKDir.existsSync()) { + APKDir.createSync(); + } + } // Load Apps into memory (in background, this is done later instead of in the constructor) await loadApps(); // Delete any partial APKs var cutoff = DateTime.now().subtract(const Duration(days: 7)); - (await getExternalCacheDirectories()) - ?.first - .listSync() + APKDir.listSync() .where((element) => element.path.endsWith('.part') || element.statSync().modified.isBefore(cutoff)) @@ -138,7 +147,7 @@ class AppsProvider with ChangeNotifier { Future downloadFile( String url, String fileNameNoExt, Function? onProgress, {bool useExisting = true, Map? headers}) async { - var destDir = (await getExternalCacheDirectories())!.first.path; + var destDir = APKDir.path; var req = Request('GET', Uri.parse(url)); if (headers != null) { req.headers.addAll(headers); @@ -783,14 +792,14 @@ class AppsProvider with ChangeNotifier { } Future removeApps(List appIds) async { - var apkFiles = (await getExternalCacheDirectories())?.first.listSync(); + var apkFiles = APKDir.listSync(); for (var appId in appIds) { File file = File('${(await getAppsDir()).path}/$appId.json'); if (file.existsSync()) { file.deleteSync(recursive: true); } apkFiles - ?.where( + .where( (element) => element.path.split('/').last.startsWith('$appId-')) .forEach((element) { element.delete(recursive: true); From 2ccff1552583f9e17032552cd8808cba9b3b4e26 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 22 May 2023 13:45:09 -0400 Subject: [PATCH 213/600] Fix Icon on Android 7 and lower (#475) --- .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3514 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2378 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4646 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7272 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9849 bytes assets/graphics/icon.png | Bin 0 -> 67744 bytes pubspec.lock | 48 ++++++++++++++++++ pubspec.yaml | 5 ++ 8 files changed, 53 insertions(+) create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 assets/graphics/icon.png diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..c915a75a073ab8c05b1bad8dcc4fc34eee5523f8 GIT binary patch literal 3514 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d739ed13445670fa9d650e682ec91c5a8814ad1e GIT binary patch literal 2378 zcmV-Q3AOf#P)EX>4Tx04R}tkv&MmKpe$iQ%glEA{G&G2-rGV5EXIMDionYsTEpvFuC+YXws0R zxHt-~1qVMCs}3&Cx;nTDg5U>;tBaGOi`{MF9QiMHIslGxgb2Dhbc=bq^n3?_xa5``n+STgjUY@QK7TOgAjzb>gW_ zOXs{#9A+g+AwDM_HRyuGk6f2se&bwpSm2pqBa@yZ4ik&THkR9%l?;`5k~pHM8s!UF zmle)ioYiubHSft^7|LtQOI)Wpgaj6_h!jM~sA2U7%63?eAmTZkz!AXW&X}`73o``jhlp zON$%`lz_>`lz@?NuyqoOy$xgZqEy+rQkr=^|zR&I5b@)i~&Mh0s*pm{FvLiKh{!&*rx}*%{v$d|z_}yh8pU{5W z_RVoQxj$yfmH#auvLzJY?!0LJ+waG3AwzUDx;u1GeeOQ|dhQ-x|Fxh;5pZ3?hsd{F zLFCRePm0BaPd?qVH+1FMLI4!AGzX!8ZAtGZvu&-dsFJTMRYU%PW*E{VM&f$p;s4(h z_u;yt6PAPsA@cQSKqwkND}z_~EcW*fjk;7-oKIT-hsC#DzbW=rBC^O33eC!XxKY{# zf~RdDVErs`oHGq{dOc1YeJB7ODFlUz!ZxTVYK4`X=Yn+0vt!0&G8wQnAu-`n;sgW) z`G-f$5b^%uIKze{H%XkEyW-)S^`3FSZXgn-U&D5JtiL3b|G+6(GBwg9AHtf09qQmhTBGo zz&{8coqz~uv*Qb$cs7d{`n_0LU1D}ITNL1f!(3ZG?)_U=dSD3EKlbP_G3D6~qk!jv zg;0{!0`5y^fTQy?IDNFiWIZrh4Dbt`ZHWTT!P|$n09QBjrL(@Q8+1DT2#-GYaDC+i zW9hV?$%d4l1C91Se^U=bi2kuq+%_=$Y2flK?~86YEVWw{VDDfr81Hujxmwu+-1~@0 zT5#>HK)gx>-eE%H&DtZN2nOW^t)}^pe}8E;@z&xX5RA)#Pymx*1q>#PdvD*~sD-=D znumEj!lN1u3JhxuZ0$_FT63ub?%wG$S;RtTE_jJ&5(;2ifyEMTRsf3O3$lN(&jHxe zN4NcUL2Z)Dk36dFK_EA+0nX>PKy-pTcn8fgMxrEF^=Gt@VG%D$-Atln4t;$ZvlYmq z00UavTH8eK3m1(3eQ}ro+8TS|=C!WjYGS&G@3i#7S07h`o0mNVNnJoudK)J{yk79i zgE3GDTRoSMya70cHrfJeYier!mX8(S=)!@GpUs2%%W5b%+61>%y<;ko;kr)Q0o9f5 zW1{6Nc?ukz%x*6xsHv@~r7fVmyrN>uJL}et*JcR6r@sI^o_BzYdAA|&yG9sL>&))F zBdv&_O;#(sNfP4>zG1WA%*iGwJlP0CeTZ2R zT)s8_C^?6efHGOt^{&3wTeJnVt5vGvf(zx*vCAbylX38R{z}3;SRUg7r_ySmlVoE0v&&(IVzKn2?%YKJ%_FsV; zb)Dd~bQZXK&LGu4Wq0ZUoxVp+WJf3f-w)8Fci!GwDY+=;*|8}-4;!NPLdYEO4|ajV zoEso=8MCE~i&ELOhK%nIr;@QHm5lYx%B$NF|GD$qll%7>?$fEl&?hQ(J}KLd_MU($M7*RFkSLtXtv8P&ct2w-sh)EA%0ubh`1{NnJ}E28~<7&N1y>DQqL_kVX{&*wXn zwFBx-I%ClG;Eh{XFRxs^%va*~@;^REPEL-94iww4&F|PF(RsI5my!NM?x8~m_qDax zU8BpvfC;4lh9_0o<^1fj*!*lKM~?*&;gQkHBoc`i4$*8U5!aSwjiMNIcWJdMRdbV4 zsjQO8WdA!~R+Kk5)O~Lvb3YLQBhh}Zu`VOi@Hw>4aLoWKJhNCF3@}{7;1hczGa7%{ wJ2DIq4F98i-cJ=%FZm`LQvxO%e|rJ{2lScQP-i>FSpWb407*qoM6N<$g3mdB<^TWy literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..f27927714ea5754007b6a91d087ca237eca6f139 GIT binary patch literal 4646 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..6ceb87e6cc253b28e7fc80c24341acf29c82c21c GIT binary patch literal 7272 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..652ac54bd758f533070fb082c30707127d1c59d4 GIT binary patch literal 9849 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 G$o~Moh5PjY literal 0 HcmV?d00001 diff --git a/assets/graphics/icon.png b/assets/graphics/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bbb75cfdfec3be051787772302af4bda0d023bca GIT binary patch literal 67744 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�aAta!dZ8!J$~ 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 ZlZTN}8f{EBUU!q6LX=3.0.0-417 <4.0.0" flutter: ">=3.4.0-17.0.pre" diff --git a/pubspec.yaml b/pubspec.yaml index 12cdeee..ac50e0d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -69,6 +69,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter + flutter_launcher_icons: ^0.13.1 # The "flutter_lints" package below contains a set of recommended lints to # encourage good coding practices. The lint set provided by the package is @@ -77,6 +78,10 @@ dev_dependencies: # rules and activating additional ones. flutter_lints: ^2.0.1 +flutter_launcher_icons: + android: "ic_launcher" + image_path: "assets/graphics/icon.png" + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From ce6e6c47dbbba529ae03a4cf4601c91165ff243a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 22 May 2023 14:47:28 -0400 Subject: [PATCH 214/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 50 +++++++++++++++++++++++++------------------------- pubspec.yaml | 4 ++-- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 089c1fb..a1494bc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.4'; +const String currentVersion = '0.13.5'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 0556e5b..d45df69 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: "direct main" description: name: android_alarm_manager_plus - sha256: ed5fb34f8befc382fb4800b02aa86a34d279b911e1c05752f702d12fcfe26e0e + sha256: "80f963d47cb7ab0818144c7b0668aea4c038f9cb8626626e89a4ea77375defb7" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.1" android_intent_plus: dependency: "direct main" description: name: android_intent_plus - sha256: f79fbb8ccb64b5584d19caa9c3d15613bf21cfbd829a6ca7f089fb5dfd43f8aa + sha256: "2c87d8330ba5deef5fe20e77f4d178190b3b24531dce08368030ab4be40a9d4e" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "4.0.1" android_package_installer: dependency: "direct main" description: @@ -158,10 +158,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "9b1a0c32b2a503f8fe9f8764fac7b5fcd4f6bd35d8f49de5350bccf9e2a33b8a" + sha256: "499c61743e13909c13374a8c209075385858c614b9c0f2487b5f9995eeaf7369" url: "https://pub.dev" source: hosted - version: "9.0.0" + version: "9.0.1" device_info_plus_platform_interface: dependency: transitive description: @@ -174,18 +174,18 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: bbebb1b7ebed819e0ec83d4abdc2a8482d934f6a85289ffc1c6acf7589fa2aad + sha256: "74dff1435a695887ca64899b8990004f8d1232b0e84bfc4faa1fdda7c6f57cc1" url: "https://pub.dev" source: hosted - version: "1.6.3" + version: "1.6.5" easy_localization: dependency: "direct main" description: name: easy_localization - sha256: f30e9b20ed4d1b890171c30241d9b9c43efe21fee55dee7bd68f94daf269ea75 + sha256: "30ebf25448ffe169e0bd9bc4b5da94faa8398967a2ad2ca09f438be8b6953645" url: "https://pub.dev" source: hosted - version: "3.0.2-dev.2" + version: "3.0.2" easy_logger: dependency: transitive description: @@ -259,10 +259,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: ee6ee56855aa920899b68586b538474d086c149932220b47b92502cbfb5ba5e5 + sha256: "12f8abacca8bf29c042ec50c554f967da4c6f88ec99fc215e0325e5b43a25188" url: "https://pub.dev" source: hosted - version: "14.0.0+2" + version: "14.1.0" flutter_local_notifications_linux: dependency: transitive description: @@ -296,10 +296,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "96af49aa6b57c10a312106ad6f71deed5a754029c24789bbf620ba784f0bd0b0" + sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360" url: "https://pub.dev" source: hosted - version: "2.0.14" + version: "2.0.15" flutter_test: dependency: "direct dev" description: flutter @@ -330,10 +330,10 @@ packages: dependency: "direct main" description: name: http - sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + sha256: "4c3f04bfb64d3efd508d06b41b825542f08122d30bda4933fb95c069d22a4fa3" url: "https://pub.dev" source: hosted - version: "0.13.6" + version: "1.0.0" http_parser: dependency: transitive description: @@ -522,10 +522,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: "8028362b40c4a45298f1cbfccd227c8dd6caf0e27088a69f2ba2ab15464159e2" + sha256: d8cc6a62ded6d0f49c6eac337e080b066ee3bce4d405bd9439a61e1f1927bfe8 url: "https://pub.dev" source: hosted - version: "10.2.0" + version: "10.2.1" permission_handler_apple: dependency: transitive description: @@ -602,10 +602,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: "322a1ec9d9fe07e2e2252c098ce93d12dbd06133cc4c00ffe6a4ef505c295c17" + sha256: "44fc0bc2d35a8fafa1b564e1c6888bdc4fbb2d0197e4a4c21bac0e66123be9cd" url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" share_plus_platform_interface: dependency: transitive description: @@ -687,10 +687,10 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "3a82c9a216b46b88617e3714dd74227eaca20c501c4abcc213e56db26b9caa00" + sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 url: "https://pub.dev" source: hosted - version: "2.2.8+2" + version: "2.2.8+4" sqflite_common: dependency: transitive description: @@ -775,10 +775,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "7aac14be5f4731b923cc697ae2d42043945076cd0dbb8806baecc92c1dc88891" + sha256: "1a5848f598acc5b7d8f7c18b8cb834ab667e59a13edc3c93e9d09cf38cc6bc87" url: "https://pub.dev" source: hosted - version: "6.0.33" + version: "6.0.34" url_launcher_ios: dependency: transitive description: @@ -916,5 +916,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0-417 <4.0.0" + dart: ">=3.0.0 <4.0.0" flutter: ">=3.4.0-17.0.pre" diff --git a/pubspec.yaml b/pubspec.yaml index ac50e0d..54acc82 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.13.4+168 # When changing this, update the tag in main() accordingly +version: 0.13.5+169 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' @@ -40,7 +40,7 @@ dependencies: flutter_fgbg: ^0.2.0 # Try removing reliance on this flutter_local_notifications: ^14.0.0+1 provider: ^6.0.3 - http: ^0.13.5 + http: ^1.0.0 webview_flutter: ^4.0.0 dynamic_color: ^1.5.4 html: ^0.15.0 From fee23cadfa5a9da9ac59ec9e42db3466562dc25c Mon Sep 17 00:00:00 2001 From: gidano Date: Fri, 26 May 2023 18:58:23 +0200 Subject: [PATCH 215/600] Update hu.json --- assets/translations/hu.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index a003fbc..6d311b6 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -227,11 +227,11 @@ "dontShowAgain": "Ne mutassa ezt újra", "dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést", "dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket", - "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", - "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", - "about": "About", - "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", - "checkOnStart": "Check Once on Start", + "moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára", + "gitlabPATLabel": "GitLab Personal Access Token (Engedélyezi a Keresést)", + "about": "Rólunk", + "requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)", + "checkOnStart": "Egyszer az indításkor", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From 833ece1ef5683e7d46d40db32ce16a5bca701991 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 27 May 2023 20:36:29 -0400 Subject: [PATCH 216/600] Infer GitHub App ID where possible --- lib/app_sources/apkcombo.dart | 6 ++-- lib/app_sources/apkpure.dart | 6 ++-- lib/app_sources/fdroid.dart | 6 ++-- lib/app_sources/github.dart | 49 ++++++++++++++++++++++++++++-- lib/app_sources/izzyondroid.dart | 6 ++-- lib/providers/source_provider.dart | 6 ++-- 6 files changed, 62 insertions(+), 17 deletions(-) diff --git a/lib/app_sources/apkcombo.dart b/lib/app_sources/apkcombo.dart index 16e21c5..c90b0cb 100644 --- a/lib/app_sources/apkcombo.dart +++ b/lib/app_sources/apkcombo.dart @@ -19,8 +19,8 @@ class APKCombo extends AppSource { } @override - String? tryInferringAppId(String standardUrl, - {Map additionalSettings = const {}}) { + Future tryInferringAppId(String standardUrl, + {Map additionalSettings = const {}}) async { return Uri.parse(standardUrl).pathSegments.last; } @@ -83,7 +83,7 @@ class APKCombo extends AppSource { String standardUrl, Map additionalSettings, ) async { - String appId = tryInferringAppId(standardUrl)!; + String appId = (await tryInferringAppId(standardUrl))!; var preres = await sourceRequest(standardUrl); if (preres.statusCode != 200) { throw getObtainiumHttpError(preres); diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index 20028a4..f3cef4e 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -24,8 +24,8 @@ class APKPure extends AppSource { } @override - String? tryInferringAppId(String standardUrl, - {Map additionalSettings = const {}}) { + Future tryInferringAppId(String standardUrl, + {Map additionalSettings = const {}}) async { return Uri.parse(standardUrl).pathSegments.last; } @@ -34,7 +34,7 @@ class APKPure extends AppSource { String standardUrl, Map additionalSettings, ) async { - String appId = tryInferringAppId(standardUrl)!; + String appId = (await tryInferringAppId(standardUrl))!; String host = Uri.parse(standardUrl).host; var res = await sourceRequest('$standardUrl/download'); if (res.statusCode == 200) { diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 28d45cc..0602f6d 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -31,8 +31,8 @@ class FDroid extends AppSource { } @override - String? tryInferringAppId(String standardUrl, - {Map additionalSettings = const {}}) { + Future tryInferringAppId(String standardUrl, + {Map additionalSettings = const {}}) async { return Uri.parse(standardUrl).pathSegments.last; } @@ -63,7 +63,7 @@ class FDroid extends AppSource { String standardUrl, Map additionalSettings, ) async { - String? appId = tryInferringAppId(standardUrl); + String? appId = await tryInferringAppId(standardUrl); String host = Uri.parse(standardUrl).host; return getAPKUrlsFromFDroidPackagesAPIResponse( await sourceRequest('https://$host/api/v1/packages/$appId'), diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index a34bda2..0d1c6a9 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -6,6 +6,7 @@ import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/apps_provider.dart'; +import 'package:obtainium/providers/logs_provider.dart'; import 'package:obtainium/providers/settings_provider.dart'; import 'package:obtainium/providers/source_provider.dart'; import 'package:url_launcher/url_launcher_string.dart'; @@ -79,6 +80,44 @@ class GitHub extends AppSource { canSearch = true; } + @override + Future tryInferringAppId(String standardUrl, + {Map additionalSettings = const {}}) async { + const possibleBuildGradleLocations = [ + '/app/build.gradle', + 'android/app/build.gradle', + 'src/app/build.gradle' + ]; + for (var path in possibleBuildGradleLocations) { + try { + var res = await sourceRequest( + '${await convertStandardUrlToAPIUrl(standardUrl)}/contents/$path'); + if (res.statusCode == 200) { + try { + var body = jsonDecode(res.body); + var appId = utf8 + .decode(base64 + .decode(body['content'].toString().split('\n').join(''))) + .split('\n') + .map((e) => e.trim()) + .where((l) => l.startsWith('applicationId "')) + .first + .split('"')[1]; + if (appId.isNotEmpty) { + return appId; + } + } catch (err) { + LogsProvider().add( + 'Error parsing build.gradle from ${res.request!.url.toString()}: ${err.toString()}'); + } + } + } catch (err) { + // Ignore - ID will be extracted from the APK + } + } + return null; + } + @override String sourceSpecificStandardizeURL(String url) { RegExp standardUrlRegEx = RegExp('^https?://$host/[^/]+/[^/]+'); @@ -97,6 +136,12 @@ class GitHub extends AppSource { return creds != null && creds.isNotEmpty ? '$creds@' : ''; } + Future getAPIHost() async => + 'https://${await getCredentialPrefixIfAny()}api.$host'; + + Future convertStandardUrlToAPIUrl(String standardUrl) async => + '${await getAPIHost()}/repos${standardUrl.substring('https://$host'.length)}'; + @override String? changeLogPageFromStandardUrl(String standardUrl) => '$standardUrl/releases'; @@ -239,7 +284,7 @@ class GitHub extends AppSource { ) async { return await getLatestAPKDetailsCommon2(standardUrl, additionalSettings, (bool useTagUrl) async { - return 'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100'; + return '${await convertStandardUrlToAPIUrl(standardUrl)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100'; }, (Response res) { rateLimitErrorCheck(res); }); @@ -281,7 +326,7 @@ class GitHub extends AppSource { Future>> search(String query) async { return searchCommon( query, - 'https://${await getCredentialPrefixIfAny()}api.$host/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100', + '${await getAPIHost()}/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100', 'items', onHttpErrorCode: (Response res) { rateLimitErrorCheck(res); }); diff --git a/lib/app_sources/izzyondroid.dart b/lib/app_sources/izzyondroid.dart index 1773558..d0fcfe8 100644 --- a/lib/app_sources/izzyondroid.dart +++ b/lib/app_sources/izzyondroid.dart @@ -18,8 +18,8 @@ class IzzyOnDroid extends AppSource { } @override - String? tryInferringAppId(String standardUrl, - {Map additionalSettings = const {}}) { + Future tryInferringAppId(String standardUrl, + {Map additionalSettings = const {}}) async { return FDroid().tryInferringAppId(standardUrl); } @@ -28,7 +28,7 @@ class IzzyOnDroid extends AppSource { String standardUrl, Map additionalSettings, ) async { - String? appId = tryInferringAppId(standardUrl); + String? appId = await tryInferringAppId(standardUrl); return FDroid().getAPKUrlsFromFDroidPackagesAPIResponse( await sourceRequest( 'https://apt.izzysoft.de/fdroid/api/v1/packages/$appId'), diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index d980e3c..fc06a03 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -434,8 +434,8 @@ abstract class AppSource { throw NotImplementedError(); } - String? tryInferringAppId(String standardUrl, - {Map additionalSettings = const {}}) { + Future tryInferringAppId(String standardUrl, + {Map additionalSettings = const {}}) async { return null; } } @@ -592,7 +592,7 @@ class SourceProvider { : apk.names.name[0].toUpperCase() + apk.names.name.substring(1); return App( currentApp?.id ?? - source.tryInferringAppId(standardUrl, + await source.tryInferringAppId(standardUrl, additionalSettings: additionalSettings) ?? generateTempID(standardUrl, additionalSettings), standardUrl, From feb4c2eabce12ef61aceaf02f6b5d70768a816b5 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 27 May 2023 20:38:20 -0400 Subject: [PATCH 217/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a1494bc..98d6d1f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.5'; +const String currentVersion = '0.13.6'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 54acc82..8d57bd9 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.13.5+169 # When changing this, update the tag in main() accordingly +version: 0.13.6+170 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From a0d466a074fcc1eb64cbd1ad8f21d70065e3d237 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 27 May 2023 21:01:16 -0400 Subject: [PATCH 218/600] Add toggle for App ID inferring where optional --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/github.dart | 1 + lib/pages/add_app.dart | 22 +++++++++++++++++++++- lib/providers/source_provider.dart | 11 ++++++++--- 12 files changed, 39 insertions(+), 4 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 7499014..f68da68 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -233,6 +233,7 @@ "about": "Über", "requiresCredentialsInSettings": "Benötigt zusätzliche Anmeldedaten (in den Einstellungen)", "checkOnStart": "Überprüfe einmalig beim Start", + "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 1f543ac..e9b4503 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -233,6 +233,7 @@ "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "checkOnStart": "Check Once on Start", + "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index d3b6500..6c7cc05 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -233,6 +233,7 @@ "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "checkOnStart": "Check Once on Start", + "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index d7eb778..0b4030a 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -233,6 +233,7 @@ "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "checkOnStart": "Check Once on Start", + "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index dfc8876..ea60088 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -233,6 +233,7 @@ "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "checkOnStart": "Check Once on Start", + "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 6d311b6..c3771af 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -232,6 +232,7 @@ "about": "Rólunk", "requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)", "checkOnStart": "Egyszer az indításkor", + "tryInferAppIdFromCode": "Try inferring App ID from source code", "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 53b20c6..93c56e1 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -233,6 +233,7 @@ "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "checkOnStart": "Check Once on Start", + "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeAppQuestion": { "one": "Rimuovere l'App?", "other": "Rimuovere le App?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 135a8ab..c0d9c22 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -233,6 +233,7 @@ "about": "概要", "requiresCredentialsInSettings": "これには追加の認証が必要です (設定にて)", "checkOnStart": "Check Once on Start", + "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 83c08b2..0b3837c 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -233,6 +233,7 @@ "about": "相关文档", "requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)", "checkOnStart": "启动时进行一次检查", + "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 0d1c6a9..d75beb2 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -14,6 +14,7 @@ import 'package:url_launcher/url_launcher_string.dart'; class GitHub extends AppSource { GitHub() { host = 'github.com'; + appIdInferIsOptional = true; additionalSourceSpecificSettingFormItems = [ GeneratedFormTextField('github-creds', diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index c439f30..b31dc4d 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -33,6 +33,7 @@ class _AddAppPageState extends State { AppSource? pickedSource; Map additionalSettings = {}; bool additionalSettingsValid = true; + bool inferAppIdIfOptional = true; List pickedCategories = []; int searchnum = 0; SourceProvider sourceProvider = SourceProvider(); @@ -78,6 +79,7 @@ class _AddAppPageState extends State { additionalSettingsValid = source != null ? !sourceProvider.ifRequiredAppSpecificSettingsExist(source) : true; + inferAppIdIfOptional = true; } }); } @@ -147,7 +149,8 @@ class _AddAppPageState extends State { app = await sourceProvider.getApp( pickedSource!, userInput, additionalSettings, trackOnlyOverride: trackOnly, - overrideSource: pickedSourceOverride); + overrideSource: pickedSourceOverride, + inferAppIdIfOptional: inferAppIdIfOptional); // Only download the APK here if you need to for the package ID if (sourceProvider.isTempId(app) && app.additionalSettings['trackOnly'] != true) { @@ -428,6 +431,23 @@ class _AddAppPageState extends State { }), ], ), + if (pickedSource != null && pickedSource!.appIdInferIsOptional) + GeneratedForm( + key: const Key('inferAppIdIfOptional'), + items: [ + [ + GeneratedFormSwitch('inferAppIdIfOptional', + label: tr('tryInferAppIdFromCode'), + defaultValue: inferAppIdIfOptional) + ] + ], + onValueChanges: (values, valid, isBuilding) { + if (!isBuilding) { + setState(() { + inferAppIdIfOptional = values['inferAppIdIfOptional']; + }); + } + }), ], ); diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index fc06a03..41caa43 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -317,6 +317,7 @@ abstract class AppSource { late String name; bool enforceTrackOnly = false; bool changeLogIfAnyIsMarkDown = true; + bool appIdInferIsOptional = false; AppSource() { name = runtimeType.toString(); @@ -552,7 +553,8 @@ class SourceProvider { AppSource source, String url, Map additionalSettings, {App? currentApp, bool trackOnlyOverride = false, - String? overrideSource}) async { + String? overrideSource, + bool inferAppIdIfOptional = false}) async { if (trackOnlyOverride || source.enforceTrackOnly) { additionalSettings['trackOnly'] = true; } @@ -592,8 +594,11 @@ class SourceProvider { : apk.names.name[0].toUpperCase() + apk.names.name.substring(1); return App( currentApp?.id ?? - await source.tryInferringAppId(standardUrl, - additionalSettings: additionalSettings) ?? + ((!source.appIdInferIsOptional || + (source.appIdInferIsOptional && inferAppIdIfOptional)) + ? await source.tryInferringAppId(standardUrl, + additionalSettings: additionalSettings) + : null) ?? generateTempID(standardUrl, additionalSettings), standardUrl, apk.names.author[0].toUpperCase() + apk.names.author.substring(1), From 1ff1c6ca339b5308e6482ab39f221e54cf311e1f Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Sun, 28 May 2023 11:57:07 +0200 Subject: [PATCH 219/600] Added translation using Weblate (Polish) --- assets/translations/pl.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 assets/translations/pl.json diff --git a/assets/translations/pl.json b/assets/translations/pl.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/assets/translations/pl.json @@ -0,0 +1 @@ +{} From eb26c0be0bb05148992cba81ef47a3d0cbbf4785 Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Sun, 28 May 2023 09:57:56 +0000 Subject: [PATCH 220/600] Translated using Weblate (Polish) --- assets/translations/pl.json | 286 +++++++++++++++++++++++++++++++++++- 1 file changed, 285 insertions(+), 1 deletion(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 0967ef4..323daa3 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -1 +1,285 @@ -{} +{ + "noDescription": "Brak opisu", + "no": "Nie", + "okay": "Okej", + "appId": "ID aplikacji", + "bgUpdateGotErrorRetryInMinutes": { + "one": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minutę", + "other": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} min" + }, + "invalidURLForSource": "Nieprawidłowy adres URL aplikacji {}", + "noReleaseFound": "Nie można znaleźć odpowiedniego wydania", + "noVersionFound": "Nie można określić wersji wydania", + "urlMatchesNoSource": "Adres URL nie pasuje do znanego źródła", + "cantInstallOlderVersion": "Nie można zainstalować starszej wersji aplikacji", + "appIdMismatch": "Pobrany identyfikator pakietu nie pasuje do istniejącego identyfikatora aplikacji", + "functionNotImplemented": "Ta klasa nie zaimplementowała tej funkcji", + "placeholder": "Placeholder", + "someErrors": "Wystąpiły pewne błędy", + "unexpectedError": "Nieoczekiwany błąd", + "ok": "Okej", + "and": "i", + "startedBgUpdateTask": "Rozpoczęto sprawdzanie aktualizacji w tle", + "bgUpdateIgnoreAfterIs": "Parametr ignoreAfter aktualizacji w tle to {}", + "startedActualBGUpdateCheck": "Rozpoczęto sprawdzanie aktualizacji w tle", + "bgUpdateTaskFinished": "Zakończono sprawdzanie aktualizacji w tle", + "firstRun": "Jest to pierwsze uruchomienie Obtainium", + "settingUpdateCheckIntervalTo": "Ustawianie interwału aktualizacji na {}", + "githubPATLabel": "Osobisty Token Dostępu GitHub (zwiększa limit zapytań)", + "githubPATHint": "Wymagany format OTD: użytkownik:token", + "githubPATFormat": "użytkownik:token", + "includePrereleases": "Uwzględnij wersje wstępne", + "fallbackToOlderReleases": "Powracaj do starszych wersji", + "filterReleaseTitlesByRegEx": "Filtruj tytuły wydań wg. wyrażeń regularnych", + "invalidRegEx": "Nieprawidłowe wyrażenie regularne", + "cancel": "Anuluj", + "continue": "Kontynuuj", + "requiredInBrackets": "(Wymagane)", + "dropdownNoOptsError": "BŁĄD: LISTA ROZWIJANA MUSI MIEĆ CO NAJMNIEJ JEDNĄ OPCJĘ", + "colour": "Kolor", + "githubStarredRepos": "Repozytoria GitHub oznaczone gwiazdką", + "uname": "Nazwa użytkownika", + "wrongArgNum": "Nieprawidłowa liczba podanych argumentów", + "xIsTrackOnly": "{} jest tylko obserwowana", + "source": "Źródło", + "app": "Aplikacja", + "appsFromSourceAreTrackOnly": "Aplikacje z tego źródła są „Obserwowane”.", + "youPickedTrackOnly": "Wybrano opcję „Tylko obserwuj”.", + "trackOnlyAppDescription": "Aplikacja będzie obserwowana pod kątem aktualizacji, ale Obtainium nie będzie w stanie jej pobrać ani zainstalować.", + "cancelled": "Anulowano", + "appAlreadyAdded": "Aplikacja już została dodana", + "alreadyUpToDateQuestion": "Aplikacja jest już aktualna?", + "addApp": "Dodaj apkę", + "appSourceURL": "Adres URL źródła aplikacji", + "error": "Błąd", + "add": "Dodaj", + "searchSomeSourcesLabel": "Szukaj (tylko niektóre źródła)", + "search": "Szukaj", + "additionalOptsFor": "Dodatkowe opcje dla {}", + "supportedSourcesBelow": "Obsługiwane źródła:", + "trackOnlyInBrackets": "(tylko obserwowane)", + "searchableInBrackets": "(Wyszukiwalne)", + "appsString": "Aplikacje", + "noApps": "Brak aplikacji", + "noAppsForFilter": "Brak aplikacji dla filtra", + "byX": "Autorstwa {}", + "percentProgress": "Postęp: {}%", + "pleaseWait": "Proszę czekać", + "updateAvailable": "Dostępna aktualizacja", + "estimateInBracketsShort": "(Szac.)", + "notInstalled": "Nie zainstalowano", + "estimateInBrackets": "(Szacunkowo)", + "selectAll": "Zaznacz wszystkie", + "deselectN": "Odznacz {}", + "xWillBeRemovedButRemainInstalled": "{} zostanie usunięty z Obtainium, ale pozostanie zainstalowany na urządzeniu.", + "removeSelectedAppsQuestion": "Usunąć wybrane aplikacje?", + "removeSelectedApps": "Usuń wybrane aplikacje", + "updateX": "Zaktualizuj {}", + "installX": "Zainstaluj {}", + "markXTrackOnlyAsUpdated": "Oznacz {}\n(Tylko obserwowana)\njako zaktualizowaną", + "changeX": "Zmień {}", + "installUpdateApps": "Instaluj/aktualizuj aplikacje", + "installUpdateSelectedApps": "Zainstaluj/zaktualizuj wybrane aplikacje", + "markXSelectedAppsAsUpdated": "Oznaczyć {} wybranych aplikacji jako zaktualizowane?", + "yes": "Tak", + "markSelectedAppsUpdated": "Oznacz wybrane aplikacje jako zaktualizowane", + "pinToTop": "Przypnij", + "unpinFromTop": "Odepnij", + "resetInstallStatusForSelectedAppsQuestion": "Zresetować status instalacji dla wybranych aplikacji?", + "installStatusOfXWillBeResetExplanation": "Stan instalacji wybranych aplikacji zostanie zresetowany.\n\nMoże być to pomocne, gdy wersja aplikacji wyświetlana w Obtainium jest nieprawidłowa z powodu nieudanych aktualizacji lub innych problemów.", + "shareSelectedAppURLs": "Udostępnij wybrane adresy URL aplikacji", + "resetInstallStatus": "Zresetuj stan instalacji", + "more": "Więcej", + "removeOutdatedFilter": "Usuń filtr nieaktualnych aplikacji", + "showOutdatedOnly": "Pokaż tylko nieaktualne aplikacje", + "filter": "FIltr", + "filterActive": "Filtruj *", + "filterApps": "Filtruj aplikacje", + "appName": "Nazwa aplikacji", + "author": "Autor", + "upToDateApps": "Aktualne aplikacje", + "nonInstalledApps": "Niezainstalowane aplikacje", + "importExport": "Import/Eksport", + "settings": "Ustawienia", + "exportedTo": "Wyeksportowano do {}", + "obtainiumExport": "Eksportuj Obtainium", + "invalidInput": "Nieprawidłowe wprowadzenie", + "importedX": "Zaimportowano {}", + "obtainiumImport": "Import Obtainium", + "importFromURLList": "Importuj z listy adresów URL", + "searchQuery": "Wyszukiwane zapytanie", + "appURLList": "Lista adresów URL aplikacji", + "line": "Linia", + "searchX": "Przeszukaj {}", + "noResults": "Nie znaleziono wyników", + "importX": "Importuj {}", + "importedAppsIdDisclaimer": "Zaimportowane aplikacje mogą być wyświetlane jako „Niezainstalowane”.\nAby to naprawić, zainstaluj je ponownie za pomocą Obtainium.\nNie powinno to mieć wpływu na dane aplikacji.\n\nDotyczy tylko adresów URL i metod importu innych aplikacji.", + "importErrors": "Błędy importowania", + "importedXOfYApps": "Zaimportowano {} z {} aplikacji.", + "followingURLsHadErrors": "Następujące adresy URL zawierały błędy:", + "selectURL": "Wybierz adres URL", + "selectURLs": "Wybierz adresy URL", + "pick": "Wybierz", + "theme": "Motyw", + "dark": "Ciemny", + "light": "Jasny", + "followSystem": "Zgodny z systemem", + "obtainium": "Obtainium", + "materialYou": "Material You", + "useBlackTheme": "Użyj czarnego motywu", + "appSortBy": "Sortuj aplikacje według", + "authorName": "Autor/Nazwa", + "nameAuthor": "Nazwa/Autor", + "asAdded": "Dodania", + "appSortOrder": "Kolejność sortowania aplikacji", + "ascending": "Rosnąco", + "descending": "Malejąco", + "bgUpdateCheckInterval": "Częstotliwość sprawdzania aktualizacji w tle", + "neverManualOnly": "Nigdy - tylko ręcznie", + "appearance": "Wygląd", + "showWebInAppView": "Pokaż stronę źródłową w widoku aplikacji", + "pinUpdates": "Przypnij aktualizacje na górze widoku aplikacji", + "updates": "Aktualizacje", + "sourceSpecific": "Zależnie od źródła", + "appSource": "Źródło aplikacji", + "noLogs": "Brak logów", + "appLogs": "Logi aplikacji", + "close": "Zamknij", + "share": "Udostępnij", + "appNotFound": "Nie znaleziono aplikacji", + "obtainiumExportHyphenatedLowercase": "obtainium-eksport", + "pickAnAPK": "Wybierz plik APK", + "appHasMoreThanOnePackage": "{} ma więcej niż jeden pakiet:", + "deviceSupportsXArch": "Urządzenie obsługuje architekturę procesora {}.", + "deviceSupportsFollowingArchs": "Urządzenie obsługuje następujące architektury procesora:", + "warning": "Uwaga", + "sourceIsXButPackageFromYPrompt": "Źródłem aplikacji jest '{}', ale pakiet wydania pochodzi z '{}'. Kontynuować?", + "updatesAvailable": "Dostępne aktualizacje", + "updatesAvailableNotifDescription": "Powiadamia użytkownika, że dostępne są aktualizacje dla jednej lub więcej aplikacji obserwowanych przez Obtainium", + "noNewUpdates": "Brak nowych aktualizacji.", + "xHasAnUpdate": "{} ma aktualizację.", + "appsUpdated": "Zaktualizowane aplikacje", + "appsUpdatedNotifDescription": "Powiadamia użytkownika, że aktualizacje jednej lub więcej aplikacji zostały zastosowane w tle", + "xWasUpdatedToY": "{} zaktualizowano do {}.", + "errorCheckingUpdates": "Sprawdzanie błędów aktualizacji", + "errorCheckingUpdatesNotifDescription": "Powiadomienie wyświetlane, gdy sprawdzanie aktualizacji w tle nie powiedzie się", + "appsRemoved": "Usunięte aplikacje", + "appsRemovedNotifDescription": "Powiadamia użytkownika, że jedna lub więcej aplikacji zostało usuniętych z powodu błędów podczas ich wczytywania", + "xWasRemovedDueToErrorY": "Usunięto {} z powodu błędu: {}", + "completeAppInstallation": "Ukończenie instalacji aplikacji", + "obtainiumMustBeOpenToInstallApps": "Aby zainstalować aplikacje, Obtainium musi być otwarte", + "completeAppInstallationNotifDescription": "Prosi użytkownika o powrót do Obtainium w celu dokończenia instalacji aplikacji", + "checkingForUpdates": "Sprawdzanie aktualizacji", + "checkingForUpdatesNotifDescription": "Tymczasowe powiadomienie pojawiające się podczas sprawdzania aktualizacji", + "pleaseAllowInstallPerm": "Pozwól Obtainium instalować aplikacje", + "trackOnly": "Tylko obserwuj", + "errorWithHttpStatusCode": "Błąd {}", + "versionCorrectionDisabled": "Korekta wersji wyłączona (wtyczka wydaje się nie działać)", + "unknown": "Nieznane", + "none": "Brak", + "never": "Nigdy", + "latestVersionX": "Najnowsza wersja: {}", + "installedVersionX": "Zainstalowana wersja: {}", + "lastUpdateCheckX": "Ostatnio sprawdzono: {}", + "remove": "Usuń", + "yesMarkUpdated": "Tak, oznacz jako zaktualizowane", + "fdroid": "Oficjalny F-Droid", + "appIdOrName": "ID aplikacji lub nazwa", + "appWithIdOrNameNotFound": "Nie znaleziono aplikacji o tym identyfikatorze lub nazwie", + "reposHaveMultipleApps": "Repozytoria mogą zawierać wiele aplikacji", + "fdroidThirdPartyRepo": "Zewnętrzne repo F-Droid", + "steam": "Steam", + "steamMobile": "Mobilny Steam", + "steamChat": "Steam Chat", + "install": "Instaluj", + "markInstalled": "Oznacz jako zainstalowane", + "update": "Zaktualizuj", + "markUpdated": "Oznacz jako zaktualizowane", + "additionalOptions": "Dodatkowe opcje", + "disableVersionDetection": "Wyłącz wykrywanie wersji", + "noVersionDetectionExplanation": "Opcja ta powinna być używana tylko w przypadku aplikacji, w których wykrywanie wersji nie działa poprawnie.", + "downloadingX": "Pobieranie {}", + "downloadNotifDescription": "Powiadamia użytkownika o postępach w pobieraniu aplikacji", + "noAPKFound": "Nie znaleziono pakietu APK", + "noVersionDetection": "Bez wykrywania wersji", + "categorize": "Skategoryzuj", + "categories": "Kategorie", + "category": "Kategoria", + "noCategory": "Bez kategorii", + "noCategories": "Brak kategorii", + "deleteCategoriesQuestion": "Usunąć kategorie?", + "categoryDeleteWarning": "Wszystkie aplikacje w usuniętych kategoriach zostaną ustawione jako nieskategoryzowane.", + "addCategory": "Dodaj kategorię", + "label": "Etykieta", + "language": "Język", + "copiedToClipboard": "Skopiowano do schowka", + "storagePermissionDenied": "Odmówiono zezwolenia dostępu do pamięci", + "selectedCategorizeWarning": "Spowoduje to zastąpienie wszystkich istniejących ustawień kategorii dla wybranych aplikacji.", + "filterAPKsByRegEx": "Filtruj pliki APK według wyrażeń regularnych", + "removeFromObtainium": "Usuń z Obtainium", + "uninstallFromDevice": "Odinstaluj z urządzenia", + "onlyWorksWithNonVersionDetectApps": "Działa tylko w przypadku aplikacji z wyłączonym wykrywaniem wersji.", + "releaseDateAsVersion": "Użyj daty wydania jako wersji", + "releaseDateAsVersionExplanation": "Opcja ta powinna być używana tylko w przypadku aplikacji, w których wykrywanie wersji nie działa poprawnie, ale dostępna jest data wydania.", + "changes": "Zmiany", + "releaseDate": "Data wydania", + "importFromURLsInFile": "Importuj z adresów URL w pliku (typu OPML)", + "versionDetection": "Wykrywanie wersji", + "standardVersionDetection": "Standardowe wykrywanie wersji", + "groupByCategory": "Grupuj według kategorii", + "autoApkFilterByArch": "Spróbuj filtrować pliki APK według architektury procesora, jeśli to możliwe", + "overrideSource": "Nadpisz źródło", + "dontShowAgain": "Nie pokazuj tego ponownie", + "dontShowTrackOnlyWarnings": "Nie wyświetlaj ostrzeżeń „Tylko obserwowana”", + "dontShowAPKOriginWarnings": "Nie pokazuj ostrzeżeń o pochodzeniu APK", + "moveNonInstalledAppsToBottom": "Przenieś niezainstalowane aplikacje na dół widoku aplikacji", + "gitlabPATLabel": "Osobisty token dostępu GitLab (umożliwia wyszukiwanie)", + "about": "Więcej informacji", + "requiresCredentialsInSettings": "Wymaga to dodatkowych poświadczeń (w Ustawieniach)", + "checkOnStart": "Sprawdź raz przy starcie", + "tryInferAppIdFromCode": "Spróbuj wywnioskować identyfikator aplikacji z kodu źródłowego", + "removeAppQuestion": { + "one": "Usunąć aplikację?", + "other": "Usunąć aplikacje?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minutę", + "other": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} min" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "Sprawdzanie aktualizacji w tle wykryło {} aktualizację - w razie potrzeby powiadomi użytkownika", + "other": "Sprawdzanie aktualizacji w tle wykryło {} aktualizacje/i - w razie potrzeby powiadomi użytkownika" + }, + "apps": { + "one": "{} aplikacja", + "other": "{} aplikacji" + }, + "url": { + "one": "{} adres URL", + "other": "{} adresów URL" + }, + "minute": { + "one": "{} min", + "other": "{} min" + }, + "hour": { + "one": "{} godz.", + "other": "{} godz." + }, + "day": { + "one": "{} dzień", + "other": "{} dni" + }, + "clearedNLogsBeforeXAfterY": { + "one": "Wyczyszczono {n} log (przed = {before}, po = {after})", + "other": "Wyczyszczono {n} logów (przed = {before}, po = {after})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "{} i jeszcze 1 aplikacja mają aktualizacje.", + "other": "{} i {} aplikacje/i otrzymało aktualizacje." + }, + "xAndNMoreUpdatesInstalled": { + "one": "Zaktualizowano {} i jeszcze 1 aplikację.", + "other": "Zaktualizowano {} i {} aplikacje/i." + } +} From 9efd0dd46e30a41afccd32b8dddc0dd58562abc1 Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Fri, 2 Jun 2023 19:58:14 +0000 Subject: [PATCH 221/600] Translated using Weblate (Polish) --- assets/translations/pl.json | 42 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 323daa3..f1b5274 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -4,8 +4,8 @@ "okay": "Okej", "appId": "ID aplikacji", "bgUpdateGotErrorRetryInMinutes": { - "one": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minutę", - "other": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} min" + "one": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} min.", + "other": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} min." }, "invalidURLForSource": "Nieprawidłowy adres URL aplikacji {}", "noReleaseFound": "Nie można znaleźć odpowiedniego wydania", @@ -19,10 +19,10 @@ "unexpectedError": "Nieoczekiwany błąd", "ok": "Okej", "and": "i", - "startedBgUpdateTask": "Rozpoczęto sprawdzanie aktualizacji w tle", + "startedBgUpdateTask": "Rozpoczęto zadanie sprawdzania aktualizacji w tle", "bgUpdateIgnoreAfterIs": "Parametr ignoreAfter aktualizacji w tle to {}", "startedActualBGUpdateCheck": "Rozpoczęto sprawdzanie aktualizacji w tle", - "bgUpdateTaskFinished": "Zakończono sprawdzanie aktualizacji w tle", + "bgUpdateTaskFinished": "Zakończono zadanie sprawdzania aktualizacji w tle", "firstRun": "Jest to pierwsze uruchomienie Obtainium", "settingUpdateCheckIntervalTo": "Ustawianie interwału aktualizacji na {}", "githubPATLabel": "Osobisty Token Dostępu GitHub (zwiększa limit zapytań)", @@ -155,16 +155,16 @@ "warning": "Uwaga", "sourceIsXButPackageFromYPrompt": "Źródłem aplikacji jest '{}', ale pakiet wydania pochodzi z '{}'. Kontynuować?", "updatesAvailable": "Dostępne aktualizacje", - "updatesAvailableNotifDescription": "Powiadamia użytkownika, że dostępne są aktualizacje dla jednej lub więcej aplikacji obserwowanych przez Obtainium", + "updatesAvailableNotifDescription": "Powiadamia użytkownika o dostępności aktualizacji dla jednej lub więcej aplikacji obserwowanych przez Obtainium", "noNewUpdates": "Brak nowych aktualizacji.", "xHasAnUpdate": "{} ma aktualizację.", "appsUpdated": "Zaktualizowane aplikacje", - "appsUpdatedNotifDescription": "Powiadamia użytkownika, że aktualizacje jednej lub więcej aplikacji zostały zastosowane w tle", + "appsUpdatedNotifDescription": "Powiadamia użytkownika, gdy jedna lub więcej aplikacji zostało zaktualizowanych w tle", "xWasUpdatedToY": "{} zaktualizowano do {}.", "errorCheckingUpdates": "Sprawdzanie błędów aktualizacji", "errorCheckingUpdatesNotifDescription": "Powiadomienie wyświetlane, gdy sprawdzanie aktualizacji w tle nie powiedzie się", "appsRemoved": "Usunięte aplikacje", - "appsRemovedNotifDescription": "Powiadamia użytkownika, że jedna lub więcej aplikacji zostało usuniętych z powodu błędów podczas ich wczytywania", + "appsRemovedNotifDescription": "Powiadamia użytkownika, gdy jedna lub więcej aplikacji zostało usuniętych z powodu błędów wczytywania", "xWasRemovedDueToErrorY": "Usunięto {} z powodu błędu: {}", "completeAppInstallation": "Ukończenie instalacji aplikacji", "obtainiumMustBeOpenToInstallApps": "Aby zainstalować aplikacje, Obtainium musi być otwarte", @@ -202,7 +202,7 @@ "downloadNotifDescription": "Powiadamia użytkownika o postępach w pobieraniu aplikacji", "noAPKFound": "Nie znaleziono pakietu APK", "noVersionDetection": "Bez wykrywania wersji", - "categorize": "Skategoryzuj", + "categorize": "Kategoryzuj", "categories": "Kategorie", "category": "Kategoria", "noCategory": "Bez kategorii", @@ -233,7 +233,7 @@ "dontShowTrackOnlyWarnings": "Nie wyświetlaj ostrzeżeń „Tylko obserwowana”", "dontShowAPKOriginWarnings": "Nie pokazuj ostrzeżeń o pochodzeniu APK", "moveNonInstalledAppsToBottom": "Przenieś niezainstalowane aplikacje na dół widoku aplikacji", - "gitlabPATLabel": "Osobisty token dostępu GitLab (umożliwia wyszukiwanie)", + "gitlabPATLabel": "Osobisty Token Dostępu GitLab (umożliwia wyszukiwanie)", "about": "Więcej informacji", "requiresCredentialsInSettings": "Wymaga to dodatkowych poświadczeń (w Ustawieniach)", "checkOnStart": "Sprawdź raz przy starcie", @@ -243,24 +243,24 @@ "other": "Usunąć aplikacje?" }, "tooManyRequestsTryAgainInMinutes": { - "one": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minutę", - "other": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} min" + "one": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} min.", + "other": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} min." }, "bgCheckFoundUpdatesWillNotifyIfNeeded": { - "one": "Sprawdzanie aktualizacji w tle wykryło {} aktualizację - w razie potrzeby powiadomi użytkownika", - "other": "Sprawdzanie aktualizacji w tle wykryło {} aktualizacje/i - w razie potrzeby powiadomi użytkownika" + "one": "Podczas sprawdzania aktualizacji w tle znaleziono {} aktualizację - w razie potrzeby użytkownik zostanie o tym powiadomiony", + "other": "Podczas sprawdzania aktualizacji w tle znaleziono {} akt. - w razie potrzeby użytkownik zostanie o tym powiadomiony" }, "apps": { - "one": "{} aplikacja", - "other": "{} aplikacji" + "one": "{} aplik.", + "other": "{} aplik." }, "url": { "one": "{} adres URL", - "other": "{} adresów URL" + "other": "{} adr. URL" }, "minute": { - "one": "{} min", - "other": "{} min" + "one": "{} min.", + "other": "{} min." }, "hour": { "one": "{} godz.", @@ -272,14 +272,14 @@ }, "clearedNLogsBeforeXAfterY": { "one": "Wyczyszczono {n} log (przed = {before}, po = {after})", - "other": "Wyczyszczono {n} logów (przed = {before}, po = {after})" + "other": "Wyczyszczono logi: {n} (przed = {before}, po = {after})" }, "xAndNMoreUpdatesAvailable": { "one": "{} i jeszcze 1 aplikacja mają aktualizacje.", - "other": "{} i {} aplikacje/i otrzymało aktualizacje." + "other": "{} i {} aplik. otrzymało aktualizacje." }, "xAndNMoreUpdatesInstalled": { "one": "Zaktualizowano {} i jeszcze 1 aplikację.", - "other": "Zaktualizowano {} i {} aplikacje/i." + "other": "Zaktualizowano {} i {} aplik." } } From f0e1831d301be3219971744a66c4f76aa4aeb90f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 2 Jun 2023 20:48:32 -0400 Subject: [PATCH 222/600] APK extension bugfix (#595) --- lib/providers/apps_provider.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 9cc7b64..47dfbde 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -159,6 +159,9 @@ class AppsProvider with ChangeNotifier { if (ext.endsWith('"') || ext.endsWith("other")) { ext = ext.substring(0, ext.length - 1); } + if (url.toLowerCase().endsWith('.apk') && ext != 'apk') { + ext = 'apk'; + } File downloadedFile = File('$destDir/$fileNameNoExt.$ext'); if (!(downloadedFile.existsSync() && useExisting)) { File tempDownloadedFile = File('${downloadedFile.path}.part'); From 0b16c28224f77bac5ebc5154f1a6892259eab129 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 2 Jun 2023 21:03:45 -0400 Subject: [PATCH 223/600] Add Polish to menu --- lib/main.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/main.dart b/lib/main.dart index 98d6d1f..23e61fa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -37,6 +37,7 @@ List> supportedLocales = const [ MapEntry(Locale('fa'), 'فارسی'), MapEntry(Locale('fr'), 'Français'), MapEntry(Locale('es'), 'Español'), + MapEntry(Locale('pl'), 'Polski'), ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; From 9294540b5d7fe92c6759d8ff57937918d6f43b6c Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 2 Jun 2023 21:07:28 -0400 Subject: [PATCH 224/600] Increment version, update modules --- lib/main.dart | 2 +- pubspec.lock | 60 +++++++++++++++++++++++++-------------------------- pubspec.yaml | 2 +- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 23e61fa..997bc10 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.6'; +const String currentVersion = '0.13.7'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index d45df69..ac55bf1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -134,10 +134,10 @@ packages: dependency: transitive description: name: csslib - sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 + sha256: "831883fb353c8bdc1d71979e5b342c7d88acfbc643113c14ae51e2442ea0f20f" url: "https://pub.dev" source: hosted - version: "0.17.2" + version: "0.17.3" cupertino_icons: dependency: "direct main" description: @@ -158,10 +158,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "499c61743e13909c13374a8c209075385858c614b9c0f2487b5f9995eeaf7369" + sha256: "2c35b6d1682b028e42d07b3aee4b98fa62996c10bc12cb651ec856a80d6a761b" url: "https://pub.dev" source: hosted - version: "9.0.1" + version: "9.0.2" device_info_plus_platform_interface: dependency: transitive description: @@ -222,10 +222,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: c7a8e25ca60e7f331b153b0cb3d405828f18d3e72a6fa1d9440c86556fffc877 + sha256: "9d6e95ec73abbd31ec54d0e0df8a961017e165aba1395e462e5b31ea0c165daf" url: "https://pub.dev" source: hosted - version: "5.3.0" + version: "5.3.1" flutter: dependency: "direct main" description: flutter @@ -259,10 +259,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "12f8abacca8bf29c042ec50c554f967da4c6f88ec99fc215e0325e5b43a25188" + sha256: "812791d43ccfc1b443a0d39fa02a206fc228c597e28ff9337e09e3ca8d370391" url: "https://pub.dev" source: hosted - version: "14.1.0" + version: "14.1.1" flutter_local_notifications_linux: dependency: transitive description: @@ -288,10 +288,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: "7b25c10de1fea883f3c4f9b8389506b54053cd00807beab69fd65c8653a2711f" + sha256: dc6d5258653f6857135b32896ccda7f7af0c54dcec832495ad6835154c6c77c0 url: "https://pub.dev" source: hosted - version: "0.6.14" + version: "0.6.15" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -314,10 +314,10 @@ packages: dependency: "direct main" description: name: fluttertoast - sha256: "2f9c4d3f4836421f7067a28f8939814597b27614e021da9d63e5d3fb6e212d25" + sha256: "474f7d506230897a3cd28c965ec21c5328ae5605fc9c400cd330e9e9d6ac175c" url: "https://pub.dev" source: hosted - version: "8.2.1" + version: "8.2.2" html: dependency: "direct main" description: @@ -386,10 +386,10 @@ packages: dependency: transitive description: name: lints - sha256: "6b0206b0bf4f04961fc5438198ccb3a885685cd67d4d4a32cc20ad7f8adbe015" + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" markdown: dependency: transitive description: @@ -490,10 +490,10 @@ packages: dependency: transitive description: name: path_provider_linux - sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" + sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57 url: "https://pub.dev" source: hosted - version: "2.1.10" + version: "2.1.11" path_provider_platform_interface: dependency: transitive description: @@ -602,10 +602,10 @@ packages: dependency: "direct main" description: name: share_plus - sha256: "44fc0bc2d35a8fafa1b564e1c6888bdc4fbb2d0197e4a4c21bac0e66123be9cd" + sha256: ed3fcea4f789ed95913328e629c0c53e69e80e08b6c24542f1b3576046c614e8 url: "https://pub.dev" source: hosted - version: "7.0.1" + version: "7.0.2" share_plus_platform_interface: dependency: transitive description: @@ -775,10 +775,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "1a5848f598acc5b7d8f7c18b8cb834ab667e59a13edc3c93e9d09cf38cc6bc87" + sha256: eed4e6a1164aa9794409325c3b707ff424d4d1c2a785e7db67f8bbda00e36e51 url: "https://pub.dev" source: hosted - version: "6.0.34" + version: "6.0.35" url_launcher_ios: dependency: transitive description: @@ -815,10 +815,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa" + sha256: "6bb1e5d7fe53daf02a8fee85352432a40b1f868a81880e99ec7440113d5cfcab" url: "https://pub.dev" source: hosted - version: "2.0.16" + version: "2.0.17" url_launcher_windows: dependency: transitive description: @@ -847,34 +847,34 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: "1a37bdbaaf5fbe09ad8579ab09ecfd473284ce482f900b5aea27cf834386a567" + sha256: "5604dac1178680a34fbe4a08c7b69ec42cca6601dc300009ec9ff69bef284cc2" url: "https://pub.dev" source: hosted - version: "4.2.0" + version: "4.2.1" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: "1acea8def62592123e2fbbca164ed8681a98a890bdcbb88f916d5b4a22687759" + sha256: "57a22c86065375c1598b57224f92d6008141be0c877c64100de8bfb6f71083d8" url: "https://pub.dev" source: hosted - version: "3.7.0" + version: "3.7.1" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "78715dc442b7849dbde74e92bb67de1cecf5addf95531c5fb474e72f5fe9a507" + sha256: "656e2aeaef318900fffd21468b6ddc7958c7092a642f0e7220bac328b70d4a81" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "4646bb68297803bdbb96d46853e8fcb560d6cb5e04153fa64581535767875dfe" + sha256: "6bbc6ade302b842999b27cbaa7171241c273deea8a9c73f92ceb3d811c767de2" url: "https://pub.dev" source: hosted - version: "3.4.3" + version: "3.4.4" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8d57bd9..7ba6e4e 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.13.6+170 # When changing this, update the tag in main() accordingly +version: 0.13.7+171 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 7fcba6c9119ee8fc1e9cb33ac79454bdd1ad90d8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 2 Jun 2023 23:04:07 -0400 Subject: [PATCH 225/600] Bugfix for GitHub appId extraction (#604) --- lib/app_sources/github.dart | 12 ++++++++++-- lib/main.dart | 2 +- pubspec.yaml | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index d75beb2..5144968 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -96,14 +96,22 @@ class GitHub extends AppSource { if (res.statusCode == 200) { try { var body = jsonDecode(res.body); - var appId = utf8 + var trimmedLines = utf8 .decode(base64 .decode(body['content'].toString().split('\n').join(''))) .split('\n') - .map((e) => e.trim()) + .map((e) => e.trim()); + var appId = trimmedLines .where((l) => l.startsWith('applicationId "')) .first .split('"')[1]; + if (appId.startsWith('\${') && appId.endsWith('}')) { + appId = trimmedLines + .where((l) => l.startsWith( + 'def ${appId.substring(2, appId.length - 1)}')) + .first + .split('"')[1]; + } if (appId.isNotEmpty) { return appId; } diff --git a/lib/main.dart b/lib/main.dart index 997bc10..9dd7f68 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.7'; +const String currentVersion = '0.13.8'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 7ba6e4e..de89b9e 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.13.7+171 # When changing this, update the tag in main() accordingly +version: 0.13.8+172 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 8ca1e09c860275d2e751b040ca87b15779ed09b8 Mon Sep 17 00:00:00 2001 From: Elliot Fleet Date: Sun, 11 Jun 2023 06:13:07 -0700 Subject: [PATCH 226/600] Extract zip files in a stream --- lib/providers/apps_provider.dart | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 47dfbde..4f69583 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -27,7 +27,7 @@ import 'package:flutter_fgbg/flutter_fgbg.dart'; import 'package:obtainium/providers/source_provider.dart'; import 'package:http/http.dart'; import 'package:android_intent_plus/android_intent.dart'; -import 'package:archive/archive.dart'; +import 'package:archive/archive_io.dart'; class AppInMemory { late App app; @@ -333,20 +333,9 @@ class AppsProvider with ChangeNotifier { } void unzipFile(String filePath, String destinationPath) { - final bytes = File(filePath).readAsBytesSync(); - final archive = ZipDecoder().decodeBytes(bytes); - - for (final file in archive) { - final filename = '$destinationPath/${file.name}'; - if (file.isFile) { - final data = file.content as List; - File(filename) - ..createSync(recursive: true) - ..writeAsBytesSync(data); - } else { - Directory(filename).create(recursive: true); - } - } + final inputStream = InputFileStream(filePath); + final archive = ZipDecoder().decodeBuffer(inputStream); + extractArchiveToDisk(archive, destinationPath); } Future installXApkDir(DownloadedXApkDir dir, From 40bec4b732c44b368adfb0f84f7e7ddf7fe8cbbb Mon Sep 17 00:00:00 2001 From: gidano Date: Wed, 14 Jun 2023 07:01:53 +0200 Subject: [PATCH 227/600] Update hu.json --- assets/translations/hu.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index c3771af..b0b553c 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -232,7 +232,7 @@ "about": "Rólunk", "requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)", "checkOnStart": "Egyszer az indításkor", - "tryInferAppIdFromCode": "Try inferring App ID from source code", + "tryInferAppIdFromCode": "Próbálja kikövetkeztetni az app azonosítót a forráskódból", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From ba3f5124456359fceb8e71f099f8b91261bb60bb Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Mon, 19 Jun 2023 07:01:13 +0300 Subject: [PATCH 228/600] Create ru.json Add Russian translations --- assets/translations/ru.json | 285 ++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 assets/translations/ru.json diff --git a/assets/translations/ru.json b/assets/translations/ru.json new file mode 100644 index 0000000..af73855 --- /dev/null +++ b/assets/translations/ru.json @@ -0,0 +1,285 @@ +{ + "invalidURLForSource": "Неверный URL-адрес {} приложения", + "noReleaseFound": "Не удалось найти подходящий релиз", + "noVersionFound": "Не удалось определить версию релиза", + "urlMatchesNoSource": "URL не соответствует известному источнику", + "cantInstallOlderVersion": "Невозможно установить более старую версию приложения", + "appIdMismatch": "Идентификатор загруженного пакета не совпадает с существующим идентификатором приложения", + "functionNotImplemented": "Этот класс не реализовал эту функцию", + "placeholder": "Заполнитель", + "someErrors": "Произошли некоторые ошибки", + "unexpectedError": "Неожиданная ошибка", + "ok": "Окей", + "and": "и", + "startedBgUpdateTask": "Запущена задача фоновой проверки обновлений", + "bgUpdateIgnoreAfterIs": "Параметр игнорирования фоновых обновлений: {}", + "startedActualBGUpdateCheck": "Запущена фактическая проверка фоновых обновлений", + "bgUpdateTaskFinished": "Завершена задача фоновой проверки обновлений", + "firstRun": "Это первый запуск Obtainium", + "settingUpdateCheckIntervalTo": "Установка интервала проверки обновлений: {}", + "githubPATLabel": "Персональный ключ доступа GitHub (увеличивает лимит запросов)", + "githubPATHint": "Ключ доступа должен быть в формате: имя_пользователя:токен", + "githubPATFormat": "имя_пользователя:токен", + "includePrereleases": "Включить предварительные релизы", + "fallbackToOlderReleases": "Откатиться к более старым версиям", + "filterReleaseTitlesByRegEx": "Фильтровать заголовки релизов с помощью регулярного выражения", + "invalidRegEx": "Неверное регулярное выражение", + "noDescription": "Нет описания" + "cancel": "Отмена", + "continue": "Продолжить", + "requiredInBrackets": "(Обязательно)", + "dropdownNoOptsError": "Ошибка: Выпадающий список должен содержать хотя бы одну опцию", + "colour": "Цвет", + "githubStarredRepos": "Помеченные звездочкой репозитории на GitHub", + "uname": "Имя пользователя", + "wrongArgNum": "Неправильное количество предоставленных аргументов", + "xIsTrackOnly": "{} является приложением только для отслеживания", + "source": "Источник", + "app": "Приложение", + "appsFromSourceAreTrackOnly": "Приложения из этого источника являются 'только для отслеживания'.", + "youPickedTrackOnly": "Вы выбрали опцию 'Только для отслеживания'.", + "trackOnlyAppDescription": "Приложение будет отслеживаться обновлениями, но Obtainium не сможет его скачивать или устанавливать.", + "cancelled": "Отменено", + "appAlreadyAdded": "Приложение уже добавлено", + "alreadyUpToDateQuestion": "Приложение уже обновлено?", + "addApp": "Добавить приложение", + "appSourceURL": "URL-источник приложения", + "error": "Ошибка", + "add": "Добавить", + "searchSomeSourcesLabel": "Поиск (только в некоторых источниках)", + "search": "Поиск", + "additionalOptsFor": "Дополнительные опции для {}", + "supportedSourcesBelow": "Поддерживаемые источники:", + "trackOnlyInBrackets": "(Только для отслеживания)", + "searchableInBrackets": "(Поиск)", + "appsString": "Приложения", + "noApps": "Нет приложений", + "noAppsForFilter": "Нет приложений для фильтра", + "byX": "От {}", + "percentProgress": "Прогресс: {}%", + "pleaseWait": "Пожалуйста, подождите", + "updateAvailable": "Доступно обновление", + "estimateInBracketsShort": "(Оценка)", + "notInstalled": "Не установлено", + "estimateInBrackets": "(Оценка)", + "selectAll": "Выбрать все", + "deselectN": "Отменить выбор {}", + "xWillBeRemovedButRemainInstalled": "{} будет удалено из Obtainium, но останется установленным на устройстве.", + "removeSelectedAppsQuestion": "Удалить выбранные приложения?", + "removeSelectedApps": "Удалить выбранные приложения", + "updateX": "Обновить {}", + "installX": "Установить {}" + "markXTrackOnlyAsUpdated": "Отметить {}\n(Только для отслеживания)\nкак обновленное", + "changeX": "Изменить {}", + "installUpdateApps": "Установить/Обновить приложения", + "installUpdateSelectedApps": "Установить/Обновить выбранные приложения", + "markXSelectedAppsAsUpdated": "Отметить {} выбранные приложения как обновленные?", + "no": "Нет", + "yes": "Да", + "markSelectedAppsUpdated": "Отметить выбранные приложения как обновленные", + "pinToTop": "Закрепить вверху", + "unpinFromTop": "Открепить", + "resetInstallStatusForSelectedAppsQuestion": "Сбросить статус установки для выбранных приложений?", + "installStatusOfXWillBeResetExplanation": "Статус установки для выбранных приложений будет сброшен.\n\nЭто может помочь, если версия приложения, отображаемая в Obtainium, неправильная из-за неудачных обновлений или других проблем.", + "shareSelectedAppURLs": "Поделиться выбранными URL-адресами приложений", + "resetInstallStatus": "Сбросить статус установки", + "more": "Еще", + "removeOutdatedFilter": "Удалить фильтр для устаревших приложений", + "showOutdatedOnly": "Показывать только устаревшие приложения", + "filter": "Фильтр", + "filterActive": "Фильтр *", + "filterApps": "Фильтровать приложения", + "appName": "Название приложения", + "author": "Автор" + "upToDateApps": "Приложения со свежими обновлениями", + "nonInstalledApps": "Неустановленные приложения", + "importExport": "Импорт/экспорт", + "settings": "Настройки", + "exportedTo": "Экспортировано в {}", + "obtainiumExport": "Экспорт из Obtainium", + "invalidInput": "Неверный ввод", + "importedX": "Импортировано {}", + "obtainiumImport": "Импорт в Obtainium", + "importFromURLList": "Импорт из списка URL-адресов", + "searchQuery": "Поисковый запрос", + "appURLList": "Список URL-адресов приложений", + "line": "Строка", + "searchX": "Поиск {}", + "noResults": "Результатов не найдено", + "importX": "Импорт {}", + "importedAppsIdDisclaimer": "Импортированные приложения могут неверно отображаться как 'Не установлены'.\nДля исправления этой проблемы повторно установите их через Obtainium.\nЭто не должно повлиять на данные приложения.\n\nПроблемы возникают только при импорте из URL-адреса и сторонних источников.", + "importErrors": "Ошибки импорта", + "importedXOfYApps": "Импортировано {} из {} приложений.", + "followingURLsHadErrors": "При импорте следующие URL-адреса содержали ошибки:", + "okay": "ОК", + "selectURL": "Выбрать URL-адрес", + "selectURLs": "Выбрать URL-адреса", + "pick": "Выбрать", + "theme": "Тема", + "dark": "Темный", + "light": "Светлый", + "followSystem": "Следовать системе", + "obtainium": "Obtainium", + "materialYou": "Material You", + "useBlackTheme": "Использовать темную тему", + "appSortBy": "Сортировка приложений по", + "authorName": "Автор/Название", + "nameAuthor": "Название/Автор", + "asAdded": "В порядке добавления", + "appSortOrder": "Порядок сортировки приложений", + "ascending": "По возрастанию", + "descending": "По убыванию", + "bgUpdateCheckInterval": "Интервал проверки обновлений в фоновом режиме", + "neverManualOnly": "Никогда - Только вручную", + "appearance": "Внешний вид", + "showWebInAppView": "Показывать веб-страницу источника в представлении приложения", + "pinUpdates": "Закрепить обновления вверху списка приложений", + "updates": "Обновления", + "sourceSpecific": "Специфика источника", + "appSource": "Источник приложения", + "noLogs": "Нет журналов", + "appLogs": "Журналы приложений", + "close": "Закрыть", + "share": "Поделиться", + "appNotFound": "Приложение не найдено", + "obtainiumExportHyphenatedLowercase": "obtainium-export", + "pickAnAPK": "Выберите APK-файл", + "appHasMoreThanOnePackage": "{} имеет более одного пакета:", + "deviceSupportsXArch": "Ваше устройство поддерживает архитектуру процессора {}.", + "deviceSupportsFollowingArchs": "Ваше устройство поддерживает следующие архитектуры процессора:", + "warning": "Предупреждение", + "sourceIsXButPackageFromYPrompt": "Источник приложения - '{}', но пакет для установки получен из '{}'. Продолжить?", + "updatesAvailable": "Доступны обновления", + "updatesAvailableNotifDescription": "Уведомляет пользователя о наличии обновлений для одного или нескольких приложений, отслеживаемых Obtainium", + "noNewUpdates": "Нет новых обновлений.", + "xHasAnUpdate": "{} есть обновление.", + "appsUpdated": "Приложения обновлены", + "appsUpdatedNotifDescription": "Уведомляет пользователя о том, что обновления для одного или нескольких приложений были применены в фоновом режиме", + "xWasUpdatedToY": "{} была обновлена до версии {}.", + "errorCheckingUpdates": "Ошибка при проверке обновлений", + "errorCheckingUpdatesNotifDescription": "Уведомление, которое появляется, когда проверка обновлений в фоновом режиме завершилась с ошибкой", + "appsRemoved": "Приложение удалено", + "appsRemovedNotifDescription": "Уведомляет пользователя о том, что одно или несколько приложений было удалено из-за ошибок при их загрузке", + "xWasRemovedDueToErrorY": "{} был удален из-за ошибки: {}", + "completeAppInstallation": "Завершение установки приложения", + "obtainiumMustBeOpenToInstallApps": "Для установки приложений Obtainium должен быть открыт", + "completeAppInstallationNotifDescription": "Просит пользователя вернуться в Obtainium, чтобы завершить установку приложения", + "checkingForUpdates": "Проверка обновлений", + "checkingForUpdatesNotifDescription": "Временное уведомление, которое появляется при проверке обновлений", + "pleaseAllowInstallPerm": "Пожалуйста, разрешите Obtainium устанавливать приложения", + "trackOnly": "Только отслеживать", + "errorWithHttpStatusCode": "Ошибка {}", + "versionCorrectionDisabled": "Коррекция версий отключена (плагин, кажется, не работает)", + "unknown": "Неизвестно", + "none": "Отсутствует", + "never": "Никогда", + "latestVersionX": "Последняя версия: {}", + "installedVersionX": "Установленная версия: {}", + "lastUpdateCheckX": "Последняя проверка обновлений: {}", + "remove": "Удалить", + "yesMarkUpdated": "Да, отметить как обновленное", + "fdroid": "Официальный F-Droid", + "appIdOrName": "ID или название приложения", + "appId": "ID приложения", + "appWithIdOrNameNotFound": "Приложение с таким ID или названием не было найдено", + "reposHaveMultipleApps": "В хранилище может быть несколько приложений", + "fdroidThirdPartyRepo": "Хранилище F-Droid сторонних разработчиков", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Chat", + "install": "Установить", + "markInstalled": "Пометить как установленное", + "update": "Обновить", + "markUpdated": "Отметить обновленным", + "additionalOptions": "Дополнительные опции", + "disableVersionDetection": "Отключить обнаружение версии", + "noVersionDetectionExplanation": "Эта опция должна использоваться только для приложений, где обнаружение версии не работает корректно.", + "downloadingX": "Загрузка {}", + "downloadNotifDescription": "Уведомляет пользователя о прогрессе загрузки приложения", + "noAPKFound": "APK не найдено", + "noVersionDetection": "Версий не обнаружено", + "categorize": "Категоризировать", + "categories": "Категории", + "category": "Категория", + "noCategory": "Без категории", + "noCategories": "Без категорий", + "deleteCategoriesQuestion": "Удалить категории?", + "categoryDeleteWarning": "Все приложения в удаленных категориях будут помечены как без категории.", + "addCategory": "Добавить категорию", + "label": "Метка", + "language": "Язык" + "copiedToClipboard": "Скопировано в буфер обмена", + "storagePermissionDenied": "Отказано в доступе к хранилищу", + "selectedCategorizeWarning": "Это заменит все текущие настройки категорий для выбранных приложений.", + "filterAPKsByRegEx": "Фильтровать APK-файлы с помощью регулярного выражения", + "removeFromObtainium": "Удалить из Obtainium", + "uninstallFromDevice": "Удалить с устройства", + "onlyWorksWithNonVersionDetectApps": "Работает только для приложений с отключенным определением версии.", + "releaseDateAsVersion": "Использовать дату выпуска в качестве версии", + "releaseDateAsVersionExplanation": "Этот параметр следует использовать только для приложений, в которых определение версии не работает правильно, но имеется дата выпуска.", + "changes": "Изменения", + "releaseDate": "Дата выпуска", + "importFromURLsInFile": "Импортировать из URL-адресов в файл (например, OPML)", + "versionDetection": "Определение версии", + "standardVersionDetection": "Стандартное определение версии", + "groupByCategory": "Группировать по категориям", + "autoApkFilterByArch": "Попытка фильтрации APK-файлов по архитектуре процессора, если это возможно", + "overrideSource": "Переопределить источник", + "dontShowAgain": "Не показывать снова", + "dontShowTrackOnlyWarnings": "Не показывать предупреждения о только отслеживаемых приложениях", + "dontShowAPKOriginWarnings": "Не показывать предупреждения об источнике APK-файлов", + "moveNonInstalledAppsToBottom": "Переместить неустановленные приложения вниз списка", + "gitlabPATLabel": "Персональный токен доступа GitLab (Включает поиск)", + "about": "О приложении", + "requiresCredentialsInSettings": "Для этого требуются дополнительные учетные данные (в настройках)", + "checkOnStart": "Проверить один раз при запуске", + "tryInferAppIdFromCode": "Попытаться определить идентификатор приложения из исходного кода", + "removeAppQuestion": { + "one": "Удалить приложение?", + "other": "Удалить приложения?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Слишком много запросов (ограничение скорости) - попробуйте снова через {} минуту", + "other": "Слишком много запросов (ограничение скорости) - попробуйте снова через {} минуты" + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "При проверке обновлений в фоновом режиме возникла ошибка {}, повторная проверка будет запланирована через {} минуту", + "other": "При проверке обновлений в фоновом режиме возникла ошибка {}, повторная проверка будет запланирована через {} минуты" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "В ходе проверки обновления в фоновом режиме было обнаружено {} обновление - Пользователю будет отправлено уведомление, если это необходимо", + "other": "В ходе проверки обновления в фоновом режиме было обнаружено {} обновлений - Пользователю будет отправлено уведомление, если это необходимо" + }, + "apps": { + "one": "{} Приложение", + "other": "{} Приложений" + }, + "url": { + "one": "{} Ссылка", + "other": "{} Ссылки" + }, + "minute": { + "one": "{} Минута", + "other": "{} Минуты" + }, + "hour": { + "one": "{} Час", + "other": "{} Часов" + }, + "day": { + "one": "{} День", + "other": "{} Дней" + }, + "clearedNLogsBeforeXAfterY": { + "one": "Очищен {n} журнал (до = {before}, после = {after})", + "other": "Очищено {n} журналов (до = {before}, после = {after})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "У {} и еще 1 приложения есть обновления.", + "other": "{} and {} more apps have updates." + }, + "xAndNMoreUpdatesInstalled": { + "one": "{} and 1 more app were updated.", + "other": "У {} и еще {} приложений есть обновления." + } +} From 038f089aacc17d507c17926d0a54cd855ce61dd3 Mon Sep 17 00:00:00 2001 From: unbranched <39440265+unbranched@users.noreply.github.com> Date: Mon, 19 Jun 2023 12:30:56 +0000 Subject: [PATCH 229/600] Update it.json Italian translation update --- assets/translations/it.json | 178 ++++++++++++++++++------------------ 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/assets/translations/it.json b/assets/translations/it.json index 93c56e1..4d4d925 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -1,25 +1,25 @@ { - "invalidURLForSource": "URL dell'App da {} non valido", + "invalidURLForSource": "URL dell'app {} non valido", "noReleaseFound": "Impossibile trovare una release adatta", "noVersionFound": "Impossibile determinare la versione della release", "urlMatchesNoSource": "L'URL non corrisponde ad alcuna fonte conosciuta", - "cantInstallOlderVersion": "Impossibile installare una versione precedente di un'App", - "appIdMismatch": "L'ID del pacchetto scaricato non corrisponde all'ID dell'App esistente", + "cantInstallOlderVersion": "Impossibile installare una versione precedente di un'app", + "appIdMismatch": "L'ID del pacchetto scaricato non corrisponde all'ID dell'app esistente", "functionNotImplemented": "Questa classe non ha implementato questa funzione", "placeholder": "Segnaposto", "someErrors": "Si sono verificati degli errori", "unexpectedError": "Errore imprevisto", "ok": "Va bene", "and": "e", - "startedBgUpdateTask": "Avviata l'attività di controllo degli aggiornamenti in background", - "bgUpdateIgnoreAfterIs": "Bg update ignoreAfter is {}", - "startedActualBGUpdateCheck": "Avviato il controllo effettivo degli aggiornamenti in background", - "bgUpdateTaskFinished": "Terminata l'attività di controllo degli aggiornamenti in background", + "startedBgUpdateTask": "Avviata l'attività di controllo degli aggiornamenti in secondo piano", + "bgUpdateIgnoreAfterIs": "Il parametro di agg. in secondo piano 'ignoreAfter' è {}", + "startedActualBGUpdateCheck": "Avviato il controllo effettivo degli aggiornamenti in secondo piano", + "bgUpdateTaskFinished": "Terminata l'attività di controllo degli aggiornamenti in secondo piano", "firstRun": "Questo è il primo avvio di sempre di Obtainium", "settingUpdateCheckIntervalTo": "Fissato intervallo di aggiornamento a {}", "githubPATLabel": "GitHub Personal Access Token (diminuisce limite di traffico)", - "githubPATHint": "PAT deve seguire questo formato: username:token", - "githubPATFormat": "username:token", + "githubPATHint": "PAT deve seguire questo formato: nomeutente:token", + "githubPATFormat": "nomeutente:token", "includePrereleases": "Includi prerelease", "fallbackToOlderReleases": "Ripiega su release precedenti", "filterReleaseTitlesByRegEx": "Filtra release con espressioni regolari", @@ -31,19 +31,19 @@ "dropdownNoOptsError": "ERRORE: LA TENDINA DEVE AVERE ALMENO UN'OPZIONE", "colour": "Colore", "githubStarredRepos": "repository stellati da GitHub", - "uname": "Username", + "uname": "Nome utente", "wrongArgNum": "Numero di argomenti forniti errato", "xIsTrackOnly": "{} è in modalità Solo-Monitoraggio", "source": "Fonte", "app": "App", - "appsFromSourceAreTrackOnly": "Le App da questa fonte sono in modalità 'Solo-Monitoraggio'.", + "appsFromSourceAreTrackOnly": "Le app da questa fonte sono in modalità 'Solo-Monitoraggio'.", "youPickedTrackOnly": "È stata selezionata l'opzione 'Solo-Monitoraggio'.", - "trackOnlyAppDescription": "L'App sarà monitorata per gli aggiornamenti, ma Obtainium non sarà in grado di scaricarli o di installarli.", + "trackOnlyAppDescription": "L'app sarà monitorata per gli aggiornamenti, ma Obtainium non sarà in grado di scaricarli o di installarli.", "cancelled": "Annullato", "appAlreadyAdded": "App già aggiunta", - "alreadyUpToDateQuestion": "L'App è già aggiornata?", - "addApp": "Aggiungi App", - "appSourceURL": "URL della fonte dell'App", + "alreadyUpToDateQuestion": "L'app è già aggiornata?", + "addApp": "Aggiungi app", + "appSourceURL": "URL della fonte dell'app", "error": "Errore", "add": "Aggiungi", "searchSomeSourcesLabel": "Cerca (solo per alcune fonti)", @@ -53,10 +53,10 @@ "trackOnlyInBrackets": "(Solo-Monitoraggio)", "searchableInBrackets": "(ricercabile)", "appsString": "App", - "noApps": "Nessuna App", - "noAppsForFilter": "Nessuna App per i filtri selezionati", + "noApps": "Nessuna app", + "noAppsForFilter": "Nessuna app per i filtri selezionati", "byX": "Di {}", - "percentProgress": "Progresso: {}%", + "percentProgress": "Avanzamento: {}%", "pleaseWait": "In attesa", "updateAvailable": "Aggiornamento disponibile", "estimateInBracketsShort": "(prev.)", @@ -65,31 +65,31 @@ "selectAll": "Seleziona tutto", "deselectN": "Deseleziona {}", "xWillBeRemovedButRemainInstalled": "Verà effettuata la rimozione di {}, ma non la disinstallazione.", - "removeSelectedAppsQuestion": "Rimuovere le App selezionate?", - "removeSelectedApps": "Rimuovi le App selezionate", + "removeSelectedAppsQuestion": "Rimuovere le app selezionate?", + "removeSelectedApps": "Rimuovi le app selezionate", "updateX": "Aggiorna {}", "installX": "Installa {}", "markXTrackOnlyAsUpdated": "Contrassegna {}\n(Solo-Monitoraggio)\ncome aggiornato", "changeX": "Modifica {}", - "installUpdateApps": "Installa/Aggiorna App", - "installUpdateSelectedApps": "Installa/Aggiorna le App selezionate", - "markXSelectedAppsAsUpdated": "Contrassegnare le {} App selezionate come aggiornate?", + "installUpdateApps": "Installa/Aggiorna app", + "installUpdateSelectedApps": "Installa/Aggiorna le app selezionate", + "markXSelectedAppsAsUpdated": "Contrassegnare le {} app selezionate come aggiornate?", "no": "No", "yes": "Sì", - "markSelectedAppsUpdated": "Contrassegna le App selezionate come aggiornate", + "markSelectedAppsUpdated": "Contrassegna le app selezionate come aggiornate", "pinToTop": "Fissa in alto", "unpinFromTop": "Rimuovi dall'alto", - "resetInstallStatusForSelectedAppsQuestion": "Ripristinare lo stato d'installazione delle App selezionate?", - "installStatusOfXWillBeResetExplanation": "Lo stato d'installazione di ogni App selezionata sarà ripristinato.\n\nCiò può essere d'aiuto nel caso in cui la versione mostrata dell'App in Obtainium non è corretta a causa di un aggiornamento fallito o di altri problemi.", - "shareSelectedAppURLs": "Condividi gli URL delle App selezionate", + "resetInstallStatusForSelectedAppsQuestion": "Ripristinare lo stato d'installazione delle app selezionate?", + "installStatusOfXWillBeResetExplanation": "Lo stato d'installazione di ogni app selezionata sarà ripristinato.\n\nCiò può essere d'aiuto nel caso in cui la versione mostrata dell'app in Obtainium non sia corretta a causa di un aggiornamento fallito o di altri problemi.", + "shareSelectedAppURLs": "Condividi gli URL delle app selezionate", "resetInstallStatus": "Ripristina lo stato d'installazione", - "more": "Di più", - "removeOutdatedFilter": "Rimuovi il filtro per le App non aggiornate", - "showOutdatedOnly": "Mostra solo le App non aggiornate", + "more": "Altro", + "removeOutdatedFilter": "Rimuovi il filtro per le app non aggiornate", + "showOutdatedOnly": "Mostra solo le app non aggiornate", "filter": "Filtri", "filterActive": "Filtri *", - "filterApps": "Filtra App", - "appName": "Nome dell'App", + "filterApps": "Filtra app", + "appName": "Nome dell'app", "author": "Autore", "upToDateApps": "App aggiornate", "nonInstalledApps": "App non installate", @@ -102,14 +102,14 @@ "obtainiumImport": "Importa in Obtainium", "importFromURLList": "Importa da lista di URL", "searchQuery": "Stringa di ricerca", - "appURLList": "Lista di URL delle App", + "appURLList": "Lista di URL delle app", "line": "Linea", "searchX": "Cerca su {}", "noResults": "Nessun risultato trovato", "importX": "Importa {}", - "importedAppsIdDisclaimer": "Le App importate potrebbero essere visualizzate erroneamente come \"Non installate\".\nPer risolvere il problema, reinstallale con Obtainium.\nQuesto non dovrebbe influire sui dati delle App.\n\nRiguarda solo l'URL e i metodi di importazione di terze parti.", - "importErrors": "Errori dell'importazione", - "importedXOfYApps": "{} App di {} importate.", + "importedAppsIdDisclaimer": "Le app importate potrebbero essere visualizzate erroneamente come \"Non installate\".\nPer risolvere il problema, reinstallale con Obtainium.\nCiò non dovrebbe influire sui dati delle app.\n\nRiguarda solo l'URL e i metodi di importazione di terze parti.", + "importErrors": "Errori di importazione", + "importedXOfYApps": "{} app di {} importate.", "followingURLsHadErrors": "I seguenti URL contengono errori:", "okay": "Va bene", "selectURL": "Seleziona l'URL", @@ -118,27 +118,27 @@ "theme": "Tema", "dark": "Scuro", "light": "Chiaro", - "followSystem": "Segui sistema", + "followSystem": "Segui il sistema", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use Pure Black Dark Theme", + "useBlackTheme": "Usa il tema Nero puro", "appSortBy": "App ordinate per", "authorName": "Autore/Nome", "nameAuthor": "Nome/Autore", "asAdded": "Data di aggiunta", - "appSortOrder": "Ordinamento", + "appSortOrder": "Ordine", "ascending": "Ascendente", "descending": "Discendente", - "bgUpdateCheckInterval": "Intervallo di controllo degli aggiornamenti in background", + "bgUpdateCheckInterval": "Intervallo di controllo degli aggiornamenti in secondo piano", "neverManualOnly": "Mai - Solo manuale", "appearance": "Aspetto", - "showWebInAppView": "Mostra pagina web dell'App se selezionata", + "showWebInAppView": "Mostra pagina web dell'app se selezionata", "pinUpdates": "Fissa aggiornamenti disponibili in alto", "updates": "Aggiornamenti", "sourceSpecific": "Specifiche per la fonte", - "appSource": "Sorgente dell'App", + "appSource": "Sorgente dell'app", "noLogs": "Nessun log", - "appLogs": "Log dell'App", + "appLogs": "Log dell'app", "close": "Chiudi", "share": "Condividi", "appNotFound": "App non trovata", @@ -148,28 +148,28 @@ "deviceSupportsXArch": "Il dispositivo in uso supporta l'architettura {} della CPU.", "deviceSupportsFollowingArchs": "Il dispositivo in uso supporta le seguenti architetture della CPU:", "warning": "Attenzione", - "sourceIsXButPackageFromYPrompt": "L'origine dell'App è '{}' ma il pacchetto della release proviene da '{}'. Continuare?", + "sourceIsXButPackageFromYPrompt": "L'origine dell'app è '{}' ma il pacchetto della release proviene da '{}'. Continuare?", "updatesAvailable": "Aggiornamenti disponibili", - "updatesAvailableNotifDescription": "Notifica all'utente che sono disponibili gli aggiornamenti di una o più App monitorate da Obtainium", + "updatesAvailableNotifDescription": "Notifica all'utente che sono disponibili gli aggiornamenti di una o più app monitorate da Obtainium", "noNewUpdates": "Nessun nuovo aggiornamento.", "xHasAnUpdate": "Aggiornamento disponibile per {}", "appsUpdated": "App aggiornate", - "appsUpdatedNotifDescription": "Notifica all'utente che una o più App sono state aggiornate in background", - "xWasUpdatedToY": "{} è stato aggiornato a {}.", + "appsUpdatedNotifDescription": "Notifica all'utente che una o più app sono state aggiornate in secondo piano", + "xWasUpdatedToY": "{} è stato aggiornato alla {}.", "errorCheckingUpdates": "Controllo degli errori per gli aggiornamenti", - "errorCheckingUpdatesNotifDescription": "Una notifica che mostra quando il controllo degli aggiornamenti in background fallisce", + "errorCheckingUpdatesNotifDescription": "Una notifica che mostra quando il controllo degli aggiornamenti in secondo piano fallisce", "appsRemoved": "App rimosse", - "appsRemovedNotifDescription": "Notifica all'utente che una o più App sono state rimosse a causa di errori durante il caricamento", + "appsRemovedNotifDescription": "Notifica all'utente che una o più app sono state rimosse a causa di errori durante il caricamento", "xWasRemovedDueToErrorY": "{} è stata rimosso a causa di questo errore: {}", - "completeAppInstallation": "Completa l'installazione dell'App", - "obtainiumMustBeOpenToInstallApps": "Obtainium deve essere aperto per poter installare le App", - "completeAppInstallationNotifDescription": "Chiede all'utente di riaprire Obtainium per terminare l'installazione di un App", + "completeAppInstallation": "Completa l'installazione dell'app", + "obtainiumMustBeOpenToInstallApps": "Obtainium deve essere aperto per poter installare le app", + "completeAppInstallationNotifDescription": "Chiede all'utente di riaprire Obtainium per terminare l'installazione di un'app", "checkingForUpdates": "Controllo degli aggiornamenti in corso", "checkingForUpdatesNotifDescription": "Notifica transitoria che appare durante la verifica degli aggiornamenti", - "pleaseAllowInstallPerm": "Per favore permetti a Obtainium di installare le App", + "pleaseAllowInstallPerm": "Per favore permetti a Obtainium di installare le app", "trackOnly": "Solo-Monitoraggio", "errorWithHttpStatusCode": "Errore {}", - "versionCorrectionDisabled": "Correzione della versione disabilitata (il plugin non pare funzionare)", + "versionCorrectionDisabled": "Correzione della versione disattivata (il plugin sembra non funzionare)", "unknown": "Sconosciuto", "none": "Nessuno", "never": "Mai", @@ -178,11 +178,11 @@ "lastUpdateCheckX": "Ultimo controllo degli aggiornamenti: {}", "remove": "Rimuovi", "yesMarkUpdated": "Sì, contrassegna come aggiornato", - "fdroid": "F-Droid Official", - "appIdOrName": "ID o nome dell'App", - "appId": "ID dell'App", - "appWithIdOrNameNotFound": "Non è stata trovata alcuna App con quell'ID o nome", - "reposHaveMultipleApps": "I repository possono contenere più App", + "fdroid": "F-Droid ufficiale", + "appIdOrName": "ID o nome dell'app", + "appId": "ID dell'app", + "appWithIdOrNameNotFound": "Non è stata trovata alcuna app con quell'ID o nome", + "reposHaveMultipleApps": "I repository possono contenere più app", "fdroidThirdPartyRepo": "Repository F-Droid di terze parti", "steam": "Steam", "steamMobile": "Steam Mobile", @@ -193,9 +193,9 @@ "markUpdated": "Contrassegna come aggiornato", "additionalOptions": "Opzioni aggiuntive", "disableVersionDetection": "Disattiva il rilevamento della versione", - "noVersionDetectionExplanation": "Questa opzione dovrebbe essere usata solo per le App la cui versione non viene rilevata correttamente.", + "noVersionDetectionExplanation": "Questa opzione dovrebbe essere usata solo per le app la cui versione non viene rilevata correttamente.", "downloadingX": "Scaricamento di {} in corso", - "downloadNotifDescription": "Notifica all'utente lo stato di avanzamento del download di un'App", + "downloadNotifDescription": "Notifica all'utente lo stato di avanzamento del download di un'app", "noAPKFound": "Nessun APK trovato", "noVersionDetection": "Disattiva rilevamento di versione", "categorize": "Aggiungi a categoria", @@ -204,19 +204,19 @@ "noCategory": "Nessuna categoria", "noCategories": "Nessuna categoria", "deleteCategoriesQuestion": "Eliminare le categorie?", - "categoryDeleteWarning": "Tutte le App nelle categorie eliminate saranno impostate come non categorizzate.", + "categoryDeleteWarning": "Tutte le app nelle categorie eliminate saranno impostate come non categorizzate.", "addCategory": "Aggiungi categoria", "label": "Etichetta", "language": "Lingua", "copiedToClipboard": "Copiato negli appunti", "storagePermissionDenied": "Accesso ai file non autorizzato", - "selectedCategorizeWarning": "Ciò sostituirà le impostazioni di categoria esistenti per le App selezionate.", + "selectedCategorizeWarning": "Ciò sostituirà le impostazioni di categoria esistenti per le app selezionate.", "filterAPKsByRegEx": "Filtra file APK con espressioni regolari", "removeFromObtainium": "Rimuovi da Obtainium", "uninstallFromDevice": "Disinstalla dal dispositivo", - "onlyWorksWithNonVersionDetectApps": "Funziona solo per le App con il rilevamento della versione disattivato.", + "onlyWorksWithNonVersionDetectApps": "Funziona solo per le app con il rilevamento della versione disattivato.", "releaseDateAsVersion": "Usa data di rilascio come versione", - "releaseDateAsVersionExplanation": "Questa opzione dovrebbe essere usata solo per le App in cui il rilevamento della versione non funziona correttamente, ma è disponibile una data di rilascio.", + "releaseDateAsVersionExplanation": "Questa opzione dovrebbe essere usata solo per le app in cui il rilevamento della versione non funziona correttamente, ma è disponibile una data di rilascio.", "changes": "Novità", "releaseDate": "Data di rilascio", "importFromURLsInFile": "Importa da URL in file (come OPML)", @@ -224,35 +224,35 @@ "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", - "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", - "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", - "about": "About", - "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", - "checkOnStart": "Check Once on Start", - "tryInferAppIdFromCode": "Try inferring App ID from source code", + "overrideSource": "Sovrascrivi fonte", + "dontShowAgain": "Non mostrarlo più", + "dontShowTrackOnlyWarnings": "Non mostrare gli avvisi 'Solo-Monitoraggio'", + "dontShowAPKOriginWarnings": "Non mostrare gli avvisi di origine dell'APK", + "moveNonInstalledAppsToBottom": "Sposta le app non installate in fondo alla lista", + "gitlabPATLabel": "GitLab Personal Access Token (attiva la ricerca)", + "about": "Informazioni", + "requiresCredentialsInSettings": "Servono credenziali aggiuntive (in Impostazioni)", + "checkOnStart": "Controlla una volta all'avvio", + "tryInferAppIdFromCode": "Prova a dedurre l'ID dell'app dal codice sorgente", "removeAppQuestion": { - "one": "Rimuovere l'App?", - "other": "Rimuovere le App?" + "one": "Rimuovere l'app?", + "other": "Rimuovere le app?" }, "tooManyRequestsTryAgainInMinutes": { "one": "Troppe richieste (traffico limitato) - riprova tra {} minuto", "other": "Troppe richieste (traffico limitato) - riprova tra {} minuti" }, "bgUpdateGotErrorRetryInMinutes": { - "one": "Il controllo degli aggiornamenti in background ha incontrato un {}, nuovo tentativo tra {} minuto", - "other": "Il controllo degli aggiornamenti in background ha incontrato un {}, nuovo tentativo tra {} minuti" + "one": "Il controllo degli aggiornamenti in secondo piano ha riscontrato un {}, nuovo tentativo tra {} minuto", + "other": "Il controllo degli aggiornamenti in secondo piano ha riscontrato un {}, nuovo tentativo tra {} minuti" }, "bgCheckFoundUpdatesWillNotifyIfNeeded": { - "one": "Il controllo degli aggiornamenti in background ha trovato {} aggiornamento - notificherà l'utente se necessario", - "other": "Il controllo degli aggiornamenti in background ha trovato {} aggiornamenti - notificherà l'utente se necessario" + "one": "Il controllo degli aggiornamenti in secondo piano ha trovato {} aggiornamento - notificherà l'utente se necessario", + "other": "Il controllo degli aggiornamenti in secondo piano ha trovato {} aggiornamenti - notificherà l'utente se necessario" }, "apps": { - "one": "{} App", - "other": "{} App" + "one": "{} app", + "other": "{} app" }, "url": { "one": "{} URL", @@ -271,15 +271,15 @@ "other": "{} giorni" }, "clearedNLogsBeforeXAfterY": { - "one": "Pulito {n} log (prima = {before}, dopo = {after})", - "other": "Puliti {n} log (prima = {before}, dopo = {after})" + "one": "Rimosso {n} log (prima = {before}, dopo = {after})", + "other": "Rimossi {n} log (prima = {before}, dopo = {after})" }, "xAndNMoreUpdatesAvailable": { - "one": "{} e un'altra App hanno aggiornamenti disponibili.", - "other": "{} e altre {} App hanno aggiornamenti disponibili." + "one": "{} e un'altra app hanno aggiornamenti disponibili.", + "other": "{} e altre {} app hanno aggiornamenti disponibili." }, "xAndNMoreUpdatesInstalled": { - "one": "{} e un'altra App sono state aggiornate.", - "other": "{} e altre {} App sono state aggiornate." + "one": "{} e un'altra app sono state aggiornate.", + "other": "{} e altre {} app sono state aggiornate." } } From 3697d74185db2e2b76dea6dab65754bf6a20950a Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Wed, 21 Jun 2023 04:31:27 +0300 Subject: [PATCH 230/600] Update ru.json Fixed some typo --- assets/translations/ru.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index af73855..aa4ae9b 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -2,9 +2,9 @@ "invalidURLForSource": "Неверный URL-адрес {} приложения", "noReleaseFound": "Не удалось найти подходящий релиз", "noVersionFound": "Не удалось определить версию релиза", - "urlMatchesNoSource": "URL не соответствует известному источнику", + "urlMatchesNoSource": "URL-адрес не соответствует известному источнику", "cantInstallOlderVersion": "Невозможно установить более старую версию приложения", - "appIdMismatch": "Идентификатор загруженного пакета не совпадает с существующим идентификатором приложения", + "appIdMismatch": "ID загруженного пакета не совпадает с существующим ID приложения", "functionNotImplemented": "Этот класс не реализовал эту функцию", "placeholder": "Заполнитель", "someErrors": "Произошли некоторые ошибки", @@ -17,8 +17,8 @@ "bgUpdateTaskFinished": "Завершена задача фоновой проверки обновлений", "firstRun": "Это первый запуск Obtainium", "settingUpdateCheckIntervalTo": "Установка интервала проверки обновлений: {}", - "githubPATLabel": "Персональный ключ доступа GitHub (увеличивает лимит запросов)", - "githubPATHint": "Ключ доступа должен быть в формате: имя_пользователя:токен", + "githubPATLabel": "Персональный токен доступа GitHub (увеличивает лимит запросов)", + "githubPATHint": "Токен доступа должен быть в формате: имя_пользователя:токен", "githubPATFormat": "имя_пользователя:токен", "includePrereleases": "Включить предварительные релизы", "fallbackToOlderReleases": "Откатиться к более старым версиям", @@ -38,7 +38,7 @@ "app": "Приложение", "appsFromSourceAreTrackOnly": "Приложения из этого источника являются 'только для отслеживания'.", "youPickedTrackOnly": "Вы выбрали опцию 'Только для отслеживания'.", - "trackOnlyAppDescription": "Приложение будет отслеживаться обновлениями, но Obtainium не сможет его скачивать или устанавливать.", + "trackOnlyAppDescription": "Приложение будет отслеживаться на предмет обновлений, но Obtainium не сможет загрузить или установить его.", "cancelled": "Отменено", "appAlreadyAdded": "Приложение уже добавлено", "alreadyUpToDateQuestion": "Приложение уже обновлено?", @@ -77,7 +77,7 @@ "no": "Нет", "yes": "Да", "markSelectedAppsUpdated": "Отметить выбранные приложения как обновленные", - "pinToTop": "Закрепить вверху", + "pinToTop": "Закрепить сверху", "unpinFromTop": "Открепить", "resetInstallStatusForSelectedAppsQuestion": "Сбросить статус установки для выбранных приложений?", "installStatusOfXWillBeResetExplanation": "Статус установки для выбранных приложений будет сброшен.\n\nЭто может помочь, если версия приложения, отображаемая в Obtainium, неправильная из-за неудачных обновлений или других проблем.", @@ -100,18 +100,18 @@ "invalidInput": "Неверный ввод", "importedX": "Импортировано {}", "obtainiumImport": "Импорт в Obtainium", - "importFromURLList": "Импорт из списка URL-адресов", + "importFromURLList": "Импорт из списка URL-адреса", "searchQuery": "Поисковый запрос", - "appURLList": "Список URL-адресов приложений", + "appURLList": "Список URL приложений", "line": "Строка", "searchX": "Поиск {}", "noResults": "Результатов не найдено", "importX": "Импорт {}", "importedAppsIdDisclaimer": "Импортированные приложения могут неверно отображаться как 'Не установлены'.\nДля исправления этой проблемы повторно установите их через Obtainium.\nЭто не должно повлиять на данные приложения.\n\nПроблемы возникают только при импорте из URL-адреса и сторонних источников.", - "importErrors": "Ошибки импорта", + "importErrors": "Ошибка импорта", "importedXOfYApps": "Импортировано {} из {} приложений.", "followingURLsHadErrors": "При импорте следующие URL-адреса содержали ошибки:", - "okay": "ОК", + "okay": "Окей", "selectURL": "Выбрать URL-адрес", "selectURLs": "Выбрать URL-адреса", "pick": "Выбрать", @@ -133,7 +133,7 @@ "neverManualOnly": "Никогда - Только вручную", "appearance": "Внешний вид", "showWebInAppView": "Показывать веб-страницу источника в представлении приложения", - "pinUpdates": "Закрепить обновления вверху списка приложений", + "pinUpdates": "Закрепить обновления сверху списка приложений", "updates": "Обновления", "sourceSpecific": "Специфика источника", "appSource": "Источник приложения", @@ -196,7 +196,7 @@ "noVersionDetectionExplanation": "Эта опция должна использоваться только для приложений, где обнаружение версии не работает корректно.", "downloadingX": "Загрузка {}", "downloadNotifDescription": "Уведомляет пользователя о прогрессе загрузки приложения", - "noAPKFound": "APK не найдено", + "noAPKFound": "APK не найден", "noVersionDetection": "Версий не обнаружено", "categorize": "Категоризировать", "categories": "Категории", @@ -233,7 +233,7 @@ "about": "О приложении", "requiresCredentialsInSettings": "Для этого требуются дополнительные учетные данные (в настройках)", "checkOnStart": "Проверить один раз при запуске", - "tryInferAppIdFromCode": "Попытаться определить идентификатор приложения из исходного кода", + "tryInferAppIdFromCode": "Попытаться определить ID приложения из исходного кода", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" From 423ba07fad561e4cbe53b7af5f716735e4efe169 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 23 Jun 2023 11:52:49 -0400 Subject: [PATCH 231/600] Allow correcting inferred IDs (#103) --- lib/custom_errors.dart | 2 +- lib/pages/app.dart | 9 ++++++--- lib/providers/apps_provider.dart | 8 +++++--- lib/providers/source_provider.dart | 19 ++++++++++++++----- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/lib/custom_errors.dart b/lib/custom_errors.dart index 8f535cf..5d0bb20 100644 --- a/lib/custom_errors.dart +++ b/lib/custom_errors.dart @@ -56,7 +56,7 @@ class InstallError extends ObtainiumError { } class IDChangedError extends ObtainiumError { - IDChangedError() : super(tr('appIdMismatch')); + IDChangedError(String newId) : super('${tr('appIdMismatch')} - $newId'); } class NotImplementedError extends ObtainiumError { diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 3e2e993..096787c 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -329,7 +329,8 @@ class _AppPageState extends State { try { HapticFeedback.heavyImpact(); var res = await appsProvider.downloadAndInstallLatestApps( - [app!.app.id], globalNavigatorKey.currentContext); + app?.app.id != null ? [app!.app.id] : [], + globalNavigatorKey.currentContext); if (res.isNotEmpty && mounted) { Navigator.of(context).pop(); } @@ -426,8 +427,10 @@ class _AppPageState extends State { onPressed: app?.downloadProgress != null ? null : () { - appsProvider.removeAppsWithModal( - context, [app!.app]).then((value) { + appsProvider + .removeAppsWithModal( + context, app != null ? [app.app] : []) + .then((value) { if (value == true) { Navigator.of(context).pop(); } diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 47dfbde..ba8b8c4 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -202,16 +202,18 @@ class AppsProvider with ChangeNotifier { // The former case should be handled (give the App its real ID), the latter is a security issue if (app.id != newInfo.packageName) { var isTempId = SourceProvider().isTempId(app); - if (apps[app.id] != null && !isTempId) { - throw IDChangedError(); + if (apps[app.id] != null && !isTempId && !app.allowIdChange) { + throw IDChangedError(newInfo.packageName); } + var idChangeWasAllowed = app.allowIdChange; + app.allowIdChange = false; var originalAppId = app.id; app.id = newInfo.packageName; downloadedFile = downloadedFile.renameSync( '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.${downloadedFile.path.split('.').last}'); if (apps[originalAppId] != null) { await removeApps([originalAppId]); - await saveApps([app], onlyIfExists: !isTempId); + await saveApps([app], onlyIfExists: !isTempId && !idChangeWasAllowed); } } return downloadedFile; diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 41caa43..f8f31ff 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -163,6 +163,7 @@ class App { late DateTime? releaseDate; late String? changeLog; late String? overrideSource; + bool allowIdChange = false; App( this.id, this.url, @@ -178,7 +179,8 @@ class App { {this.categories = const [], this.releaseDate, this.changeLog, - this.overrideSource}); + this.overrideSource, + this.allowIdChange = false}); @override String toString() { @@ -209,7 +211,8 @@ class App { categories: categories, changeLog: changeLog, releaseDate: releaseDate, - overrideSource: overrideSource); + overrideSource: overrideSource, + allowIdChange: allowIdChange); factory App.fromJson(Map json) { json = appJSONCompatibilityModifiers(json); @@ -241,7 +244,8 @@ class App { : DateTime.fromMicrosecondsSinceEpoch(json['releaseDate']), changeLog: json['changeLog'] == null ? null : json['changeLog'] as String, - overrideSource: json['overrideSource']); + overrideSource: json['overrideSource'], + allowIdChange: json['allowIdChange'] ?? false); } Map toJson() => { @@ -259,7 +263,8 @@ class App { 'categories': categories, 'releaseDate': releaseDate?.microsecondsSinceEpoch, 'changeLog': changeLog, - 'overrideSource': overrideSource + 'overrideSource': overrideSource, + 'allowIdChange': allowIdChange }; } @@ -613,7 +618,11 @@ class SourceProvider { categories: currentApp?.categories ?? const [], releaseDate: apk.releaseDate, changeLog: apk.changeLog, - overrideSource: overrideSource ?? currentApp?.overrideSource); + overrideSource: overrideSource ?? currentApp?.overrideSource, + allowIdChange: currentApp?.allowIdChange ?? + source.appIdInferIsOptional && + inferAppIdIfOptional // Optional ID inferring may be incorrect - allow correction on first install + ); } // Returns errors in [results, errors] instead of throwing them From d31bbd9ea8cccda53a70e86557a33dc77daf8dce Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 23 Jun 2023 12:02:18 -0400 Subject: [PATCH 232/600] Improve version text alignment on app page (#607) --- lib/pages/app.dart | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 096787c..2b3ba2e 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -82,20 +84,20 @@ class _AppPageState extends State { const SizedBox( height: 32, ), - Text( - tr('latestVersionX', - args: [app?.app.latestVersion ?? tr('unknown')]), - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.bodyLarge, - ), - Text( - '${tr('installedVersionX', args: [ - app?.app.installedVersion ?? tr('none') - ])}${trackOnly ? ' ${tr('estimateInBrackets')}\n\n${tr('xIsTrackOnly', args: [ - tr('app') - ])}' : ''}', - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.bodyLarge, + Column( + children: [ + Text( + '${tr('latestVersionX', args: [ + app?.app.latestVersion ?? tr('unknown') + ])}\n${tr('installedVersionX', args: [ + app?.app.installedVersion ?? tr('none') + ])}${trackOnly ? ' ${tr('estimateInBrackets')}\n\n${tr('xIsTrackOnly', args: [ + tr('app') + ])}' : ''}', + textAlign: TextAlign.end, + style: Theme.of(context).textTheme.bodyLarge!, + ), + ], ), if (app?.app.installedVersion != null && !isVersionDetectionStandard) From ff5152bf7957fa70f4e2dbf428db294d5bd63950 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 23 Jun 2023 12:07:34 -0400 Subject: [PATCH 233/600] Added RU language menu entry --- lib/main.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/main.dart b/lib/main.dart index 9dd7f68..d0710a4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,6 +38,7 @@ List> supportedLocales = const [ MapEntry(Locale('fr'), 'Français'), MapEntry(Locale('es'), 'Español'), MapEntry(Locale('pl'), 'Polski'), + MapEntry(Locale('ru'), 'Русский язык'), ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; From 4366b4e36995760e60db8ee0bb31f6c3b32fb72b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 23 Jun 2023 16:15:10 -0400 Subject: [PATCH 234/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 72 +++++++++++++++++++++++++-------------------------- pubspec.yaml | 2 +- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index d0710a4..bf63852 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.8'; +const String currentVersion = '0.13.9'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index ac55bf1..5209b77 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -46,10 +46,10 @@ packages: dependency: transitive description: name: args - sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" async: dependency: transitive description: @@ -134,10 +134,10 @@ packages: dependency: transitive description: name: csslib - sha256: "831883fb353c8bdc1d71979e5b342c7d88acfbc643113c14ae51e2442ea0f20f" + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" url: "https://pub.dev" source: hosted - version: "0.17.3" + version: "1.0.0" cupertino_icons: dependency: "direct main" description: @@ -222,10 +222,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: "9d6e95ec73abbd31ec54d0e0df8a961017e165aba1395e462e5b31ea0c165daf" + sha256: b1729fc96627dd44012d0a901558177418818d6bd428df59dcfeb594e5f66432 url: "https://pub.dev" source: hosted - version: "5.3.1" + version: "5.3.2" flutter: dependency: "direct main" description: flutter @@ -322,10 +322,10 @@ packages: dependency: "direct main" description: name: html - sha256: "58e3491f7bf0b6a4ea5110c0c688877460d1a6366731155c4a4580e7ded773e8" + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" url: "https://pub.dev" source: hosted - version: "0.15.3" + version: "0.15.4" http: dependency: "direct main" description: @@ -506,42 +506,42 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6 + sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" url: "https://pub.dev" source: hosted - version: "2.1.6" + version: "2.1.7" permission_handler: dependency: "direct main" description: name: permission_handler - sha256: "33c6a1253d1f95fd06fa74b65b7ba907ae9811f9d5c1d3150e51417d04b8d6a8" + sha256: "1b6b3e73f0bcbc856548bbdfb1c33084a401c4f143e220629a9055233d76c331" url: "https://pub.dev" source: hosted - version: "10.2.0" + version: "10.3.0" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: d8cc6a62ded6d0f49c6eac337e080b066ee3bce4d405bd9439a61e1f1927bfe8 + sha256: "8f6a95ccbca13766882f95d32684d7c9bfe6c45650c32bedba948ef1c6a4ddf7" url: "https://pub.dev" source: hosted - version: "10.2.1" + version: "10.2.3" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: ee96ac32f5a8e6f80756e25b25b9f8e535816c8e6665a96b6d70681f8c4f7e85 + sha256: "08dcb6ce628ac0b257e429944b4c652c2a4e6af725bdf12b498daa2c6b2b1edb" url: "https://pub.dev" source: hosted - version: "9.0.8" + version: "9.1.0" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: "68abbc472002b5e6dfce47fe9898c6b7d8328d58b5d2524f75e277c07a97eb84" + sha256: de20a5c3269229c1ae2e5a6b822f6cb59578b23e8255c93fbeebfc82116e6b11 url: "https://pub.dev" source: hosted - version: "3.9.0" + version: "3.10.0" permission_handler_windows: dependency: transitive description: @@ -618,10 +618,10 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "16d3fb6b3692ad244a695c0183fca18cf81fd4b821664394a781de42386bf022" + sha256: "396f85b8afc6865182610c0a2fc470853d56499f75f7499e2a73a9f0539d23d0" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" shared_preferences_android: dependency: transitive description: @@ -695,10 +695,10 @@ packages: dependency: transitive description: name: sqflite_common - sha256: e77abf6ff961d69dfef41daccbb66b51e9983cdd5cb35bf30733598057401555 + sha256: "8f7603f3f8f126740bc55c4ca2d1027aab4b74a1267a3e31ce51fe40e3b65b8f" url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.4.5+1" stack_trace: dependency: transitive description: @@ -775,10 +775,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: eed4e6a1164aa9794409325c3b707ff424d4d1c2a785e7db67f8bbda00e36e51 + sha256: "15f5acbf0dce90146a0f5a2c4a002b1814a6303c4c5c075aa2623b2d16156f03" url: "https://pub.dev" source: hosted - version: "6.0.35" + version: "6.0.36" url_launcher_ios: dependency: transitive description: @@ -807,10 +807,10 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" url_launcher_web: dependency: transitive description: @@ -847,18 +847,18 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: "5604dac1178680a34fbe4a08c7b69ec42cca6601dc300009ec9ff69bef284cc2" + sha256: "789d52bd789373cc1e100fb634af2127e86c99cf9abde09499743270c5de8d00" url: "https://pub.dev" source: hosted - version: "4.2.1" + version: "4.2.2" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: "57a22c86065375c1598b57224f92d6008141be0c877c64100de8bfb6f71083d8" + sha256: "532135f6f6b8030cd039f30eab23f340d650350e29f38e9b37d2eaad028f1018" url: "https://pub.dev" source: hosted - version: "3.7.1" + version: "3.8.0" webview_flutter_platform_interface: dependency: transitive description: @@ -871,26 +871,26 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "6bbc6ade302b842999b27cbaa7171241c273deea8a9c73f92ceb3d811c767de2" + sha256: ecc9e9ea15216afc5ba3b1f14aa19414ceba526e57b19cebd970bfa91a0f4058 url: "https://pub.dev" source: hosted - version: "3.4.4" + version: "3.5.0" win32: dependency: transitive description: name: win32 - sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" + sha256: "1414f27dd781737e51afa9711f2ac2ace6ab4498ee98e20863fa5505aa00c58c" url: "https://pub.dev" source: hosted - version: "4.1.4" + version: "5.0.4" win32_registry: dependency: transitive description: name: win32_registry - sha256: "1c52f994bdccb77103a6231ad4ea331a244dbcef5d1f37d8462f713143b0bfae" + sha256: e4506d60b7244251bc59df15656a3093501c37fb5af02105a944d73eb95be4c9 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index de89b9e..d65d7db 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.13.8+172 # When changing this, update the tag in main() accordingly +version: 0.13.9+173 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 7577f3ac9ba24f20cc137c7392d6aa6e699e4886 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 23 Jun 2023 16:30:35 -0400 Subject: [PATCH 235/600] App ID infer bugfix for GitHub --- lib/app_sources/github.dart | 13 ++++++++----- lib/main.dart | 2 +- pubspec.yaml | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 5144968..8cb08e2 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -102,15 +102,18 @@ class GitHub extends AppSource { .split('\n') .map((e) => e.trim()); var appId = trimmedLines - .where((l) => l.startsWith('applicationId "')) - .first - .split('"')[1]; + .where((l) => + l.startsWith('applicationId "') || + l.startsWith('applicationId \'')) + .first; + appId = appId + .split(appId.startsWith('applicationId "') ? '"' : '\'')[1]; if (appId.startsWith('\${') && appId.endsWith('}')) { appId = trimmedLines .where((l) => l.startsWith( 'def ${appId.substring(2, appId.length - 1)}')) - .first - .split('"')[1]; + .first; + appId = appId.split(appId.contains('"') ? '"' : '\'')[1]; } if (appId.isNotEmpty) { return appId; diff --git a/lib/main.dart b/lib/main.dart index bf63852..d6e2460 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.9'; +const String currentVersion = '0.13.10'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index d65d7db..a1475e9 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.13.9+173 # When changing this, update the tag in main() accordingly +version: 0.13.10+174 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 5979957d6026d34e8645f847494bee84ab905f25 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 23 Jun 2023 18:01:34 -0400 Subject: [PATCH 236/600] Fixed syntax errors in RU translation file --- assets/translations/ru.json | 8 ++++---- lib/main.dart | 2 +- pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index aa4ae9b..ce91304 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -24,7 +24,7 @@ "fallbackToOlderReleases": "Откатиться к более старым версиям", "filterReleaseTitlesByRegEx": "Фильтровать заголовки релизов с помощью регулярного выражения", "invalidRegEx": "Неверное регулярное выражение", - "noDescription": "Нет описания" + "noDescription": "Нет описания", "cancel": "Отмена", "continue": "Продолжить", "requiredInBrackets": "(Обязательно)", @@ -68,7 +68,7 @@ "removeSelectedAppsQuestion": "Удалить выбранные приложения?", "removeSelectedApps": "Удалить выбранные приложения", "updateX": "Обновить {}", - "installX": "Установить {}" + "installX": "Установить {}", "markXTrackOnlyAsUpdated": "Отметить {}\n(Только для отслеживания)\nкак обновленное", "changeX": "Изменить {}", "installUpdateApps": "Установить/Обновить приложения", @@ -90,7 +90,7 @@ "filterActive": "Фильтр *", "filterApps": "Фильтровать приложения", "appName": "Название приложения", - "author": "Автор" + "author": "Автор", "upToDateApps": "Приложения со свежими обновлениями", "nonInstalledApps": "Неустановленные приложения", "importExport": "Импорт/экспорт", @@ -207,7 +207,7 @@ "categoryDeleteWarning": "Все приложения в удаленных категориях будут помечены как без категории.", "addCategory": "Добавить категорию", "label": "Метка", - "language": "Язык" + "language": "Язык", "copiedToClipboard": "Скопировано в буфер обмена", "storagePermissionDenied": "Отказано в доступе к хранилищу", "selectedCategorizeWarning": "Это заменит все текущие настройки категорий для выбранных приложений.", diff --git a/lib/main.dart b/lib/main.dart index d6e2460..bc1ab9c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.10'; +const String currentVersion = '0.13.11'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index a1475e9..915f307 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.13.10+174 # When changing this, update the tag in main() accordingly +version: 0.13.11+175 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 16d63a44161f6b876e2e0d2b915ee53bf349d66b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 24 Jun 2023 17:58:00 -0400 Subject: [PATCH 237/600] HTML Source: treat whole link as version (also applies to APK filter regex) --- lib/app_sources/html.dart | 10 ++++------ lib/main.dart | 2 +- pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 7b69ade..47d6acd 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -111,8 +111,7 @@ class HTML extends AppSource { .where((element) => Uri.parse(element).path.toLowerCase().endsWith('.apk')) .toList(); - links.sort( - (a, b) => compareAlphaNumeric(a.split('/').last, b.split('/').last)); + links.sort((a, b) => compareAlphaNumeric(a, b)); if (additionalSettings['apkFilterRegEx'] != null) { var reg = RegExp(additionalSettings['apkFilterRegEx']); links = links.where((element) => reg.hasMatch(element)).toList(); @@ -121,12 +120,11 @@ class HTML extends AppSource { throw NoReleasesError(); } var rel = links.last; - var apkName = rel.split('/').last; - var version = apkName.substring(0, apkName.length - 4); + var version = rel.hashCode.toString(); List apkUrls = [rel].map((e) => ensureAbsoluteUrl(e, uri)).toList(); - return APKDetails( - version, getApkUrlsFromUrls(apkUrls), AppNames(uri.host, tr('app'))); + return APKDetails(version, apkUrls.map((e) => MapEntry(e, e)).toList(), + AppNames(uri.host, tr('app'))); } else { throw getObtainiumHttpError(res); } diff --git a/lib/main.dart b/lib/main.dart index bc1ab9c..a46ca2d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.11'; +const String currentVersion = '0.13.12'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 915f307..7e0c65b 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.13.11+175 # When changing this, update the tag in main() accordingly +version: 0.13.12+176 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 69656e65c32251ed4e1260d5ddd47fc4f3210379 Mon Sep 17 00:00:00 2001 From: 1xFF <100185670+1xFF@users.noreply.github.com> Date: Sat, 24 Jun 2023 21:48:57 -0700 Subject: [PATCH 238/600] Basic OBB support --- lib/providers/apps_provider.dart | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index ee30f2c..10a8f8c 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -344,12 +344,14 @@ class AppsProvider with ChangeNotifier { {bool silent = false}) async { try { var somethingInstalled = false; - for (var apk in dir.extracted - .listSync() - .where((f) => f is File && f.path.toLowerCase().endsWith('.apk'))) { - somethingInstalled = somethingInstalled || - await installApk(DownloadedApk(dir.appId, apk as File), - silent: silent); + for (var file in dir.extracted.listSync(recursive: true, followLinks: true).whereType()) { + if (file.path.toLowerCase().endsWith('.apk')) { + somethingInstalled = somethingInstalled || + await installApk(DownloadedApk(dir.appId, file), silent: silent); + } + else if (file.path.toLowerCase().endsWith('.obb')) { + moveObbFile(file, dir.appId); + } } if (somethingInstalled) { dir.file.delete(recursive: true); @@ -388,6 +390,18 @@ class AppsProvider with ChangeNotifier { return installed; } + void moveObbFile(File file, String appId) async { + if(!file.path.toLowerCase().endsWith('.obb')) return; + + // REQUEST_INSTALL_PACKAGES is required to access Android/obb + // But it seems impossible to check if obb access has been explicitly granted + String obbDirPath = "/storage/emulated/0/Android/obb/$appId"; + Directory(obbDirPath).createSync(); + + String obbFileName = file.path.split("/").last; + await file.copy("$obbDirPath/$obbFileName"); + } + void uninstallApp(String appId) async { var intent = AndroidIntent( action: 'android.intent.action.DELETE', From e75ca05aa46cec1b5c363a40e385090759b044f8 Mon Sep 17 00:00:00 2001 From: 1xFF <100185670+1xFF@users.noreply.github.com> Date: Wed, 28 Jun 2023 02:50:18 -0700 Subject: [PATCH 239/600] Change recursion --- lib/providers/apps_provider.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 10a8f8c..60e0359 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -344,7 +344,7 @@ class AppsProvider with ChangeNotifier { {bool silent = false}) async { try { var somethingInstalled = false; - for (var file in dir.extracted.listSync(recursive: true, followLinks: true).whereType()) { + for (var file in dir.extracted.listSync(recursive: true, followLinks: false).whereType()) { if (file.path.toLowerCase().endsWith('.apk')) { somethingInstalled = somethingInstalled || await installApk(DownloadedApk(dir.appId, file), silent: silent); @@ -396,7 +396,7 @@ class AppsProvider with ChangeNotifier { // REQUEST_INSTALL_PACKAGES is required to access Android/obb // But it seems impossible to check if obb access has been explicitly granted String obbDirPath = "/storage/emulated/0/Android/obb/$appId"; - Directory(obbDirPath).createSync(); + Directory(obbDirPath).createSync(recursive: true); String obbFileName = file.path.split("/").last; await file.copy("$obbDirPath/$obbFileName"); From af5ea3db0fb913bb36a9e04bd22def6df9e5662b Mon Sep 17 00:00:00 2001 From: 1xFF <100185670+1xFF@users.noreply.github.com> Date: Wed, 28 Jun 2023 03:47:18 -0700 Subject: [PATCH 240/600] add Permissions for android 10 and below --- lib/providers/apps_provider.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 60e0359..fc00b8a 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -393,8 +393,11 @@ class AppsProvider with ChangeNotifier { void moveObbFile(File file, String appId) async { if(!file.path.toLowerCase().endsWith('.obb')) return; - // REQUEST_INSTALL_PACKAGES is required to access Android/obb - // But it seems impossible to check if obb access has been explicitly granted + // TODO: Does not support Android 11+ + if ((await DeviceInfoPlugin().androidInfo).version.sdkInt <= 29) { + await Permission.storage.request(); + } + String obbDirPath = "/storage/emulated/0/Android/obb/$appId"; Directory(obbDirPath).createSync(recursive: true); From 0fa0a4b19a0a53ac111dac67d714b90ded07d423 Mon Sep 17 00:00:00 2001 From: 1xFF <100185670+1xFF@users.noreply.github.com> Date: Wed, 28 Jun 2023 13:31:10 -0700 Subject: [PATCH 241/600] fix race condition --- lib/providers/apps_provider.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index fc00b8a..a81ec37 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -350,7 +350,7 @@ class AppsProvider with ChangeNotifier { await installApk(DownloadedApk(dir.appId, file), silent: silent); } else if (file.path.toLowerCase().endsWith('.obb')) { - moveObbFile(file, dir.appId); + await moveObbFile(file, dir.appId); } } if (somethingInstalled) { @@ -390,7 +390,7 @@ class AppsProvider with ChangeNotifier { return installed; } - void moveObbFile(File file, String appId) async { + Future moveObbFile(File file, String appId) async { if(!file.path.toLowerCase().endsWith('.obb')) return; // TODO: Does not support Android 11+ From ede54531c8ad83bd65289979e0b52f7a104be2ea Mon Sep 17 00:00:00 2001 From: Mehdee <85278288+mehdeej@users.noreply.github.com> Date: Thu, 29 Jun 2023 14:35:09 +0000 Subject: [PATCH 242/600] Update (Persian) fa.json --- assets/translations/fa.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 0b4030a..555868d 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -228,12 +228,12 @@ "dontShowAgain": "دوباره این را نشان نده", "dontShowTrackOnlyWarnings": "هشدار 'فقط ردیابی' را نشان ندهید", "dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید", - "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", - "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", - "about": "About", - "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", - "checkOnStart": "Check Once on Start", - "tryInferAppIdFromCode": "Try inferring App ID from source code", + "moveNonInstalledAppsToBottom": "برنامه های نصب نشده را به نمای پایین برنامه ها منتقل کنید", + "gitlabPATLabel": "رمز دسترسی شخصی GitLab (جستجو را فعال می کند)", + "about": "درباره", + "requiresCredentialsInSettings": "این به اعتبارنامه های اضافی نیاز دارد (در تنظیمات)", + "checkOnStart": "بررسی در شروع", + "tryInferAppIdFromCode": "شناسه برنامه را از کد منبع استنباط کنید", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" From f4c3951f6d1a25c30eef4584455754bcb57a287a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 1 Jul 2023 18:02:34 -0400 Subject: [PATCH 243/600] Increment version, update modules --- lib/main.dart | 2 +- lib/pages/app.dart | 2 -- pubspec.lock | 74 +++++++++++++++++++++++----------------------- pubspec.yaml | 2 +- 4 files changed, 39 insertions(+), 41 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a46ca2d..ae1ccf6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.12'; +const String currentVersion = '0.13.13'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 2b3ba2e..75aa675 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; diff --git a/pubspec.lock b/pubspec.lock index 5209b77..3e9ef24 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -251,10 +251,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" flutter_local_notifications: dependency: "direct main" description: @@ -288,10 +288,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: dc6d5258653f6857135b32896ccda7f7af0c54dcec832495ad6835154c6c77c0 + sha256: "9e0202b5339cd88ac0f109abae8502681bfab0b13a8e02a0e7158124610b5d98" url: "https://pub.dev" source: hosted - version: "0.6.15" + version: "0.6.15+1" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -330,10 +330,10 @@ packages: dependency: "direct main" description: name: http - sha256: "4c3f04bfb64d3efd508d06b41b825542f08122d30bda4933fb95c069d22a4fa3" + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.1.0" http_parser: dependency: transitive description: @@ -514,42 +514,42 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "1b6b3e73f0bcbc856548bbdfb1c33084a401c4f143e220629a9055233d76c331" + sha256: "37fcc3c3182ac0bf8856f3e973e11c7bef5556d69f1a0d8fb908f51019c2912d" url: "https://pub.dev" source: hosted - version: "10.3.0" + version: "10.4.1" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "8f6a95ccbca13766882f95d32684d7c9bfe6c45650c32bedba948ef1c6a4ddf7" + sha256: "3b61f3da3b1c83bc3fb6a2b431e8dab01d0e5b45f6a3d9c7609770ec88b2a89e" url: "https://pub.dev" source: hosted - version: "10.2.3" + version: "10.3.0" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: "08dcb6ce628ac0b257e429944b4c652c2a4e6af725bdf12b498daa2c6b2b1edb" + sha256: "0d1f8007b17573ff1fbeae0f04b6c8e83e1d2f6c4fe8e8226d4d2456aa8ecffe" url: "https://pub.dev" source: hosted - version: "9.1.0" + version: "9.1.2" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: de20a5c3269229c1ae2e5a6b822f6cb59578b23e8255c93fbeebfc82116e6b11 + sha256: "79b36d93a41a4aecfd0d635d77552f327cb84227c718ce5e68b5f7b85546fe7e" url: "https://pub.dev" source: hosted - version: "3.10.0" + version: "3.11.0+1" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - sha256: f67cab14b4328574938ecea2db3475dad7af7ead6afab6338772c5f88963e38b + sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 url: "https://pub.dev" source: hosted - version: "0.1.2" + version: "0.1.3" petitparser: dependency: transitive description: @@ -618,58 +618,58 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "396f85b8afc6865182610c0a2fc470853d56499f75f7499e2a73a9f0539d23d0" + sha256: "0344316c947ffeb3a529eac929e1978fcd37c26be4e8468628bac399365a3ca1" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.2.0" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749" + sha256: fe8401ec5b6dcd739a0fe9588802069e608c3fdbfd3c3c93e546cf2f90438076 url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb + sha256: "0dc5c49ad8a05ed358b991b60c7b0ba1a14e16dae58af9b420d6b9e82dc024ab" url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.3.0" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa" + sha256: "71d6806d1449b0a9d4e85e0c7a917771e672a3d5dc61149cc9fac871115018e1" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d + sha256: "23b052f17a25b90ff2b61aad4cc962154da76fb62848a9ce088efe30d7c50ab1" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5" + sha256: "7347b194fb0bbeb4058e6a4e87ee70350b6b2b90f8ac5f8bd5b3a01548f6d33a" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.0" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173" + sha256: f95e6a43162bce43c9c3405f3eb6f39e5b5d11f65fab19196cf8225e2777624d url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.0" sky_engine: dependency: transitive description: flutter @@ -855,10 +855,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "532135f6f6b8030cd039f30eab23f340d650350e29f38e9b37d2eaad028f1018" + sha256: "69787707339e7588aad256386475c18223cc0da87d9812343bc27c33c01eeab4" url: "https://pub.dev" source: hosted - version: "3.8.0" + version: "3.8.1" webview_flutter_platform_interface: dependency: transitive description: @@ -871,18 +871,18 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: ecc9e9ea15216afc5ba3b1f14aa19414ceba526e57b19cebd970bfa91a0f4058 + sha256: "7b203961d6830f3e5ed1df4c4f0493fea8388a46c4d43716167c4a8ba8ecbe83" url: "https://pub.dev" source: hosted - version: "3.5.0" + version: "3.6.0" win32: dependency: transitive description: name: win32 - sha256: "1414f27dd781737e51afa9711f2ac2ace6ab4498ee98e20863fa5505aa00c58c" + sha256: dfdf0136e0aa7a1b474ea133e67cb0154a0acd2599c4f3ada3b49d38d38793ee url: "https://pub.dev" source: hosted - version: "5.0.4" + version: "5.0.5" win32_registry: dependency: transitive description: @@ -917,4 +917,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=3.4.0-17.0.pre" + flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index 7e0c65b..053fcbf 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.13.12+176 # When changing this, update the tag in main() accordingly +version: 0.13.13+177 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From da027b7734cec6c79d9a2c4141496ebdf972c31d Mon Sep 17 00:00:00 2001 From: 1xFF <100185670+1xFF@users.noreply.github.com> Date: Sun, 2 Jul 2023 02:16:47 -0700 Subject: [PATCH 244/600] change archive library --- lib/providers/apps_provider.dart | 10 ++++------ pubspec.lock | 10 +++++++++- pubspec.yaml | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index a81ec37..1a0a124 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -27,7 +27,7 @@ import 'package:flutter_fgbg/flutter_fgbg.dart'; import 'package:obtainium/providers/source_provider.dart'; import 'package:http/http.dart'; import 'package:android_intent_plus/android_intent.dart'; -import 'package:archive/archive_io.dart'; +import 'package:flutter_archive/flutter_archive.dart'; class AppInMemory { late App app; @@ -264,7 +264,7 @@ class AppsProvider with ChangeNotifier { } else { // Assume XAPK String xapkDirPath = '${downloadedFile.path}-dir'; - unzipFile(downloadedFile.path, '${downloadedFile.path}-dir'); + await unzipFile(downloadedFile.path, '${downloadedFile.path}-dir'); xapkDir = Directory(xapkDirPath); var apks = xapkDir .listSync() @@ -334,10 +334,8 @@ class AppsProvider with ChangeNotifier { } } - void unzipFile(String filePath, String destinationPath) { - final inputStream = InputFileStream(filePath); - final archive = ZipDecoder().decodeBuffer(inputStream); - extractArchiveToDisk(archive, destinationPath); + Future unzipFile(String filePath, String destinationPath) async { + await ZipFile.extractToDirectory(zipFile: File(filePath), destinationDir: Directory(destinationPath)); } Future installXApkDir(DownloadedXApkDir dir, diff --git a/pubspec.lock b/pubspec.lock index 3e9ef24..d4ccccd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -35,7 +35,7 @@ packages: source: hosted version: "2.0.7" archive: - dependency: "direct main" + dependency: transitive description: name: archive sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" @@ -231,6 +231,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_archive: + dependency: "direct main" + description: + name: flutter_archive + sha256: aec85d1da65e5b33a529db00a86df0b8e92bda78088a7cfaeeba5187701d0d85 + url: "https://pub.dev" + source: hosted + version: "5.0.0" flutter_fgbg: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 053fcbf..1abf315 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -63,7 +63,7 @@ dependencies: easy_localization: ^3.0.1 android_intent_plus: ^4.0.0 flutter_markdown: ^0.6.14 - archive: ^3.3.7 + flutter_archive: ^5.0.0 dev_dependencies: From bcc0d280abdb2a61781b3649ca5c5a0626742d60 Mon Sep 17 00:00:00 2001 From: 1xFF <100185670+1xFF@users.noreply.github.com> Date: Mon, 3 Jul 2023 01:27:12 -0700 Subject: [PATCH 245/600] fix race condition when checking updates --- lib/providers/apps_provider.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index a81ec37..9ff770c 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -902,7 +902,7 @@ class AppsProvider with ChangeNotifier { if (currentApp.preferredApkIndex < newApp.apkUrls.length) { newApp.preferredApkIndex = currentApp.preferredApkIndex; } - await saveApps([newApp]); + if (apps.containsKey(appId)) await saveApps([newApp]); return newApp.latestVersion != currentApp.latestVersion ? newApp : null; } From 667e909a7095be82aac5eb292513f0e847f4b9cf Mon Sep 17 00:00:00 2001 From: 1xFF <100185670+1xFF@users.noreply.github.com> Date: Mon, 3 Jul 2023 15:57:23 -0700 Subject: [PATCH 246/600] Add changelog for apkpure --- lib/app_sources/apkpure.dart | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index f3cef4e..cac34d0 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -37,8 +37,10 @@ class APKPure extends AppSource { String appId = (await tryInferringAppId(standardUrl))!; String host = Uri.parse(standardUrl).host; var res = await sourceRequest('$standardUrl/download'); - if (res.statusCode == 200) { + var resChangelog = await sourceRequest(standardUrl); + if (res.statusCode == 200 && resChangelog.statusCode == 200) { var html = parse(res.body); + var htmlAbout = parse(resChangelog.body); String? version = html.querySelector('span.info-sdk span')?.text.trim(); if (version == null) { throw NoVersionError(); @@ -68,8 +70,11 @@ class APKPure extends AppSource { Uri.parse(standardUrl).pathSegments.reversed.last; String appName = html.querySelector('h1.info-title')?.text.trim() ?? appId; + String? changeLog = htmlAbout.querySelector("div.whats-new-info p:not(.date)")?.innerHtml + .trim().replaceAll("
", " \n"); return APKDetails(version, apkUrls, AppNames(author, appName), - releaseDate: releaseDate); + releaseDate: releaseDate, + changeLog: changeLog); } else { throw getObtainiumHttpError(res); } From ab1f7e717909f6a3e7ddeb68d980cbd46b90e989 Mon Sep 17 00:00:00 2001 From: 1xFF <100185670+1xFF@users.noreply.github.com> Date: Mon, 3 Jul 2023 16:50:28 -0700 Subject: [PATCH 247/600] keep naming convention --- lib/app_sources/apkpure.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index cac34d0..ff63d2b 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -40,7 +40,7 @@ class APKPure extends AppSource { var resChangelog = await sourceRequest(standardUrl); if (res.statusCode == 200 && resChangelog.statusCode == 200) { var html = parse(res.body); - var htmlAbout = parse(resChangelog.body); + var htmlChangelog = parse(resChangelog.body); String? version = html.querySelector('span.info-sdk span')?.text.trim(); if (version == null) { throw NoVersionError(); @@ -70,7 +70,7 @@ class APKPure extends AppSource { Uri.parse(standardUrl).pathSegments.reversed.last; String appName = html.querySelector('h1.info-title')?.text.trim() ?? appId; - String? changeLog = htmlAbout.querySelector("div.whats-new-info p:not(.date)")?.innerHtml + String? changeLog = htmlChangelog.querySelector("div.whats-new-info p:not(.date)")?.innerHtml .trim().replaceAll("
", " \n"); return APKDetails(version, apkUrls, AppNames(author, appName), releaseDate: releaseDate, From 48acbc563aeca712ebe6585724644ea3a50a86ed Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Thu, 6 Jul 2023 00:36:47 -0400 Subject: [PATCH 248/600] Update README.md Removed izzydroid as it was out of date. --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index d65389a..47ece7c 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,6 @@ Currently supported App sources: [Get it on GitHub](https://github.com/ImranR98/Obtainium/releases) -[Get it on IzzyOnDroid](https://apt.izzysoft.de/fdroid/index/apk/dev.imranr.obtainium) ## Limitations - Auto (unattended) updates are unsupported due to a lack of any capable Flutter plugin. From 5bbe306f8f46bf6b03bf431dfc3cdab600d46804 Mon Sep 17 00:00:00 2001 From: Matsuri Date: Sat, 8 Jul 2023 21:45:57 +0800 Subject: [PATCH 249/600] Update zh.json - Translate new strings - Slight improvements Signed-off-by: Matsuri --- assets/translations/zh.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 0b3837c..9e0bbdb 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -135,7 +135,7 @@ "showWebInAppView": "在应用详情页显示来源网页", "pinUpdates": "将待更新应用置顶", "updates": "更新", - "sourceSpecific": "来源相关", + "sourceSpecific": "来源", "appSource": "源代码", "noLogs": "无日志", "appLogs": "日志", @@ -229,11 +229,11 @@ "dontShowTrackOnlyWarnings": "不显示“仅追踪”模式警告", "dontShowAPKOriginWarnings": "不显示 APK 文件来源警告", "moveNonInstalledAppsToBottom": "将未安装应用置底", - "gitlabPATLabel": "GitLab 个人访问令牌(用于搜索)", + "gitlabPATLabel": "GitLab 个人访问令牌(用于搜索应用)", "about": "相关文档", "requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)", "checkOnStart": "启动时进行一次检查", - "tryInferAppIdFromCode": "Try inferring App ID from source code", + "tryInferAppIdFromCode": "尝试从源代码推断应用 ID", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" From 7877a14f07e20cde93f883346b1b0f4d31640e18 Mon Sep 17 00:00:00 2001 From: 1xFF <100185670+1xFF@users.noreply.github.com> Date: Sat, 8 Jul 2023 21:02:46 -0700 Subject: [PATCH 250/600] Use onlyIfExists flag --- lib/providers/apps_provider.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 9ff770c..5054ce2 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -787,8 +787,10 @@ class AppsProvider with ChangeNotifier { if (attemptToCorrectInstallStatus) { app = getCorrectedInstallStatusAppIfPossible(app, info) ?? app; } - File('${(await getAppsDir()).path}/${app.id}.json') - .writeAsStringSync(jsonEncode(app.toJson())); + if (!onlyIfExists || this.apps.containsKey(app.id)) { + File('${(await getAppsDir()).path}/${app.id}.json') + .writeAsStringSync(jsonEncode(app.toJson())); + } try { this.apps.update( app.id, (value) => AppInMemory(app, value.downloadProgress, info), @@ -902,7 +904,7 @@ class AppsProvider with ChangeNotifier { if (currentApp.preferredApkIndex < newApp.apkUrls.length) { newApp.preferredApkIndex = currentApp.preferredApkIndex; } - if (apps.containsKey(appId)) await saveApps([newApp]); + await saveApps([newApp]); return newApp.latestVersion != currentApp.latestVersion ? newApp : null; } From 60ad3199ca4a634f4ecb1b1585d7e808bfc75c71 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 9 Jul 2023 01:02:43 -0400 Subject: [PATCH 251/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 48 ++++++++++++++++++++++++------------------------ pubspec.yaml | 4 ++-- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index ae1ccf6..bbbe37d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.13'; +const String currentVersion = '0.13.14'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index d4ccccd..9f6cc31 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -174,10 +174,10 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: "74dff1435a695887ca64899b8990004f8d1232b0e84bfc4faa1fdda7c6f57cc1" + sha256: de4798a7069121aee12d5895315680258415de9b00e717723a1bd73d58f0126d url: "https://pub.dev" source: hosted - version: "1.6.5" + version: "1.6.6" easy_localization: dependency: "direct main" description: @@ -267,10 +267,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "812791d43ccfc1b443a0d39fa02a206fc228c597e28ff9337e09e3ca8d370391" + sha256: "3cc40fe8c50ab8383f3e053a499f00f975636622ecdc8e20a77418ece3b1e975" url: "https://pub.dev" source: hosted - version: "14.1.1" + version: "15.1.0+1" flutter_local_notifications_linux: dependency: transitive description: @@ -296,10 +296,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: "9e0202b5339cd88ac0f109abae8502681bfab0b13a8e02a0e7158124610b5d98" + sha256: "4b1bfbb802d76320a1a46d9ce984106135093efd9d969765d07c2125af107bdf" url: "https://pub.dev" source: hosted - version: "0.6.15+1" + version: "0.6.17" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -522,10 +522,10 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "37fcc3c3182ac0bf8856f3e973e11c7bef5556d69f1a0d8fb908f51019c2912d" + sha256: "415af30ba76a84faccfe1eb251fe1e4fdc790f876924c65ad7d6ed7a1404bcd6" url: "https://pub.dev" source: hosted - version: "10.4.1" + version: "10.4.2" permission_handler_android: dependency: transitive description: @@ -538,18 +538,18 @@ packages: dependency: transitive description: name: permission_handler_apple - sha256: "0d1f8007b17573ff1fbeae0f04b6c8e83e1d2f6c4fe8e8226d4d2456aa8ecffe" + sha256: "7a187b671a39919462af2b5e813148365b71a615979165a119868d667fe90c03" url: "https://pub.dev" source: hosted - version: "9.1.2" + version: "9.1.3" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: "79b36d93a41a4aecfd0d635d77552f327cb84227c718ce5e68b5f7b85546fe7e" + sha256: "463a07cb7cc6c758a7a1c7da36ce666bb80a0b4b5e92df0fa36872e0ed456993" url: "https://pub.dev" source: hosted - version: "3.11.0+1" + version: "3.11.1" permission_handler_windows: dependency: transitive description: @@ -642,10 +642,10 @@ packages: dependency: transitive description: name: shared_preferences_foundation - sha256: "0dc5c49ad8a05ed358b991b60c7b0ba1a14e16dae58af9b420d6b9e82dc024ab" + sha256: b046999bf0ff58f04c364491bb803dcfa8f42e47b19c75478f53d323684a8cc1 url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" shared_preferences_linux: dependency: transitive description: @@ -775,10 +775,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 + sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e" url: "https://pub.dev" source: hosted - version: "6.1.11" + version: "6.1.12" url_launcher_android: dependency: transitive description: @@ -823,18 +823,18 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "6bb1e5d7fe53daf02a8fee85352432a40b1f868a81880e99ec7440113d5cfcab" + sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4 url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.0.18" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771" + sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422" url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.7" uuid: dependency: transitive description: @@ -863,10 +863,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "69787707339e7588aad256386475c18223cc0da87d9812343bc27c33c01eeab4" + sha256: "1c93e96f3069bacdc734fad6b7e1d3a480fd516a3ae5b8858becf7f07515a2f3" url: "https://pub.dev" source: hosted - version: "3.8.1" + version: "3.8.2" webview_flutter_platform_interface: dependency: transitive description: @@ -879,10 +879,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "7b203961d6830f3e5ed1df4c4f0493fea8388a46c4d43716167c4a8ba8ecbe83" + sha256: a8d7e8b4be2a79e83b70235369971ec97d14df4cdbb40d305a8eeae67d8e6432 url: "https://pub.dev" source: hosted - version: "3.6.0" + version: "3.6.2" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 1abf315..2c02964 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.13.13+177 # When changing this, update the tag in main() accordingly +version: 0.13.14+178 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' @@ -38,7 +38,7 @@ dependencies: cupertino_icons: ^1.0.5 path_provider: ^2.0.11 flutter_fgbg: ^0.2.0 # Try removing reliance on this - flutter_local_notifications: ^14.0.0+1 + flutter_local_notifications: ^15.1.0+1 provider: ^6.0.3 http: ^1.0.0 webview_flutter: ^4.0.0 From 3ec33a1c778c56dcbae28dfe6cc4190be85e8e38 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 14 Jul 2023 21:09:20 -0400 Subject: [PATCH 252/600] Add auto-remove option (#656) + on-foreground bugfix --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/main.dart | 4 ++-- lib/pages/settings.dart | 16 +++++++++++++ lib/providers/apps_provider.dart | 36 +++++++++++++++++++++------- lib/providers/settings_provider.dart | 9 +++++++ 15 files changed, 65 insertions(+), 11 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index f68da68..87ecd2d 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -234,6 +234,7 @@ "requiresCredentialsInSettings": "Benötigt zusätzliche Anmeldedaten (in den Einstellungen)", "checkOnStart": "Überprüfe einmalig beim Start", "tryInferAppIdFromCode": "Try inferring App ID from source code", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index e9b4503..8bed92b 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -234,6 +234,7 @@ "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "checkOnStart": "Check Once on Start", "tryInferAppIdFromCode": "Try inferring App ID from source code", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 6c7cc05..3f05649 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -234,6 +234,7 @@ "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "checkOnStart": "Check Once on Start", "tryInferAppIdFromCode": "Try inferring App ID from source code", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 555868d..1673f7b 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -234,6 +234,7 @@ "requiresCredentialsInSettings": "این به اعتبارنامه های اضافی نیاز دارد (در تنظیمات)", "checkOnStart": "بررسی در شروع", "tryInferAppIdFromCode": "شناسه برنامه را از کد منبع استنباط کنید", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index ea60088..6a804b6 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -234,6 +234,7 @@ "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "checkOnStart": "Check Once on Start", "tryInferAppIdFromCode": "Try inferring App ID from source code", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index b0b553c..c6ebc55 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -233,6 +233,7 @@ "requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)", "checkOnStart": "Egyszer az indításkor", "tryInferAppIdFromCode": "Próbálja kikövetkeztetni az app azonosítót a forráskódból", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "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 4d4d925..c06180b 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -234,6 +234,7 @@ "requiresCredentialsInSettings": "Servono credenziali aggiuntive (in Impostazioni)", "checkOnStart": "Controlla una volta all'avvio", "tryInferAppIdFromCode": "Prova a dedurre l'ID dell'app dal codice sorgente", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index c0d9c22..270e3a2 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -234,6 +234,7 @@ "requiresCredentialsInSettings": "これには追加の認証が必要です (設定にて)", "checkOnStart": "Check Once on Start", "tryInferAppIdFromCode": "Try inferring App ID from source code", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index f1b5274..2837709 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -238,6 +238,7 @@ "requiresCredentialsInSettings": "Wymaga to dodatkowych poświadczeń (w Ustawieniach)", "checkOnStart": "Sprawdź raz przy starcie", "tryInferAppIdFromCode": "Spróbuj wywnioskować identyfikator aplikacji z kodu źródłowego", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index ce91304..d036167 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -234,6 +234,7 @@ "requiresCredentialsInSettings": "Для этого требуются дополнительные учетные данные (в настройках)", "checkOnStart": "Проверить один раз при запуске", "tryInferAppIdFromCode": "Попытаться определить ID приложения из исходного кода", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 9e0bbdb..81179e9 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -234,6 +234,7 @@ "requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)", "checkOnStart": "启动时进行一次检查", "tryInferAppIdFromCode": "尝试从源代码推断应用 ID", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/main.dart b/lib/main.dart index bbbe37d..dbcf44d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -226,9 +226,9 @@ class _ObtainiumState extends State { if (!supportedLocales .map((e) => e.key.languageCode) .contains(context.locale.languageCode) || - settingsProvider.forcedLocale == null && + (settingsProvider.forcedLocale == null && context.deviceLocale.languageCode != - context.locale.languageCode) { + context.locale.languageCode)) { settingsProvider.resetLocaleSafe(context); } // Register the background update task according to the user's setting diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 7827111..7135a25 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -322,6 +322,22 @@ class _SettingsPageState extends State { ], ), height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: + Text(tr('removeOnExternalUninstall'))), + Switch( + value: settingsProvider + .removeOnExternalUninstall, + onChanged: (value) { + settingsProvider + .removeOnExternalUninstall = value; + }) + ], + ), + height16, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index ff77731..b1da1b2 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -335,19 +335,21 @@ class AppsProvider with ChangeNotifier { } Future unzipFile(String filePath, String destinationPath) async { - await ZipFile.extractToDirectory(zipFile: File(filePath), destinationDir: Directory(destinationPath)); + await ZipFile.extractToDirectory( + zipFile: File(filePath), destinationDir: Directory(destinationPath)); } Future installXApkDir(DownloadedXApkDir dir, {bool silent = false}) async { try { var somethingInstalled = false; - for (var file in dir.extracted.listSync(recursive: true, followLinks: false).whereType()) { + for (var file in dir.extracted + .listSync(recursive: true, followLinks: false) + .whereType()) { if (file.path.toLowerCase().endsWith('.apk')) { somethingInstalled = somethingInstalled || await installApk(DownloadedApk(dir.appId, file), silent: silent); - } - else if (file.path.toLowerCase().endsWith('.obb')) { + } else if (file.path.toLowerCase().endsWith('.obb')) { await moveObbFile(file, dir.appId); } } @@ -389,7 +391,7 @@ class AppsProvider with ChangeNotifier { } Future moveObbFile(File file, String appId) async { - if(!file.path.toLowerCase().endsWith('.obb')) return; + if (!file.path.toLowerCase().endsWith('.obb')) return; // TODO: Does not support Android 11+ if ((await DeviceInfoPlugin().androidInfo).version.sdkInt <= 29) { @@ -754,21 +756,37 @@ class AppsProvider with ChangeNotifier { } loadingApps = false; notifyListeners(); - refreshInstallStatuses(); + + refreshInstallStatuses(useExistingInstalledInfo: true); } - Future refreshInstallStatuses() async { + Future refreshInstallStatuses( + {bool useExistingInstalledInfo = false}) async { if (await doesInstalledAppsPluginWork()) { List modifiedApps = []; for (var app in apps.values) { - var moddedApp = - getCorrectedInstallStatusAppIfPossible(app.app, app.installedInfo); + var moddedApp = getCorrectedInstallStatusAppIfPossible( + app.app, + useExistingInstalledInfo + ? app.installedInfo + : await getInstalledInfo(app.app.id)); if (moddedApp != null) { modifiedApps.add(moddedApp); } } if (modifiedApps.isNotEmpty) { await saveApps(modifiedApps, attemptToCorrectInstallStatus: false); + var removedAppIds = modifiedApps + .where((a) => a.installedVersion == null) + .map((e) => e.id) + .toList(); + if (removedAppIds.isNotEmpty) { + var settingsProvider = SettingsProvider(); + await settingsProvider.initializeSettings(); + if (settingsProvider.removeOnExternalUninstall) { + await removeApps(removedAppIds); + } + } } } } diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 8ddfdf2..2319a6d 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -273,4 +273,13 @@ class SettingsProvider with ChangeNotifier { context.deleteSaveLocale(); } } + + bool get removeOnExternalUninstall { + return prefs?.getBool('removeOnExternalUninstall') ?? false; + } + + set removeOnExternalUninstall(bool show) { + prefs?.setBool('removeOnExternalUninstall', show); + notifyListeners(); + } } From 41d9edcf83f218c99581a16ddff14dd6de846c33 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 14 Jul 2023 21:36:42 -0400 Subject: [PATCH 253/600] Auto-select version code for F-Droid Third-Party Repos (#658) --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/fdroidrepo.dart | 16 +++++++++++++++- 12 files changed, 26 insertions(+), 1 deletion(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 87ecd2d..06c1337 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -235,6 +235,7 @@ "checkOnStart": "Überprüfe einmalig beim Start", "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 8bed92b..e06e460 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -235,6 +235,7 @@ "checkOnStart": "Check Once on Start", "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 3f05649..4e53acc 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -235,6 +235,7 @@ "checkOnStart": "Check Once on Start", "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 1673f7b..0f3c621 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -235,6 +235,7 @@ "checkOnStart": "بررسی در شروع", "tryInferAppIdFromCode": "شناسه برنامه را از کد منبع استنباط کنید", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 6a804b6..315f3d4 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -235,6 +235,7 @@ "checkOnStart": "Check Once on Start", "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index c6ebc55..9927e40 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -234,6 +234,7 @@ "checkOnStart": "Egyszer az indításkor", "tryInferAppIdFromCode": "Próbálja kikövetkeztetni az app azonosítót a forráskódból", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", "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 c06180b..6450895 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -235,6 +235,7 @@ "checkOnStart": "Controlla una volta all'avvio", "tryInferAppIdFromCode": "Prova a dedurre l'ID dell'app dal codice sorgente", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 270e3a2..00f4412 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -235,6 +235,7 @@ "checkOnStart": "Check Once on Start", "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 2837709..0885008 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -239,6 +239,7 @@ "checkOnStart": "Sprawdź raz przy starcie", "tryInferAppIdFromCode": "Spróbuj wywnioskować identyfikator aplikacji z kodu źródłowego", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index d036167..2e8da04 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -235,6 +235,7 @@ "checkOnStart": "Проверить один раз при запуске", "tryInferAppIdFromCode": "Попытаться определить ID приложения из исходного кода", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 81179e9..0439230 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -235,6 +235,7 @@ "checkOnStart": "启动时进行一次检查", "tryInferAppIdFromCode": "尝试从源代码推断应用 ID", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index 9bf2931..31f8435 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -14,6 +14,10 @@ class FDroidRepo extends AppSource { label: tr('appIdOrName'), hint: tr('reposHaveMultipleApps'), required: true) + ], + [ + GeneratedFormSwitch('pickHighestVersionCode', + label: tr('pickHighestVersionCode'), defaultValue: false) ] ]; } @@ -24,6 +28,7 @@ class FDroidRepo extends AppSource { Map additionalSettings, ) async { String? appIdOrName = additionalSettings['appIdOrName']; + bool pickHighestVersionCode = additionalSettings['pickHighestVersionCode']; if (appIdOrName == null) { throw NoReleasesError(); } @@ -62,10 +67,19 @@ class FDroidRepo extends AppSource { if (latestVersion == null) { throw NoVersionError(); } - List apkUrls = releases + var latestVersionReleases = releases .where((element) => element.querySelector('version')?.innerHtml == latestVersion && element.querySelector('apkname') != null) + .toList(); + if (latestVersionReleases.length > 1 && pickHighestVersionCode) { + latestVersionReleases.sort((e1, e2) { + return int.parse(e2.querySelector('versioncode')!.innerHtml) + .compareTo(int.parse(e1.querySelector('versioncode')!.innerHtml)); + }); + latestVersionReleases = [latestVersionReleases[0]]; + } + List apkUrls = latestVersionReleases .map((e) => '$standardUrl/${e.querySelector('apkname')!.innerHtml}') .toList(); return APKDetails(latestVersion, getApkUrlsFromUrls(apkUrls), From 2a58ee87293b1a7f971501d6f286ecf383e85831 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 14 Jul 2023 21:53:50 -0400 Subject: [PATCH 254/600] Toggle to disable update check on detail page (#659), string capitalization consistency --- assets/translations/de.json | 1 + assets/translations/en.json | 15 ++++++++------- assets/translations/es.json | 5 +++-- assets/translations/fa.json | 1 + assets/translations/fr.json | 9 +++++---- assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 3 ++- assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/pages/app.dart | 5 ++++- lib/pages/settings.dart | 15 +++++++++++++++ lib/providers/settings_provider.dart | 9 +++++++++ 14 files changed, 53 insertions(+), 15 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 06c1337..0386135 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -236,6 +236,7 @@ "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index e06e460..15e46dc 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -121,7 +121,7 @@ "followSystem": "Follow System", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use Pure Black Dark Theme", + "useBlackTheme": "Use pure black dark theme", "appSortBy": "App Sort By", "authorName": "Author/Name", "nameAuthor": "Name/Author", @@ -132,8 +132,8 @@ "bgUpdateCheckInterval": "Background Update Checking Interval", "neverManualOnly": "Never - Manual Only", "appearance": "Appearance", - "showWebInAppView": "Show Source Webpage in App View", - "pinUpdates": "Pin Updates to Top of Apps View", + "showWebInAppView": "Show Source webpage in App view", + "pinUpdates": "Pin updates to top of Apps view", "updates": "Updates", "sourceSpecific": "Source-Specific", "appSource": "App Source", @@ -226,16 +226,17 @@ "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", - "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "dontShowTrackOnlyWarnings": "Don't show 'Track-Only' warnings", + "dontShowAPKOriginWarnings": "Don't show APK origin warnings", + "moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view", "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", - "checkOnStart": "Check Once on Start", + "checkOnStart": "Check for updates on startup", "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 4e53acc..1e557ab 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -228,14 +228,15 @@ "dontShowAgain": "No mostrar de nuevo", "dontShowTrackOnlyWarnings": "No mostrar avisos de 'Solo Seguimiento'", "dontShowAPKOriginWarnings": "No mostrar avisos de las fuentes de las APks", - "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view", "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", - "checkOnStart": "Check Once on Start", + "checkOnStart": "Check for updates on startup", "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 0f3c621..476b80a 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -236,6 +236,7 @@ "tryInferAppIdFromCode": "شناسه برنامه را از کد منبع استنباط کنید", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 315f3d4..42a3c2d 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -121,7 +121,7 @@ "followSystem": "Suivre le système", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use Pure Black Dark Theme", + "useBlackTheme": "Use pure black dark theme", "appSortBy": "Applications triées par", "authorName": "Auteur/Nom", "nameAuthor": "Nom/Auteur", @@ -227,15 +227,16 @@ "overrideSource": "Override Source", "dontShowAgain": "Don't show this again", "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", - "dontShowAPKOriginWarnings": "Don't Show APK Origin Warnings", - "moveNonInstalledAppsToBottom": "Move Non-Installed Apps to Bottom of Apps View", + "dontShowAPKOriginWarnings": "Don't show APK origin warnings", + "moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view", "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", - "checkOnStart": "Check Once on Start", + "checkOnStart": "Check for updates on startup", "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 9927e40..787b05a 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -235,6 +235,7 @@ "tryInferAppIdFromCode": "Próbálja kikövetkeztetni az app azonosítót a forráskódból", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "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 6450895..1bed996 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -236,6 +236,7 @@ "tryInferAppIdFromCode": "Prova a dedurre l'ID dell'app dal codice sorgente", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 00f4412..0892ecc 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -232,10 +232,11 @@ "gitlabPATLabel": "GitLab パーソナルアクセストークン (検索を有効化する)", "about": "概要", "requiresCredentialsInSettings": "これには追加の認証が必要です (設定にて)", - "checkOnStart": "Check Once on Start", + "checkOnStart": "Check for updates on startup", "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 0885008..241af7e 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -240,6 +240,7 @@ "tryInferAppIdFromCode": "Spróbuj wywnioskować identyfikator aplikacji z kodu źródłowego", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 2e8da04..b20fedd 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -236,6 +236,7 @@ "tryInferAppIdFromCode": "Попытаться определить ID приложения из исходного кода", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 0439230..49da8bc 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -236,6 +236,7 @@ "tryInferAppIdFromCode": "尝试从源代码推断应用 ID", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 75aa675..2ba6a96 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -44,7 +44,10 @@ class _AppPageState extends State { ? sourceProvider.getSource(app.app.url, overrideSource: app.app.overrideSource) : null; - if (!areDownloadsRunning && prevApp == null && app != null) { + if (!areDownloadsRunning && + prevApp == null && + app != null && + settingsProvider.checkUpdateOnDetailPage) { prevApp = app; getUpdate(app.app.id); } diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 7135a25..c63d2e8 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -240,6 +240,21 @@ class _SettingsPageState extends State { }) ], ), + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text(tr('checkUpdateOnDetailPage'))), + Switch( + value: settingsProvider + .checkUpdateOnDetailPage, + onChanged: (value) { + settingsProvider.checkUpdateOnDetailPage = + value; + }) + ], + ), height32, Text( tr('sourceSpecific'), diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 2319a6d..9fcfba0 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -282,4 +282,13 @@ class SettingsProvider with ChangeNotifier { prefs?.setBool('removeOnExternalUninstall', show); notifyListeners(); } + + bool get checkUpdateOnDetailPage { + return prefs?.getBool('checkUpdateOnDetailPage') ?? true; + } + + set checkUpdateOnDetailPage(bool show) { + prefs?.setBool('checkUpdateOnDetailPage', show); + notifyListeners(); + } } From 6b29a0f0f367be6ce2c9e9b6c77ebc7c37e8bcf2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 14 Jul 2023 21:56:57 -0400 Subject: [PATCH 255/600] Update Packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 56 ++++++++++++++++++++++----------------------------- pubspec.yaml | 2 +- 3 files changed, 26 insertions(+), 34 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index dbcf44d..db60abe 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.14'; +const String currentVersion = '0.13.15'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 9f6cc31..8d10c85 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -402,10 +402,10 @@ packages: dependency: transitive description: name: markdown - sha256: "8e332924094383133cee218b676871f42db2514f1f6ac617b6cf6152a7faab8e" + sha256: acf35edccc0463a9d7384e437c015a3535772e09714cf60e07eeef3a15870dcd url: "https://pub.dev" source: hosted - version: "7.1.0" + version: "7.1.1" matcher: dependency: transitive description: @@ -490,10 +490,10 @@ packages: dependency: transitive description: name: path_provider_foundation - sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3" + sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.2.4" path_provider_linux: dependency: transitive description: @@ -522,34 +522,34 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "415af30ba76a84faccfe1eb251fe1e4fdc790f876924c65ad7d6ed7a1404bcd6" + sha256: "63e5216aae014a72fe9579ccd027323395ce7a98271d9defa9d57320d001af81" url: "https://pub.dev" source: hosted - version: "10.4.2" + version: "10.4.3" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "3b61f3da3b1c83bc3fb6a2b431e8dab01d0e5b45f6a3d9c7609770ec88b2a89e" + sha256: c0c9754479a4c4b1c1f3862ddc11930c9b3f03bef2816bb4ea6eed1e13551d6f url: "https://pub.dev" source: hosted - version: "10.3.0" + version: "10.3.2" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: "7a187b671a39919462af2b5e813148365b71a615979165a119868d667fe90c03" + sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" url: "https://pub.dev" source: hosted - version: "9.1.3" + version: "9.1.4" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: "463a07cb7cc6c758a7a1c7da36ce666bb80a0b4b5e92df0fa36872e0ed456993" + sha256: "7c6b1500385dd1d2ca61bb89e2488ca178e274a69144d26bbd65e33eae7c02a9" url: "https://pub.dev" source: hosted - version: "3.11.1" + version: "3.11.3" permission_handler_windows: dependency: transitive description: @@ -590,14 +590,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.7.3" - process: - dependency: transitive - description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" - url: "https://pub.dev" - source: hosted - version: "4.2.4" provider: dependency: "direct main" description: @@ -642,10 +634,10 @@ packages: dependency: transitive description: name: shared_preferences_foundation - sha256: b046999bf0ff58f04c364491bb803dcfa8f42e47b19c75478f53d323684a8cc1 + sha256: f39696b83e844923b642ce9dd4bd31736c17e697f6731a5adf445b1274cf3cd4 url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" shared_preferences_linux: dependency: transitive description: @@ -807,10 +799,10 @@ packages: dependency: transitive description: name: url_launcher_macos - sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" + sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1" url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" url_launcher_platform_interface: dependency: transitive description: @@ -863,26 +855,26 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "1c93e96f3069bacdc734fad6b7e1d3a480fd516a3ae5b8858becf7f07515a2f3" + sha256: "27ad6a99c4b2d5e1ffd2b993a10f738b6b4979f139b4d64c34ac511595fcd748" url: "https://pub.dev" source: hosted - version: "3.8.2" + version: "3.9.0" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "656e2aeaef318900fffd21468b6ddc7958c7092a642f0e7220bac328b70d4a81" + sha256: "564ef378cafc1a0e29f1d76ce175ef517a0a6115875dff7b43fccbef2b0aeb30" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.4.0" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - sha256: a8d7e8b4be2a79e83b70235369971ec97d14df4cdbb40d305a8eeae67d8e6432 + sha256: "369fdf6160944a7db660ff15fa048c2bd681b09557907beaef1f95e8557d21dc" url: "https://pub.dev" source: hosted - version: "3.6.2" + version: "3.7.0" win32: dependency: transitive description: @@ -903,10 +895,10 @@ packages: dependency: transitive description: name: xdg_directories - sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.1" xml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2c02964..37e0533 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.13.14+178 # When changing this, update the tag in main() accordingly +version: 0.13.15+179 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 814ff2c2e5e50656e1bb3cf338227e01a9e29cf5 Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Sat, 15 Jul 2023 06:32:08 +0300 Subject: [PATCH 256/600] Update ru.json fix and update --- assets/translations/ru.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index b20fedd..2c34499 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -7,7 +7,7 @@ "appIdMismatch": "ID загруженного пакета не совпадает с существующим ID приложения", "functionNotImplemented": "Этот класс не реализовал эту функцию", "placeholder": "Заполнитель", - "someErrors": "Произошли некоторые ошибки", + "someErrors": "Возникли некоторые ошибки", "unexpectedError": "Неожиданная ошибка", "ok": "Окей", "and": "и", @@ -121,7 +121,7 @@ "followSystem": "Следовать системе", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Использовать темную тему", + "useBlackTheme": "Использовать чёрную тему", "appSortBy": "Сортировка приложений по", "authorName": "Автор/Название", "nameAuthor": "Название/Автор", @@ -132,7 +132,7 @@ "bgUpdateCheckInterval": "Интервал проверки обновлений в фоновом режиме", "neverManualOnly": "Никогда - Только вручную", "appearance": "Внешний вид", - "showWebInAppView": "Показывать веб-страницу источника в представлении приложения", + "showWebInAppView": "Показывать исходную веб-страницу в представлении приложения", "pinUpdates": "Закрепить обновления сверху списка приложений", "updates": "Обновления", "sourceSpecific": "Специфика источника", @@ -232,11 +232,11 @@ "gitlabPATLabel": "Персональный токен доступа GitLab (Включает поиск)", "about": "О приложении", "requiresCredentialsInSettings": "Для этого требуются дополнительные учетные данные (в настройках)", - "checkOnStart": "Проверить один раз при запуске", + "checkOnStart": "Проверять наличие обновлений при запуске", "tryInferAppIdFromCode": "Попытаться определить ID приложения из исходного кода", - "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", - "pickHighestVersionCode": "Auto-select highest version code APK", - "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "removeOnExternalUninstall": "Автоматически удалять удаленные извне приложения", + "pickHighestVersionCode": "Автовыбор кода наивысшей версии APK", + "checkUpdateOnDetailPage": "Проверять наличие обновлений при открытии страницы представления приложения", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" @@ -278,11 +278,11 @@ "other": "Очищено {n} журналов (до = {before}, после = {after})" }, "xAndNMoreUpdatesAvailable": { - "one": "У {} и еще 1 приложения есть обновления.", - "other": "{} and {} more apps have updates." + "one": "У {} и еще 1 приложения есть обновление.", + "other": "У {} и ещё {} приложений есть обновления." }, "xAndNMoreUpdatesInstalled": { - "one": "{} and 1 more app were updated.", - "other": "У {} и еще {} приложений есть обновления." + "one": "{} и еще 1 приложение были обновлены.", + "other": "{} и еще {} приложений были обновлены." } } From 360591ebb9ea403ef2cb9018c5b3f499ad48f6ad Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 14 Jul 2023 23:53:28 -0400 Subject: [PATCH 257/600] Add better GitLab APK discover when API key set (#3) --- assets/translations/de.json | 2 +- assets/translations/en.json | 2 +- assets/translations/es.json | 2 +- assets/translations/fa.json | 2 +- assets/translations/fr.json | 2 +- assets/translations/hu.json | 2 +- assets/translations/it.json | 2 +- assets/translations/ja.json | 2 +- assets/translations/pl.json | 2 +- assets/translations/ru.json | 2 +- assets/translations/zh.json | 2 +- lib/app_sources/gitlab.dart | 71 ++++++++++++++++++++++++++++--------- lib/main.dart | 2 +- pubspec.yaml | 2 +- 14 files changed, 68 insertions(+), 29 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 0386135..7e0b4a6 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "Warnung für 'Nur Nachverfolgen' nicht anzeigen", "dontShowAPKOriginWarnings": "Warnung für APK-Herkunft nicht anzeigen", "moveNonInstalledAppsToBottom": "Nicht installierte Apps ans Ende der Apps Ansicht verschieben", - "gitlabPATLabel": "GitLab Personal Access Token (Aktiviert Suche)", + "gitlabPATLabel": "GitLab Personal Access Token\n(Aktiviert Suche and Better APK Discovery)", "about": "Über", "requiresCredentialsInSettings": "Benötigt zusätzliche Anmeldedaten (in den Einstellungen)", "checkOnStart": "Überprüfe einmalig beim Start", diff --git a/assets/translations/en.json b/assets/translations/en.json index 15e46dc..cb9bf5d 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "Don't show 'Track-Only' warnings", "dontShowAPKOriginWarnings": "Don't show APK origin warnings", "moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view", - "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "checkOnStart": "Check for updates on startup", diff --git a/assets/translations/es.json b/assets/translations/es.json index 1e557ab..8e31c7c 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "No mostrar avisos de 'Solo Seguimiento'", "dontShowAPKOriginWarnings": "No mostrar avisos de las fuentes de las APks", "moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view", - "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "checkOnStart": "Check for updates on startup", diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 476b80a..393d0c7 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "هشدار 'فقط ردیابی' را نشان ندهید", "dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید", "moveNonInstalledAppsToBottom": "برنامه های نصب نشده را به نمای پایین برنامه ها منتقل کنید", - "gitlabPATLabel": "رمز دسترسی شخصی GitLab (جستجو را فعال می کند)", + "gitlabPATLabel": "رمز دسترسی شخصی GitLab\n(جستجو را فعال می کند and Better APK Discovery)", "about": "درباره", "requiresCredentialsInSettings": "این به اعتبارنامه های اضافی نیاز دارد (در تنظیمات)", "checkOnStart": "بررسی در شروع", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 42a3c2d..b403c1f 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning", "dontShowAPKOriginWarnings": "Don't show APK origin warnings", "moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view", - "gitlabPATLabel": "GitLab Personal Access Token (Enables Search)", + "gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)", "about": "About", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", "checkOnStart": "Check for updates on startup", diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 787b05a..69b8ab6 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -228,7 +228,7 @@ "dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést", "dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket", "moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára", - "gitlabPATLabel": "GitLab Personal Access Token (Engedélyezi a Keresést)", + "gitlabPATLabel": "GitLab Personal Access Token\n(Engedélyezi a Keresést and Better APK Discovery)", "about": "Rólunk", "requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)", "checkOnStart": "Egyszer az indításkor", diff --git a/assets/translations/it.json b/assets/translations/it.json index 1bed996..8010b37 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "Non mostrare gli avvisi 'Solo-Monitoraggio'", "dontShowAPKOriginWarnings": "Non mostrare gli avvisi di origine dell'APK", "moveNonInstalledAppsToBottom": "Sposta le app non installate in fondo alla lista", - "gitlabPATLabel": "GitLab Personal Access Token (attiva la ricerca)", + "gitlabPATLabel": "GitLab Personal Access Token\n(attiva la ricerca and Better APK Discovery)", "about": "Informazioni", "requiresCredentialsInSettings": "Servono credenziali aggiuntive (in Impostazioni)", "checkOnStart": "Controlla una volta all'avvio", diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 0892ecc..e53c79c 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "「追跡のみ」の警告を表示しない", "dontShowAPKOriginWarnings": "APK Originの警告を表示しない", "moveNonInstalledAppsToBottom": "未インストールのアプリをアプリ一覧の下部に移動させる", - "gitlabPATLabel": "GitLab パーソナルアクセストークン (検索を有効化する)", + "gitlabPATLabel": "GitLab パーソナルアクセストークン\n(検索を有効化する and Better APK Discovery)", "about": "概要", "requiresCredentialsInSettings": "これには追加の認証が必要です (設定にて)", "checkOnStart": "Check for updates on startup", diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 241af7e..59ae37a 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -233,7 +233,7 @@ "dontShowTrackOnlyWarnings": "Nie wyświetlaj ostrzeżeń „Tylko obserwowana”", "dontShowAPKOriginWarnings": "Nie pokazuj ostrzeżeń o pochodzeniu APK", "moveNonInstalledAppsToBottom": "Przenieś niezainstalowane aplikacje na dół widoku aplikacji", - "gitlabPATLabel": "Osobisty Token Dostępu GitLab (umożliwia wyszukiwanie)", + "gitlabPATLabel": "Osobisty Token Dostępu GitLab\n(umożliwia wyszukiwanie and Better APK Discovery)", "about": "Więcej informacji", "requiresCredentialsInSettings": "Wymaga to dodatkowych poświadczeń (w Ustawieniach)", "checkOnStart": "Sprawdź raz przy starcie", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index b20fedd..5697c68 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "Не показывать предупреждения о только отслеживаемых приложениях", "dontShowAPKOriginWarnings": "Не показывать предупреждения об источнике APK-файлов", "moveNonInstalledAppsToBottom": "Переместить неустановленные приложения вниз списка", - "gitlabPATLabel": "Персональный токен доступа GitLab (Включает поиск)", + "gitlabPATLabel": "Персональный токен доступа GitLab\n(Включает поиск and Better APK Discovery)", "about": "О приложении", "requiresCredentialsInSettings": "Для этого требуются дополнительные учетные данные (в настройках)", "checkOnStart": "Проверить один раз при запуске", diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 49da8bc..f72eb31 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "不显示“仅追踪”模式警告", "dontShowAPKOriginWarnings": "不显示 APK 文件来源警告", "moveNonInstalledAppsToBottom": "将未安装应用置底", - "gitlabPATLabel": "GitLab 个人访问令牌(用于搜索应用)", + "gitlabPATLabel": "GitLab 个人访问令牌\n(用于搜索应用 and Better APK Discovery)", "about": "相关文档", "requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)", "checkOnStart": "启动时进行一次检查", diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index c6d8a63..574e814 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -102,11 +102,53 @@ class GitLab extends AppSource { ) async { bool fallbackToOlderReleases = additionalSettings['fallbackToOlderReleases'] == true; - Response res = await sourceRequest('$standardUrl/-/tags?format=atom'); - if (res.statusCode == 200) { + String? PAT = await getPATIfAny(); + Iterable apkDetailsList = []; + if (PAT != null) { + var names = GitHub().getAppNames(standardUrl); + Response res = await sourceRequest( + 'https://$host/api/v4/projects/${names.author}%2F${names.name}/releases?private_token=$PAT'); + if (res.statusCode != 200) { + throw getObtainiumHttpError(res); + } + var json = jsonDecode(res.body) as List; + apkDetailsList = json.map((e) { + var apkUrlsFromAssets = (e['assets']?['links'] as List? ?? []) + .map((e) { + return (e['direct_asset_url'] ?? e['url'] ?? '') as String; + }) + .where((s) => s.isNotEmpty) + .toList(); + List uploadedAPKsFromDescription = + ((e['description'] ?? '') as String) + .split('](') + .join('\n') + .split('.apk)') + .join('.apk\n') + .split('\n') + .where((s) => s.startsWith('/uploads/') && s.endsWith('apk')) + .map((s) => '$standardUrl$s') + .toList(); + var apkUrlsSet = apkUrlsFromAssets.toSet(); + apkUrlsSet.addAll(uploadedAPKsFromDescription); + var releaseDateString = e['released_at'] ?? e['created_at']; + DateTime? releaseDate = releaseDateString != null + ? DateTime.parse(releaseDateString) + : null; + return APKDetails( + e['tag_name'] ?? e['name'], + getApkUrlsFromUrls(apkUrlsSet.toList()), + GitHub().getAppNames(standardUrl), + releaseDate: releaseDate); + }); + } else { + Response res = await sourceRequest('$standardUrl/-/tags?format=atom'); + if (res.statusCode != 200) { + throw getObtainiumHttpError(res); + } var standardUri = Uri.parse(standardUrl); var parsedHtml = parse(res.body); - var apkDetailsList = parsedHtml.querySelectorAll('entry').map((entry) { + apkDetailsList = parsedHtml.querySelectorAll('entry').map((entry) { var entryContent = parse( parseFragment(entry.querySelector('content')!.innerHtml).text); var apkUrls = [ @@ -124,7 +166,6 @@ class GitLab extends AppSource { .where((element) => Uri.parse(element).host != '') .toList() ]; - var entryId = entry.querySelector('id')?.innerHtml; var version = entryId == null ? null : Uri.parse(entryId).pathSegments.last; @@ -139,21 +180,19 @@ class GitLab extends AppSource { GitHub().getAppNames(standardUrl), releaseDate: releaseDate); }); + } + if (apkDetailsList.isEmpty) { + throw NoReleasesError(); + } + if (fallbackToOlderReleases) { + if (additionalSettings['trackOnly'] != true) { + apkDetailsList = + apkDetailsList.where((e) => e.apkUrls.isNotEmpty).toList(); + } if (apkDetailsList.isEmpty) { throw NoReleasesError(); } - if (fallbackToOlderReleases) { - if (additionalSettings['trackOnly'] != true) { - apkDetailsList = - apkDetailsList.where((e) => e.apkUrls.isNotEmpty).toList(); - } - if (apkDetailsList.isEmpty) { - throw NoReleasesError(); - } - } - return apkDetailsList.first; - } else { - throw getObtainiumHttpError(res); } + return apkDetailsList.first; } } diff --git a/lib/main.dart b/lib/main.dart index db60abe..51e56f0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.15'; +const String currentVersion = '0.13.16'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 37e0533..06fd3fb 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.13.15+179 # When changing this, update the tag in main() accordingly +version: 0.13.16+180 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From e909c033569a80353517a440cf7fa173414a7da6 Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Sat, 15 Jul 2023 07:10:46 +0300 Subject: [PATCH 258/600] Update ru.json --- assets/translations/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 320906b..edb9773 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "Не показывать предупреждения о только отслеживаемых приложениях", "dontShowAPKOriginWarnings": "Не показывать предупреждения об источнике APK-файлов", "moveNonInstalledAppsToBottom": "Переместить неустановленные приложения вниз списка", - "gitlabPATLabel": "Персональный токен доступа GitLab\n(Включает поиск and Better APK Discovery)", + "gitlabPATLabel": "Персональный токен доступа GitLab\n(Включает поиск и улучшает обнаружение APK)", "about": "О приложении", "requiresCredentialsInSettings": "Для этого требуются дополнительные учетные данные (в настройках)", "checkOnStart": "Проверять наличие обновлений при запуске", From 6395dd820bd592c00a96b626dda27d35be96e786 Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Sat, 15 Jul 2023 07:38:34 +0300 Subject: [PATCH 259/600] Update ru.json Fix --- assets/translations/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index edb9773..d6b6844 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -234,7 +234,7 @@ "requiresCredentialsInSettings": "Для этого требуются дополнительные учетные данные (в настройках)", "checkOnStart": "Проверять наличие обновлений при запуске", "tryInferAppIdFromCode": "Попытаться определить ID приложения из исходного кода", - "removeOnExternalUninstall": "Автоматически удалять удаленные извне приложения", + "removeOnExternalUninstall": "Автоматически убирать из списка удаленные извне приложения", "pickHighestVersionCode": "Автовыбор кода наивысшей версии APK", "checkUpdateOnDetailPage": "Проверять наличие обновлений при открытии страницы представления приложения", "removeAppQuestion": { From bb98dfe0b3a9b74aba41dcfe728b6da1393c4154 Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Sat, 15 Jul 2023 14:09:13 +0900 Subject: [PATCH 260/600] Update ja.json --- assets/translations/ja.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index e53c79c..51b2ede 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -229,14 +229,14 @@ "dontShowTrackOnlyWarnings": "「追跡のみ」の警告を表示しない", "dontShowAPKOriginWarnings": "APK Originの警告を表示しない", "moveNonInstalledAppsToBottom": "未インストールのアプリをアプリ一覧の下部に移動させる", - "gitlabPATLabel": "GitLab パーソナルアクセストークン\n(検索を有効化する and Better APK Discovery)", + "gitlabPATLabel": "GitLab パーソナルアクセストークン\n(検索とより良いAPK検出の有効化)", "about": "概要", "requiresCredentialsInSettings": "これには追加の認証が必要です (設定にて)", - "checkOnStart": "Check for updates on startup", - "tryInferAppIdFromCode": "Try inferring App ID from source code", - "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", - "pickHighestVersionCode": "Auto-select highest version code APK", - "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "checkOnStart": "起動時にアップデートを確認する", + "tryInferAppIdFromCode": "ソースコードからApp IDを推測する", + "removeOnExternalUninstall": "外部でアンインストールされたアプリを自動的に削除する", + "pickHighestVersionCode": "最も高いバージョンコードのAPKを自動的に選択する", + "checkUpdateOnDetailPage": "アプリの詳細ページを開く際にアップデートを確認する", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" From 1cc4241fac92c6c45eeb62c1c2c57535ed6cf678 Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Sat, 15 Jul 2023 14:47:27 +0900 Subject: [PATCH 261/600] Update ja.json --- assets/translations/ja.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 51b2ede..08977e7 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -135,7 +135,7 @@ "showWebInAppView": "アプリページにソースのWebページを表示する", "pinUpdates": "アップデートがあるアプリをトップに固定する", "updates": "アップデート", - "sourceSpecific": "Github アクセストークン", + "sourceSpecific": "ソース別の設定", "appSource": "アプリのソース", "noLogs": "ログはありません", "appLogs": "アプリのログ", @@ -227,7 +227,7 @@ "overrideSource": "ソースの上書き", "dontShowAgain": "二度と表示しない", "dontShowTrackOnlyWarnings": "「追跡のみ」の警告を表示しない", - "dontShowAPKOriginWarnings": "APK Originの警告を表示しない", + "dontShowAPKOriginWarnings": "APKのダウンロード元の警告を表示しない", "moveNonInstalledAppsToBottom": "未インストールのアプリをアプリ一覧の下部に移動させる", "gitlabPATLabel": "GitLab パーソナルアクセストークン\n(検索とより良いAPK検出の有効化)", "about": "概要", From e2a8f40e3e78a3706e6abdff9365ab30c67b362d Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Sat, 15 Jul 2023 08:49:35 +0300 Subject: [PATCH 262/600] Update ru.json Updated, fix and added \n for ru --- assets/translations/ru.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index d6b6844..2a78445 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -22,7 +22,7 @@ "githubPATFormat": "имя_пользователя:токен", "includePrereleases": "Включить предварительные релизы", "fallbackToOlderReleases": "Откатиться к более старым версиям", - "filterReleaseTitlesByRegEx": "Фильтровать заголовки релизов с помощью регулярного выражения", + "filterReleaseTitlesByRegEx": "Фильтровать заголовки релизов\nс помощью регулярного выражения", "invalidRegEx": "Неверное регулярное выражение", "noDescription": "Нет описания", "cancel": "Отмена", @@ -33,7 +33,7 @@ "githubStarredRepos": "Помеченные звездочкой репозитории на GitHub", "uname": "Имя пользователя", "wrongArgNum": "Неправильное количество предоставленных аргументов", - "xIsTrackOnly": "{} является приложением только для отслеживания", + "xIsTrackOnly": "{} только для отслеживания", "source": "Источник", "app": "Приложение", "appsFromSourceAreTrackOnly": "Приложения из этого источника являются 'только для отслеживания'.", @@ -100,7 +100,7 @@ "invalidInput": "Неверный ввод", "importedX": "Импортировано {}", "obtainiumImport": "Импорт в Obtainium", - "importFromURLList": "Импорт из списка URL-адреса", + "importFromURLList": "Импорт из списка URL-адресов", "searchQuery": "Поисковый запрос", "appURLList": "Список URL приложений", "line": "Строка", @@ -183,7 +183,7 @@ "appId": "ID приложения", "appWithIdOrNameNotFound": "Приложение с таким ID или названием не было найдено", "reposHaveMultipleApps": "В хранилище может быть несколько приложений", - "fdroidThirdPartyRepo": "Хранилище F-Droid сторонних разработчиков", + "fdroidThirdPartyRepo": "Репозитории F-Droid сторонних разработчиков", "steam": "Steam", "steamMobile": "Steam Mobile", "steamChat": "Steam Chat", @@ -211,7 +211,7 @@ "copiedToClipboard": "Скопировано в буфер обмена", "storagePermissionDenied": "Отказано в доступе к хранилищу", "selectedCategorizeWarning": "Это заменит все текущие настройки категорий для выбранных приложений.", - "filterAPKsByRegEx": "Фильтровать APK-файлы с помощью регулярного выражения", + "filterAPKsByRegEx": "Фильтровать APK-файлы с помощью\nрегулярного выражения", "removeFromObtainium": "Удалить из Obtainium", "uninstallFromDevice": "Удалить с устройства", "onlyWorksWithNonVersionDetectApps": "Работает только для приложений с отключенным определением версии.", @@ -219,7 +219,7 @@ "releaseDateAsVersionExplanation": "Этот параметр следует использовать только для приложений, в которых определение версии не работает правильно, но имеется дата выпуска.", "changes": "Изменения", "releaseDate": "Дата выпуска", - "importFromURLsInFile": "Импортировать из URL-адресов в файл (например, OPML)", + "importFromURLsInFile": "Импорт из URL-адресов в файле (например, OPML)", "versionDetection": "Определение версии", "standardVersionDetection": "Стандартное определение версии", "groupByCategory": "Группировать по категориям", @@ -258,8 +258,8 @@ "other": "{} Приложений" }, "url": { - "one": "{} Ссылка", - "other": "{} Ссылки" + "one": "{} URL-адрес", + "other": "{} URL-адреса" }, "minute": { "one": "{} Минута", From d587e9f7080dfdc09f3be7ab46340e5aa1907dfd Mon Sep 17 00:00:00 2001 From: gidano Date: Sat, 15 Jul 2023 13:21:58 +0200 Subject: [PATCH 263/600] Update hu.json --- assets/translations/hu.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 69b8ab6..e071a50 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -233,9 +233,9 @@ "requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)", "checkOnStart": "Egyszer az indításkor", "tryInferAppIdFromCode": "Próbálja kikövetkeztetni az app azonosítót a forráskódból", - "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", - "pickHighestVersionCode": "Auto-select highest version code APK", - "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "removeOnExternalUninstall": "A külsőleg eltávolított appok auto. eltávolítása", + "pickHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", + "checkUpdateOnDetailPage": "Frissítések keresése az app részleteit tartalmazó oldal megnyitásakor", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From a8aa63daa3c308b8eebd45e0b371a59b6b918c08 Mon Sep 17 00:00:00 2001 From: Weblate Date: Sat, 15 Jul 2023 23:53:20 +0200 Subject: [PATCH 264/600] locale(pl): Update Polish translation Co-authored-by: Daviteusz Co-authored-by: Weblate --- assets/translations/pl.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 59ae37a..903640e 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -25,8 +25,8 @@ "bgUpdateTaskFinished": "Zakończono zadanie sprawdzania aktualizacji w tle", "firstRun": "Jest to pierwsze uruchomienie Obtainium", "settingUpdateCheckIntervalTo": "Ustawianie interwału aktualizacji na {}", - "githubPATLabel": "Osobisty Token Dostępu GitHub (zwiększa limit zapytań)", - "githubPATHint": "Wymagany format OTD: użytkownik:token", + "githubPATLabel": "Osobisty token dostępu GitHub (zwiększa limit zapytań)", + "githubPATHint": "Wymagany format: użytkownik:token", "githubPATFormat": "użytkownik:token", "includePrereleases": "Uwzględnij wersje wstępne", "fallbackToOlderReleases": "Powracaj do starszych wersji", @@ -233,14 +233,14 @@ "dontShowTrackOnlyWarnings": "Nie wyświetlaj ostrzeżeń „Tylko obserwowana”", "dontShowAPKOriginWarnings": "Nie pokazuj ostrzeżeń o pochodzeniu APK", "moveNonInstalledAppsToBottom": "Przenieś niezainstalowane aplikacje na dół widoku aplikacji", - "gitlabPATLabel": "Osobisty Token Dostępu GitLab\n(umożliwia wyszukiwanie and Better APK Discovery)", + "gitlabPATLabel": "Osobisty token dostępu GitLab\n(Umożliwia wyszukiwanie i lepsze wykrywanie APK)", "about": "Więcej informacji", "requiresCredentialsInSettings": "Wymaga to dodatkowych poświadczeń (w Ustawieniach)", - "checkOnStart": "Sprawdź raz przy starcie", + "checkOnStart": "Sprawdź aktualizacje przy uruchomieniu", "tryInferAppIdFromCode": "Spróbuj wywnioskować identyfikator aplikacji z kodu źródłowego", - "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", - "pickHighestVersionCode": "Auto-select highest version code APK", - "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "removeOnExternalUninstall": "Automatyczne usuń odinstalowane zewnętrznie aplikacje", + "pickHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", + "checkUpdateOnDetailPage": "Sprawdzaj aktualizacje podczas otwierania strony szczegółów aplikacji", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" From 2558c851c056f6b4ee48a8403e5e13e85286d262 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 15 Jul 2023 18:18:35 -0400 Subject: [PATCH 265/600] Improve App load performance (#579) --- lib/providers/apps_provider.dart | 39 ++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index b1da1b2..52fcec3 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -725,21 +725,12 @@ class AppsProvider with ChangeNotifier { notifyListeners(); var sp = SourceProvider(); List> errors = []; - List newApps = (await getAppsDir()) + List newApps = (await getAppsDir()) // Parse Apps from JSON .listSync() .where((item) => item.path.toLowerCase().endsWith('.json')) - .toList(); - for (var e in newApps) { + .map((e) { try { - var app = App.fromJson(jsonDecode(File(e.path).readAsStringSync())); - try { - var info = await getInstalledInfo(app.id); - sp.getSource(app.url, overrideSource: app.overrideSource); - apps[app.id] = AppInMemory(app, null, info); - notifyListeners(); - } catch (e) { - errors.add([app.id, app.finalName, e.toString()]); - } + return App.fromJson(jsonDecode(File(e.path).readAsStringSync())); } catch (err) { if (err is FormatException) { logs.add('Corrupt JSON when loading App (will be ignored): $e'); @@ -748,6 +739,30 @@ class AppsProvider with ChangeNotifier { rethrow; } } + }).toList(); + for (var app in newApps) { + // Put Apps into memory to list them (fast) + if (app != null) { + try { + apps[app.id] = AppInMemory(app, null, null); + } catch (e) { + errors.add([app.id, app.finalName, e.toString()]); + } + } + } + notifyListeners(); + for (var app in newApps) { + // Check install status for each App (slow) + if (app != null) { + try { + apps[app.id]?.installedInfo = await getInstalledInfo(app.id); + sp.getSource(app.url, overrideSource: app.overrideSource); + } catch (e) { + apps.remove(app.id); + errors.add([app.id, app.finalName, e.toString()]); + } + notifyListeners(); + } } if (errors.isNotEmpty) { removeApps(errors.map((e) => e[0]).toList()); From fda9e6195a995e00c067e129bca394d00f66d060 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 15 Jul 2023 18:54:53 -0400 Subject: [PATCH 266/600] Make transition animation directional (#675) --- lib/pages/home.dart | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 1e74fcc..c64ed03 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -26,6 +26,7 @@ class NavigationPageItem { class _HomePageState extends State { List selectedIndexHistory = []; + bool isReversing = false; int prevAppCount = -1; bool prevIsLoading = true; @@ -42,7 +43,16 @@ class _HomePageState extends State { Widget build(BuildContext context) { AppsProvider appsProvider = context.watch(); + setIsReversing(int targetIndex) { + bool reversing = selectedIndexHistory.isNotEmpty && + selectedIndexHistory.last > targetIndex; + setState(() { + isReversing = reversing; + }); + } + switchToPage(int index) async { + setIsReversing(index); if (index == 0) { while ((pages[0].widget.key as GlobalKey).currentState != null) { @@ -79,6 +89,7 @@ class _HomePageState extends State { child: Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, body: PageTransitionSwitcher( + reverse: isReversing, transitionBuilder: ( Widget child, Animation animation, @@ -104,13 +115,16 @@ class _HomePageState extends State { .toList(), onDestinationSelected: (int index) async { HapticFeedback.selectionClick(); - await switchToPage(index); + switchToPage(index); }, selectedIndex: selectedIndexHistory.isEmpty ? 0 : selectedIndexHistory.last, ), ), onWillPop: () async { + setIsReversing(selectedIndexHistory.length >= 2 + ? selectedIndexHistory.reversed.toList()[1] + : 0); if (selectedIndexHistory.isNotEmpty) { setState(() { selectedIndexHistory.removeLast(); From d32e7acc8f68ae13ee5b864667436eab25b79c29 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 15 Jul 2023 19:20:17 -0400 Subject: [PATCH 267/600] Fix missing update button bug (perform full load on foreground) --- lib/providers/apps_provider.dart | 46 +++++++++++++------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 52fcec3..d6dc4be 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -117,7 +117,7 @@ class AppsProvider with ChangeNotifier { foregroundStream = FGBGEvents.stream.asBroadcastStream(); foregroundSubscription = foregroundStream?.listen((event) async { isForeground = event == FGBGType.foreground; - if (isForeground) await refreshInstallStatuses(); + if (isForeground) await loadApps(); }); () async { var cacheDirs = await getExternalCacheDirectories(); @@ -744,47 +744,35 @@ class AppsProvider with ChangeNotifier { // Put Apps into memory to list them (fast) if (app != null) { try { - apps[app.id] = AppInMemory(app, null, null); + sp.getSource(app.url, overrideSource: app.overrideSource); + apps.update( + app.id, + (value) => + AppInMemory(app, value.downloadProgress, value.installedInfo), + ifAbsent: () => AppInMemory(app, null, null)); } catch (e) { errors.add([app.id, app.finalName, e.toString()]); } } } notifyListeners(); - for (var app in newApps) { - // Check install status for each App (slow) - if (app != null) { - try { - apps[app.id]?.installedInfo = await getInstalledInfo(app.id); - sp.getSource(app.url, overrideSource: app.overrideSource); - } catch (e) { - apps.remove(app.id); - errors.add([app.id, app.finalName, e.toString()]); - } - notifyListeners(); - } - } if (errors.isNotEmpty) { removeApps(errors.map((e) => e[0]).toList()); NotificationsProvider().notify( AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList())); } - loadingApps = false; - notifyListeners(); - refreshInstallStatuses(useExistingInstalledInfo: true); - } - - Future refreshInstallStatuses( - {bool useExistingInstalledInfo = false}) async { if (await doesInstalledAppsPluginWork()) { + for (var app in apps.values) { + // Check install status for each App (slow) + apps[app.app.id]?.installedInfo = await getInstalledInfo(app.app.id); + notifyListeners(); + } + // Reconcile version differences List modifiedApps = []; for (var app in apps.values) { - var moddedApp = getCorrectedInstallStatusAppIfPossible( - app.app, - useExistingInstalledInfo - ? app.installedInfo - : await getInstalledInfo(app.app.id)); + var moddedApp = + getCorrectedInstallStatusAppIfPossible(app.app, app.installedInfo); if (moddedApp != null) { modifiedApps.add(moddedApp); } @@ -795,6 +783,7 @@ class AppsProvider with ChangeNotifier { .where((a) => a.installedVersion == null) .map((e) => e.id) .toList(); + // After reconciliation, delete externally uninstalled Apps if needed if (removedAppIds.isNotEmpty) { var settingsProvider = SettingsProvider(); await settingsProvider.initializeSettings(); @@ -804,6 +793,9 @@ class AppsProvider with ChangeNotifier { } } } + + loadingApps = false; + notifyListeners(); } Future saveApps(List apps, From f05902925d45336fbe049d23d7e677ed43ffa28c Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 15 Jul 2023 19:23:00 -0400 Subject: [PATCH 268/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 51e56f0..0e1a60e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.16'; +const String currentVersion = '0.13.17'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 06fd3fb..db13b8a 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.13.16+180 # When changing this, update the tag in main() accordingly +version: 0.13.17+181 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 3befcbc16dbb8c66e2fa96cfc8ca9dad29b7a9d4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 15 Jul 2023 19:35:40 -0400 Subject: [PATCH 269/600] Don't auto-capitalize names (#669) --- lib/providers/source_provider.dart | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index f8f31ff..6917ba5 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -594,9 +594,7 @@ class SourceProvider { } String apkVersion = apk.version.replaceAll('/', '-'); var name = currentApp != null ? currentApp.name.trim() : ''; - name = name.isNotEmpty - ? name - : apk.names.name[0].toUpperCase() + apk.names.name.substring(1); + name = name.isNotEmpty ? name : apk.names.name; return App( currentApp?.id ?? ((!source.appIdInferIsOptional || @@ -606,7 +604,7 @@ class SourceProvider { : null) ?? generateTempID(standardUrl, additionalSettings), standardUrl, - apk.names.author[0].toUpperCase() + apk.names.author.substring(1), + apk.names.author, name, currentApp?.installedVersion, apkVersion, From 6b16857186d0f35a2a9e0082caba404c9b7669c0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 16 Jul 2023 11:36:49 -0400 Subject: [PATCH 270/600] Make page transition animation optional (#683) --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/main.dart | 2 +- lib/pages/home.dart | 5 +++++ lib/pages/settings.dart | 15 +++++++++++++++ lib/providers/settings_provider.dart | 9 +++++++++ pubspec.yaml | 2 +- 16 files changed, 42 insertions(+), 2 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 7e0b4a6..fbb9ed9 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -237,6 +237,7 @@ "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "disablePageTransitions": "Disable page transition animations", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index cb9bf5d..08d8bb5 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -237,6 +237,7 @@ "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "disablePageTransitions": "Disable page transition animations", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 8e31c7c..5b3ecec 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -237,6 +237,7 @@ "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "disablePageTransitions": "Disable page transition animations", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 393d0c7..8110064 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -237,6 +237,7 @@ "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "disablePageTransitions": "Disable page transition animations", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index b403c1f..7b26b45 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -237,6 +237,7 @@ "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "disablePageTransitions": "Disable page transition animations", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index e071a50..4dc30ba 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -236,6 +236,7 @@ "removeOnExternalUninstall": "A külsőleg eltávolított appok auto. eltávolítása", "pickHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", "checkUpdateOnDetailPage": "Frissítések keresése az app részleteit tartalmazó oldal megnyitásakor", + "disablePageTransitions": "Disable page transition animations", "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 8010b37..9c368e1 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -237,6 +237,7 @@ "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "disablePageTransitions": "Disable page transition animations", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 08977e7..eff5b48 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -237,6 +237,7 @@ "removeOnExternalUninstall": "外部でアンインストールされたアプリを自動的に削除する", "pickHighestVersionCode": "最も高いバージョンコードのAPKを自動的に選択する", "checkUpdateOnDetailPage": "アプリの詳細ページを開く際にアップデートを確認する", + "disablePageTransitions": "Disable page transition animations", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 903640e..28c6b43 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -241,6 +241,7 @@ "removeOnExternalUninstall": "Automatyczne usuń odinstalowane zewnętrznie aplikacje", "pickHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", "checkUpdateOnDetailPage": "Sprawdzaj aktualizacje podczas otwierania strony szczegółów aplikacji", + "disablePageTransitions": "Disable page transition animations", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 2a78445..c36c992 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -237,6 +237,7 @@ "removeOnExternalUninstall": "Автоматически убирать из списка удаленные извне приложения", "pickHighestVersionCode": "Автовыбор кода наивысшей версии APK", "checkUpdateOnDetailPage": "Проверять наличие обновлений при открытии страницы представления приложения", + "disablePageTransitions": "Disable page transition animations", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index f72eb31..f8828ee 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -237,6 +237,7 @@ "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "disablePageTransitions": "Disable page transition animations", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/main.dart b/lib/main.dart index 0e1a60e..bd11b10 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.17'; +const String currentVersion = '0.13.18'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/home.dart b/lib/pages/home.dart index c64ed03..0c9cc3a 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -7,6 +7,7 @@ import 'package:obtainium/pages/apps.dart'; import 'package:obtainium/pages/import_export.dart'; import 'package:obtainium/pages/settings.dart'; import 'package:obtainium/providers/apps_provider.dart'; +import 'package:obtainium/providers/settings_provider.dart'; import 'package:provider/provider.dart'; class HomePage extends StatefulWidget { @@ -42,6 +43,7 @@ class _HomePageState extends State { @override Widget build(BuildContext context) { AppsProvider appsProvider = context.watch(); + SettingsProvider settingsProvider = context.watch(); setIsReversing(int targetIndex) { bool reversing = selectedIndexHistory.isNotEmpty && @@ -89,6 +91,9 @@ class _HomePageState extends State { child: Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, body: PageTransitionSwitcher( + duration: Duration( + milliseconds: + settingsProvider.disablePageTransitions ? 0 : 300), reverse: isReversing, transitionBuilder: ( Widget child, diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index c63d2e8..bfd52df 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -396,6 +396,21 @@ class _SettingsPageState extends State { }) ], ), + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text(tr('disablePageTransitions'))), + Switch( + value: + settingsProvider.disablePageTransitions, + onChanged: (value) { + settingsProvider.disablePageTransitions = + value; + }) + ], + ), height32, Text( tr('categories'), diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 9fcfba0..deef897 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -291,4 +291,13 @@ class SettingsProvider with ChangeNotifier { prefs?.setBool('checkUpdateOnDetailPage', show); notifyListeners(); } + + bool get disablePageTransitions { + return prefs?.getBool('disablePageTransitions') ?? false; + } + + set disablePageTransitions(bool show) { + prefs?.setBool('disablePageTransitions', show); + notifyListeners(); + } } diff --git a/pubspec.yaml b/pubspec.yaml index db13b8a..67cc8bf 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.13.17+181 # When changing this, update the tag in main() accordingly +version: 0.13.18+182 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 1c390a7f04c9ef73343d873354ea415bcf204bce Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 16 Jul 2023 11:41:02 -0400 Subject: [PATCH 271/600] Add reverse transition animation toggle (#683) --- assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/pages/home.dart | 4 +++- lib/pages/settings.dart | 15 +++++++++++++++ lib/providers/settings_provider.dart | 9 +++++++++ 14 files changed, 38 insertions(+), 1 deletion(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index fbb9ed9..bee3009 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -238,6 +238,7 @@ "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 08d8bb5..6937f3e 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -238,6 +238,7 @@ "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 5b3ecec..a572f71 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -238,6 +238,7 @@ "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 8110064..4db143d 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -238,6 +238,7 @@ "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 7b26b45..8c014b4 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -238,6 +238,7 @@ "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 4dc30ba..32fd821 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -237,6 +237,7 @@ "pickHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", "checkUpdateOnDetailPage": "Frissítések keresése az app részleteit tartalmazó oldal megnyitásakor", "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", "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 9c368e1..057d88f 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -238,6 +238,7 @@ "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index eff5b48..c88ee6e 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -238,6 +238,7 @@ "pickHighestVersionCode": "最も高いバージョンコードのAPKを自動的に選択する", "checkUpdateOnDetailPage": "アプリの詳細ページを開く際にアップデートを確認する", "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 28c6b43..726d1da 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -242,6 +242,7 @@ "pickHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", "checkUpdateOnDetailPage": "Sprawdzaj aktualizacje podczas otwierania strony szczegółów aplikacji", "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index c36c992..7d5f874 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -238,6 +238,7 @@ "pickHighestVersionCode": "Автовыбор кода наивысшей версии APK", "checkUpdateOnDetailPage": "Проверять наличие обновлений при открытии страницы представления приложения", "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index f8828ee..2904972 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -238,6 +238,7 @@ "pickHighestVersionCode": "Auto-select highest version code APK", "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 0c9cc3a..c14e83f 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -94,7 +94,9 @@ class _HomePageState extends State { duration: Duration( milliseconds: settingsProvider.disablePageTransitions ? 0 : 300), - reverse: isReversing, + reverse: settingsProvider.reversePageTransitions + ? !isReversing + : isReversing, transitionBuilder: ( Widget child, Animation animation, diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index bfd52df..950d2d5 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -411,6 +411,21 @@ class _SettingsPageState extends State { }) ], ), + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text(tr('reversePageTransitions'))), + Switch( + value: + settingsProvider.reversePageTransitions, + onChanged: (value) { + settingsProvider.reversePageTransitions = + value; + }) + ], + ), height32, Text( tr('categories'), diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index deef897..ea79e38 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -300,4 +300,13 @@ class SettingsProvider with ChangeNotifier { prefs?.setBool('disablePageTransitions', show); notifyListeners(); } + + bool get reversePageTransitions { + return prefs?.getBool('reversePageTransitions') ?? false; + } + + set reversePageTransitions(bool show) { + prefs?.setBool('reversePageTransitions', show); + notifyListeners(); + } } From 53dba06cc365f74de9057a73ee5b0fb6bf6aac62 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 16 Jul 2023 11:52:18 -0400 Subject: [PATCH 272/600] Fix text alignment + visibility on app page (#680) --- lib/pages/app.dart | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 2ba6a96..4d97d54 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -57,6 +57,11 @@ class _AppPageState extends State { app?.app.additionalSettings['versionDetection'] == 'standardVersionDetection'; + bool installedVersionIsEstimate = trackOnly || + (app?.app.installedVersion != null && + app?.app.additionalSettings['versionDetection'] == + 'noVersionDetection'); + getInfoColumn() => Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, @@ -92,9 +97,7 @@ class _AppPageState extends State { app?.app.latestVersion ?? tr('unknown') ])}\n${tr('installedVersionX', args: [ app?.app.installedVersion ?? tr('none') - ])}${trackOnly ? ' ${tr('estimateInBrackets')}\n\n${tr('xIsTrackOnly', args: [ - tr('app') - ])}' : ''}', + ])}${installedVersionIsEstimate ? '\n${tr('estimateInBrackets')}' : ''}', textAlign: TextAlign.end, style: Theme.of(context).textTheme.bodyLarge!, ), @@ -105,11 +108,14 @@ class _AppPageState extends State { Column( children: [ const SizedBox( - height: 4, + height: 16, ), Text( - tr('noVersionDetection'), + '${trackOnly ? '${tr('xIsTrackOnly', args: [ + tr('app') + ])}\n' : ''}${tr('noVersionDetection')}', style: Theme.of(context).textTheme.labelSmall, + textAlign: TextAlign.center, ) ], ), From 579bc948473a7c3832de55b853715cfff4ed82ef Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 16 Jul 2023 12:05:43 -0400 Subject: [PATCH 273/600] Attempt at more resilient XAPK installs (#682) --- lib/providers/apps_provider.dart | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index d6dc4be..80e6312 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -341,20 +341,33 @@ class AppsProvider with ChangeNotifier { Future installXApkDir(DownloadedXApkDir dir, {bool silent = false}) async { + // We don't know which APKs in an XAPK are supported by the user's device + // So we try installing all of them and assume success if at least one installed + // If 0 APKs installed, throw the first install error encountered try { var somethingInstalled = false; + var firstError = null; for (var file in dir.extracted .listSync(recursive: true, followLinks: false) .whereType()) { if (file.path.toLowerCase().endsWith('.apk')) { - somethingInstalled = somethingInstalled || - await installApk(DownloadedApk(dir.appId, file), silent: silent); + try { + somethingInstalled = somethingInstalled || + await installApk(DownloadedApk(dir.appId, file), + silent: silent); + } catch (e) { + logs.add( + 'Could not install APK from XAPK \'${file.path}\': ${e.toString()}'); + firstError ??= e; + } } else if (file.path.toLowerCase().endsWith('.obb')) { await moveObbFile(file, dir.appId); } } if (somethingInstalled) { dir.file.delete(recursive: true); + } else if (firstError) { + throw firstError; } } finally { dir.extracted.delete(recursive: true); From d885ca5db74c4bc25685279fbb02a241e0827d38 Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Sun, 16 Jul 2023 22:46:44 +0300 Subject: [PATCH 274/600] Update ru.json --- assets/translations/ru.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 7d5f874..aa3d2eb 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -116,9 +116,9 @@ "selectURLs": "Выбрать URL-адреса", "pick": "Выбрать", "theme": "Тема", - "dark": "Темный", - "light": "Светлый", - "followSystem": "Следовать системе", + "dark": "Темная", + "light": "Светлая", + "followSystem": "Как в системе", "obtainium": "Obtainium", "materialYou": "Material You", "useBlackTheme": "Использовать чёрную тему", @@ -183,7 +183,7 @@ "appId": "ID приложения", "appWithIdOrNameNotFound": "Приложение с таким ID или названием не было найдено", "reposHaveMultipleApps": "В хранилище может быть несколько приложений", - "fdroidThirdPartyRepo": "Репозитории F-Droid сторонних разработчиков", + "fdroidThirdPartyRepo": "Сторонние репозитории F-Droid", "steam": "Steam", "steamMobile": "Steam Mobile", "steamChat": "Steam Chat", @@ -219,7 +219,7 @@ "releaseDateAsVersionExplanation": "Этот параметр следует использовать только для приложений, в которых определение версии не работает правильно, но имеется дата выпуска.", "changes": "Изменения", "releaseDate": "Дата выпуска", - "importFromURLsInFile": "Импорт из URL-адресов в файле (например, OPML)", + "importFromURLsInFile": "Импорт URL-адресов из файла (например, OPML)", "versionDetection": "Определение версии", "standardVersionDetection": "Стандартное определение версии", "groupByCategory": "Группировать по категориям", @@ -237,8 +237,8 @@ "removeOnExternalUninstall": "Автоматически убирать из списка удаленные извне приложения", "pickHighestVersionCode": "Автовыбор кода наивысшей версии APK", "checkUpdateOnDetailPage": "Проверять наличие обновлений при открытии страницы представления приложения", - "disablePageTransitions": "Disable page transition animations", - "reversePageTransitions": "Reverse page transition animations", + "disablePageTransitions": "Отключить анимацию перехода между страницами", + "reversePageTransitions": "Реверс анимации перехода между страницами", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" From 324773ba58e51d408544ed502ca7a7dd1f9f444d Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Sun, 16 Jul 2023 23:01:31 +0300 Subject: [PATCH 275/600] Correct ru main.dart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That's more correct😅 --- lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index bd11b10..aaca489 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,7 +38,7 @@ List> supportedLocales = const [ MapEntry(Locale('fr'), 'Français'), MapEntry(Locale('es'), 'Español'), MapEntry(Locale('pl'), 'Polski'), - MapEntry(Locale('ru'), 'Русский язык'), + MapEntry(Locale('ru'), 'Русский'), ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; From 04b49c2e613a6a14cc5acac3845b8063845bccea Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 17 Jul 2023 15:57:10 -0400 Subject: [PATCH 276/600] Fix null check error for GitHub repos w/o releases --- lib/app_sources/github.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 8cb08e2..4334abd 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -211,8 +211,8 @@ class GitHub extends AppSource { (nameA as String).substring(matchA!.start, matchA.end), (nameB as String).substring(matchB!.start, matchB.end)); } else { - return getReleaseDateFromRelease(a)! - .compareTo(getReleaseDateFromRelease(b)!); + return (getReleaseDateFromRelease(a) ?? DateTime(1)) + .compareTo(getReleaseDateFromRelease(b) ?? DateTime(0)); } } }); From e6467452a6a1b9eafb9d8afa460d5700fc52a4cc Mon Sep 17 00:00:00 2001 From: Erudaro <91962669+Erudaro@users.noreply.github.com> Date: Tue, 18 Jul 2023 22:49:13 +0200 Subject: [PATCH 277/600] Add files via upload Adding Bosnian language json file --- assets/translations/bs.json | 290 ++++++++++++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) create mode 100644 assets/translations/bs.json diff --git a/assets/translations/bs.json b/assets/translations/bs.json new file mode 100644 index 0000000..38e2b0d --- /dev/null +++ b/assets/translations/bs.json @@ -0,0 +1,290 @@ + { + "invalidURLForSource": "Nije važeći URL aplikacije {}", + "noReleaseFound": "Nije moguće pronaći odgovarajuće izdanje", + "noVersionFound": "Nije moguće odrediti verziju izdanja", + "urlMatchesNoSource": "URL se ne podudara s poznatim izvorom", + "cantInstallOlderVersion": "Nije moguće instalirati stariju verziju aplikacije", + "appIdMismatch": "ID preuzetog paketa se ne podudara s postojećim ID-om aplikacije", + "functionNotImplemented": "Ova klasa nije implementirala ovu funkciju", + "placeholder": "Rezervirano mjesto", + "someErrors": "Došlo je do nekih grešaka", + "unexpectedError": "Neočekivana greška", + "ok": "Dobro", + "and": "i", + "startedBgUpdateTask": "Započeo je pozadinski zadatak provjere ažuriranja", + "bgUpdateIgnoreAfterIs": "ignoreAfter pozadinskog zadataka je {}", + "startedActualBGUpdateCheck": "Započela je stvarna provjera ažuriranja", + "bgUpdateTaskFinished": "Završen zadatak provjere ažuriranja", + "firstRun": "Ovo je prvi put da pokrećete Obtainium", + "settingUpdateCheckIntervalTo": "Podešavanje intervala ažuriranja na {}", + "githubPATLabel": "GitHub token za lični pristup (eng. PAT, povećava ograničenje stope)", + "githubPATHint": "PAT mora biti u ovom formatu: korisničko_ime:token", + "githubPATFormat": "korisničko_ime:token", + "includePrereleases": "Uključi preliminarna izdanja", + "fallbackToOlderReleases": "Povratak na starija izdanja", + "filterReleaseTitlesByRegEx": "Filtrirajte naslove izdanja prema regularnom izrazu", + "invalidRegEx": "Nevažeći regularni izraz", + "noDescription": "Bez opisa", + "cancel": "Otkaži", + "continue": "Nastavite", + "requiredInBrackets": "(obavezno)", + "dropdownNoOptsError": "GREŠKA: PADAJUĆI MENI MORA IMATI NAJMANJE JEDNU OPCIJU", + "colour": "Boja", + "githubStarredRepos": "GitHub repo-i sa zvjezdicom", + "uname": "Korisničko ime", + "wrongArgNum": "Naveden je pogrešan broj argumenata", + "xIsTrackOnly": "{} je samo za praćenje", + "source": "Izvor", + "app": "Aplikacija. ", + "appsFromSourceAreTrackOnly": "Aplikacije iz ovog izvora su 'Samo za praćenje'.", + "youPickedTrackOnly": "Odabrali ste opciju „Samo za praćenje”.", + "trackOnlyAppDescription": "Aplikacija će se pratiti radi ažuriranja, ali Obtainium neće moći da je preuzme ili instalira.", + "cancelled": "Otkazano", + "appAlreadyAdded": "Aplikacija je već dodana", + "alreadyUpToDateQuestion": "Aplikacija je već ažurirana?", + "addApp": "Dodaj aplikaciju", + "appSourceURL": "Izvorni URL aplikacije", + "error": "Greška", + "add": "Dodaj", + "searchSomeSourcesLabel": "Pretraživanje (samo neki izvori)", + "search": "Pretraživanje", + "additionalOptsFor": "Dodatne opcije za {}", + "supportedSourcesBelow": "Podržani izvori:", + "trackOnlyInBrackets": "(Samo za praćenje)", + "searchableInBrackets": "(Može se pretraživati)", + "appsString": "Aplikacije", + "noApps": "Nema aplikacija", + "noAppsForFilter": "Nema aplikacija za filter", + "byX": "Autor {}", + "percentProgress": "Napredak: {}%", + "pleaseWait": "Molimo sačekajte", + "updateAvailable": "Ažuriranje dostupno", + "estimateInBracketsShort": "(Procjena)", + "notInstalled": "Nije instalirano", + "estimateInBrackets": "(Procjena)", + "selectAll": "Označi sve", + "deselectN": "Poništi odabir {}", + "xWillBeRemovedButRemainInstalled": "{} će biti uklonjen iz Obtainiuma, ali će ostati instaliran na uređaju.", + "removeSelectedAppsQuestion": "Želite li ukloniti odabrane aplikacije?", + "removeSelectedApps": "Ukloni odabrane aplikacije", + "updateX": "Nadogradi {}", + "installX": "Instaliraj {}", + "markXTrackOnlyAsUpdated": "Označi {}\n(samo za praćenje)\nkao ažurirano", + "changeX": "Promjena {}", + "installUpdateApps": "Instalirajte/ažurirajte aplikacije", + "installUpdateSelectedApps": "Instalirajte/ažurirajte odabrane aplikacije", + "markXSelectedAppsAsUpdated": "Označite {} odabrane aplikacije kao ažurirane?", + "no": "Ne", + "yes": "Da", + "markSelectedAppsUpdated": "Označi odabrane aplikacije kao ažurirane", + "pinToTop": "Prikvači na vrh", + "unpinFromTop": "Otkvači sa vrha", + "resetInstallStatusForSelectedAppsQuestion": "Resetujte status instalacije za odabrane aplikacije?", + "installStatusOfXWillBeResetExplanation": "Status instalacije bilo koje odabrane aplikacije će se resetovati.\n\nTo može pomoći kada je verzija aplikacije prikazana u Obtainiumu netačna zbog neuspjelih ažuriranja ili drugih problema.", + "shareSelectedAppURLs": "Podijeli odabrane URL-ove aplikacija", + "resetInstallStatus": "Resetujte status instalacije", + "more": "Više", + "removeOutdatedFilter": "Uklonite zastarjeli filter aplikacija", + "showOutdatedOnly": "Prikaži samo zastarjele aplikacije", + "filter": "Filtriranje", + "filterActive": "Filtriranje", + "filterApps": "Filtriraj aplikacije", + "appName": "Naziv aplikacije", + "author": "Autor", + "upToDateApps": "Ažurirane aplikacije", + "nonInstalledApps": "Neinstalirane aplikacije", + "importExport": "Uvoz/izvoz", + "settings": "Postavke", + "exportedTo": "Izvezeno u {}", + "obtainiumExport": "Obtainium Export", + "invalidInput": "Neispravan unos.", + "importedX": "Uvezeno {}", + "obtainiumImport": "Obtainium uvoz", + "importFromURLList": "Uvoz iz URL liste", + "searchQuery": "Pretraga za: ", + "appURLList": "Lista URL adresa aplikacija", + "line": "Linija", + "searchX": "Pretraživanje {}", + "noResults": "Nema rezultata", + "importX": "Uvoz {}", + "importedAppsIdDisclaimer": "Uvezene aplikacije mogu se pogrešno prikazati kao „Nije instalirano”.\nDa biste to riješili, ponovo ih instalirajte putem aplikacije Obtainium.\nTo ne bi trebalo uticati na podatke aplikacije.\n\nUtječe samo na URL i metode uvoza treće strane.", + "importErrors": "Uvezi greške", + "importedXOfYApps": "{} od {} aplikacija uvezeno.", + "followingURLsHadErrors": "Sljedeći URL-ovi su imali greške:", + "okay": "Dobro", + "selectURL": "Odaberite URL", + "selectURLs": "Odaberite URL-ove", + "pick": "Odaberi", + "theme": "Tema", + "dark": "Tamna", + "light": "Svijetla", + "followSystem": "Pratite sistem", + "obtainium": "Obtainium", + "materialYou": "Material You", + "useBlackTheme": "Koristite čisto crnu tamnu temu", + "appSortBy": "Aplikacije sortirane po", + "authorName": "Autor/Ime", + "nameAuthor": "Ime/Autor", + "asAdded": "Kao što je dodano", + "appSortOrder": "Redoslijed sortiranja aplikacija", + "ascending": "Uzlazno", + "descending": "Silazno", + "bgUpdateCheckInterval": "Interval provjere ažuriranja u pozadini", + "neverManualOnly": "Nikada - samo ručno", + "appearance": "Izgled", + "showWebInAppView": "Prikaži izvornu web stranicu u prikazu aplikacije", + "pinUpdates": "Prikvačite ažuriranja na vrh prikaza aplikacija", + "updates": "Nadogradnje", + "sourceSpecific": "Specifično za izvor", + "appSource": "Izvor aplikacije", + "noLogs": "Nema evidencije", + "appLogs": "Evidencije aplikacija", + "close": "Zatvori", + "share": "Podijeli", + "appNotFound": "Aplikacija nije pronađena", + "obtainiumExportHyphenatedLowercase": "obtainium-export", + "pickAnAPK": "Odaberite APK", + "appHasMoreThanOnePackage": "{} ima više od jednog paketa:", + "deviceSupportsXArch": "Vaš uređaj podržava {} arhitekturu procesora.", + "deviceSupportsFollowingArchs": "Vaš uređaj podržava sljedeće arhitekture procesora:", + "warning": "Upozorenje", + "sourceIsXButPackageFromYPrompt": "Izvor aplikacije je '{}', ali paket za izdavanje dolazi iz '{}'. Želite li nastaviti?", + "updatesAvailable": "Dostupna ažuriranja", + "updatesAvailableNotifDescription": "Obavještava korisnika da su ažuriranja dostupna za jednu ili više aplikacija koje prati Obtainium", + "noNewUpdates": "Nema novih ažuriranja.", + "xHasAnUpdate": "{} ima ažuriranje.", + "appsUpdated": "Aplikacije su ažurirane", + "appsUpdatedNotifDescription": "Obavještava korisnika da su u pozadini primijenjena ažuriranja na jednu ili više aplikacija", + "xWasUpdatedToY": "{} je ažuriran na {}.", + "errorCheckingUpdates": "Greška pri provjeri ažuriranja", + "errorCheckingUpdatesNotifDescription": "Obavijest koja se prikazuje kada provjera sigurnosnog ažuriranja ne uspije", + "appsRemoved": "Aplikacije su uklonjene", + "appsRemovedNotifDescription": "Obavještava korisnika da je jedna ili više aplikacija uklonjeno zbog grešaka prilikom učitavanja", + "xWasRemovedDueToErrorY": "{} je uklonjen zbog ove greške: {}", + "completeAppInstallation": "Dovršite instalaciju aplikacije", + "obtainiumMustBeOpenToInstallApps": "Obtainium mora biti otvoren za instalaciju aplikacija", + "completeAppInstallationNotifDescription": "Traži od korisnika da se vrati u Obtainium kako bi dovršio instalaciju aplikacije", + "checkingForUpdates": "Tražim moguće nadogradnje", + "checkingForUpdatesNotifDescription": "Privremeno obavještenje koje se pojavljuje prilikom provjere ažuriranja", + "pleaseAllowInstallPerm": "Dozvolite Obtainiumu da instalira aplikacije", + "trackOnly": "Samo za praćenje", + "errorWithHttpStatusCode": "Greška {}", + "versionCorrectionDisabled": "Ispravka verzije je onemogućena (izgleda da plugin ne radi)", + "unknown": "Nepoznato", + "none": "Ništa", + "never": "Nikad", + "latestVersionX": "Najnovija verzija: {}", + "installedVersionX": "Instalirana verzija: {}", + "lastUpdateCheckX": "Posljednja provjera ažuriranja: {}", + "remove": "Izbriši", + "yesMarkUpdated": "Da, označi kao ažurirano", + "fdroid": "F-Droid Official", + "appIdOrName": "ID ili ime aplikacije", + "appId": "Apl ID", + "appWithIdOrNameNotFound": "Nije pronađena aplikacija s tim ID-om ili imenom", + "reposHaveMultipleApps": "Repo-i mogu sadržavati više aplikacija", + "fdroidThirdPartyRepo": "F-Droid Repo treće strane", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Razgovor na Steamu (chat)", + "install": "Instaliraj", + "markInstalled": "Označi kao instalirano", + "update": "Nadogradi", + "markUpdated": "Označi kao ažurirano", + "additionalOptions": "Dodatne opcije", + "disableVersionDetection": "Onemogući detekciju verzije", + "noVersionDetectionExplanation": "Ova opcija bi se trebala koristiti samo za aplikacije gdje detekcija verzije ne radi ispravno.", + "downloadingX": "Preuzimanje {}", + "downloadNotifDescription": "Obavještava korisnika o napretku u preuzimanju aplikacije", + "noAPKFound": "APK nije pronađen", + "noVersionDetection": "Nema detekcije verzije", + "categorize": "Kategoriziraj", + "categories": "Kategorije", + "category": "Kategorija", + "noCategory": "Nema kategorije", + "noCategories": "Nema kategorija", + "deleteCategoriesQuestion": "Želite li izbrisati kategorije?", + "categoryDeleteWarning": "Sve aplikacije u izbrisanim kategorijama će biti postavljene kao nekategorisane.", + "addCategory": "Dodaj kategoriju", + "label": "Oznaka", + "language": "Jezik", + "copiedToClipboard": "Podaci kopirani u međuspremnik", + "storagePermissionDenied": "Dozvola za pohranu je odbijena", + "selectedCategorizeWarning": "Ovo će zamijeniti sve postojeće postavke kategorije za odabrane aplikacije.", + "filterAPKsByRegEx": "Filtrirajte APK-ove prema regularnom izrazu", + "removeFromObtainium": "Ukloni iz Obtainiuma", + "uninstallFromDevice": "Deinstaliraj s uređaja", + "onlyWorksWithNonVersionDetectApps": "Radi samo za aplikacije s onemogućenom detekcijom verzije.", + "releaseDateAsVersion": "Koristi datum izdanja kao verziju", + "releaseDateAsVersionExplanation": "Ova opcija bi se trebala koristiti samo za aplikacije gdje detekcija verzije ne radi ispravno, ali je datum izdavanja dostupan.", + "changes": "Promjene", + "releaseDate": "Datum izdavanja", + "importFromURLsInFile": "Uvoz iz URL-ova u datoteci (kao što je OPML)", + "versionDetection": "Otkrivanje verzije", + "standardVersionDetection": "Detekcija standardne verzije", + "groupByCategory": "Grupiši po kategoriji", + "autoApkFilterByArch": "Pokušajte filtrirati APK-ove po arhitekturi procesora ako je moguće", + "overrideSource": "Premosti izvor", + "dontShowAgain": "Ne prikazuj ovo ponovo", + "dontShowTrackOnlyWarnings": "Ne prikazuj upozorenja „Samo za praćenje”", + "dontShowAPKOriginWarnings": "Ne prikazuj upozorenja o porijeklu APK-a", + "moveNonInstalledAppsToBottom": "Premjesti neinstalirane aplikacije na dno prikaza aplikacija", + "gitlabPATLabel": "GitLab token za lični pristup\n(Omogućava pretraživanje i bolje otkrivanje APK-a)", + "about": "O nama", + "requiresCredentialsInSettings": "Za ovo su potrebni dodatni akreditivi (u Postavkama)", + "checkOnStart": "Provjerite ima li novosti pri pokretanju", + "tryInferAppIdFromCode": "Pokušati otkriti ID aplikacije iz izvornog koda", + "removeOnExternalUninstall": "Automatski ukloni eksterno deinstalirane aplikacije", + "pickHighestVersionCode": "Automatski odaberite najviši kôd verzije APK-a", + "checkUpdateOnDetailPage": "Provjerite ima li novosti pri otvaranju stranice s detaljima aplikacije", + "disablePageTransitions": "Ugasite animaciju prijelaza stranice", + "reversePageTransitions": "Reverzne animacije prijelaza stranice", + "removeAppQuestion": { + "one": "Želite li ukloniti aplikaciju?", + "other": "Želite li ukloniti aplikacije?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Previše zahtjeva (ograničena broj zahteva) - pokušajte ponovo za {} minutu", + "other": "Previše zahtjeva (ograničena cijena) - pokušajte ponovo za {} min." + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "Provjera ažuriranja u pozadini naišla je na {}, zakazuje se ponovni pokušaj za {} minutu", + "other": "Provjera ažuriranja u pozadini naišla je na {}, zakazuje se ponovni pokušaj za {} min." + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "Provjera ažuriranja u pozadini je pronašla {} ažuriranje - korisnik će biti obavješten ako je to potrebno", + "other": "Provjera ažuriranja u pozadini je pronašla {} ažuriranja - korisnik će biti obavješten ako je to potrebno" + }, + "apps": { + "one": "{} aplikacija", + "other": "{} aplikacije" + }, + "url": { + "one": "{} URL", + "other": "{} URL-ovi" + }, + "minute": { + "one": "{} minuta", + "other": "min." + }, + "hour": { + "one": "{} sat", + "other": "{} sat/i" + }, + "day": { + "one": "{} dan", + "other": "{} dana" + }, + "clearedNLogsBeforeXAfterY": { + "one": "Izbrisan {n} log (prije = {before}, nakon = {after})", + "other": "Izbrisano {n} log-ova (prije = {before}, nakon = {after})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "{} i još 1 aplikacija ima ažuriranja.", + "other": "{} i još {} aplikacija imaju ažuriranja." + }, + "xAndNMoreUpdatesInstalled": { + "one": "{} i još 1 aplikacija je ažurirana.", + "other": "{} i još {} aplikacija je ažurirano." + } +} From ac5660de88e19cc55ae259b6fafcaab307ffc0e8 Mon Sep 17 00:00:00 2001 From: Erudaro <91962669+Erudaro@users.noreply.github.com> Date: Tue, 18 Jul 2023 23:16:57 +0200 Subject: [PATCH 278/600] Update main.dart supportedLocales with bs --- lib/main.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/main.dart b/lib/main.dart index bd11b10..609f9d9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -39,6 +39,7 @@ List> supportedLocales = const [ MapEntry(Locale('es'), 'Español'), MapEntry(Locale('pl'), 'Polski'), MapEntry(Locale('ru'), 'Русский язык'), + MapEntry(Locale('bs'), 'Bosanski'), ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; From 9c723c75223f5efde9ad2b3800c7f318c45c1494 Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Wed, 19 Jul 2023 11:38:09 +0900 Subject: [PATCH 279/600] Update ja.json --- assets/translations/ja.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index c88ee6e..b5532f3 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -237,8 +237,8 @@ "removeOnExternalUninstall": "外部でアンインストールされたアプリを自動的に削除する", "pickHighestVersionCode": "最も高いバージョンコードのAPKを自動的に選択する", "checkUpdateOnDetailPage": "アプリの詳細ページを開く際にアップデートを確認する", - "disablePageTransitions": "Disable page transition animations", - "reversePageTransitions": "Reverse page transition animations", + "disablePageTransitions": "ページ遷移アニメーションを無効化する", + "reversePageTransitions": "ページ遷移アニメーションを反転する", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" From d2150320fae66c316968fa1a390c468b5c6a8903 Mon Sep 17 00:00:00 2001 From: Daniel Martin Date: Sat, 22 Jul 2023 14:25:38 +1000 Subject: [PATCH 280/600] Add dependency: hsluv --- pubspec.lock | 8 ++++++++ pubspec.yaml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pubspec.lock b/pubspec.lock index 8d10c85..003eae3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -326,6 +326,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.2.2" + hsluv: + dependency: "direct main" + description: + name: hsluv + sha256: f33e63b0c24ceee0f6492874424aa8edc671ef9a20cc889e4b969284d8f02eb1 + url: "https://pub.dev" + source: hosted + version: "1.1.3" html: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 67cc8bf..9f785ad 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,7 +64,7 @@ dependencies: android_intent_plus: ^4.0.0 flutter_markdown: ^0.6.14 flutter_archive: ^5.0.0 - + hsluv: ^1.1.3 dev_dependencies: flutter_test: From 852decbe7d25627c1869cbb6db03d48fbf34db5f Mon Sep 17 00:00:00 2001 From: Daniel Martin Date: Sat, 22 Jul 2023 14:26:19 +1000 Subject: [PATCH 281/600] Remove redundant `generateRandomLightColor()` --- lib/pages/settings.dart | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 950d2d5..2a42376 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -1,5 +1,3 @@ -import 'dart:math'; - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:obtainium/components/custom_app_bar.dart'; @@ -21,21 +19,6 @@ class SettingsPage extends StatefulWidget { State createState() => _SettingsPageState(); } -// Generates a random light color -// Courtesy of ChatGPT 😭 (with a bugfix 🥳) -Color generateRandomLightColor() { - // Create a random number generator - final Random random = Random(); - - // Generate random hue, saturation, and value values - final double hue = random.nextDouble() * 360; - final double saturation = 0.5 + random.nextDouble() * 0.5; - final double value = 0.9 + random.nextDouble() * 0.1; - - // Create a HSV color with the random values - return HSVColor.fromAHSV(1.0, hue, saturation, value).toColor(); -} - class _SettingsPageState extends State { @override Widget build(BuildContext context) { From 543e7d8cdcf4cca922ae0aace5c3be787d4280e5 Mon Sep 17 00:00:00 2001 From: Weblate Date: Sat, 22 Jul 2023 16:31:20 +0200 Subject: [PATCH 282/600] locale(pl): Update Polish translation Co-authored-by: Daviteusz Co-authored-by: Weblate --- assets/translations/pl.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 726d1da..e475cc0 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -12,7 +12,7 @@ "noVersionFound": "Nie można określić wersji wydania", "urlMatchesNoSource": "Adres URL nie pasuje do znanego źródła", "cantInstallOlderVersion": "Nie można zainstalować starszej wersji aplikacji", - "appIdMismatch": "Pobrany identyfikator pakietu nie pasuje do istniejącego identyfikatora aplikacji", + "appIdMismatch": "Pobrane ID pakietu nie pasuje do istniejącego ID aplikacji", "functionNotImplemented": "Ta klasa nie zaimplementowała tej funkcji", "placeholder": "Placeholder", "someErrors": "Wystąpiły pewne błędy", @@ -230,7 +230,7 @@ "autoApkFilterByArch": "Spróbuj filtrować pliki APK według architektury procesora, jeśli to możliwe", "overrideSource": "Nadpisz źródło", "dontShowAgain": "Nie pokazuj tego ponownie", - "dontShowTrackOnlyWarnings": "Nie wyświetlaj ostrzeżeń „Tylko obserwowana”", + "dontShowTrackOnlyWarnings": "Nie pokazuj ostrzeżeń „Tylko obserwowana”", "dontShowAPKOriginWarnings": "Nie pokazuj ostrzeżeń o pochodzeniu APK", "moveNonInstalledAppsToBottom": "Przenieś niezainstalowane aplikacje na dół widoku aplikacji", "gitlabPATLabel": "Osobisty token dostępu GitLab\n(Umożliwia wyszukiwanie i lepsze wykrywanie APK)", @@ -241,8 +241,8 @@ "removeOnExternalUninstall": "Automatyczne usuń odinstalowane zewnętrznie aplikacje", "pickHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", "checkUpdateOnDetailPage": "Sprawdzaj aktualizacje podczas otwierania strony szczegółów aplikacji", - "disablePageTransitions": "Disable page transition animations", - "reversePageTransitions": "Reverse page transition animations", + "disablePageTransitions": "Wyłącz animacje przejścia między stronami", + "reversePageTransitions": "Odwróć animacje przejścia pomiędzy stronami", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" From b27bdc63c1787b88351772906838dfe82495b22b Mon Sep 17 00:00:00 2001 From: Daniel Martin Date: Sat, 22 Jul 2023 14:27:48 +1000 Subject: [PATCH 283/600] Make colors more accessible Using a combination of the HSLuv (Pastel) color space and incrementing by the Golden Angle --- lib/components/generated_form.dart | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/components/generated_form.dart b/lib/components/generated_form.dart index 8ab4149..761d6bc 100644 --- a/lib/components/generated_form.dart +++ b/lib/components/generated_form.dart @@ -1,5 +1,6 @@ import 'dart:math'; +import 'package:hsluv/hsluv.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:obtainium/components/generated_form_modal.dart'; @@ -132,19 +133,19 @@ class GeneratedForm extends StatefulWidget { State createState() => _GeneratedFormState(); } -// Generates a random light color -// Courtesy of ChatGPT 😭 (with a bugfix 🥳) +// Generates a color in the HSLuv (Pastel) color space +// https://pub.dev/documentation/hsluv/latest/hsluv/Hsluv/hpluvToRgb.html Color generateRandomLightColor() { - // Create a random number generator - final Random random = Random(); - - // Generate random hue, saturation, and value values - final double hue = random.nextDouble() * 360; - final double saturation = 0.5 + random.nextDouble() * 0.5; - final double value = 0.9 + random.nextDouble() * 0.1; - - // Create a HSV color with the random values - return HSVColor.fromAHSV(1.0, hue, saturation, value).toColor(); + final randomSeed = Random().nextInt(120); + // https://en.wikipedia.org/wiki/Golden_angle + final goldenAngle = 180 * (3 - sqrt(5)); + // Generate next golden angle hue + final double hue = randomSeed * goldenAngle; + // Map from HPLuv color space to RGB, use constant saturation=100, lightness=70 + final List rgbValuesDbl = Hsluv.hpluvToRgb([hue, 100, 70]); + // Map RBG values from 0-1 to 0-255: + final List rgbValues = rgbValuesDbl.map((rgb) => (rgb * 255).toInt()).toList(); + return Color.fromARGB(255, rgbValues[0], rgbValues[1], rgbValues[2]); } class _GeneratedFormState extends State { From e4b26be01f362d394b104e0aefd01c42656ca993 Mon Sep 17 00:00:00 2001 From: Daniel Martin Date: Sat, 22 Jul 2023 17:46:08 +1000 Subject: [PATCH 284/600] Add color button to Category editor Prevent randomly picking the same color --- lib/components/generated_form.dart | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/components/generated_form.dart b/lib/components/generated_form.dart index 761d6bc..300b679 100644 --- a/lib/components/generated_form.dart +++ b/lib/components/generated_form.dart @@ -369,6 +369,36 @@ class _GeneratedFormState extends State { )); }) ?? [const SizedBox.shrink()], + (values[widget.items[r][e].key] + as Map>?) + ?.values + .where((e) => e.value) + .length == 1 + ? Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: IconButton( + onPressed: () { + setState(() { + var temp = values[widget.items[r][e].key] + as Map>; + // get selected category str where bool is true + final oldEntry = temp.entries.firstWhere((entry) => entry.value.value); + // generate new color, ensure it is not the same + int newColor = oldEntry.value.key; + while(oldEntry.value.key == newColor) { + newColor = generateRandomLightColor().value; + } + // Update entry with new color, remain selected + temp.update(oldEntry.key, (old) => MapEntry(newColor, old.value)); + values[widget.items[r][e].key] = temp; + someValueChanged(); + }); + }, + icon: const Icon(Icons.format_color_fill_rounded), + visualDensity: VisualDensity.compact, + tooltip: tr('colour'), + )) + : const SizedBox.shrink(), (values[widget.items[r][e].key] as Map>?) ?.values From ed89e2082682b7cba00c00adbf98a8a21ce2edc4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Jul 2023 01:30:21 -0400 Subject: [PATCH 285/600] Fix error from previous conflict resolution commit --- lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 22692b7..609f9d9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -39,7 +39,7 @@ List> supportedLocales = const [ MapEntry(Locale('es'), 'Español'), MapEntry(Locale('pl'), 'Polski'), MapEntry(Locale('ru'), 'Русский язык'), - MapEntry(Locale('bs'), 'Bosanski'),Z + MapEntry(Locale('bs'), 'Bosanski'), ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; From 5cee527d6f33bfb8f5488da57f208ae4362ca5f2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Jul 2023 01:34:12 -0400 Subject: [PATCH 286/600] Copy error dialog on long press (#692) --- lib/custom_errors.dart | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/custom_errors.dart b/lib/custom_errors.dart index 5d0bb20..6343c87 100644 --- a/lib/custom_errors.dart +++ b/lib/custom_errors.dart @@ -1,6 +1,7 @@ import 'package:android_package_installer/android_package_installer.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:obtainium/providers/logs_provider.dart'; import 'package:provider/provider.dart'; @@ -101,7 +102,14 @@ showError(dynamic e, BuildContext context) { title: Text(e is MultiAppMultiError ? tr('someErrors') : tr('unexpectedError')), - content: Text(e.toString()), + content: GestureDetector( + onLongPress: () { + Clipboard.setData(ClipboardData(text: e.toString())); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(tr('copiedToClipboard')), + )); + }, + child: Text(e.toString())), actions: [ TextButton( onPressed: () { From 41f102c0cef786a6ee180f79158553d45053841b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Jul 2023 02:04:40 -0400 Subject: [PATCH 287/600] Minimum star count for GitHub/Codeberg search (#688) --- assets/translations/bs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/codeberg.dart | 10 ++++--- lib/app_sources/fdroid.dart | 3 +- lib/app_sources/github.dart | 46 ++++++++++++++++++++++-------- lib/app_sources/gitlab.dart | 3 +- lib/pages/import_export.dart | 7 +++-- lib/providers/source_provider.dart | 4 ++- 18 files changed, 63 insertions(+), 22 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 38e2b0d..b0296f6 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -239,6 +239,7 @@ "checkUpdateOnDetailPage": "Provjerite ima li novosti pri otvaranju stranice s detaljima aplikacije", "disablePageTransitions": "Ugasite animaciju prijelaza stranice", "reversePageTransitions": "Reverzne animacije prijelaza stranice", + "minStarCount": "Minimum Star Count", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index bee3009..78911ce 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -239,6 +239,7 @@ "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", + "minStarCount": "Minimum Star Count", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 6937f3e..d6afd88 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -239,6 +239,7 @@ "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", + "minStarCount": "Minimum Star Count", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index a572f71..ad5789e 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -239,6 +239,7 @@ "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", + "minStarCount": "Minimum Star Count", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 4db143d..eaa94a6 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -239,6 +239,7 @@ "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", + "minStarCount": "Minimum Star Count", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 8c014b4..6869452 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -239,6 +239,7 @@ "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", + "minStarCount": "Minimum Star Count", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 32fd821..7a9b1dd 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -238,6 +238,7 @@ "checkUpdateOnDetailPage": "Frissítések keresése az app részleteit tartalmazó oldal megnyitásakor", "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", + "minStarCount": "Minimum Star Count", "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 057d88f..064382e 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -239,6 +239,7 @@ "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", + "minStarCount": "Minimum Star Count", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index b5532f3..bf70542 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -239,6 +239,7 @@ "checkUpdateOnDetailPage": "アプリの詳細ページを開く際にアップデートを確認する", "disablePageTransitions": "ページ遷移アニメーションを無効化する", "reversePageTransitions": "ページ遷移アニメーションを反転する", + "minStarCount": "Minimum Star Count", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index e475cc0..755db7e 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -243,6 +243,7 @@ "checkUpdateOnDetailPage": "Sprawdzaj aktualizacje podczas otwierania strony szczegółów aplikacji", "disablePageTransitions": "Wyłącz animacje przejścia między stronami", "reversePageTransitions": "Odwróć animacje przejścia pomiędzy stronami", + "minStarCount": "Minimum Star Count", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index aa3d2eb..4b90d63 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -239,6 +239,7 @@ "checkUpdateOnDetailPage": "Проверять наличие обновлений при открытии страницы представления приложения", "disablePageTransitions": "Отключить анимацию перехода между страницами", "reversePageTransitions": "Реверс анимации перехода между страницами", + "minStarCount": "Minimum Star Count", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 2904972..55763dd 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -239,6 +239,7 @@ "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", + "minStarCount": "Minimum Star Count", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index f94cdb9..669e0d9 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -5,6 +5,7 @@ import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; class Codeberg extends AppSource { + GitHub gh = GitHub(); Codeberg() { host = 'codeberg.org'; @@ -32,10 +33,9 @@ class Codeberg extends AppSource { ]; canSearch = true; + searchQuerySettingFormItems = gh.searchQuerySettingFormItems; } - var gh = GitHub(); - @override String sourceSpecificStandardizeURL(String url) { RegExp standardUrlRegEx = RegExp('^https?://$host/[^/]+/[^/]+'); @@ -68,10 +68,12 @@ class Codeberg extends AppSource { } @override - Future>> search(String query) async { + Future>> search(String query, + {Map querySettings = const {}}) async { return gh.searchCommon( query, 'https://$host/api/v1/repos/search?q=${Uri.encodeQueryComponent(query)}&limit=100', - 'data'); + 'data', + querySettings: querySettings); } } diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 0602f6d..2f96fe7 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -72,7 +72,8 @@ class FDroid extends AppSource { } @override - Future>> search(String query) async { + Future>> search(String query, + {Map querySettings = const {}}) async { Response res = await sourceRequest( 'https://search.$host/?q=${Uri.encodeQueryComponent(query)}'); if (res.statusCode == 200) { diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 4334abd..0f74c47 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -79,6 +79,21 @@ class GitHub extends AppSource { ]; canSearch = true; + searchQuerySettingFormItems = [ + GeneratedFormTextField('minStarCount', + label: tr('minStarCount'), + defaultValue: '0', + additionalValidators: [ + (value) { + try { + int.parse(value ?? '0'); + } catch (e) { + return tr('invalidInput'); + } + return null; + } + ]) + ]; } @override @@ -310,20 +325,26 @@ class GitHub extends AppSource { Future>> searchCommon( String query, String requestUrl, String rootProp, - {Function(Response)? onHttpErrorCode}) async { + {Function(Response)? onHttpErrorCode, + Map querySettings = const {}}) async { Response res = await sourceRequest(requestUrl); if (res.statusCode == 200) { + int minStarCount = querySettings['minStarCount'] != null + ? int.parse(querySettings['minStarCount']) + : 0; Map> urlsWithDescriptions = {}; for (var e in (jsonDecode(res.body)[rootProp] as List)) { - urlsWithDescriptions.addAll({ - e['html_url'] as String: [ - e['full_name'] as String, - ((e['archived'] == true ? '[ARCHIVED] ' : '') + - (e['description'] != null - ? e['description'] as String - : tr('noDescription'))) - ] - }); + if ((e['stargazers_count'] ?? e['stars_count'] ?? 0) >= minStarCount) { + urlsWithDescriptions.addAll({ + e['html_url'] as String: [ + e['full_name'] as String, + ((e['archived'] == true ? '[ARCHIVED] ' : '') + + (e['description'] != null + ? e['description'] as String + : tr('noDescription'))) + ] + }); + } } return urlsWithDescriptions; } else { @@ -335,13 +356,14 @@ class GitHub extends AppSource { } @override - Future>> search(String query) async { + Future>> search(String query, + {Map querySettings = const {}}) async { return searchCommon( query, '${await getAPIHost()}/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100', 'items', onHttpErrorCode: (Response res) { rateLimitErrorCheck(res); - }); + }, querySettings: querySettings); } rateLimitErrorCheck(Response res) { diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index 574e814..ec2fd94 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -69,7 +69,8 @@ class GitLab extends AppSource { } @override - Future>> search(String query) async { + Future>> search(String query, + {Map querySettings = const {}}) async { String? PAT = await getPATIfAny(); if (PAT == null) { throw CredsNeededError(name); diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index fd10f86..e2ebdf9 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -182,7 +182,8 @@ class _ImportExportPageState extends State { [ GeneratedFormTextField('searchQuery', label: tr('searchQuery')) - ] + ], + ...source.searchQuerySettingFormItems.map((e) => [e]) ], ); }); @@ -191,8 +192,8 @@ class _ImportExportPageState extends State { setState(() { importInProgress = true; }); - var urlsWithDescriptions = - await source.search(values['searchQuery'] as String); + var urlsWithDescriptions = await source + .search(values['searchQuery'] as String, querySettings: values); if (urlsWithDescriptions.isNotEmpty) { var selectedUrls = // ignore: use_build_context_synchronously diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 6917ba5..f71c238 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -436,7 +436,9 @@ abstract class AppSource { } bool canSearch = false; - Future>> search(String query) { + List searchQuerySettingFormItems = []; + Future>> search(String query, + {Map querySettings = const {}}) { throw NotImplementedError(); } From 7671ab95f938b2cbfd0befaea946064739e89577 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Jul 2023 02:05:34 -0400 Subject: [PATCH 288/600] Update packages, increment versions --- lib/main.dart | 2 +- pubspec.lock | 24 ++++++++++++------------ pubspec.yaml | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 609f9d9..2b0d098 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.18'; +const String currentVersion = '0.13.19'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 003eae3..e80522b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -243,10 +243,10 @@ packages: dependency: "direct main" description: name: flutter_fgbg - sha256: d37511eef6afb7e2e3f2278ec6498bb12c650ed517c81bcd09452d910e8b9174 + sha256: "08c4d2fd229e3df26083d5aecc3dea9ff4f2d188f8cd57aaf2b3f047bd08a047" url: "https://pub.dev" source: hosted - version: "0.2.2" + version: "0.3.0" flutter_launcher_icons: dependency: "direct dev" description: @@ -538,10 +538,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: c0c9754479a4c4b1c1f3862ddc11930c9b3f03bef2816bb4ea6eed1e13551d6f + sha256: "2ffaf52a21f64ac9b35fe7369bb9533edbd4f698e5604db8645b1064ff4cf221" url: "https://pub.dev" source: hosted - version: "10.3.2" + version: "10.3.3" permission_handler_apple: dependency: transitive description: @@ -586,10 +586,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" pointycastle: dependency: transitive description: @@ -783,10 +783,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "15f5acbf0dce90146a0f5a2c4a002b1814a6303c4c5c075aa2623b2d16156f03" + sha256: "78cb6dea3e93148615109e58e42c35d1ffbf5ef66c44add673d0ab75f12ff3af" url: "https://pub.dev" source: hosted - version: "6.0.36" + version: "6.0.37" url_launcher_ios: dependency: transitive description: @@ -863,10 +863,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "27ad6a99c4b2d5e1ffd2b993a10f738b6b4979f139b4d64c34ac511595fcd748" + sha256: "8587d0b4991bd0f223f4b4957101c2c7449f905601571315f4967072498dd3fb" url: "https://pub.dev" source: hosted - version: "3.9.0" + version: "3.9.1" webview_flutter_platform_interface: dependency: transitive description: @@ -879,10 +879,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "369fdf6160944a7db660ff15fa048c2bd681b09557907beaef1f95e8557d21dc" + sha256: "3e36a8f564809cb7c257ff4278502b185e2191349df0ddee98837f91805c74b8" url: "https://pub.dev" source: hosted - version: "3.7.0" + version: "3.7.1" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9f785ad..0ab3397 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.13.18+182 # When changing this, update the tag in main() accordingly +version: 0.13.19+183 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' @@ -37,7 +37,7 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.5 path_provider: ^2.0.11 - flutter_fgbg: ^0.2.0 # Try removing reliance on this + flutter_fgbg: ^0.3.0 # Try removing reliance on this flutter_local_notifications: ^15.1.0+1 provider: ^6.0.3 http: ^1.0.0 From 58361a04936492d0ab95f215e7bea641e71ea8c4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Jul 2023 02:08:35 -0400 Subject: [PATCH 289/600] Ran dart fix --- lib/providers/apps_provider.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 80e6312..6cf8507 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -346,7 +346,7 @@ class AppsProvider with ChangeNotifier { // If 0 APKs installed, throw the first install error encountered try { var somethingInstalled = false; - var firstError = null; + Object? firstError; for (var file in dir.extracted .listSync(recursive: true, followLinks: false) .whereType()) { @@ -366,7 +366,7 @@ class AppsProvider with ChangeNotifier { } if (somethingInstalled) { dir.file.delete(recursive: true); - } else if (firstError) { + } else if (firstError != null) { throw firstError; } } finally { From b6a64129b3a0373eb4c64f844ce3dc54cf4a0b6f Mon Sep 17 00:00:00 2001 From: gidano Date: Sun, 23 Jul 2023 08:52:14 +0200 Subject: [PATCH 290/600] Update hu.json --- assets/translations/hu.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 7a9b1dd..21c11e1 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -236,9 +236,9 @@ "removeOnExternalUninstall": "A külsőleg eltávolított appok auto. eltávolítása", "pickHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", "checkUpdateOnDetailPage": "Frissítések keresése az app részleteit tartalmazó oldal megnyitásakor", - "disablePageTransitions": "Disable page transition animations", - "reversePageTransitions": "Reverse page transition animations", - "minStarCount": "Minimum Star Count", + "disablePageTransitions": "Lap áttűnési animációk tiltása", + "reversePageTransitions": "Fordított lap áttűnési animációk", + "minStarCount": "Minimális csillag szám", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From 42f87531668620bec01cf6b8a67d28620cdfbc43 Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Sun, 23 Jul 2023 14:34:15 +0300 Subject: [PATCH 291/600] Update ru.json --- assets/translations/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 4b90d63..8ce8341 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -239,7 +239,7 @@ "checkUpdateOnDetailPage": "Проверять наличие обновлений при открытии страницы представления приложения", "disablePageTransitions": "Отключить анимацию перехода между страницами", "reversePageTransitions": "Реверс анимации перехода между страницами", - "minStarCount": "Minimum Star Count", + "minStarCount": "Минимальное количество звёзд", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" From 6e047e96fa1c6b037081d5ad43fb3e7ce9653214 Mon Sep 17 00:00:00 2001 From: Matsuri Date: Sun, 23 Jul 2023 19:56:23 +0800 Subject: [PATCH 292/600] Update Chinese translation - Translate new strings Signed-off-by: Matsuri --- assets/translations/zh.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 55763dd..c622c70 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -234,12 +234,12 @@ "requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)", "checkOnStart": "启动时进行一次检查", "tryInferAppIdFromCode": "尝试从源代码推断应用 ID", - "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", - "pickHighestVersionCode": "Auto-select highest version code APK", - "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", - "disablePageTransitions": "Disable page transition animations", - "reversePageTransitions": "Reverse page transition animations", - "minStarCount": "Minimum Star Count", + "removeOnExternalUninstall": "自动删除已卸载的外部应用", + "pickHighestVersionCode": "自动选择版本号最高的 APK 文件", + "checkUpdateOnDetailPage": "打开应用详情页时检查更新", + "disablePageTransitions": "禁用页面过渡动画效果", + "reversePageTransitions": "反转页面过渡动画效果", + "minStarCount": "最小星标数", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" From 3a4c782aab44b106bd98e14f6e2c2c98d9be5fa3 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Jul 2023 14:23:34 -0400 Subject: [PATCH 293/600] Fix empty error messages for HTTP errors --- lib/providers/source_provider.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index f71c238..8ddea20 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -449,8 +449,11 @@ abstract class AppSource { } ObtainiumError getObtainiumHttpError(Response res) { - return ObtainiumError(res.reasonPhrase ?? - tr('errorWithHttpStatusCode', args: [res.statusCode.toString()])); + return ObtainiumError((res.reasonPhrase != null && + res.reasonPhrase != null && + res.reasonPhrase!.isNotEmpty) + ? res.reasonPhrase! + : tr('errorWithHttpStatusCode', args: [res.statusCode.toString()])); } abstract class MassAppUrlSource { From 7767468d5d71b6a7eac6dd54c62ed1cc1ffe603e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Jul 2023 14:26:22 -0400 Subject: [PATCH 294/600] Increment version, update modules --- lib/main.dart | 2 +- pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 2b0d098..5e22d51 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.19'; +const String currentVersion = '0.13.20'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index e80522b..662156b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -222,10 +222,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: b1729fc96627dd44012d0a901558177418818d6bd428df59dcfeb594e5f66432 + sha256: "21145c9c268d54b1f771d8380c195d2d6f655e0567dc1ca2f9c134c02c819e0a" url: "https://pub.dev" source: hosted - version: "5.3.2" + version: "5.3.3" flutter: dependency: "direct main" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 0ab3397..801a7d9 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.13.19+183 # When changing this, update the tag in main() accordingly +version: 0.13.20+184 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 995d44551cd020d143ed2cb2180c90ff5ebd14eb Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 23 Jul 2023 15:02:58 -0400 Subject: [PATCH 295/600] Auto retry failed download (3 times) (#634) --- lib/main.dart | 2 +- lib/providers/apps_provider.dart | 23 +++++++++++++++++++++-- pubspec.yaml | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 5e22d51..51c252c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.20'; +const String currentVersion = '0.13.21'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 6cf8507..7bd83be 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -144,6 +144,24 @@ class AppsProvider with ChangeNotifier { }(); } + Future downloadFileWithRetry( + String url, String fileNameNoExt, Function? onProgress, + {bool useExisting = true, + Map? headers, + int retries = 3}) async { + try { + return await downloadFile(url, fileNameNoExt, onProgress, + useExisting: useExisting, headers: headers); + } catch (e) { + if (retries > 0 && e is ClientException) { + return await downloadFileWithRetry(url, fileNameNoExt, onProgress, + useExisting: useExisting, headers: headers, retries: (retries - 1)); + } else { + rethrow; + } + } + } + Future downloadFile( String url, String fileNameNoExt, Function? onProgress, {bool useExisting = true, Map? headers}) async { @@ -236,8 +254,9 @@ class AppsProvider with ChangeNotifier { notificationsProvider?.cancel(notif.id); int? prevProg; var fileNameNoExt = '${app.id}-${downloadUrl.hashCode}'; - var downloadedFile = await downloadFile(downloadUrl, fileNameNoExt, - headers: source.requestHeaders, (double? progress) { + var downloadedFile = await downloadFileWithRetry( + downloadUrl, fileNameNoExt, headers: source.requestHeaders, + (double? progress) { int? prog = progress?.ceil(); if (apps[app.id] != null) { apps[app.id]!.downloadProgress = progress; diff --git a/pubspec.yaml b/pubspec.yaml index 801a7d9..9cdc749 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.13.20+184 # When changing this, update the tag in main() accordingly +version: 0.13.21+185 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From af5a6857ba6f085b191fb22ab07db954fb66776a Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Mon, 24 Jul 2023 23:42:11 +0200 Subject: [PATCH 296/600] locale(pl): Update Polish translations Co-authored-by: Daviteusz --- assets/translations/pl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 755db7e..adbd473 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -243,7 +243,7 @@ "checkUpdateOnDetailPage": "Sprawdzaj aktualizacje podczas otwierania strony szczegółów aplikacji", "disablePageTransitions": "Wyłącz animacje przejścia między stronami", "reversePageTransitions": "Odwróć animacje przejścia pomiędzy stronami", - "minStarCount": "Minimum Star Count", + "minStarCount": "Minimalna ilość gwiazdek", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" From 10ead4f3e0bcd04e002dfef98031ebbac5d4d42a Mon Sep 17 00:00:00 2001 From: Markus <82206269+markus-gitdev@users.noreply.github.com> Date: Sat, 29 Jul 2023 14:44:21 +0200 Subject: [PATCH 297/600] Update de.json --- assets/translations/de.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 78911ce..9ddaff8 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -233,13 +233,13 @@ "about": "Über", "requiresCredentialsInSettings": "Benötigt zusätzliche Anmeldedaten (in den Einstellungen)", "checkOnStart": "Überprüfe einmalig beim Start", - "tryInferAppIdFromCode": "Try inferring App ID from source code", - "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", - "pickHighestVersionCode": "Auto-select highest version code APK", - "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", - "disablePageTransitions": "Disable page transition animations", - "reversePageTransitions": "Reverse page transition animations", - "minStarCount": "Minimum Star Count", + "tryInferAppIdFromCode": "Versuche, die App-ID aus dem Quellcode zu ermitteln", + "removeOnExternalUninstall": "Automatisches Entfernen von extern deinstallierten Apps", + "pickHighestVersionCode": "Automatische Auswahl des APK mit höchstem Versionscode", + "checkUpdateOnDetailPage": "Nach Updates suchen, wenn eine App-Detailseite geöffnet wird", + "disablePageTransitions": "Animationen für Seitenübergänge deaktivieren", + "reversePageTransitions": "Umgekehrte Animationen für Seitenübergänge", + "minStarCount": "Minimale Anzahl von Sternen", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" From a8bfb03f58477a5edc5b5cb720f6d3844cd8a3f6 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 29 Jul 2023 20:22:04 -0400 Subject: [PATCH 298/600] Wait 5s between download retries --- lib/providers/apps_provider.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 7bd83be..9c8d7db 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -154,6 +154,7 @@ class AppsProvider with ChangeNotifier { useExisting: useExisting, headers: headers); } catch (e) { if (retries > 0 && e is ClientException) { + await Future.delayed(const Duration(seconds: 5)); return await downloadFileWithRetry(url, fileNameNoExt, onProgress, useExisting: useExisting, headers: headers, retries: (retries - 1)); } else { From 76f8cd4102adef7926dcb636bbd7c3e76d2c4001 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 29 Jul 2023 22:06:42 -0400 Subject: [PATCH 299/600] Source configuration settings changes - "Source config" refers to source-specific, app-agnostic settings - Don't use saved config for overridden sources - For overridden sources, use app-specific source config - Allow sources to show notes on add-app page (#720) --- assets/translations/bs.json | 4 ++++ assets/translations/de.json | 4 ++++ assets/translations/en.json | 4 ++++ assets/translations/es.json | 4 ++++ 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/pl.json | 4 ++++ assets/translations/ru.json | 4 ++++ assets/translations/zh.json | 4 ++++ lib/app_sources/codeberg.dart | 2 -- lib/app_sources/github.dart | 33 ++++++++++++++++++--------- lib/app_sources/gitlab.dart | 21 ++++++++++++----- lib/mass_app_sources/githubstars.dart | 2 +- lib/pages/add_app.dart | 28 ++++++++++++++++++----- lib/pages/settings.dart | 4 ++-- lib/providers/source_provider.dart | 22 +++++++++++++++++- 19 files changed, 131 insertions(+), 29 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index b0296f6..dd9c8be 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Ugasite animaciju prijelaza stranice", "reversePageTransitions": "Reverzne animacije prijelaza stranice", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 78911ce..f58b4ba 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index d6afd88..e86bf32 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index ad5789e..2708bce 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index eaa94a6..781b45b 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 6869452..1619faf 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 21c11e1..399686d 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -239,6 +239,10 @@ "disablePageTransitions": "Lap áttűnési animációk tiltása", "reversePageTransitions": "Fordított lap áttűnési animációk", "minStarCount": "Minimális csillag szám", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "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 064382e..e905551 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index bf70542..58129b4 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -240,6 +240,10 @@ "disablePageTransitions": "ページ遷移アニメーションを無効化する", "reversePageTransitions": "ページ遷移アニメーションを反転する", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 755db7e..360b928 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -244,6 +244,10 @@ "disablePageTransitions": "Wyłącz animacje przejścia między stronami", "reversePageTransitions": "Odwróć animacje przejścia pomiędzy stronami", "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 8ce8341..68f8e6c 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -240,6 +240,10 @@ "disablePageTransitions": "Отключить анимацию перехода между страницами", "reversePageTransitions": "Реверс анимации перехода между страницами", "minStarCount": "Минимальное количество звёзд", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index c622c70..8bed1fa 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -240,6 +240,10 @@ "disablePageTransitions": "禁用页面过渡动画效果", "reversePageTransitions": "反转页面过渡动画效果", "minStarCount": "最小星标数", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index 669e0d9..8e9ef04 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -9,8 +9,6 @@ class Codeberg extends AppSource { Codeberg() { host = 'codeberg.org'; - additionalSourceSpecificSettingFormItems = []; - additionalSourceAppSpecificSettingFormItems = [ [ GeneratedFormSwitch('includePrereleases', diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 0f74c47..b6a5e2d 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -16,7 +16,7 @@ class GitHub extends AppSource { host = 'github.com'; appIdInferIsOptional = true; - additionalSourceSpecificSettingFormItems = [ + sourceConfigSettingFormItems = [ GeneratedFormTextField('github-creds', label: tr('githubPATLabel'), password: true, @@ -107,7 +107,7 @@ class GitHub extends AppSource { for (var path in possibleBuildGradleLocations) { try { var res = await sourceRequest( - '${await convertStandardUrlToAPIUrl(standardUrl)}/contents/$path'); + '${await convertStandardUrlToAPIUrl(standardUrl, additionalSettings)}/contents/$path'); if (res.statusCode == 200) { try { var body = jsonDecode(res.body); @@ -155,19 +155,30 @@ class GitHub extends AppSource { return url.substring(0, match.end); } - Future getCredentialPrefixIfAny() async { + Future getCredentialPrefixIfAny( + Map additionalSettings) async { SettingsProvider settingsProvider = SettingsProvider(); await settingsProvider.initializeSettings(); - String? creds = settingsProvider - .getSettingString(additionalSourceSpecificSettingFormItems[0].key); + var sourceConfig = + await getSourceConfigValues(additionalSettings, settingsProvider); + String? creds = sourceConfig['github-creds']; return creds != null && creds.isNotEmpty ? '$creds@' : ''; } - Future getAPIHost() async => - 'https://${await getCredentialPrefixIfAny()}api.$host'; + @override + Future getSourceNote() async { + if (!hostChanged && (await getCredentialPrefixIfAny({})).isEmpty) { + return '${tr('githubSourceNote')} ${hostChanged ? tr('addInfoBelow') : tr('addInfoInSettings')}'; + } + return null; + } - Future convertStandardUrlToAPIUrl(String standardUrl) async => - '${await getAPIHost()}/repos${standardUrl.substring('https://$host'.length)}'; + Future getAPIHost(Map additionalSettings) async => + 'https://${await getCredentialPrefixIfAny(additionalSettings)}api.$host'; + + Future convertStandardUrlToAPIUrl( + String standardUrl, Map additionalSettings) async => + '${await getAPIHost(additionalSettings)}/repos${standardUrl.substring('https://$host'.length)}'; @override String? changeLogPageFromStandardUrl(String standardUrl) => @@ -311,7 +322,7 @@ class GitHub extends AppSource { ) async { return await getLatestAPKDetailsCommon2(standardUrl, additionalSettings, (bool useTagUrl) async { - return '${await convertStandardUrlToAPIUrl(standardUrl)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100'; + return '${await convertStandardUrlToAPIUrl(standardUrl, additionalSettings)}/${useTagUrl ? 'tags' : 'releases'}?per_page=100'; }, (Response res) { rateLimitErrorCheck(res); }); @@ -360,7 +371,7 @@ class GitHub extends AppSource { {Map querySettings = const {}}) async { return searchCommon( query, - '${await getAPIHost()}/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100', + '${await getAPIHost({})}/search/repositories?q=${Uri.encodeQueryComponent(query)}&per_page=100', 'items', onHttpErrorCode: (Response res) { rateLimitErrorCheck(res); }, querySettings: querySettings); diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index ec2fd94..bea24eb 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -16,7 +16,7 @@ class GitLab extends AppSource { host = 'gitlab.com'; canSearch = true; - additionalSourceSpecificSettingFormItems = [ + sourceConfigSettingFormItems = [ GeneratedFormTextField('gitlab-creds', label: tr('gitlabPATLabel'), password: true, @@ -60,18 +60,27 @@ class GitLab extends AppSource { return url.substring(0, match.end); } - Future getPATIfAny() async { + Future getPATIfAny(Map additionalSettings) async { SettingsProvider settingsProvider = SettingsProvider(); await settingsProvider.initializeSettings(); - String? creds = settingsProvider - .getSettingString(additionalSourceSpecificSettingFormItems[0].key); + var sourceConfig = + await getSourceConfigValues(additionalSettings, settingsProvider); + String? creds = sourceConfig['gitlab-creds']; return creds != null && creds.isNotEmpty ? creds : null; } + @override + Future getSourceNote() async { + if ((await getPATIfAny({})) == null) { + return '${tr('gitlabSourceNote')} ${hostChanged ? tr('addInfoBelow') : tr('addInfoInSettings')}'; + } + return null; + } + @override Future>> search(String query, {Map querySettings = const {}}) async { - String? PAT = await getPATIfAny(); + String? PAT = await getPATIfAny({}); if (PAT == null) { throw CredsNeededError(name); } @@ -103,7 +112,7 @@ class GitLab extends AppSource { ) async { bool fallbackToOlderReleases = additionalSettings['fallbackToOlderReleases'] == true; - String? PAT = await getPATIfAny(); + String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {}); Iterable apkDetailsList = []; if (PAT != null) { var names = GitHub().getAppNames(standardUrl); diff --git a/lib/mass_app_sources/githubstars.dart b/lib/mass_app_sources/githubstars.dart index 5a086f1..db8495b 100644 --- a/lib/mass_app_sources/githubstars.dart +++ b/lib/mass_app_sources/githubstars.dart @@ -16,7 +16,7 @@ class GitHubStars implements MassAppUrlSource { Future>> getOnePageOfUserStarredUrlsWithDescriptions( String username, int page) async { Response res = await get(Uri.parse( - 'https://${await GitHub().getCredentialPrefixIfAny()}api.github.com/users/$username/starred?per_page=100&page=$page')); + 'https://${await GitHub().getCredentialPrefixIfAny({})}api.github.com/users/$username/starred?per_page=100&page=$page')); if (res.statusCode == 200) { Map> urlsWithDescriptions = {}; for (var e in (jsonDecode(res.body) as List)) { diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index b31dc4d..0f8095c 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -41,6 +41,7 @@ class _AddAppPageState extends State { @override Widget build(BuildContext context) { AppsProvider appsProvider = context.read(); + SettingsProvider settingsProvider = context.watch(); bool doingSomething = gettingAppInfo || searching; @@ -85,8 +86,7 @@ class _AddAppPageState extends State { } } - Future getTrackOnlyConfirmationIfNeeded( - bool userPickedTrackOnly, SettingsProvider settingsProvider, + Future getTrackOnlyConfirmationIfNeeded(bool userPickedTrackOnly, {bool ignoreHideSetting = false}) async { var useTrackOnly = userPickedTrackOnly || pickedSource!.enforceTrackOnly; if (useTrackOnly && @@ -138,11 +138,9 @@ class _AddAppPageState extends State { gettingAppInfo = true; }); try { - var settingsProvider = context.read(); var userPickedTrackOnly = additionalSettings['trackOnly'] == true; App? app; - if ((await getTrackOnlyConfirmationIfNeeded( - userPickedTrackOnly, settingsProvider)) && + if ((await getTrackOnlyConfirmationIfNeeded(userPickedTrackOnly)) && (await getReleaseDateAsVersionConfirmationIfNeeded( userPickedTrackOnly))) { var trackOnly = pickedSource!.enforceTrackOnly || userPickedTrackOnly; @@ -410,7 +408,13 @@ class _AddAppPageState extends State { ), GeneratedForm( key: Key(pickedSource.runtimeType.toString()), - items: pickedSource!.combinedAppSpecificSettingFormItems, + items: [ + ...pickedSource!.combinedAppSpecificSettingFormItems, + ...(pickedSourceOverride != null + ? pickedSource!.sourceConfigSettingFormItems + .map((e) => [e]) + : []) + ], onValueChanges: (values, valid, isBuilding) { if (!isBuilding) { setState(() { @@ -504,6 +508,18 @@ class _AddAppPageState extends State { HTML().runtimeType.toString())) getHTMLSourceOverrideDropdown(), if (shouldShowSearchBar()) getSearchBarRow(), + if (pickedSource != null) + FutureBuilder( + builder: (ctx, val) { + return val.data != null && val.data!.isNotEmpty + ? Text( + val.data!, + style: + Theme.of(context).textTheme.bodySmall, + ) + : const SizedBox(); + }, + future: pickedSource?.getSourceNote()), const SizedBox( height: 16, ), diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 2a42376..c96c72d 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -166,9 +166,9 @@ class _SettingsPageState extends State { }); var sourceSpecificFields = sourceProvider.sources.map((e) { - if (e.additionalSourceSpecificSettingFormItems.isNotEmpty) { + if (e.sourceConfigSettingFormItems.isNotEmpty) { return GeneratedForm( - items: e.additionalSourceSpecificSettingFormItems.map((e) { + items: e.sourceConfigSettingFormItems.map((e) { e.defaultValue = settingsProvider.getSettingString(e.key); return [e]; }).toList(), diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 8ddea20..ca2c969 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -28,6 +28,7 @@ import 'package:obtainium/app_sources/vlc.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; @@ -424,12 +425,31 @@ abstract class AppSource { } // Some Sources may have additional settings at the Source level (not specific to Apps) - these use SettingsProvider - List additionalSourceSpecificSettingFormItems = []; + // If the source has been overridden, we expect the user to define one-time values as additional settings - don't use the stored values + List sourceConfigSettingFormItems = []; + Future> getSourceConfigValues( + Map additionalSettings, + SettingsProvider settingsProvider) async { + Map results = {}; + sourceConfigSettingFormItems.forEach((e) { + var val = hostChanged + ? additionalSettings[e.key] + : settingsProvider.getSettingString(e.key); + if (val != null) { + results[e.key] = val; + } + }); + return results; + } String? changeLogPageFromStandardUrl(String standardUrl) { return null; } + Future getSourceNote() async { + return null; + } + Future apkUrlPrefetchModifier( String apkUrl, String standardUrl) async { return apkUrl; From 3dafd643c010630e0a9277367fdbdb3a4cc9c497 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 29 Jul 2023 22:21:07 -0400 Subject: [PATCH 300/600] Only show host+path for ClientException log (#714) --- lib/main.dart | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 51c252c..da6a35f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:http/http.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/pages/home.dart'; import 'package:obtainium/providers/apps_provider.dart'; @@ -101,10 +102,15 @@ Future bgUpdateCheck(int taskId, Map? params) async { await appsProvider.checkUpdates( ignoreAppsCheckedAfter: ignoreAfter, throwErrorsForRetry: true); } catch (e) { - if (e is RateLimitError || e is SocketException) { + if (e is RateLimitError || e is ClientException) { var remainingMinutes = e is RateLimitError ? e.remainingMinutes : 15; - logs.add(plural('bgUpdateGotErrorRetryInMinutes', remainingMinutes, - args: [e.toString(), remainingMinutes.toString()])); + logs.add( + plural('bgUpdateGotErrorRetryInMinutes', remainingMinutes, args: [ + e is ClientException + ? '${(e).message}, ${e.uri?.path}' + : e.toString(), + remainingMinutes.toString() + ])); AndroidAlarmManager.oneShot(Duration(minutes: remainingMinutes), Random().nextInt(pow(2, 31) as int), bgUpdateCheck, params: { 'ignoreAfterMicroseconds': nextIgnoreAfter.microsecondsSinceEpoch From cccde7e135024db56ff8c8d5129b06f1c7aeb6bb Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 29 Jul 2023 22:29:08 -0400 Subject: [PATCH 301/600] UI bugfix (#723) --- lib/pages/apps.dart | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 173beb2..894967e 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -543,20 +543,19 @@ class AppsPageState extends State { : FontWeight.normal)), trailing: listedApps[index].downloadProgress != null ? SizedBox( - width: 90, child: Text( - listedApps[index].downloadProgress! >= 0 - ? tr('percentProgress', args: [ - listedApps[index] - .downloadProgress! - .toInt() - .toString() - ]) - : tr('pleaseWait'), - textAlign: (listedApps[index].downloadProgress! >= 0) - ? TextAlign.start - : TextAlign.end, - )) + listedApps[index].downloadProgress! >= 0 + ? tr('percentProgress', args: [ + listedApps[index] + .downloadProgress! + .toInt() + .toString() + ]) + : tr('pleaseWait'), + textAlign: (listedApps[index].downloadProgress! >= 0) + ? TextAlign.start + : TextAlign.end, + )) : trailingRow, onTap: () { if (selectedAppIds.isNotEmpty) { From 14755134bf36d4df7f34857fc64a841409d82fc9 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 29 Jul 2023 22:39:50 -0400 Subject: [PATCH 302/600] Use icon button for delete on app page (#722) --- lib/pages/app.dart | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 4d97d54..0708b02 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -431,8 +431,7 @@ class _AppPageState extends State { ? getResetInstallStatusButton() : getInstallOrUpdateButton()), const SizedBox(width: 16.0), - Expanded( - child: TextButton( + IconButton( onPressed: app?.downloadProgress != null ? null : () { @@ -445,13 +444,9 @@ class _AppPageState extends State { } }); }, - style: TextButton.styleFrom( - foregroundColor: - Theme.of(context).colorScheme.error, - surfaceTintColor: - Theme.of(context).colorScheme.error), - child: Text(tr('remove')), - )), + tooltip: tr('remove'), + icon: const Icon(Icons.delete_outline), + ), ])), if (app?.downloadProgress != null) Padding( From 5dd79707f10b409d83d8937cebaee2f1c7876a26 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 29 Jul 2023 22:40:52 -0400 Subject: [PATCH 303/600] Update packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 20 ++++++++++---------- pubspec.yaml | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index da6a35f..d330268 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -22,7 +22,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.21'; +const String currentVersion = '0.13.22'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 662156b..c4ff360 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -695,18 +695,18 @@ packages: dependency: "direct main" description: name: sqflite - sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 + sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" url: "https://pub.dev" source: hosted - version: "2.2.8+4" + version: "2.3.0" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "8f7603f3f8f126740bc55c4ca2d1027aab4b74a1267a3e31ce51fe40e3b65b8f" + sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a" url: "https://pub.dev" source: hosted - version: "2.4.5+1" + version: "2.5.0" stack_trace: dependency: transitive description: @@ -863,10 +863,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "8587d0b4991bd0f223f4b4957101c2c7449f905601571315f4967072498dd3fb" + sha256: d936a09fbfd08cb78f7329e0bbacf6158fbdfe24ffc908b22444c07d295eb193 url: "https://pub.dev" source: hosted - version: "3.9.1" + version: "3.9.2" webview_flutter_platform_interface: dependency: transitive description: @@ -879,18 +879,18 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "3e36a8f564809cb7c257ff4278502b185e2191349df0ddee98837f91805c74b8" + sha256: "5fa098f28b606f699e8ca52d9e4e11edbbfef65189f5f77ae92703ba5408fd25" url: "https://pub.dev" source: hosted - version: "3.7.1" + version: "3.7.2" win32: dependency: transitive description: name: win32 - sha256: dfdf0136e0aa7a1b474ea133e67cb0154a0acd2599c4f3ada3b49d38d38793ee + sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0 url: "https://pub.dev" source: hosted - version: "5.0.5" + version: "5.0.6" win32_registry: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9cdc749..8f84e5d 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.13.21+185 # When changing this, update the tag in main() accordingly +version: 0.13.22+186 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 6d22788f9274154ad19d890eee62b14480764a70 Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Sun, 30 Jul 2023 13:03:14 +0300 Subject: [PATCH 304/600] Update ru.json --- assets/translations/ru.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 68f8e6c..14b5f06 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -240,10 +240,10 @@ "disablePageTransitions": "Отключить анимацию перехода между страницами", "reversePageTransitions": "Реверс анимации перехода между страницами", "minStarCount": "Минимальное количество звёзд", - "addInfoBelow": "Add this info below.", - "addInfoInSettings": "Add this info in the Settings.", - "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", - "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "addInfoBelow": "Добавьте эту информацию ниже.", + "addInfoInSettings": "Добавьте эту информацию в Настройки.", + "githubSourceNote": "Лимит запросов GitHub можно обойти, используя ключ API.", + "gitlabSourceNote": "Извлечение APK из GitLab может не работать без ключа API.", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" From 2a603f410fd84423b1f745ec89a7a7b28abc4466 Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Sun, 30 Jul 2023 16:28:42 +0200 Subject: [PATCH 305/600] locale(pl): Update Polish translations Co-authored-by: Daviteusz --- assets/translations/pl.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index f771b20..e957c9b 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -244,10 +244,10 @@ "disablePageTransitions": "Wyłącz animacje przejścia między stronami", "reversePageTransitions": "Odwróć animacje przejścia pomiędzy stronami", "minStarCount": "Minimalna ilość gwiazdek", - "addInfoBelow": "Add this info below.", - "addInfoInSettings": "Add this info in the Settings.", - "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", - "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "addInfoBelow": "Dodaj tę informację poniżej.", + "addInfoInSettings": "Dodaj tę informację w Ustawieniach.", + "githubSourceNote": "Limit żądań GitHub można ominąć za pomocą klucza API.", + "gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" From 6861a71efb97e65cf1bc3080adc234ee87c825e7 Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Mon, 31 Jul 2023 19:52:12 +0900 Subject: [PATCH 306/600] Update ja.json --- assets/translations/ja.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 58129b4..aaf4530 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -239,11 +239,11 @@ "checkUpdateOnDetailPage": "アプリの詳細ページを開く際にアップデートを確認する", "disablePageTransitions": "ページ遷移アニメーションを無効化する", "reversePageTransitions": "ページ遷移アニメーションを反転する", - "minStarCount": "Minimum Star Count", - "addInfoBelow": "Add this info below.", - "addInfoInSettings": "Add this info in the Settings.", - "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", - "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "minStarCount": "最小スター数", + "addInfoBelow": "下部でこの情報を追加してください。", + "addInfoInSettings": "設定でこの情報を追加してください。", + "githubSourceNote": "GitHubのレート制限はAPIキーを使うことで回避できます。", + "gitlabSourceNote": "GitLabのAPK抽出はAPIキーがないと動作しない場合があります。", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" From 3f8cfae64ea10f36021687cf07e53e727f92dbd7 Mon Sep 17 00:00:00 2001 From: gidano Date: Tue, 1 Aug 2023 16:28:31 +0200 Subject: [PATCH 307/600] Update hu.json --- assets/translations/hu.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 399686d..6beafe7 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -17,7 +17,7 @@ "bgUpdateTaskFinished": "A háttérfrissítés ellenőrzési feladat befejeződött", "firstRun": "Ez az Obtainium első futása", "settingUpdateCheckIntervalTo": "A frissítési intervallum beállítása erre: {}", - "githubPATLabel": "GitHub személyes hozzáférési token (megnöveli a díjkorlátot)", + "githubPATLabel": "GitHub Personal Access Token (megnöveli a díjkorlátot)", "githubPATHint": "A PAT-nak a következő formátumban kell lennie: felhasználónév:token", "githubPATFormat": "felhasználónév:token", "includePrereleases": "Tartalmazza az előzetes kiadásokat", @@ -228,7 +228,7 @@ "dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést", "dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket", "moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára", - "gitlabPATLabel": "GitLab Personal Access Token\n(Engedélyezi a Keresést and Better APK Discovery)", + "gitlabPATLabel": "GitLab Personal Access Token\n(Engedélyezi a Keresést és jobb APK felfedezés)", "about": "Rólunk", "requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)", "checkOnStart": "Egyszer az indításkor", @@ -239,10 +239,10 @@ "disablePageTransitions": "Lap áttűnési animációk tiltása", "reversePageTransitions": "Fordított lap áttűnési animációk", "minStarCount": "Minimális csillag szám", - "addInfoBelow": "Add this info below.", - "addInfoInSettings": "Add this info in the Settings.", - "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", - "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "addInfoBelow": "Adja hozzá ezt az infót alább.", + "addInfoInSettings": "Adja hozzá ezt az infót a Beállításokban.", + "githubSourceNote": "A GitHub értékelési korlátozása elkerülhető API-kulcs használatával.", + "gitlabSourceNote": "Előfordulhat, hogy a GitLab APK kibontása nem működik API-kulcs nélkül.", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From 16ae8d8e4d5dda8e6e190a229317d01e2bda3df0 Mon Sep 17 00:00:00 2001 From: vaginessa Date: Sat, 5 Aug 2023 15:53:09 +0200 Subject: [PATCH 308/600] Update de.json - translate missing strings --- assets/translations/de.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 3d709d4..95028a6 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -240,10 +240,10 @@ "disablePageTransitions": "Animationen für Seitenübergänge deaktivieren", "reversePageTransitions": "Umgekehrte Animationen für Seitenübergänge", "minStarCount": "Minimale Anzahl von Sternen", - "addInfoBelow": "Add this info below.", - "addInfoInSettings": "Add this info in the Settings.", - "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", - "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "addInfoBelow": "Fügen Sie diese Informationen unten hinzu.", + "addInfoInSettings": "Fügen Sie diese Info in den Einstellungen hinzu.", + "githubSourceNote": "Die GitHub-Ratenbegrenzung kann mit einem API-Schlüssel umgangen werden.", + "gitlabSourceNote": "GitLab APK-Extraktion funktioniert möglicherweise nicht ohne API-Schlüssel", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" From 73c20a53d20e8405ccac64e6ae82af2eb0b77b90 Mon Sep 17 00:00:00 2001 From: Matsuri Date: Sat, 5 Aug 2023 23:27:13 +0800 Subject: [PATCH 309/600] Update zh.json - Translate new strings - Slight improvements Signed-off-by: Matsuri --- assets/translations/zh.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 8bed1fa..6a3058e 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -107,7 +107,7 @@ "searchX": "搜索 {}", "noResults": "无结果", "importX": "导入 {}", - "importedAppsIdDisclaimer": "导入的应用可能错误地显示为“未安装”。\n请通过 Obtainium 重新安装这些应用来解决此问题。", + "importedAppsIdDisclaimer": "导入的应用可能会错误地显示为“未安装”状态。\n请通过 Obtainium 重新安装这些应用来解决此问题。", "importErrors": "导入错误", "importedXOfYApps": "已导入 {} 中的 {} 个应用。", "followingURLsHadErrors": "下列 URL 存在错误:", @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "不显示“仅追踪”模式警告", "dontShowAPKOriginWarnings": "不显示 APK 文件来源警告", "moveNonInstalledAppsToBottom": "将未安装应用置底", - "gitlabPATLabel": "GitLab 个人访问令牌\n(用于搜索应用 and Better APK Discovery)", + "gitlabPATLabel": "GitLab 个人访问令牌\n(启用搜索功能并增强 APK 发现)", "about": "相关文档", "requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)", "checkOnStart": "启动时进行一次检查", @@ -240,10 +240,10 @@ "disablePageTransitions": "禁用页面过渡动画效果", "reversePageTransitions": "反转页面过渡动画效果", "minStarCount": "最小星标数", - "addInfoBelow": "Add this info below.", - "addInfoInSettings": "Add this info in the Settings.", - "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", - "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "addInfoBelow": "在下方添加此凭据。", + "addInfoInSettings": "在“设置”中添加此凭据。", + "githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。", + "gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" From 12a8ef5e319f229374cdec17bb63ab0f328ae950 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 5 Aug 2023 12:39:58 -0400 Subject: [PATCH 310/600] Fix a French word (#735) --- assets/translations/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 1619faf..728f500 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -45,7 +45,7 @@ "addApp": "Ajouter une application", "appSourceURL": "URL de la source de l'application", "error": "Erreur", - "add": "Ajoutée", + "add": "Ajouter", "searchSomeSourcesLabel": "Rechercher (certaines sources uniquement)", "search": "Rechercher", "additionalOptsFor": "Options supplémentaires pour {}", From f426b5e118389b6dab47fba4c0a268fbb70aeb29 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 5 Aug 2023 12:52:08 -0400 Subject: [PATCH 311/600] Add filename-only sort for HTML (#734) --- assets/translations/bs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/html.dart | 14 +++++++++++++- 13 files changed, 25 insertions(+), 1 deletion(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index dd9c8be..433984e 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -244,6 +244,7 @@ "addInfoInSettings": "Add this info in the Settings.", "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 95028a6..d7ea035 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -244,6 +244,7 @@ "addInfoInSettings": "Fügen Sie diese Info in den Einstellungen hinzu.", "githubSourceNote": "Die GitHub-Ratenbegrenzung kann mit einem API-Schlüssel umgangen werden.", "gitlabSourceNote": "GitLab APK-Extraktion funktioniert möglicherweise nicht ohne API-Schlüssel", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index e86bf32..551cdb6 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -244,6 +244,7 @@ "addInfoInSettings": "Add this info in the Settings.", "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 2708bce..b7aae29 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -244,6 +244,7 @@ "addInfoInSettings": "Add this info in the Settings.", "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 781b45b..a7dace4 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -244,6 +244,7 @@ "addInfoInSettings": "Add this info in the Settings.", "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 728f500..0a8cfbf 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -244,6 +244,7 @@ "addInfoInSettings": "Add this info in the Settings.", "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 6beafe7..6498b44 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -243,6 +243,7 @@ "addInfoInSettings": "Adja hozzá ezt az infót a Beállításokban.", "githubSourceNote": "A GitHub értékelési korlátozása elkerülhető API-kulcs használatával.", "gitlabSourceNote": "Előfordulhat, hogy a GitLab APK kibontása nem működik API-kulcs nélkül.", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "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 e905551..49eec85 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -244,6 +244,7 @@ "addInfoInSettings": "Add this info in the Settings.", "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index aaf4530..528469a 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -244,6 +244,7 @@ "addInfoInSettings": "設定でこの情報を追加してください。", "githubSourceNote": "GitHubのレート制限はAPIキーを使うことで回避できます。", "gitlabSourceNote": "GitLabのAPK抽出はAPIキーがないと動作しない場合があります。", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index e957c9b..3b73db6 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -248,6 +248,7 @@ "addInfoInSettings": "Dodaj tę informację w Ustawieniach.", "githubSourceNote": "Limit żądań GitHub można ominąć za pomocą klucza API.", "gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 14b5f06..6330f01 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -244,6 +244,7 @@ "addInfoInSettings": "Добавьте эту информацию в Настройки.", "githubSourceNote": "Лимит запросов GitHub можно обойти, используя ключ API.", "gitlabSourceNote": "Извлечение APK из GitLab может не работать без ключа API.", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 6a3058e..be03d5b 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -244,6 +244,7 @@ "addInfoInSettings": "在“设置”中添加此凭据。", "githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。", "gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 47d6acd..a60386e 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -1,6 +1,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:html/parser.dart'; import 'package:http/http.dart'; +import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -85,6 +86,15 @@ bool _isNumeric(String s) { } class HTML extends AppSource { + HTML() { + additionalSourceAppSpecificSettingFormItems = [ + [ + GeneratedFormSwitch('sortByFileNamesNotLinks', + label: tr('sortByFileNamesNotLinks')) + ] + ]; + } + @override // TODO: implement requestHeaders choice, hardcoded for now Map? get requestHeaders => { @@ -111,7 +121,9 @@ class HTML extends AppSource { .where((element) => Uri.parse(element).path.toLowerCase().endsWith('.apk')) .toList(); - links.sort((a, b) => compareAlphaNumeric(a, b)); + links.sort((a, b) => additionalSettings['sortByFileNamesNotLinks'] == true + ? compareAlphaNumeric(a.split('/').last, b.split('/').last) + : compareAlphaNumeric(a, b)); if (additionalSettings['apkFilterRegEx'] != null) { var reg = RegExp(additionalSettings['apkFilterRegEx']); links = links.where((element) => reg.hasMatch(element)).toList(); From a5494115891e0e99ee5086ed373377b80d5010c8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 5 Aug 2023 13:55:25 -0400 Subject: [PATCH 312/600] Add dynamic mirror picking to VLC (#715) --- lib/app_sources/vlc.dart | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/app_sources/vlc.dart b/lib/app_sources/vlc.dart index c531f26..bbdec76 100644 --- a/lib/app_sources/vlc.dart +++ b/lib/app_sources/vlc.dart @@ -38,16 +38,14 @@ class VLC extends AppSource { } String? targetUrl = 'https://$dwUrlBase/$version/'; Response res2 = await sourceRequest(targetUrl); - String mirrorDwBase = - 'https://plug-mirror.rcac.purdue.edu/vlc/vlc-android/$version/'; List apkUrls = []; if (res2.statusCode == 200) { apkUrls = parse(res2.body) .querySelectorAll('a') - .map((e) => e.attributes['href']) + .map((e) => e.attributes['href']?.split('/').last) .where((h) => h != null && h.isNotEmpty && h.toLowerCase().endsWith('.apk')) - .map((e) => mirrorDwBase + e!) + .map((e) => targetUrl + e!) .toList(); } else { throw getObtainiumHttpError(res2); @@ -59,4 +57,20 @@ class VLC extends AppSource { throw getObtainiumHttpError(res); } } + + @override + Future apkUrlPrefetchModifier( + String apkUrl, String standardUrl) async { + Response res = await sourceRequest(apkUrl); + if (res.statusCode == 200) { + String? apkUrl = + parse(res.body).querySelector('#alt_link')?.attributes['href']; + if (apkUrl == null) { + throw NoAPKError(); + } + return apkUrl; + } else { + throw getObtainiumHttpError(res); + } + } } From 09fe7f3ecdba2eefd29af401179e24c927750ccd Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 5 Aug 2023 14:00:50 -0400 Subject: [PATCH 313/600] Disable reverse transition method when n/a (#739) --- lib/pages/settings.dart | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index c96c72d..2ea391e 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -403,10 +403,13 @@ class _SettingsPageState extends State { Switch( value: settingsProvider.reversePageTransitions, - onChanged: (value) { - settingsProvider.reversePageTransitions = - value; - }) + onChanged: settingsProvider + .disablePageTransitions + ? null + : (value) { + settingsProvider + .reversePageTransitions = value; + }) ], ), height32, From aeb0a5d8eac490c310cadcff3770936f3768286c Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 5 Aug 2023 14:12:03 -0400 Subject: [PATCH 314/600] Make delete confirmation button red (#741) --- lib/components/generated_form_modal.dart | 8 +++++++- lib/providers/apps_provider.dart | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/components/generated_form_modal.dart b/lib/components/generated_form_modal.dart index f44acc4..838b187 100644 --- a/lib/components/generated_form_modal.dart +++ b/lib/components/generated_form_modal.dart @@ -11,7 +11,8 @@ class GeneratedFormModal extends StatefulWidget { this.initValid = false, this.message = '', this.additionalWidgets = const [], - this.singleNullReturnButton}); + this.singleNullReturnButton, + this.primaryActionColour}); final String title; final String message; @@ -19,6 +20,7 @@ class GeneratedFormModal extends StatefulWidget { final bool initValid; final List additionalWidgets; final String? singleNullReturnButton; + final Color? primaryActionColour; @override State createState() => _GeneratedFormModalState(); @@ -71,6 +73,10 @@ class _GeneratedFormModalState extends State { : widget.singleNullReturnButton!)), widget.singleNullReturnButton == null ? TextButton( + style: widget.primaryActionColour == null + ? null + : TextButton.styleFrom( + foregroundColor: widget.primaryActionColour), onPressed: !valid ? null : () { diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 9c8d7db..ec9c104 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -892,6 +892,7 @@ class AppsProvider with ChangeNotifier { context: context, builder: (BuildContext ctx) { return GeneratedFormModal( + primaryActionColour: Theme.of(context).colorScheme.error, title: plural('removeAppQuestion', apps.length), items: !showUninstallOption ? [] From c8e90a755d02b5c7807c6b5271eba3d4a113c84d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 5 Aug 2023 14:23:23 -0400 Subject: [PATCH 315/600] Add release notes filter for GitHub/Codeberg(#719) --- assets/translations/bs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/codeberg.dart | 24 ++---------------------- lib/app_sources/github.dart | 21 +++++++++++++++++++++ 14 files changed, 35 insertions(+), 22 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 433984e..54fa76b 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -245,6 +245,7 @@ "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index d7ea035..fe26fab 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -245,6 +245,7 @@ "githubSourceNote": "Die GitHub-Ratenbegrenzung kann mit einem API-Schlüssel umgangen werden.", "gitlabSourceNote": "GitLab APK-Extraktion funktioniert möglicherweise nicht ohne API-Schlüssel", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 551cdb6..2daf50e 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -245,6 +245,7 @@ "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index b7aae29..76bddc6 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -245,6 +245,7 @@ "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index a7dace4..342d98d 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -245,6 +245,7 @@ "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 0a8cfbf..32d1e35 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -245,6 +245,7 @@ "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 6498b44..ab5be1f 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -244,6 +244,7 @@ "githubSourceNote": "A GitHub értékelési korlátozása elkerülhető API-kulcs használatával.", "gitlabSourceNote": "Előfordulhat, hogy a GitLab APK kibontása nem működik API-kulcs nélkül.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "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 49eec85..be3e441 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -245,6 +245,7 @@ "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 528469a..a89fc20 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -245,6 +245,7 @@ "githubSourceNote": "GitHubのレート制限はAPIキーを使うことで回避できます。", "gitlabSourceNote": "GitLabのAPK抽出はAPIキーがないと動作しない場合があります。", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 3b73db6..be2f699 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -249,6 +249,7 @@ "githubSourceNote": "Limit żądań GitHub można ominąć za pomocą klucza API.", "gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 6330f01..94a6ebf 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -245,6 +245,7 @@ "githubSourceNote": "Лимит запросов GitHub можно обойти, используя ключ API.", "gitlabSourceNote": "Извлечение APK из GitLab может не работать без ключа API.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index be03d5b..e59296d 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -245,6 +245,7 @@ "githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。", "gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。", "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/codeberg.dart b/lib/app_sources/codeberg.dart index 8e9ef04..df06b9f 100644 --- a/lib/app_sources/codeberg.dart +++ b/lib/app_sources/codeberg.dart @@ -1,6 +1,4 @@ -import 'package:easy_localization/easy_localization.dart'; import 'package:obtainium/app_sources/github.dart'; -import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -9,26 +7,8 @@ class Codeberg extends AppSource { Codeberg() { host = 'codeberg.org'; - additionalSourceAppSpecificSettingFormItems = [ - [ - GeneratedFormSwitch('includePrereleases', - label: tr('includePrereleases'), defaultValue: false) - ], - [ - GeneratedFormSwitch('fallbackToOlderReleases', - label: tr('fallbackToOlderReleases'), defaultValue: true) - ], - [ - GeneratedFormTextField('filterReleaseTitlesByRegEx', - label: tr('filterReleaseTitlesByRegEx'), - required: false, - additionalValidators: [ - (value) { - return regExValidator(value); - } - ]) - ] - ]; + additionalSourceAppSpecificSettingFormItems = + gh.additionalSourceAppSpecificSettingFormItems; canSearch = true; searchQuerySettingFormItems = gh.searchQuerySettingFormItems; diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index b6a5e2d..608c31c 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -75,6 +75,16 @@ class GitHub extends AppSource { return regExValidator(value); } ]) + ], + [ + GeneratedFormTextField('filterReleaseNotesByRegEx', + label: tr('filterReleaseNotesByRegEx'), + required: false, + additionalValidators: [ + (value) { + return regExValidator(value); + } + ]) ] ]; @@ -196,6 +206,12 @@ class GitHub extends AppSource { true ? additionalSettings['filterReleaseTitlesByRegEx'] : null; + String? regexNotesFilter = + (additionalSettings['filterReleaseNotesByRegEx'] as String?) + ?.isNotEmpty == + true + ? additionalSettings['filterReleaseNotesByRegEx'] + : null; Response res = await sourceRequest(requestUrl); if (res.statusCode == 200) { var releases = jsonDecode(res.body) as List; @@ -264,6 +280,11 @@ class GitHub extends AppSource { !RegExp(regexFilter).hasMatch(nameToFilter.trim())) { continue; } + if (regexNotesFilter != null && + !RegExp(regexNotesFilter) + .hasMatch(((releases[i]['body'] as String?) ?? '').trim())) { + continue; + } var apkUrls = getReleaseAPKUrls(releases[i]); if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) { continue; From 8073723e1fab6270433dbab7904ea29742aec14d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 5 Aug 2023 14:28:40 -0400 Subject: [PATCH 316/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 40 ++++++++++++++++++++-------------------- pubspec.yaml | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index d330268..7861e1b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -22,7 +22,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.22'; +const String currentVersion = '0.13.23'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index c4ff360..f1e82a6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: "direct main" description: name: android_alarm_manager_plus - sha256: "80f963d47cb7ab0818144c7b0668aea4c038f9cb8626626e89a4ea77375defb7" + sha256: c20d91a9096596f66274bf8172321c278f9cba8091638f80205fe66d31587fa5 url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" android_intent_plus: dependency: "direct main" description: name: android_intent_plus - sha256: "2c87d8330ba5deef5fe20e77f4d178190b3b24531dce08368030ab4be40a9d4e" + sha256: f72ae20bb37108694f442e7ae6acbd28b453ca62ce86842f6787b784355abfe6 url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.2" android_package_installer: dependency: "direct main" description: @@ -158,10 +158,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "2c35b6d1682b028e42d07b3aee4b98fa62996c10bc12cb651ec856a80d6a761b" + sha256: "86add5ef97215562d2e090535b0a16f197902b10c369c558a100e74ea06e8659" url: "https://pub.dev" source: hosted - version: "9.0.2" + version: "9.0.3" device_info_plus_platform_interface: dependency: transitive description: @@ -490,42 +490,42 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" + sha256: "5d44fc3314d969b84816b569070d7ace0f1dea04bd94a83f74c4829615d22ad8" url: "https://pub.dev" source: hosted - version: "2.0.27" + version: "2.1.0" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297" + sha256: "1b744d3d774e5a879bb76d6cd1ecee2ba2c6960c03b1020cd35212f6aa267ac5" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.3.0" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57 + sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3 url: "https://pub.dev" source: hosted - version: "2.1.11" + version: "2.2.0" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84 url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.1.0" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" + sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.2.0" permission_handler: dependency: "direct main" description: @@ -610,18 +610,18 @@ packages: dependency: "direct main" description: name: share_plus - sha256: ed3fcea4f789ed95913328e629c0c53e69e80e08b6c24542f1b3576046c614e8 + sha256: "6cec740fa0943a826951223e76218df002804adb588235a8910dc3d6b0654e11" url: "https://pub.dev" source: hosted - version: "7.0.2" + version: "7.1.0" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface - sha256: "0c6e61471bd71b04a138b8b588fa388e66d8b005e6f2deda63371c5c505a0981" + sha256: "357412af4178d8e11d14f41723f80f12caea54cf0d5cd29af9dcdab85d58aea7" url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.3.0" shared_preferences: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 8f84e5d..7e52a3a 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.13.22+186 # When changing this, update the tag in main() accordingly +version: 0.13.23+187 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 347c56da55a43810cd3ea905689968f93aea5a20 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 5 Aug 2023 14:29:42 -0400 Subject: [PATCH 317/600] Ran dart fix --- lib/providers/source_provider.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index ca2c969..da88640 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -431,14 +431,14 @@ abstract class AppSource { Map additionalSettings, SettingsProvider settingsProvider) async { Map results = {}; - sourceConfigSettingFormItems.forEach((e) { + for (var e in sourceConfigSettingFormItems) { var val = hostChanged ? additionalSettings[e.key] : settingsProvider.getSettingString(e.key); if (val != null) { results[e.key] = val; } - }); + } return results; } From d473cb49c53ab6d599bc543f06953662c382cd9f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 6 Aug 2023 13:14:48 -0400 Subject: [PATCH 318/600] Add custom link filter for HTML --- assets/translations/bs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/html.dart | 36 ++++++++++++++++++++++++++++++------ 13 files changed, 42 insertions(+), 6 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 54fa76b..2c3c5d3 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -246,6 +246,7 @@ "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index fe26fab..0884158 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -246,6 +246,7 @@ "gitlabSourceNote": "GitLab APK-Extraktion funktioniert möglicherweise nicht ohne API-Schlüssel", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 2daf50e..397c7a2 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -246,6 +246,7 @@ "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 76bddc6..b5d3d25 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -246,6 +246,7 @@ "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 342d98d..beaf442 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -246,6 +246,7 @@ "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 32d1e35..ec680f8 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -246,6 +246,7 @@ "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index ab5be1f..8b10f31 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -245,6 +245,7 @@ "gitlabSourceNote": "Előfordulhat, hogy a GitLab APK kibontása nem működik API-kulcs nélkül.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "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 be3e441..4dd0383 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -246,6 +246,7 @@ "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index a89fc20..6c1f7eb 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -246,6 +246,7 @@ "gitlabSourceNote": "GitLabのAPK抽出はAPIキーがないと動作しない場合があります。", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index be2f699..d227ee2 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -250,6 +250,7 @@ "gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 94a6ebf..1f27453 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -246,6 +246,7 @@ "gitlabSourceNote": "Извлечение APK из GitLab может не работать без ключа API.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index e59296d..d5bc0eb 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -246,6 +246,7 @@ "gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index a60386e..2331d54 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -91,7 +91,18 @@ class HTML extends AppSource { [ GeneratedFormSwitch('sortByFileNamesNotLinks', label: tr('sortByFileNamesNotLinks')) - ] + ], + [ + GeneratedFormTextField('customLinkFilterRegex', + label: tr('customLinkFilterRegex'), + hint: 'download/(.*/)?(android|apk|mobile)', + required: false, + additionalValidators: [ + (value) { + return regExValidator(value); + } + ]) + ], ]; } @@ -115,16 +126,29 @@ class HTML extends AppSource { var uri = Uri.parse(standardUrl); Response res = await sourceRequest(standardUrl); if (res.statusCode == 200) { - List links = parse(res.body) + var html = parse(res.body); + List allLinks = html .querySelectorAll('a') .map((element) => element.attributes['href'] ?? '') - .where((element) => - Uri.parse(element).path.toLowerCase().endsWith('.apk')) .toList(); + List links = []; + if ((additionalSettings['customLinkFilterRegex'] as String?) + ?.isNotEmpty == + true) { + var reg = RegExp(additionalSettings['customLinkFilterRegex']); + links = allLinks.where((element) => reg.hasMatch(element)).toList(); + } else { + links = allLinks + .where((element) => + Uri.parse(element).path.toLowerCase().endsWith('.apk')) + .toList(); + } links.sort((a, b) => additionalSettings['sortByFileNamesNotLinks'] == true - ? compareAlphaNumeric(a.split('/').last, b.split('/').last) + ? compareAlphaNumeric(a.split('/').where((e) => e.isNotEmpty).last, + b.split('/').where((e) => e.isNotEmpty).last) : compareAlphaNumeric(a, b)); - if (additionalSettings['apkFilterRegEx'] != null) { + if ((additionalSettings['apkFilterRegEx'] as String?)?.isNotEmpty == + true) { var reg = RegExp(additionalSettings['apkFilterRegEx']); links = links.where((element) => reg.hasMatch(element)).toList(); } From 3df801c54e8febfd131070afd8b03916fd79a814 Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Sun, 6 Aug 2023 22:49:52 +0200 Subject: [PATCH 319/600] locale(pl): Update Polish translations Polish translation has been updated Signed-off-by: Daviteusz --- assets/translations/pl.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index be2f699..a18a7ee 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -248,8 +248,8 @@ "addInfoInSettings": "Dodaj tę informację w Ustawieniach.", "githubSourceNote": "Limit żądań GitHub można ominąć za pomocą klucza API.", "gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.", - "sortByFileNamesNotLinks": "Sort by file names instead of full links", - "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "sortByFileNamesNotLinks": "Sortuj wg nazw plików zamiast pełnych linków", + "filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" From 1de274df39aadf8a103ef722cf5fdbb347ea857b Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Wed, 9 Aug 2023 08:15:07 +0200 Subject: [PATCH 320/600] Update de.json translated the two new added lines, and one yet to be translated string. --- assets/translations/de.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index fe26fab..9e62db4 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -229,7 +229,7 @@ "dontShowTrackOnlyWarnings": "Warnung für 'Nur Nachverfolgen' nicht anzeigen", "dontShowAPKOriginWarnings": "Warnung für APK-Herkunft nicht anzeigen", "moveNonInstalledAppsToBottom": "Nicht installierte Apps ans Ende der Apps Ansicht verschieben", - "gitlabPATLabel": "GitLab Personal Access Token\n(Aktiviert Suche and Better APK Discovery)", + "gitlabPATLabel": "GitLab Personal Access Token\n(Aktiviert Suche und bessere APK Entdeckung)", "about": "Über", "requiresCredentialsInSettings": "Benötigt zusätzliche Anmeldedaten (in den Einstellungen)", "checkOnStart": "Überprüfe einmalig beim Start", @@ -244,8 +244,8 @@ "addInfoInSettings": "Fügen Sie diese Info in den Einstellungen hinzu.", "githubSourceNote": "Die GitHub-Ratenbegrenzung kann mit einem API-Schlüssel umgangen werden.", "gitlabSourceNote": "GitLab APK-Extraktion funktioniert möglicherweise nicht ohne API-Schlüssel", - "sortByFileNamesNotLinks": "Sort by file names instead of full links", - "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "sortByFileNamesNotLinks": "Sortiere nach Dateinamen, anstelle von ganzen Links", + "filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck filtern", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" From 5f8638d349d7723e41f0c23e555e15a5e2b33a8b Mon Sep 17 00:00:00 2001 From: Marocco2 Date: Fri, 11 Aug 2023 17:27:12 +0200 Subject: [PATCH 321/600] Update html.dart Swap user agent with a chrome browser on Android --- lib/app_sources/html.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index a60386e..f00cc14 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -99,7 +99,7 @@ class HTML extends AppSource { // TODO: implement requestHeaders choice, hardcoded for now Map? get requestHeaders => { "User-Agent": - "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0" + "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36" }; @override From d6a4b0a96d166757d055cacebceed973dc6b0087 Mon Sep 17 00:00:00 2001 From: Octopus Date: Fri, 11 Aug 2023 18:56:25 +0200 Subject: [PATCH 322/600] Make Hungarian translation more understandable --- assets/translations/hu.json | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index ab5be1f..cc1019f 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -93,13 +93,13 @@ "author": "Szerző", "upToDateApps": "Naprakész appok", "nonInstalledApps": "Nem telepített appok", - "importExport": "Import/Export", + "importExport": "Importálás/Exportálás", "settings": "Beállítások", "exportedTo": "Exportálva ide {}", - "obtainiumExport": "Obtainium Export", + "obtainiumExport": "Obtainium Adat Exportálás", "invalidInput": "Hibás bemenet", "importedX": "Importálva innen {}", - "obtainiumImport": "Obtainium Import", + "obtainiumImport": "Obtainium Adat Importálás", "importFromURLList": "Importálás URL listából", "searchQuery": "Keresési lekérdezés", "appURLList": "App URL lista", @@ -139,11 +139,11 @@ "appSource": "App forrás", "noLogs": "Nincsenek naplók", "appLogs": "App naplók", - "close": "Bezár", - "share": "Megoszt", + "close": "Bezárás", + "share": "Megosztás", "appNotFound": "App nem található", "obtainiumExportHyphenatedLowercase": "obtainium-export", - "pickAnAPK": "Válasszon egy APK-t", + "pickAnAPK": "Válasszon egy APK-ot", "appHasMoreThanOnePackage": "A(z) {} egynél több csomaggal rendelkezik:", "deviceSupportsXArch": "Eszköze támogatja a {} CPU architektúrát.", "deviceSupportsFollowingArchs": "Az eszköze a következő CPU architektúrákat támogatja:", @@ -210,7 +210,7 @@ "copiedToClipboard": "Másolva a vágólapra", "storagePermissionDenied": "Tárhely engedély megtagadva", "selectedCategorizeWarning": "Ez felváltja a kiválasztott alkalmazások meglévő kategória-beállításait.", - "filterAPKsByRegEx": "Az APK-k szűrése reguláris kifejezéssel", + "filterAPKsByRegEx": "Az APK-ok szűrése reguláris kifejezéssel", "removeFromObtainium": "Eltávolítás az Obtainiumból", "uninstallFromDevice": "Eltávolítás a készülékről", "onlyWorksWithNonVersionDetectApps": "Csak azoknál az alkalmazásoknál működik, amelyeknél a verzióérzékelés le van tiltva.", @@ -222,7 +222,7 @@ "versionDetection": "Verzió érzékelés", "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", + "autoApkFilterByArch": "Ha lehetséges, próbálja CPU architektúra szerint szűrni az APK-okat", "overrideSource": "Forrás felülbírálása", "dontShowAgain": "Ne mutassa ezt újra", "dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést", @@ -231,20 +231,20 @@ "gitlabPATLabel": "GitLab Personal Access Token\n(Engedélyezi a Keresést és jobb APK felfedezés)", "about": "Rólunk", "requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)", - "checkOnStart": "Egyszer az indításkor", + "checkOnStart": "Egyszer az alkalmazás indításakor is", "tryInferAppIdFromCode": "Próbálja kikövetkeztetni az app azonosítót a forráskódból", "removeOnExternalUninstall": "A külsőleg eltávolított appok auto. eltávolítása", "pickHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", "checkUpdateOnDetailPage": "Frissítések keresése az app részleteit tartalmazó oldal megnyitásakor", - "disablePageTransitions": "Lap áttűnési animációk tiltása", + "disablePageTransitions": "Lap áttűnési animációk letiltása", "reversePageTransitions": "Fordított lap áttűnési animációk", "minStarCount": "Minimális csillag szám", "addInfoBelow": "Adja hozzá ezt az infót alább.", "addInfoInSettings": "Adja hozzá ezt az infót a Beállításokban.", - "githubSourceNote": "A GitHub értékelési korlátozása elkerülhető API-kulcs használatával.", + "githubSourceNote": "A GitHub sebességkorlátozás elkerülhető API-kulcs használatával.", "gitlabSourceNote": "Előfordulhat, hogy a GitLab APK kibontása nem működik API-kulcs nélkül.", - "sortByFileNamesNotLinks": "Sort by file names instead of full links", - "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "sortByFileNamesNotLinks": "Fájlnevek szerinti elrendezés teljes linkek helyett", + "filterReleaseNotesByRegEx": "Kiadási megjegyzések szűrése reguláris kifejezéssel", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" @@ -287,10 +287,10 @@ }, "xAndNMoreUpdatesAvailable": { "one": "A(z) {} és 1 további alkalmazás frissítéseket kapott.", - "other": "{} és további {} alkalmazás frissítéseket kapott." + "other": "{} és {} további alkalmazás frissítéseket kapott." }, "xAndNMoreUpdatesInstalled": { "one": "A(z) {} és 1 további alkalmazás frissítve.", - "other": "{} és további {} alkalmazás frissítve." + "other": "{} és {} további alkalmazás frissítve." } } From dcf5bd37ca13b6fcd797c3afe96f3cf2d57d540e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 13 Aug 2023 21:18:53 -0400 Subject: [PATCH 323/600] Foreground-only silent install support --- android/app/src/main/AndroidManifest.xml | 1 + pubspec.lock | 34 ++++++++++++------------ 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 35f7597..cfeac66 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -62,6 +62,7 @@ + diff --git a/pubspec.lock b/pubspec.lock index f1e82a6..41f8b1e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -22,7 +22,7 @@ packages: description: path: "." ref: main - resolved-ref: f09c79eee5be3c60b04760143eb954a13fdd07f1 + resolved-ref: "2edf5dbbfeeb33257d526861f2a992aee5d97bb4" url: "https://github.com/ImranR98/android_package_installer" source: git version: "0.0.1" @@ -206,10 +206,10 @@ packages: dependency: transitive description: name: ffi - sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.0" file: dependency: transitive description: @@ -296,10 +296,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: "4b1bfbb802d76320a1a46d9ce984106135093efd9d969765d07c2125af107bdf" + sha256: "2b206d397dd7836ea60035b2d43825c8a303a76a5098e66f42d55a753e18d431" url: "https://pub.dev" source: hosted - version: "0.6.17" + version: "0.6.17+1" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -482,10 +482,10 @@ packages: dependency: "direct main" description: name: path_provider - sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" + sha256: "909b84830485dbcd0308edf6f7368bc8fd76afa26a270420f34cabea2a6467a0" url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.1.0" path_provider_android: dependency: transitive description: @@ -642,10 +642,10 @@ packages: dependency: transitive description: name: shared_preferences_foundation - sha256: f39696b83e844923b642ce9dd4bd31736c17e697f6731a5adf445b1274cf3cd4 + sha256: d29753996d8eb8f7619a1f13df6ce65e34bc107bef6330739ed76f18b22310ef url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.3" shared_preferences_linux: dependency: transitive description: @@ -783,10 +783,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "78cb6dea3e93148615109e58e42c35d1ffbf5ef66c44add673d0ab75f12ff3af" + sha256: "3dd2388cc0c42912eee04434531a26a82512b9cb1827e0214430c9bcbddfe025" url: "https://pub.dev" source: hosted - version: "6.0.37" + version: "6.0.38" url_launcher_ios: dependency: transitive description: @@ -863,10 +863,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: d936a09fbfd08cb78f7329e0bbacf6158fbdfe24ffc908b22444c07d295eb193 + sha256: bca797abba472868655b5f1a6029c1132385685ee9db4713cb0e7f33076210c6 url: "https://pub.dev" source: hosted - version: "3.9.2" + version: "3.9.3" webview_flutter_platform_interface: dependency: transitive description: @@ -879,10 +879,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "5fa098f28b606f699e8ca52d9e4e11edbbfef65189f5f77ae92703ba5408fd25" + sha256: ed749f94ac9e814d04a258a9255cf69cfa4cc6006ff59542aea7fb4590144972 url: "https://pub.dev" source: hosted - version: "3.7.2" + version: "3.7.3" win32: dependency: transitive description: @@ -903,10 +903,10 @@ packages: dependency: transitive description: name: xdg_directories - sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff + sha256: f0c26453a2d47aa4c2570c6a033246a3fc62da2fe23c7ffdd0a7495086dc0247 url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.0.2" xml: dependency: transitive description: From cfd04dc60294978c618df9b7ed2845ce26f789a4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 13 Aug 2023 21:27:41 -0400 Subject: [PATCH 324/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 7861e1b..a9f0caa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -22,7 +22,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.23'; +const String currentVersion = '0.13.24'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 7e52a3a..b445ab3 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.13.23+187 # When changing this, update the tag in main() accordingly +version: 0.13.24+188 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 75a0cb11896e856df6b5b8b9f44960716811acf3 Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Mon, 14 Aug 2023 14:38:38 +0200 Subject: [PATCH 325/600] Update de.json translated newly added line --- assets/translations/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 16ae9d0..b47e385 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -246,7 +246,7 @@ "gitlabSourceNote": "GitLab APK-Extraktion funktioniert möglicherweise nicht ohne API-Schlüssel", "sortByFileNamesNotLinks": "Sortiere nach Dateinamen, anstelle von ganzen Links", "filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck filtern", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "customLinkFilterRegex": "Benutzerdefinierter Link Filter nach Regulärem Ausdruck (Standard '.apk$')", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" From 0dadd8bffeae4e73d5f6a0fe624f4f666a1cbe5a Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Tue, 15 Aug 2023 02:57:31 +0900 Subject: [PATCH 326/600] Update ja.json --- assets/translations/ja.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 6c1f7eb..1ade9f2 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -22,7 +22,7 @@ "githubPATFormat": "ユーザー名:トークン", "includePrereleases": "プレリリースを含む", "fallbackToOlderReleases": "旧リリースへのフォールバック", - "filterReleaseTitlesByRegEx": "正規表現でリリースタイトルを絞り込む", + "filterReleaseTitlesByRegEx": "正規表現でリリースタイトルをフィルタリングする", "invalidRegEx": "無効な正規表現", "noDescription": "説明はありません", "cancel": "キャンセル", @@ -88,7 +88,7 @@ "showOutdatedOnly": "アップデートが存在するアプリのみ表示する", "filter": "フィルター", "filterActive": "フィルター *", - "filterApps": "アプリを絞り込む", + "filterApps": "アプリをフィルタリングする", "appName": "アプリ名", "author": "作者", "upToDateApps": "最新のアプリ", @@ -211,7 +211,7 @@ "copiedToClipboard": "クリップボードにコピーしました", "storagePermissionDenied": "ストレージ権限が拒否されました", "selectedCategorizeWarning": "これにより、選択したアプリの既存のカテゴリ設定がすべて置き換えられます。", - "filterAPKsByRegEx": "正規表現でAPKを絞り込む", + "filterAPKsByRegEx": "正規表現でAPKをフィルタリングする", "removeFromObtainium": "Obtainiumから削除する", "uninstallFromDevice": "デバイスからアンインストールする", "onlyWorksWithNonVersionDetectApps": "バージョン検出を無効にしているアプリにのみ動作します。", @@ -244,9 +244,9 @@ "addInfoInSettings": "設定でこの情報を追加してください。", "githubSourceNote": "GitHubのレート制限はAPIキーを使うことで回避できます。", "gitlabSourceNote": "GitLabのAPK抽出はAPIキーがないと動作しない場合があります。", - "sortByFileNamesNotLinks": "Sort by file names instead of full links", - "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "sortByFileNamesNotLinks": "フルのリンクではなくファイル名でソートする", + "filterReleaseNotesByRegEx": "正規表現でリリースノートをフィルタリングする", + "customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" From 0de12c7c07f7e9d7feadf365ff33d36e7a6400d5 Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Mon, 14 Aug 2023 23:24:16 +0200 Subject: [PATCH 327/600] locale(pl): Update Polish translations Polish translation has been updated Signed-off-by: Daviteusz --- assets/translations/pl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index afcb7cf..b8a1a81 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -250,7 +250,7 @@ "gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.", "sortByFileNamesNotLinks": "Sortuj wg nazw plików zamiast pełnych linków", "filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "customLinkFilterRegex": "Niestandardowy filtr linków wg. wyrażenia regularnego (domyślnie \".apk$\")", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" From 483840279775df56beed32db9ae9f131a71fe873 Mon Sep 17 00:00:00 2001 From: Mehdee <85278288+mehdeej@users.noreply.github.com> Date: Wed, 16 Aug 2023 18:54:58 +0000 Subject: [PATCH 328/600] Update fa.json --- assets/translations/fa.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/assets/translations/fa.json b/assets/translations/fa.json index beaf442..3f98e69 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -229,24 +229,24 @@ "dontShowTrackOnlyWarnings": "هشدار 'فقط ردیابی' را نشان ندهید", "dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید", "moveNonInstalledAppsToBottom": "برنامه های نصب نشده را به نمای پایین برنامه ها منتقل کنید", - "gitlabPATLabel": "رمز دسترسی شخصی GitLab\n(جستجو را فعال می کند and Better APK Discovery)", + "gitlabPATLabel": "رمز دسترسی شخصی GitLab\n(جستجو و کشف بهتر APK را فعال میکند)", "about": "درباره", "requiresCredentialsInSettings": "این به اعتبارنامه های اضافی نیاز دارد (در تنظیمات)", "checkOnStart": "بررسی در شروع", "tryInferAppIdFromCode": "شناسه برنامه را از کد منبع استنباط کنید", - "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", - "pickHighestVersionCode": "Auto-select highest version code APK", - "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", - "disablePageTransitions": "Disable page transition animations", - "reversePageTransitions": "Reverse page transition animations", - "minStarCount": "Minimum Star Count", - "addInfoBelow": "Add this info below.", - "addInfoInSettings": "Add this info in the Settings.", - "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", - "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", - "sortByFileNamesNotLinks": "Sort by file names instead of full links", - "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "removeOnExternalUninstall": "حذف خودکار برنامه های حذف نصب شده خارجی", + "pickHighestVersionCode": "انتخاب خودکار بالاترین کد نسخه APK", + "checkUpdateOnDetailPage": "برای باز کردن صفحه جزئیات برنامه، به‌روزرسانی‌ها را بررسی کنید", + "disablePageTransitions": "غیرفعال کردن انیمیشن های انتقال صفحه", + "reversePageTransitions": "انیمیشن های انتقال معکوس صفحه", + "minStarCount": "حداقل تعداد ستاره", + "addInfoBelow": "این اطلاعات را در زیر اضافه کنید", + "addInfoInSettings": "این اطلاعات را در تنظیمات اضافه کنید.", + "githubSourceNote": "با استفاده از کلید API می توان از محدودیت نرخ GitHub جلوگیری کرد.", + "gitlabSourceNote": "استخراج APK GitLab ممکن است بدون کلید API کار نکند.", + "sortByFileNamesNotLinks": "مرتب سازی بر اساس نام فایل به جای پیوندهای کامل", + "filterReleaseNotesByRegEx": "یادداشت های انتشار را با بیان منظم فیلتر کنید", + "customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیش‌فرض '.apk$')", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" From 05ac76e3e94a4c014abe05b5ff839e395ca0c1c9 Mon Sep 17 00:00:00 2001 From: Nriver <6752679+Nriver@users.noreply.github.com> Date: Fri, 18 Aug 2023 16:56:20 +0800 Subject: [PATCH 329/600] update chinese translation --- assets/translations/zh.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/zh.json b/assets/translations/zh.json index d5bc0eb..028e8d1 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -244,9 +244,9 @@ "addInfoInSettings": "在“设置”中添加此凭据。", "githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。", "gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。", - "sortByFileNamesNotLinks": "Sort by file names instead of full links", - "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "sortByFileNamesNotLinks": "根据文件名而不是完整链接来排序", + "filterReleaseNotesByRegEx": "用正则表达式筛选发布说明", + "customLinkFilterRegex": "用正则表达式自定义链接筛选(默认 '.apk$')", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" From 7ef9c43ee37d52f51cb0a62f9078b0ac1e7f3b99 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 18 Aug 2023 19:36:56 -0400 Subject: [PATCH 330/600] Don't wait for foreground if install is silent --- android/app/build.gradle | 1 - lib/providers/apps_provider.dart | 60 ++++++++++++++++++++++---------- pubspec.lock | 9 +++++ pubspec.yaml | 10 ++++-- 4 files changed, 57 insertions(+), 23 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 09eb008..764d501 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -49,7 +49,6 @@ android { } defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "dev.imranr.obtainium" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index ec9c104..bc03997 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -7,6 +7,7 @@ import 'dart:io'; import 'package:android_intent_plus/flag.dart'; import 'package:android_package_installer/android_package_installer.dart'; +import 'package:android_package_manager/android_package_manager.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -29,6 +30,8 @@ import 'package:http/http.dart'; import 'package:android_intent_plus/android_intent.dart'; import 'package:flutter_archive/flutter_archive.dart'; +final pm = AndroidPackageManager(); + class AppInMemory { late App app; double? downloadProgress; @@ -322,16 +325,39 @@ class AppsProvider with ChangeNotifier { .isNotEmpty; Future canInstallSilently(App app) async { - return false; - // TODO: Uncomment the below if silent updates are ever figured out - // // NOTE: This is unreliable - try to get from OS in the future - // if (app.apkUrls.length > 1) { - // return false; - // } - // var osInfo = await DeviceInfoPlugin().androidInfo; - // return app.installedVersion != null && - // osInfo.version.sdkInt >= 30 && - // osInfo.version.release.compareTo('12') >= 0; + if (app.apkUrls.length > 1) { + // Manual API selection means silent install is not possible + return false; + } + + var osInfo = await DeviceInfoPlugin().androidInfo; + String? installerPackageName; + try { + installerPackageName = osInfo.version.sdkInt >= 30 + ? (await pm.getInstallSourceInfo(packageName: app.id)) + ?.installingPackageName + : (await pm.getInstallerPackageName(packageName: app.id)); + } catch (e) { + // Probably not installed - ignore + } + if (installerPackageName != obtainiumId) { + // If we did not install the app (or it isn't installed), silent install is not possible + return false; + } + var targetSDK; + try { + targetSDK = (await pm.getPackageInfo(packageName: app.id)) + ?.applicationInfo + ?.targetSdkVersion; + } catch (e) { + // Weird if you get here - ignore + } + + // The OS must also be new enough and the APK should target a new enough API + return osInfo.version.sdkInt >= 30 && + targetSDK != null && + targetSDK >= // https://developer.android.com/reference/android/content/pm/PackageInstaller.SessionParams#setRequireUserAction(int) + (osInfo.version.sdkInt - 3); } Future waitForUserToReturnToForeground(BuildContext context) async { @@ -359,8 +385,7 @@ class AppsProvider with ChangeNotifier { zipFile: File(filePath), destinationDir: Directory(destinationPath)); } - Future installXApkDir(DownloadedXApkDir dir, - {bool silent = false}) async { + Future installXApkDir(DownloadedXApkDir dir) async { // We don't know which APKs in an XAPK are supported by the user's device // So we try installing all of them and assume success if at least one installed // If 0 APKs installed, throw the first install error encountered @@ -373,8 +398,7 @@ class AppsProvider with ChangeNotifier { if (file.path.toLowerCase().endsWith('.apk')) { try { somethingInstalled = somethingInstalled || - await installApk(DownloadedApk(dir.appId, file), - silent: silent); + await installApk(DownloadedApk(dir.appId, file)); } catch (e) { logs.add( 'Could not install APK from XAPK \'${file.path}\': ${e.toString()}'); @@ -394,8 +418,7 @@ class AppsProvider with ChangeNotifier { } } - Future installApk(DownloadedApk file, {bool silent = false}) async { - // TODO: Use 'silent' when/if ever possible + Future installApk(DownloadedApk file) async { var newInfo = await PackageArchiveInfo.fromPath(file.file.path); AppInfo? appInfo; try { @@ -571,7 +594,6 @@ class AppsProvider with ChangeNotifier { } bool willBeSilent = await canInstallSilently( apps[downloadedFile?.appId ?? downloadedDir!.appId]!.app); - willBeSilent = false; // TODO: Remove this when silent updates work if (!(await settingsProvider?.getInstallPermission(enforce: false) ?? true)) { throw ObtainiumError(tr('cancelled')); @@ -584,9 +606,9 @@ class AppsProvider with ChangeNotifier { notifyListeners(); try { if (downloadedFile != null) { - await installApk(downloadedFile, silent: willBeSilent); + await installApk(downloadedFile); } else { - await installXApkDir(downloadedDir!, silent: willBeSilent); + await installXApkDir(downloadedDir!); } } finally { apps[id]?.downloadProgress = null; diff --git a/pubspec.lock b/pubspec.lock index 41f8b1e..65b039e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -26,6 +26,15 @@ packages: url: "https://github.com/ImranR98/android_package_installer" source: git version: "0.0.1" + android_package_manager: + dependency: "direct main" + description: + path: "." + ref: master + resolved-ref: "5f58196561734d0f499bb844cdb43e7762a8f019" + url: "https://github.com/ImranR98/android_package_manager" + source: git + version: "0.5.4" animations: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index b445ab3..df430a3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: obtainium -description: A new Flutter project. +description: Get Android App Updates Directly From the Source. # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. @@ -55,9 +55,13 @@ dependencies: git: url: https://github.com/ImranR98/android_package_installer ref: main + android_package_manager: + git: + url: https://github.com/ImranR98/android_package_manager + ref: master share_plus: ^7.0.0 - installed_apps: ^1.3.1 - package_archive_info: ^0.1.0 + installed_apps: ^1.3.1 # TODO: Remove when android_package_manager supports getting icon as UInt8List and versionCode + package_archive_info: ^0.1.0 # TODO: Remove when android_package_manager supports getting versionCode android_alarm_manager_plus: ^3.0.0 sqflite: ^2.2.0+3 easy_localization: ^3.0.1 From 81c4d4f3931449135d32485314c047ed298b87ef Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 18 Aug 2023 19:55:31 -0400 Subject: [PATCH 331/600] Fix default multi-"app change" selection bug --- lib/pages/apps.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 894967e..f8ee0e4 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -643,15 +643,15 @@ class AppsPageState extends State { label: tr('installX', args: [ plural('apps', newInstallIdsAllOrSelected.length) ]), - defaultValue: existingUpdateIdsAllOrSelected.isNotEmpty)); + defaultValue: existingUpdateIdsAllOrSelected.isEmpty)); } if (trackOnlyUpdateIdsAllOrSelected.isNotEmpty) { formItems.add(GeneratedFormSwitch('trackonlies', label: tr('markXTrackOnlyAsUpdated', args: [ plural('apps', trackOnlyUpdateIdsAllOrSelected.length) ]), - defaultValue: existingUpdateIdsAllOrSelected.isNotEmpty || - newInstallIdsAllOrSelected.isNotEmpty)); + defaultValue: existingUpdateIdsAllOrSelected.isEmpty && + newInstallIdsAllOrSelected.isEmpty)); } showDialog?>( context: context, From eaeee188eba3461f885eeee18532725a31587b3f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 18 Aug 2023 19:58:54 -0400 Subject: [PATCH 332/600] Upgrade packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 10 +++++----- pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a9f0caa..efcce43 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -22,7 +22,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.24'; +const String currentVersion = '0.13.25'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 65b039e..fc2d4e4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -31,7 +31,7 @@ packages: description: path: "." ref: master - resolved-ref: "5f58196561734d0f499bb844cdb43e7762a8f019" + resolved-ref: "6e68991ef9c6232695abce2eef345d3cca2f52ac" url: "https://github.com/ImranR98/android_package_manager" source: git version: "0.5.4" @@ -587,10 +587,10 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "57c07bf82207aee366dfaa3867b3164e4f03a238a461a11b0e8a3a510d51203d" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" plugin_platform_interface: dependency: transitive description: @@ -880,10 +880,10 @@ packages: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "564ef378cafc1a0e29f1d76ce175ef517a0a6115875dff7b43fccbef2b0aeb30" + sha256: "0ca3cfcc6781a7de701d580917af4a9efc4e3e129f8ead95a80587f0a749480a" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.5.0" webview_flutter_wkwebview: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index df430a3..e2e43e4 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.13.24+188 # When changing this, update the tag in main() accordingly +version: 0.13.25+189 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 734a1aeb01273113500e49c8e7bcf2f97db2f124 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 18 Aug 2023 22:12:16 -0400 Subject: [PATCH 333/600] Enable Android TV 'OK' Button (#281) --- lib/main.dart | 6 ++++-- lib/providers/apps_provider.dart | 2 +- pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index efcce43..5074433 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -22,7 +22,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.25'; +const String currentVersion = '0.13.26'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES @@ -299,7 +299,9 @@ class _ObtainiumState extends State { ? lightColorScheme : darkColorScheme, fontFamily: 'Metropolis'), - home: const HomePage()); + home: Shortcuts(shortcuts: { + LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(), + }, child: const HomePage())); }); } } diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index bc03997..73cd19e 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -344,7 +344,7 @@ class AppsProvider with ChangeNotifier { // If we did not install the app (or it isn't installed), silent install is not possible return false; } - var targetSDK; + int? targetSDK; try { targetSDK = (await pm.getPackageInfo(packageName: app.id)) ?.applicationInfo diff --git a/pubspec.yaml b/pubspec.yaml index e2e43e4..83b618f 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.13.25+189 # When changing this, update the tag in main() accordingly +version: 0.13.26+190 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From f61824ff0d67c0685b2f390087bda30b3f354b91 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 19 Aug 2023 00:19:52 -0400 Subject: [PATCH 334/600] Add Huawei AppGallery (#756) --- README.md | 1 + lib/app_sources/huaweiappgallery.dart | 90 +++++++++++++++++++++++++++ lib/providers/source_provider.dart | 12 +++- 3 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 lib/app_sources/huaweiappgallery.dart diff --git a/README.md b/README.md index 47ece7c..d0c3f1a 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Currently supported App sources: - [SourceHut](https://git.sr.ht/) - [APKMirror](https://apkmirror.com/) (Track-Only) - [APKPure](https://apkpure.com/) +- [Huawei AppGallery](https://appgallery.huawei.com/) - Third Party F-Droid Repos - Jenkins Jobs - [Steam](https://store.steampowered.com/mobile) diff --git a/lib/app_sources/huaweiappgallery.dart b/lib/app_sources/huaweiappgallery.dart new file mode 100644 index 0000000..1a97774 --- /dev/null +++ b/lib/app_sources/huaweiappgallery.dart @@ -0,0 +1,90 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class HuaweiAppGallery extends AppSource { + HuaweiAppGallery() { + name = 'Huawei AppGallery'; + host = 'appgallery.huawei.com'; + overrideVersionDetectionFormDefault('releaseDateAsVersion', true); + } + + @override + String sourceSpecificStandardizeURL(String url) { + RegExp standardUrlRegEx = RegExp('^https?://$host/app/[^/]+'); + RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); + if (match == null) { + throw InvalidURLError(name); + } + return url.substring(0, match.end); + } + + getDlUrl(String standardUrl) => + 'https://${host!.replaceAll('appgallery.', 'appgallery.cloud.')}/appdl/${standardUrl.split('/').last}'; + + requestAppdlRedirect(String dlUrl) async { + Response res = await sourceRequest(dlUrl, followRedirects: false); + if (res.statusCode == 200 || + res.statusCode == 302 || + res.statusCode == 304) { + return res; + } else { + throw getObtainiumHttpError(res); + } + } + + appIdFromRedirectDlUrl(String redirectDlUrl) { + var parts = redirectDlUrl + .split('?')[0] + .split('/') + .last + .split('.') + .reversed + .toList(); + parts.removeAt(0); + parts.removeAt(0); + return parts.reversed.join('.'); + } + + @override + Future tryInferringAppId(String standardUrl, + {Map additionalSettings = const {}}) async { + String dlUrl = getDlUrl(standardUrl); + Response res = await requestAppdlRedirect(dlUrl); + return res.headers['location'] != null + ? appIdFromRedirectDlUrl(res.headers['location']!) + : null; + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + String dlUrl = getDlUrl(standardUrl); + Response res = await requestAppdlRedirect(dlUrl); + if (res.headers['location'] == null) { + throw NoReleasesError(); + } + String appId = appIdFromRedirectDlUrl(res.headers['location']!); + var relDateStr = + res.headers['location']?.split('?')[0].split('.').reversed.toList()[1]; + var relDateStrAdj = relDateStr?.split(''); + var tempLen = relDateStrAdj?.length ?? 0; + var i = 2; + while (i < tempLen) { + relDateStrAdj?.insert((i + i ~/ 2 - 1), '-'); + i += 2; + } + var relDate = relDateStrAdj == null + ? null + : DateFormat('yy-MM-dd-HH-mm').parse(relDateStrAdj.join('')); + if (relDateStr == null) { + throw NoVersionError(); + } + return APKDetails( + relDateStr, [MapEntry('$appId.apk', dlUrl)], AppNames(name, appId), + releaseDate: relDate); + } +} diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index da88640..1fff134 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -14,6 +14,7 @@ import 'package:obtainium/app_sources/fdroid.dart'; import 'package:obtainium/app_sources/fdroidrepo.dart'; import 'package:obtainium/app_sources/github.dart'; import 'package:obtainium/app_sources/gitlab.dart'; +import 'package:obtainium/app_sources/huaweiappgallery.dart'; import 'package:obtainium/app_sources/izzyondroid.dart'; import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/app_sources/jenkins.dart'; @@ -355,10 +356,14 @@ abstract class AppSource { Map? get requestHeaders => null; - Future sourceRequest(String url) async { - if (requestHeaders != null) { + Future sourceRequest(String url, + {bool followRedirects = true}) async { + if (requestHeaders != null || followRedirects == false) { var req = Request('GET', Uri.parse(url)); - req.headers.addAll(requestHeaders!); + req.followRedirects = followRedirects; + if (requestHeaders != null) { + req.headers.addAll(requestHeaders!); + } return Response.fromStream(await Client().send(req)); } else { return get(Uri.parse(url)); @@ -508,6 +513,7 @@ class SourceProvider { SourceHut(), APKMirror(), APKPure(), + HuaweiAppGallery(), // APKCombo(), // Can't get past their scraping blocking yet (get 403 Forbidden) Mullvad(), Signal(), From a2571e61a85d043c2e8700e5524a0cc0df087443 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 19 Aug 2023 01:28:25 -0400 Subject: [PATCH 335/600] Fix VLC Source (#758) --- lib/app_sources/vlc.dart | 70 ++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/lib/app_sources/vlc.dart b/lib/app_sources/vlc.dart index bbdec76..6787996 100644 --- a/lib/app_sources/vlc.dart +++ b/lib/app_sources/vlc.dart @@ -1,5 +1,6 @@ import 'package:html/parser.dart'; import 'package:http/http.dart'; +import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -7,55 +8,60 @@ class VLC extends AppSource { VLC() { host = 'videolan.org'; } + get dwUrlBase => 'https://get.$host/vlc-android/'; + + @override + Map? get requestHeaders => HTML().requestHeaders; @override String sourceSpecificStandardizeURL(String url) { return 'https://$host'; } + Future getLatestVersion(String standardUrl) async { + Response res = await sourceRequest(dwUrlBase); + if (res.statusCode == 200) { + var dwLinks = parse(res.body) + .querySelectorAll('a') + .where((element) => element.attributes['href'] != 'last/') + .map((e) => e.attributes['href']?.split('/')[0]) + .toList(); + String? version = dwLinks.isNotEmpty ? dwLinks.last : null; + if (version == null) { + throw NoVersionError(); + } + return version; + } else { + throw getObtainiumHttpError(res); + } + } + @override Future getLatestAPKDetails( String standardUrl, Map additionalSettings, ) async { - Response res = await sourceRequest( - 'https://www.videolan.org/vlc/download-android.html'); + String? version = await getLatestVersion(standardUrl); + if (version == null) { + throw NoVersionError(); + } + String? targetUrl = '$dwUrlBase$version/'; + Response res = await sourceRequest(targetUrl); + List apkUrls = []; if (res.statusCode == 200) { - var dwUrlBase = 'get.videolan.org/vlc-android'; - var dwLinks = parse(res.body) + apkUrls = parse(res.body) .querySelectorAll('a') - .where((element) => - element.attributes['href']?.contains(dwUrlBase) ?? false) + .map((e) => e.attributes['href']?.split('/').last) + .where((h) => + h != null && h.isNotEmpty && h.toLowerCase().endsWith('.apk')) + .map((e) => targetUrl + e!) .toList(); - String? version = dwLinks.isNotEmpty - ? dwLinks.first.attributes['href'] - ?.split('/') - .where((s) => s.isNotEmpty) - .last - : null; - if (version == null) { - throw NoVersionError(); - } - String? targetUrl = 'https://$dwUrlBase/$version/'; - Response res2 = await sourceRequest(targetUrl); - List apkUrls = []; - if (res2.statusCode == 200) { - apkUrls = parse(res2.body) - .querySelectorAll('a') - .map((e) => e.attributes['href']?.split('/').last) - .where((h) => - h != null && h.isNotEmpty && h.toLowerCase().endsWith('.apk')) - .map((e) => targetUrl + e!) - .toList(); - } else { - throw getObtainiumHttpError(res2); - } - - return APKDetails( - version, getApkUrlsFromUrls(apkUrls), AppNames('VideoLAN', 'VLC')); } else { throw getObtainiumHttpError(res); } + + return APKDetails( + version, getApkUrlsFromUrls(apkUrls), AppNames('VideoLAN', 'VLC')); } @override From 6baf6ccf4b89adca014a12c6d71139030786c4e8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 19 Aug 2023 01:40:14 -0400 Subject: [PATCH 336/600] Slightly better error reporting for failed xapk install --- lib/providers/apps_provider.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 73cd19e..4f5b475 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -391,7 +391,7 @@ class AppsProvider with ChangeNotifier { // If 0 APKs installed, throw the first install error encountered try { var somethingInstalled = false; - Object? firstError; + MultiAppMultiError errors = MultiAppMultiError(); for (var file in dir.extracted .listSync(recursive: true, followLinks: false) .whereType()) { @@ -402,7 +402,7 @@ class AppsProvider with ChangeNotifier { } catch (e) { logs.add( 'Could not install APK from XAPK \'${file.path}\': ${e.toString()}'); - firstError ??= e; + errors.add(dir.appId, e.toString()); } } else if (file.path.toLowerCase().endsWith('.obb')) { await moveObbFile(file, dir.appId); @@ -410,8 +410,8 @@ class AppsProvider with ChangeNotifier { } if (somethingInstalled) { dir.file.delete(recursive: true); - } else if (firstError != null) { - throw firstError; + } else if (errors.content.isNotEmpty) { + throw errors; } } finally { dir.extracted.delete(recursive: true); From a0c48fcca6c7a9ead60475da960de5d2bdbea8d4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 19 Aug 2023 01:44:02 -0400 Subject: [PATCH 337/600] Pub update --- pubspec.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.lock b/pubspec.lock index fc2d4e4..d702e92 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -22,7 +22,7 @@ packages: description: path: "." ref: main - resolved-ref: "2edf5dbbfeeb33257d526861f2a992aee5d97bb4" + resolved-ref: ba2aa7a11edc2649d1d80c25ed9291521262f714 url: "https://github.com/ImranR98/android_package_installer" source: git version: "0.0.1" From 7c41692d5f1b9ef22ce6815ed510b751be62950c Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 20 Aug 2023 16:03:41 -0400 Subject: [PATCH 338/600] Enable version correction in background (replace plugin) --- android/app/src/main/AndroidManifest.xml | 1 + lib/pages/app.dart | 4 +- lib/pages/apps.dart | 4 +- lib/providers/apps_provider.dart | 162 ++++++++++------------- pubspec.lock | 26 +--- pubspec.yaml | 2 - 6 files changed, 78 insertions(+), 121 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index cfeac66..d48e3f5 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -71,4 +71,5 @@ + \ No newline at end of file diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 0708b02..de64bb3 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -153,10 +153,10 @@ class _AppPageState extends State { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: 125), - app?.installedInfo != null + app?.icon != null ? Row(mainAxisAlignment: MainAxisAlignment.center, children: [ Image.memory( - app!.installedInfo!.icon!, + app!.icon!, height: 150, gaplessPlayback: true, ) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index f8ee0e4..516a6a6 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -393,9 +393,9 @@ class AppsPageState extends State { } getAppIcon(int appIndex) { - return listedApps[appIndex].installedInfo != null + return listedApps[appIndex].icon != null ? Image.memory( - listedApps[appIndex].installedInfo!.icon!, + listedApps[appIndex].icon!, gaplessPlayback: true, ) : Row( diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 4f5b475..3c63a72 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -12,15 +12,12 @@ import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:installed_apps/app_info.dart'; -import 'package:installed_apps/installed_apps.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/providers/logs_provider.dart'; import 'package:obtainium/providers/notifications_provider.dart'; import 'package:obtainium/providers/settings_provider.dart'; -import 'package:package_archive_info/package_archive_info.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:path_provider/path_provider.dart'; @@ -35,13 +32,14 @@ final pm = AndroidPackageManager(); class AppInMemory { late App app; double? downloadProgress; - AppInfo? installedInfo; + PackageInfo? installedInfo; + Uint8List? icon; - AppInMemory(this.app, this.downloadProgress, this.installedInfo); + AppInMemory(this.app, this.downloadProgress, this.installedInfo, this.icon); AppInMemory deepCopy() => - AppInMemory(app.deepCopy(), downloadProgress, installedInfo); + AppInMemory(app.deepCopy(), downloadProgress, installedInfo, icon); - String get name => app.overrideName ?? installedInfo?.name ?? app.finalName; + String get name => app.overrideName ?? app.finalName; } class DownloadedApk { @@ -218,19 +216,19 @@ class AppsProvider with ChangeNotifier { return downloadedFile; } - Future handleAPKIDChange(App app, PackageArchiveInfo newInfo, + Future handleAPKIDChange(App app, PackageInfo newInfo, File downloadedFile, String downloadUrl) async { // If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed // The former case should be handled (give the App its real ID), the latter is a security issue if (app.id != newInfo.packageName) { var isTempId = SourceProvider().isTempId(app); if (apps[app.id] != null && !isTempId && !app.allowIdChange) { - throw IDChangedError(newInfo.packageName); + throw IDChangedError(newInfo.packageName!); } var idChangeWasAllowed = app.allowIdChange; app.allowIdChange = false; var originalAppId = app.id; - app.id = newInfo.packageName; + app.id = newInfo.packageName!; downloadedFile = downloadedFile.renameSync( '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.${downloadedFile.path.split('.').last}'); if (apps[originalAppId] != null) { @@ -279,11 +277,12 @@ class AppsProvider with ChangeNotifier { notif = DownloadNotification(app.finalName, -1); notificationsProvider?.notify(notif); } - PackageArchiveInfo? newInfo; + PackageInfo? newInfo; var isAPK = downloadedFile.path.toLowerCase().endsWith('.apk'); Directory? xapkDir; if (isAPK) { - newInfo = await PackageArchiveInfo.fromPath(downloadedFile.path); + newInfo = await pm.getPackageArchiveInfo( + archiveFilePath: downloadedFile.path); } else { // Assume XAPK String xapkDirPath = '${downloadedFile.path}-dir'; @@ -293,10 +292,11 @@ class AppsProvider with ChangeNotifier { .listSync() .where((e) => e.path.toLowerCase().endsWith('.apk')) .toList(); - newInfo = await PackageArchiveInfo.fromPath(apks.first.path); + newInfo = + await pm.getPackageArchiveInfo(archiveFilePath: apks.first.path); } downloadedFile = - await handleAPKIDChange(app, newInfo, downloadedFile, downloadUrl); + await handleAPKIDChange(app, newInfo!, downloadedFile, downloadUrl); // Delete older versions of the file if any for (var file in downloadedFile.parent.listSync()) { var fn = file.path.split('/').last; @@ -344,14 +344,8 @@ class AppsProvider with ChangeNotifier { // If we did not install the app (or it isn't installed), silent install is not possible return false; } - int? targetSDK; - try { - targetSDK = (await pm.getPackageInfo(packageName: app.id)) - ?.applicationInfo - ?.targetSdkVersion; - } catch (e) { - // Weird if you get here - ignore - } + int? targetSDK = + (await getInstalledInfo(app.id))?.applicationInfo?.targetSdkVersion; // The OS must also be new enough and the APK should target a new enough API return osInfo.version.sdkInt >= 30 && @@ -371,14 +365,8 @@ class AppsProvider with ChangeNotifier { } } - Future canDowngradeApps() async { - try { - await InstalledApps.getAppInfo('com.berdik.letmedowngrade'); - return true; - } catch (e) { - return false; - } - } + Future canDowngradeApps() async => + (await getInstalledInfo('com.berdik.letmedowngrade')) != null; Future unzipFile(String filePath, String destinationPath) async { await ZipFile.extractToDirectory( @@ -419,15 +407,11 @@ class AppsProvider with ChangeNotifier { } Future installApk(DownloadedApk file) async { - var newInfo = await PackageArchiveInfo.fromPath(file.file.path); - AppInfo? appInfo; - try { - appInfo = await InstalledApps.getAppInfo(apps[file.appId]!.app.id); - } catch (e) { - // OK - } + var newInfo = + await pm.getPackageArchiveInfo(archiveFilePath: file.file.path); + PackageInfo? appInfo = await getInstalledInfo(apps[file.appId]!.app.id); if (appInfo != null && - int.parse(newInfo.buildNumber) < appInfo.versionCode! && + newInfo!.versionCode! < appInfo.versionCode! && !(await canDowngradeApps())) { throw DowngradeError(); } @@ -638,27 +622,17 @@ class AppsProvider with ChangeNotifier { return appsDir; } - Future getInstalledInfo(String? packageName) async { + Future getInstalledInfo(String? packageName) async { if (packageName != null) { try { - return await InstalledApps.getAppInfo(packageName); + return await pm.getPackageInfo(packageName: packageName); } catch (e) { - // OK + print(e); // OK } } return null; } - Future doesInstalledAppsPluginWork() async { - bool res = false; - try { - res = (await InstalledApps.getAppInfo(obtainiumId)).versionName != null; - } catch (e) { - // - } - return res; - } - bool isVersionDetectionPossible(AppInMemory? app) { return app?.app.additionalSettings['trackOnly'] != true && app?.app.additionalSettings['versionDetection'] != @@ -672,7 +646,8 @@ class AppsProvider with ChangeNotifier { // Given an App and it's on-device info... // Reconcile unexpected differences between its reported installed version, real installed version, and reported latest version - App? getCorrectedInstallStatusAppIfPossible(App app, AppInfo? installedInfo) { + App? getCorrectedInstallStatusAppIfPossible( + App app, PackageInfo? installedInfo) { var modded = false; var trackOnly = app.additionalSettings['trackOnly'] == true; var noVersionDetection = app.additionalSettings['versionDetection'] != @@ -718,7 +693,8 @@ class AppsProvider with ChangeNotifier { if (installedInfo != null && app.additionalSettings['versionDetection'] == 'standardVersionDetection' && - !isVersionDetectionPossible(AppInMemory(app, null, installedInfo))) { + !isVersionDetectionPossible( + AppInMemory(app, null, installedInfo, null))) { app.additionalSettings['versionDetection'] = 'noVersionDetection'; logs.add('Could not reconcile version formats for: ${app.id}'); modded = true; @@ -802,9 +778,9 @@ class AppsProvider with ChangeNotifier { sp.getSource(app.url, overrideSource: app.overrideSource); apps.update( app.id, - (value) => - AppInMemory(app, value.downloadProgress, value.installedInfo), - ifAbsent: () => AppInMemory(app, null, null)); + (value) => AppInMemory( + app, value.downloadProgress, value.installedInfo, value.icon), + ifAbsent: () => AppInMemory(app, null, null, null)); } catch (e) { errors.add([app.id, app.finalName, e.toString()]); } @@ -817,34 +793,39 @@ class AppsProvider with ChangeNotifier { AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList())); } - if (await doesInstalledAppsPluginWork()) { - for (var app in apps.values) { - // Check install status for each App (slow) - apps[app.app.id]?.installedInfo = await getInstalledInfo(app.app.id); - notifyListeners(); + for (var app in apps.values) { + // Get install status and other OS info for each App (slow) + apps[app.app.id]?.installedInfo = await getInstalledInfo(app.app.id); + apps[app.app.id]?.icon = + await apps[app.app.id]?.installedInfo?.applicationInfo?.getAppIcon(); + apps[app.app.id]?.app.name = await (apps[app.app.id] + ?.installedInfo + ?.applicationInfo + ?.getAppLabel()) ?? + app.name; + notifyListeners(); + } + // Reconcile version differences + List modifiedApps = []; + for (var app in apps.values) { + var moddedApp = + getCorrectedInstallStatusAppIfPossible(app.app, app.installedInfo); + if (moddedApp != null) { + modifiedApps.add(moddedApp); } - // Reconcile version differences - List modifiedApps = []; - for (var app in apps.values) { - var moddedApp = - getCorrectedInstallStatusAppIfPossible(app.app, app.installedInfo); - if (moddedApp != null) { - modifiedApps.add(moddedApp); - } - } - if (modifiedApps.isNotEmpty) { - await saveApps(modifiedApps, attemptToCorrectInstallStatus: false); - var removedAppIds = modifiedApps - .where((a) => a.installedVersion == null) - .map((e) => e.id) - .toList(); - // After reconciliation, delete externally uninstalled Apps if needed - if (removedAppIds.isNotEmpty) { - var settingsProvider = SettingsProvider(); - await settingsProvider.initializeSettings(); - if (settingsProvider.removeOnExternalUninstall) { - await removeApps(removedAppIds); - } + } + if (modifiedApps.isNotEmpty) { + await saveApps(modifiedApps, attemptToCorrectInstallStatus: false); + var removedAppIds = modifiedApps + .where((a) => a.installedVersion == null) + .map((e) => e.id) + .toList(); + // After reconciliation, delete externally uninstalled Apps if needed + if (removedAppIds.isNotEmpty) { + var settingsProvider = SettingsProvider(); + await settingsProvider.initializeSettings(); + if (settingsProvider.removeOnExternalUninstall) { + await removeApps(removedAppIds); } } } @@ -856,12 +837,12 @@ class AppsProvider with ChangeNotifier { Future saveApps(List apps, {bool attemptToCorrectInstallStatus = true, bool onlyIfExists = true}) async { - attemptToCorrectInstallStatus = - attemptToCorrectInstallStatus && (await doesInstalledAppsPluginWork()); + attemptToCorrectInstallStatus = attemptToCorrectInstallStatus; for (var a in apps) { var app = a.deepCopy(); - AppInfo? info = await getInstalledInfo(app.id); - app.name = info?.name ?? app.name; + PackageInfo? info = await getInstalledInfo(app.id); + var icon = await info?.applicationInfo?.getAppIcon(); + app.name = await (info?.applicationInfo?.getAppLabel()) ?? app.name; if (attemptToCorrectInstallStatus) { app = getCorrectedInstallStatusAppIfPossible(app, info) ?? app; } @@ -870,9 +851,10 @@ class AppsProvider with ChangeNotifier { .writeAsStringSync(jsonEncode(app.toJson())); } try { - this.apps.update( - app.id, (value) => AppInMemory(app, value.downloadProgress, info), - ifAbsent: onlyIfExists ? null : () => AppInMemory(app, null, info)); + this.apps.update(app.id, + (value) => AppInMemory(app, value.downloadProgress, info, icon), + ifAbsent: + onlyIfExists ? null : () => AppInMemory(app, null, info, icon)); } catch (e) { if (e is! ArgumentError || e.name != 'key') { rethrow; diff --git a/pubspec.lock b/pubspec.lock index d702e92..ffb90fa 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -31,7 +31,7 @@ packages: description: path: "." ref: master - resolved-ref: "6e68991ef9c6232695abce2eef345d3cca2f52ac" + resolved-ref: c7c2f992a9dc452393c94d96cdf2b1f5a5ce7c80 url: "https://github.com/ImranR98/android_package_manager" source: git version: "0.5.4" @@ -375,14 +375,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.17" - installed_apps: - dependency: "direct main" - description: - name: installed_apps - sha256: "145af8eb6e4e7c830e9888d6de0573ae5c139e8e0742a3e67316e1db21ab6fe0" - url: "https://pub.dev" - source: hosted - version: "1.3.1" intl: dependency: transitive description: @@ -463,22 +455,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" - package_archive_info: - dependency: "direct main" - description: - name: package_archive_info - sha256: "8f671a29b79d15f192e5e2b0dab9d0bad66b9ee93fb58d4e0afdb62f91a259be" - url: "https://pub.dev" - source: hosted - version: "0.1.0" - package_info: - dependency: transitive - description: - name: package_info - sha256: "6c07d9d82c69e16afeeeeb6866fe43985a20b3b50df243091bfc4a4ad2b03b75" - url: "https://pub.dev" - source: hosted - version: "2.0.2" path: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 83b618f..551bf12 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,8 +60,6 @@ dependencies: url: https://github.com/ImranR98/android_package_manager ref: master share_plus: ^7.0.0 - installed_apps: ^1.3.1 # TODO: Remove when android_package_manager supports getting icon as UInt8List and versionCode - package_archive_info: ^0.1.0 # TODO: Remove when android_package_manager supports getting versionCode android_alarm_manager_plus: ^3.0.0 sqflite: ^2.2.0+3 easy_localization: ^3.0.1 From b59d3e77f9e7eb99fc2175201580ec8734423171 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 20 Aug 2023 22:32:33 -0400 Subject: [PATCH 339/600] Enable experimental BG update support (not well tested) (#25) --- assets/translations/bs.json | 7 ++++ assets/translations/de.json | 7 ++++ assets/translations/en.json | 7 ++++ assets/translations/es.json | 7 ++++ assets/translations/fa.json | 7 ++++ assets/translations/fr.json | 7 ++++ assets/translations/hu.json | 7 ++++ assets/translations/it.json | 7 ++++ assets/translations/ja.json | 7 ++++ assets/translations/pl.json | 7 ++++ assets/translations/ru.json | 7 ++++ assets/translations/zh.json | 7 ++++ lib/main.dart | 43 +++++++++----------- lib/providers/apps_provider.dart | 49 +++++++++++++++++------ lib/providers/notifications_provider.dart | 32 +++++++++++---- 15 files changed, 164 insertions(+), 44 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 2c3c5d3..ef08037 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -247,6 +247,9 @@ "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" @@ -294,5 +297,9 @@ "xAndNMoreUpdatesInstalled": { "one": "{} i još 1 aplikacija je ažurirana.", "other": "{} i još {} aplikacija je ažurirano." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/assets/translations/de.json b/assets/translations/de.json index b47e385..ffc08dc 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -247,6 +247,9 @@ "sortByFileNamesNotLinks": "Sortiere nach Dateinamen, anstelle von ganzen Links", "filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck filtern", "customLinkFilterRegex": "Benutzerdefinierter Link Filter nach Regulärem Ausdruck (Standard '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" @@ -294,5 +297,9 @@ "xAndNMoreUpdatesInstalled": { "one": "{} und 1 weitere Anwendung wurden aktualisiert.", "other": "{} und {} weitere Anwendungen wurden aktualisiert." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/assets/translations/en.json b/assets/translations/en.json index 397c7a2..8fa9763 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -247,6 +247,9 @@ "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" @@ -294,5 +297,9 @@ "xAndNMoreUpdatesInstalled": { "one": "{} and 1 more app were updated.", "other": "{} and {} more apps were updated." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/assets/translations/es.json b/assets/translations/es.json index b5d3d25..bffc0de 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -247,6 +247,9 @@ "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" @@ -294,5 +297,9 @@ "xAndNMoreUpdatesInstalled": { "one": "{} y 1 aplicación más han sido actualizadas.", "other": "{} y {} aplicaciones más han sido actualizadas." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 3f98e69..02027bf 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -247,6 +247,9 @@ "sortByFileNamesNotLinks": "مرتب سازی بر اساس نام فایل به جای پیوندهای کامل", "filterReleaseNotesByRegEx": "یادداشت های انتشار را با بیان منظم فیلتر کنید", "customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیش‌فرض '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" @@ -294,5 +297,9 @@ "xAndNMoreUpdatesInstalled": { "one": "{} و 1 برنامه دیگر به روز شدند.", "other": "{} و {} برنامه دیگر به روز شدند." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/assets/translations/fr.json b/assets/translations/fr.json index ec680f8..582e286 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -247,6 +247,9 @@ "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" @@ -294,5 +297,9 @@ "xAndNMoreUpdatesInstalled": { "one": "{} et 1 autre application ont été mises à jour.", "other": "{} et {} autres applications ont été mises à jour." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/assets/translations/hu.json b/assets/translations/hu.json index da0b17a..5164bcd 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -246,6 +246,9 @@ "sortByFileNamesNotLinks": "Fájlnevek szerinti elrendezés teljes linkek helyett", "filterReleaseNotesByRegEx": "Kiadási megjegyzések szűrése reguláris kifejezéssel", "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" @@ -293,5 +296,9 @@ "xAndNMoreUpdatesInstalled": { "one": "A(z) {} és 1 további alkalmazás frissítve.", "other": "{} és {} további alkalmazás frissítve." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/assets/translations/it.json b/assets/translations/it.json index 4dd0383..ed43216 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -247,6 +247,9 @@ "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" @@ -294,5 +297,9 @@ "xAndNMoreUpdatesInstalled": { "one": "{} e un'altra app sono state aggiornate.", "other": "{} e altre {} app sono state aggiornate." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 1ade9f2..37edc58 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -247,6 +247,9 @@ "sortByFileNamesNotLinks": "フルのリンクではなくファイル名でソートする", "filterReleaseNotesByRegEx": "正規表現でリリースノートをフィルタリングする", "customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" @@ -294,5 +297,9 @@ "xAndNMoreUpdatesInstalled": { "one": "{} とさらに {} 個のアプリがアップデートされました", "other": "{} とさらに {} 個のアプリがアップデートされました" + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/assets/translations/pl.json b/assets/translations/pl.json index b8a1a81..ea8be8a 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -251,6 +251,9 @@ "sortByFileNamesNotLinks": "Sortuj wg nazw plików zamiast pełnych linków", "filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego", "customLinkFilterRegex": "Niestandardowy filtr linków wg. wyrażenia regularnego (domyślnie \".apk$\")", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" @@ -294,5 +297,9 @@ "xAndNMoreUpdatesInstalled": { "one": "Zaktualizowano {} i jeszcze 1 aplikację.", "other": "Zaktualizowano {} i {} aplik." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 1f27453..609b5e3 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -247,6 +247,9 @@ "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" @@ -294,5 +297,9 @@ "xAndNMoreUpdatesInstalled": { "one": "{} и еще 1 приложение были обновлены.", "other": "{} и еще {} приложений были обновлены." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 028e8d1..1aa36fc 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -247,6 +247,9 @@ "sortByFileNamesNotLinks": "根据文件名而不是完整链接来排序", "filterReleaseNotesByRegEx": "用正则表达式筛选发布说明", "customLinkFilterRegex": "用正则表达式自定义链接筛选(默认 '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" @@ -294,5 +297,9 @@ "xAndNMoreUpdatesInstalled": { "one": "{} 和另外 1 个应用已更新。", "other": "{} 和另外 {} 个应用已更新。" + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "Attempts were made to update {} and 1 more app.", + "other": "Attempts were made to update {} and {} more apps." } } diff --git a/lib/main.dart b/lib/main.dart index 5074433..79bdfcb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -88,10 +88,8 @@ Future bgUpdateCheck(int taskId, Map? params) async { : null; logs.add(tr('bgUpdateIgnoreAfterIs', args: [ignoreAfter.toString()])); var notificationsProvider = NotificationsProvider(); - await notificationsProvider.notify(checkingUpdatesNotification); try { var appsProvider = AppsProvider(); - await notificationsProvider.cancel(ErrorCheckingUpdatesNotification('').id); await appsProvider.loadApps(); List existingUpdateIds = appsProvider.findExistingUpdates(installedOnly: true); @@ -100,7 +98,9 @@ Future bgUpdateCheck(int taskId, Map? params) async { try { logs.add(tr('startedActualBGUpdateCheck')); await appsProvider.checkUpdates( - ignoreAppsCheckedAfter: ignoreAfter, throwErrorsForRetry: true); + ignoreAppsCheckedAfter: ignoreAfter, + throwErrorsForRetry: true, + notificationsProvider: notificationsProvider); } catch (e) { if (e is RateLimitError || e is ClientException) { var remainingMinutes = e is RateLimitError ? e.remainingMinutes : 15; @@ -124,34 +124,29 @@ Future bgUpdateCheck(int taskId, Map? params) async { .where((id) => !existingUpdateIds.contains(id)) .map((e) => appsProvider.apps[e]!.app) .toList(); - - // TODO: This silent update code doesn't work yet - // List silentlyUpdated = await appsProvider - // .downloadAndInstallLatestApp( - // [...newUpdates.map((e) => e.id), ...existingUpdateIds], null); - // if (silentlyUpdated.isNotEmpty) { - // newUpdates = newUpdates - // .where((element) => !silentlyUpdated.contains(element.id)) - // .toList(); - // notificationsProvider.notify( - // SilentUpdateNotification( - // silentlyUpdated.map((e) => appsProvider.apps[e]!.app).toList()), - // cancelExisting: true); - // } - logs.add( - plural('bgCheckFoundUpdatesWillNotifyIfNeeded', newUpdates.length)); - if (newUpdates.isNotEmpty) { - notificationsProvider.notify(UpdateNotification(newUpdates)); + List nonSilentUpdates = []; + List silentUpdates = []; + for (var a in newUpdates) { + if (await appsProvider.canInstallSilently(a)) { + silentUpdates.add(a); + } else { + nonSilentUpdates.add(a); + } } + if (silentUpdates.isNotEmpty) { + await appsProvider.downloadAndInstallLatestApps( + silentUpdates.map((e) => e.id).toList(), null, + notificationsProvider: notificationsProvider); + } + logs.add(plural( + 'bgCheckFoundUpdatesWillNotifyIfNeeded', nonSilentUpdates.length)); if (err != null) { throw err; } } catch (e) { - notificationsProvider - .notify(ErrorCheckingUpdatesNotification(e.toString())); + logs.add('${tr('errorCheckingUpdates')}: ${e.toString()}'); } finally { logs.add(tr('bgUpdateTaskFinished')); - await notificationsProvider.cancel(checkingUpdatesNotification.id); } } diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 3c63a72..30f75bd 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -239,9 +239,8 @@ class AppsProvider with ChangeNotifier { return downloadedFile; } - Future downloadApp(App app, BuildContext? context) async { - NotificationsProvider? notificationsProvider = - context?.read(); + Future downloadApp(App app, BuildContext? context, + {NotificationsProvider? notificationsProvider}) async { var notifId = DownloadNotification(app.finalName, 0).id; if (apps[app.id] != null) { apps[app.id]!.downloadProgress = 0; @@ -507,7 +506,10 @@ class AppsProvider with ChangeNotifier { // Returns an array of Ids for Apps that were successfully downloaded, regardless of installation result Future> downloadAndInstallLatestApps( List appIds, BuildContext? context, - {SettingsProvider? settingsProvider}) async { + {SettingsProvider? settingsProvider, + NotificationsProvider? notificationsProvider}) async { + notificationsProvider = + notificationsProvider ?? context?.read(); List appsToInstall = []; List trackOnlyAppsToUpdate = []; // For all specified Apps, filter out those for which: @@ -567,8 +569,10 @@ class AppsProvider with ChangeNotifier { for (var id in appsToInstall) { try { - // ignore: use_build_context_synchronously - var downloadedArtifact = await downloadApp(apps[id]!.app, context); + var downloadedArtifact = + // ignore: use_build_context_synchronously + await downloadApp(apps[id]!.app, context, + notificationsProvider: notificationsProvider); DownloadedApk? downloadedFile; DownloadedXApkDir? downloadedDir; if (downloadedArtifact is DownloadedApk) { @@ -576,8 +580,8 @@ class AppsProvider with ChangeNotifier { } else { downloadedDir = downloadedArtifact as DownloadedXApkDir; } - bool willBeSilent = await canInstallSilently( - apps[downloadedFile?.appId ?? downloadedDir!.appId]!.app); + var appId = downloadedFile?.appId ?? downloadedDir!.appId; + bool willBeSilent = await canInstallSilently(apps[appId]!.app); if (!(await settingsProvider?.getInstallPermission(enforce: false) ?? true)) { throw ObtainiumError(tr('cancelled')); @@ -590,9 +594,24 @@ class AppsProvider with ChangeNotifier { notifyListeners(); try { if (downloadedFile != null) { - await installApk(downloadedFile); + if (willBeSilent) { + // Would await forever - workaround - TODO + installApk(downloadedFile); + } else { + await installApk(downloadedFile); + } } else { - await installXApkDir(downloadedDir!); + if (willBeSilent) { + // Would await forever - workaround - TODO + installXApkDir(downloadedDir!); + } else { + await installXApkDir(downloadedDir!); + } + } + if (willBeSilent) { + notificationsProvider?.notify(SilentUpdateAttemptNotification( + [apps[appId]!.app], + id: appId.hashCode)); } } finally { apps[id]?.downloadProgress = null; @@ -608,8 +627,6 @@ class AppsProvider with ChangeNotifier { throw errors; } - NotificationsProvider().cancel(UpdateNotification([]).id); - return installedIds; } @@ -971,7 +988,8 @@ class AppsProvider with ChangeNotifier { Future> checkUpdates( {DateTime? ignoreAppsCheckedAfter, - bool throwErrorsForRetry = false}) async { + bool throwErrorsForRetry = false, + NotificationsProvider? notificationsProvider}) async { List updates = []; MultiAppMultiError errors = MultiAppMultiError(); if (!gettingUpdates) { @@ -998,9 +1016,14 @@ class AppsProvider with ChangeNotifier { rethrow; } errors.add(appIds[i], e.toString()); + notificationsProvider?.notify(ErrorCheckingUpdatesNotification( + '${appIds[i]}: ${e.toString()}', + id: appIds[i].hashCode)); } if (newApp != null) { updates.add(newApp); + notificationsProvider + ?.notify(UpdateNotification([newApp], id: newApp.id.hashCode)); } } } finally { diff --git a/lib/providers/notifications_provider.dart b/lib/providers/notifications_provider.dart index 1f39cc8..1c2ab23 100644 --- a/lib/providers/notifications_provider.dart +++ b/lib/providers/notifications_provider.dart @@ -22,9 +22,9 @@ class ObtainiumNotification { } class UpdateNotification extends ObtainiumNotification { - UpdateNotification(List updates) + UpdateNotification(List updates, {int? id}) : super( - 2, + id ?? 2, tr('updatesAvailable'), '', 'UPDATES_AVAILABLE', @@ -41,8 +41,8 @@ class UpdateNotification extends ObtainiumNotification { } class SilentUpdateNotification extends ObtainiumNotification { - SilentUpdateNotification(List updates) - : super(3, tr('appsUpdated'), '', 'APPS_UPDATED', tr('appsUpdated'), + SilentUpdateNotification(List updates, {int? id}) + : super(id ?? 3, tr('appsUpdated'), '', 'APPS_UPDATED', tr('appsUpdated'), tr('appsUpdatedNotifDescription'), Importance.defaultImportance) { message = updates.length == 1 ? tr('xWasUpdatedToY', @@ -52,10 +52,28 @@ class SilentUpdateNotification extends ObtainiumNotification { } } -class ErrorCheckingUpdatesNotification extends ObtainiumNotification { - ErrorCheckingUpdatesNotification(String error) +class SilentUpdateAttemptNotification extends ObtainiumNotification { + SilentUpdateAttemptNotification(List updates, {int? id}) : super( - 5, + id ?? 3, + tr('appsPossiblyUpdated'), + '', + 'APPS_POSSIBLY_UPDATED', + tr('appsPossiblyUpdated'), + tr('appsPossiblyUpdatedNotifDescription'), + Importance.defaultImportance) { + message = updates.length == 1 + ? tr('xWasPossiblyUpdatedToY', + args: [updates[0].finalName, updates[0].latestVersion]) + : plural('xAndNMoreUpdatesPossiblyInstalled', updates.length - 1, + args: [updates[0].finalName, (updates.length - 1).toString()]); + } +} + +class ErrorCheckingUpdatesNotification extends ObtainiumNotification { + ErrorCheckingUpdatesNotification(String error, {int? id}) + : super( + id ?? 5, tr('errorCheckingUpdates'), error, 'BG_UPDATE_CHECK_ERROR', From 03bb1ad9a65812fcbad65fd7a6e22d677af8c747 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 21 Aug 2023 09:48:35 -0400 Subject: [PATCH 340/600] bugfix --- lib/providers/apps_provider.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 30f75bd..00a6bd0 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -594,21 +594,21 @@ class AppsProvider with ChangeNotifier { notifyListeners(); try { if (downloadedFile != null) { - if (willBeSilent) { + if (willBeSilent && context == null) { // Would await forever - workaround - TODO installApk(downloadedFile); } else { await installApk(downloadedFile); } } else { - if (willBeSilent) { + if (willBeSilent && context == null) { // Would await forever - workaround - TODO installXApkDir(downloadedDir!); } else { await installXApkDir(downloadedDir!); } } - if (willBeSilent) { + if (willBeSilent && context == null) { notificationsProvider?.notify(SilentUpdateAttemptNotification( [apps[appId]!.app], id: appId.hashCode)); From 3eb25c4060258b61ece5331c23bfb9ae6aeb9d41 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 21 Aug 2023 20:10:30 -0400 Subject: [PATCH 341/600] Switch to per-app BG update tasks --- assets/translations/bs.json | 16 ++-- assets/translations/de.json | 12 +-- assets/translations/en.json | 14 +--- assets/translations/es.json | 12 +-- assets/translations/fa.json | 12 +-- assets/translations/fr.json | 12 +-- assets/translations/hu.json | 12 +-- assets/translations/it.json | 12 +-- assets/translations/ja.json | 12 +-- assets/translations/pl.json | 12 +-- assets/translations/ru.json | 12 +-- assets/translations/zh.json | 12 +-- lib/main.dart | 132 +++++++++++++++---------------- lib/providers/apps_provider.dart | 43 +++++----- 14 files changed, 129 insertions(+), 196 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index ef08037..7c86b74 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -1,4 +1,4 @@ - { +{ "invalidURLForSource": "Nije važeći URL aplikacije {}", "noReleaseFound": "Nije moguće pronaći odgovarajuće izdanje", "noVersionFound": "Nije moguće odrediti verziju izdanja", @@ -11,12 +11,6 @@ "unexpectedError": "Neočekivana greška", "ok": "Dobro", "and": "i", - "startedBgUpdateTask": "Započeo je pozadinski zadatak provjere ažuriranja", - "bgUpdateIgnoreAfterIs": "ignoreAfter pozadinskog zadataka je {}", - "startedActualBGUpdateCheck": "Započela je stvarna provjera ažuriranja", - "bgUpdateTaskFinished": "Završen zadatak provjere ažuriranja", - "firstRun": "Ovo je prvi put da pokrećete Obtainium", - "settingUpdateCheckIntervalTo": "Podešavanje intervala ažuriranja na {}", "githubPATLabel": "GitHub token za lični pristup (eng. PAT, povećava ograničenje stope)", "githubPATHint": "PAT mora biti u ovom formatu: korisničko_ime:token", "githubPATFormat": "korisničko_ime:token", @@ -249,7 +243,7 @@ "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" @@ -299,7 +293,7 @@ "other": "{} i još {} aplikacija je ažurirano." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } -} +} \ No newline at end of file diff --git a/assets/translations/de.json b/assets/translations/de.json index ffc08dc..973c229 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -11,12 +11,6 @@ "unexpectedError": "Unerwarteter Fehler", "ok": "Okay", "and": "und", - "startedBgUpdateTask": "Hintergrundaktualisierungsprüfung gestartet", - "bgUpdateIgnoreAfterIs": "Hintergrundaktualisierung 'ignoreAfter' ist {}", - "startedActualBGUpdateCheck": "Überprüfung der Hintergrundaktualisierung gestartet", - "bgUpdateTaskFinished": "Hintergrundaktualisierungsprüfung abgeschlossen", - "firstRun": "Dies ist der erste Start von Obtainium überhaupt", - "settingUpdateCheckIntervalTo": "Aktualisierungsintervall auf {} stellen", "githubPATLabel": "GitHub Personal Access Token (Erhöht das Ratenlimit)", "githubPATHint": "PAT muss in diesem Format sein: Benutzername:Token", "githubPATFormat": "Benutzername:Token", @@ -249,7 +243,7 @@ "customLinkFilterRegex": "Benutzerdefinierter Link Filter nach Regulärem Ausdruck (Standard '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" @@ -299,7 +293,7 @@ "other": "{} und {} weitere Anwendungen wurden aktualisiert." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } } diff --git a/assets/translations/en.json b/assets/translations/en.json index 8fa9763..7a76230 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -11,12 +11,6 @@ "unexpectedError": "Unexpected Error", "ok": "Okay", "and": "and", - "startedBgUpdateTask": "Started BG update check task", - "bgUpdateIgnoreAfterIs": "Bg update ignoreAfter is {}", - "startedActualBGUpdateCheck": "Started actual BG update checking", - "bgUpdateTaskFinished": "Finished BG update check task", - "firstRun": "This is the first ever run of Obtainium", - "settingUpdateCheckIntervalTo": "Setting update interval to {}", "githubPATLabel": "GitHub Personal Access Token (Increases Rate Limit)", "githubPATHint": "PAT must be in this format: username:token", "githubPATFormat": "username:token", @@ -249,7 +243,7 @@ "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" @@ -295,11 +289,11 @@ "other": "{} and {} more apps have updates." }, "xAndNMoreUpdatesInstalled": { - "one": "{} and 1 more app were updated.", + "one": "{} and 1 more app was updated.", "other": "{} and {} more apps were updated." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } } diff --git a/assets/translations/es.json b/assets/translations/es.json index bffc0de..63f9dc1 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -11,12 +11,6 @@ "unexpectedError": "Error Inesperado", "ok": "Correcto", "and": "y", - "startedBgUpdateTask": "Empezada la tarea de comprobación de actualizaciones en segundo plano", - "bgUpdateIgnoreAfterIs": "El parámetro ignoreAfter de la actualización en segundo plano es {}", - "startedActualBGUpdateCheck": "Ha comenzado la comprobación de actualizaciones en segundo plano", - "bgUpdateTaskFinished": "Ha finalizado la comprobación de actualizaciones en segundo plano", - "firstRun": "Esta es la primera ejecución de Obtainium", - "settingUpdateCheckIntervalTo": "Cambiando intervalo de actualización a {}", "githubPATLabel": "Token de Acceso Personal de GitHub (Reduce tiempos de espera)", "githubPATHint": "El TAP debe tener este formato: nombre_de_usuario:token", "githubPATFormat": "nombre_de_usuario:token", @@ -249,7 +243,7 @@ "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" @@ -299,7 +293,7 @@ "other": "{} y {} aplicaciones más han sido actualizadas." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } } diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 02027bf..4342244 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -11,12 +11,6 @@ "unexpectedError": "خطای غیرمنتظره", "ok": "باشه", "and": "و", - "startedBgUpdateTask": "شروع بررسی بروزرسانی BG", - "bgUpdateIgnoreAfterIs": "نادیده گرفتن بروزرسانی BG بعد از {} است", - "startedActualBGUpdateCheck": "بررسی به‌روزرسانی واقعی BG آغاز شد", - "bgUpdateTaskFinished": "کار بررسی به‌روزرسانی BG تمام شد", - "firstRun": "این اولین اجرای Obtainium است", - "settingUpdateCheckIntervalTo": "تنظیم فاصله به‌روزرسانی روی {}", "githubPATLabel": "توکن دسترسی شخصی گیت هاب(محدودیت نرخ را افزایش میدهد)", "githubPATHint": "PAT باید در این قالب باشد: username:token", "githubPATFormat": "username:token", @@ -249,7 +243,7 @@ "customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیش‌فرض '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" @@ -299,7 +293,7 @@ "other": "{} و {} برنامه دیگر به روز شدند." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } } diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 582e286..1bc1a6e 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -11,12 +11,6 @@ "unexpectedError": "Erreur inattendue", "ok": "Okay", "and": "et", - "startedBgUpdateTask": "Démarrage de la tâche de vérification de mise à jour en arrière-plan", - "bgUpdateIgnoreAfterIs": "Mise à jour en arrière-plan est ignoré après {}", - "startedActualBGUpdateCheck": "Démarrage de la vérification de la mise à jour en arrière-plan", - "bgUpdateTaskFinished": "Tâche de vérification de la mise à jour en arrière-plan terminée", - "firstRun": "Il s'agit de la toute première exécution d'Obtainium", - "settingUpdateCheckIntervalTo": "Définition de l'intervalle de mise à jour sur {}", "githubPATLabel": "Jeton d'Accès Personnel GitHub (Augmente la limite de débit)", "githubPATHint": "Le JAP doit être dans ce format : username:token", "githubPATFormat": "username:token", @@ -249,7 +243,7 @@ "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" @@ -299,7 +293,7 @@ "other": "{} et {} autres applications ont été mises à jour." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } } diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 5164bcd..117bd54 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -11,12 +11,6 @@ "unexpectedError": "Váratlan hiba", "ok": "Oké", "and": "és", - "startedBgUpdateTask": "Háttérfrissítés ellenőrzési feladat elindítva", - "bgUpdateIgnoreAfterIs": "Háttérfrissítés ignoreAfter a következő: {}", - "startedActualBGUpdateCheck": "Elkezdődött a tényleges háttérfrissítés ellenőrzése", - "bgUpdateTaskFinished": "A háttérfrissítés ellenőrzési feladat befejeződött", - "firstRun": "Ez az Obtainium első futása", - "settingUpdateCheckIntervalTo": "A frissítési intervallum beállítása erre: {}", "githubPATLabel": "GitHub Personal Access Token (megnöveli a díjkorlátot)", "githubPATHint": "A PAT-nak a következő formátumban kell lennie: felhasználónév:token", "githubPATFormat": "felhasználónév:token", @@ -248,7 +242,7 @@ "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" @@ -298,7 +292,7 @@ "other": "{} és {} további alkalmazás frissítve." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } } diff --git a/assets/translations/it.json b/assets/translations/it.json index ed43216..e3a5211 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -11,12 +11,6 @@ "unexpectedError": "Errore imprevisto", "ok": "Va bene", "and": "e", - "startedBgUpdateTask": "Avviata l'attività di controllo degli aggiornamenti in secondo piano", - "bgUpdateIgnoreAfterIs": "Il parametro di agg. in secondo piano 'ignoreAfter' è {}", - "startedActualBGUpdateCheck": "Avviato il controllo effettivo degli aggiornamenti in secondo piano", - "bgUpdateTaskFinished": "Terminata l'attività di controllo degli aggiornamenti in secondo piano", - "firstRun": "Questo è il primo avvio di sempre di Obtainium", - "settingUpdateCheckIntervalTo": "Fissato intervallo di aggiornamento a {}", "githubPATLabel": "GitHub Personal Access Token (diminuisce limite di traffico)", "githubPATHint": "PAT deve seguire questo formato: nomeutente:token", "githubPATFormat": "nomeutente:token", @@ -249,7 +243,7 @@ "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" @@ -299,7 +293,7 @@ "other": "{} e altre {} app sono state aggiornate." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } } diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 37edc58..f228582 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -11,12 +11,6 @@ "unexpectedError": "予期せぬエラーが発生しました", "ok": "OK", "and": "と", - "startedBgUpdateTask": "バックグラウンドのアップデート確認タスクを開始", - "bgUpdateIgnoreAfterIs": "Bg update ignoreAfter is {}", - "startedActualBGUpdateCheck": "実際のバックグラウンドのアップデート確認を開始", - "bgUpdateTaskFinished": "バックグラウンドのアップデート確認タスクを終了", - "firstRun": "これがObtainiumの最初の実行です", - "settingUpdateCheckIntervalTo": "確認間隔を{}に設定する", "githubPATLabel": "GitHub パーソナルアクセストークン (レート制限の引き上げ)", "githubPATHint": "PATは次の形式でなければなりません: ユーザー名:トークン", "githubPATFormat": "ユーザー名:トークン", @@ -249,7 +243,7 @@ "customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" @@ -299,7 +293,7 @@ "other": "{} とさらに {} 個のアプリがアップデートされました" }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } } diff --git a/assets/translations/pl.json b/assets/translations/pl.json index ea8be8a..1b5809c 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -19,12 +19,6 @@ "unexpectedError": "Nieoczekiwany błąd", "ok": "Okej", "and": "i", - "startedBgUpdateTask": "Rozpoczęto zadanie sprawdzania aktualizacji w tle", - "bgUpdateIgnoreAfterIs": "Parametr ignoreAfter aktualizacji w tle to {}", - "startedActualBGUpdateCheck": "Rozpoczęto sprawdzanie aktualizacji w tle", - "bgUpdateTaskFinished": "Zakończono zadanie sprawdzania aktualizacji w tle", - "firstRun": "Jest to pierwsze uruchomienie Obtainium", - "settingUpdateCheckIntervalTo": "Ustawianie interwału aktualizacji na {}", "githubPATLabel": "Osobisty token dostępu GitHub (zwiększa limit zapytań)", "githubPATHint": "Wymagany format: użytkownik:token", "githubPATFormat": "użytkownik:token", @@ -253,7 +247,7 @@ "customLinkFilterRegex": "Niestandardowy filtr linków wg. wyrażenia regularnego (domyślnie \".apk$\")", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" @@ -299,7 +293,7 @@ "other": "Zaktualizowano {} i {} aplik." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } } diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 609b5e3..798793a 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -11,12 +11,6 @@ "unexpectedError": "Неожиданная ошибка", "ok": "Окей", "and": "и", - "startedBgUpdateTask": "Запущена задача фоновой проверки обновлений", - "bgUpdateIgnoreAfterIs": "Параметр игнорирования фоновых обновлений: {}", - "startedActualBGUpdateCheck": "Запущена фактическая проверка фоновых обновлений", - "bgUpdateTaskFinished": "Завершена задача фоновой проверки обновлений", - "firstRun": "Это первый запуск Obtainium", - "settingUpdateCheckIntervalTo": "Установка интервала проверки обновлений: {}", "githubPATLabel": "Персональный токен доступа GitHub (увеличивает лимит запросов)", "githubPATHint": "Токен доступа должен быть в формате: имя_пользователя:токен", "githubPATFormat": "имя_пользователя:токен", @@ -249,7 +243,7 @@ "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" @@ -299,7 +293,7 @@ "other": "{} и еще {} приложений были обновлены." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } } diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 1aa36fc..05f3bc3 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -11,12 +11,6 @@ "unexpectedError": "意外错误", "ok": "好的", "and": "和", - "startedBgUpdateTask": "后台更新检查任务已启动", - "bgUpdateIgnoreAfterIs": "后台更新检查间隔为 {}", - "startedActualBGUpdateCheck": "开始后台更新检查", - "bgUpdateTaskFinished": "后台更新检查任务已完成", - "firstRun": "这是 Obtainium 首次启动", - "settingUpdateCheckIntervalTo": "更新检查间隔设置为 {}", "githubPATLabel": "GitHub 个人访问令牌(提升 API 请求限额)", "githubPATHint": "个人访问令牌必须为“username:token”的格式", "githubPATFormat": "username:token", @@ -249,7 +243,7 @@ "customLinkFilterRegex": "用正则表达式自定义链接筛选(默认 '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "An attempt was made to update {} to {}.", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" @@ -299,7 +293,7 @@ "other": "{} 和另外 {} 个应用已更新。" }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "Attempts were made to update {} and 1 more app.", - "other": "Attempts were made to update {} and {} more apps." + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." } } diff --git a/lib/main.dart b/lib/main.dart index 79bdfcb..4506787 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,4 @@ import 'dart:io'; -import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -73,80 +72,80 @@ Future loadTranslations() async { } @pragma('vm:entry-point') -Future bgUpdateCheck(int taskId, Map? params) async { +Future bgUpdateCheckApps(int taskId, Map? params) async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); - + await AndroidAlarmManager.initialize(); await loadTranslations(); LogsProvider logs = LogsProvider(); - logs.add(tr('startedBgUpdateTask')); - int? ignoreAfterMicroseconds = params?['ignoreAfterMicroseconds']; + AppsProvider appsProvider = AppsProvider(); + await appsProvider.loadApps(); + + logs.add('BG update master task started.'); + var appIds = appsProvider.getAppsSortedByUpdateCheckTime(); + for (var id in appIds) { + AndroidAlarmManager.oneShot( + const Duration(minutes: 0), id.hashCode, bgUpdateCheckApp, + params: {'appId': id}); + await Future.delayed(const Duration(seconds: 1)); + } + logs.add('BG update master task - all $appIds child tasks started.'); +} + +@pragma('vm:entry-point') +Future bgUpdateCheckApp(int taskId, Map? params) async { + WidgetsFlutterBinding.ensureInitialized(); + await EasyLocalization.ensureInitialized(); await AndroidAlarmManager.initialize(); - DateTime? ignoreAfter = ignoreAfterMicroseconds != null - ? DateTime.fromMicrosecondsSinceEpoch(ignoreAfterMicroseconds) - : null; - logs.add(tr('bgUpdateIgnoreAfterIs', args: [ignoreAfter.toString()])); - var notificationsProvider = NotificationsProvider(); + await loadTranslations(); + + LogsProvider logs = LogsProvider(); + NotificationsProvider notificationsProvider = NotificationsProvider(); + AppsProvider appsProvider = AppsProvider(); + + String appId = params!['appId']; try { - var appsProvider = AppsProvider(); - await appsProvider.loadApps(); - List existingUpdateIds = - appsProvider.findExistingUpdates(installedOnly: true); - DateTime nextIgnoreAfter = DateTime.now(); - String? err; - try { - logs.add(tr('startedActualBGUpdateCheck')); - await appsProvider.checkUpdates( - ignoreAppsCheckedAfter: ignoreAfter, - throwErrorsForRetry: true, - notificationsProvider: notificationsProvider); - } catch (e) { - if (e is RateLimitError || e is ClientException) { - var remainingMinutes = e is RateLimitError ? e.remainingMinutes : 15; - logs.add( - plural('bgUpdateGotErrorRetryInMinutes', remainingMinutes, args: [ - e is ClientException - ? '${(e).message}, ${e.uri?.path}' - : e.toString(), - remainingMinutes.toString() - ])); - AndroidAlarmManager.oneShot(Duration(minutes: remainingMinutes), - Random().nextInt(pow(2, 31) as int), bgUpdateCheck, params: { - 'ignoreAfterMicroseconds': nextIgnoreAfter.microsecondsSinceEpoch - }); - } else { - err = e.toString(); + await appsProvider.loadApps(singleId: appId); + AppInMemory app = appsProvider.apps[appId]!; + App? newApp; + if (app.app.installedVersion == app.app.latestVersion && + app.app.installedVersion != null) { + try { + notificationsProvider.notify(checkingUpdatesNotification, + cancelExisting: true); + newApp = await appsProvider.checkUpdate(appId); + } catch (e) { + logs.add('BG update check for $appId got error \'${e.toString()}\'.'); + if (e is RateLimitError || e is ClientException) { + var remainingMinutes = e is RateLimitError ? e.remainingMinutes : 15; + logs.add( + 'BG update check for $appId will be retried in $remainingMinutes minutes.'); + AndroidAlarmManager.oneShot( + Duration(minutes: remainingMinutes), taskId, bgUpdateCheckApp, + params: params); + } else { + rethrow; + } + } finally { + notificationsProvider.cancel(checkingUpdatesNotification.id); } } - List newUpdates = appsProvider - .findExistingUpdates(installedOnly: true) - .where((id) => !existingUpdateIds.contains(id)) - .map((e) => appsProvider.apps[e]!.app) - .toList(); - List nonSilentUpdates = []; - List silentUpdates = []; - for (var a in newUpdates) { - if (await appsProvider.canInstallSilently(a)) { - silentUpdates.add(a); + if (newApp != null) { + var canInstallSilently = await appsProvider.canInstallSilently(app.app); + if (!canInstallSilently) { + notificationsProvider + .notify(UpdateNotification([newApp], id: newApp.id.hashCode * 10)); } else { - nonSilentUpdates.add(a); + logs.add('Attempting to update $appId in the background.'); + await appsProvider.downloadAndInstallLatestApps([appId], null, + notificationsProvider: notificationsProvider); } } - if (silentUpdates.isNotEmpty) { - await appsProvider.downloadAndInstallLatestApps( - silentUpdates.map((e) => e.id).toList(), null, - notificationsProvider: notificationsProvider); - } - logs.add(plural( - 'bgCheckFoundUpdatesWillNotifyIfNeeded', nonSilentUpdates.length)); - if (err != null) { - throw err; - } } catch (e) { - logs.add('${tr('errorCheckingUpdates')}: ${e.toString()}'); - } finally { - logs.add(tr('bgUpdateTaskFinished')); + notificationsProvider.notify(ErrorCheckingUpdatesNotification( + '$appId: ${e.toString()}', + id: appId.hashCode * 20)); } } @@ -207,7 +206,7 @@ class _ObtainiumState extends State { } else { bool isFirstRun = settingsProvider.checkAndFlipFirstRun(); if (isFirstRun) { - logs.add(tr('firstRun')); + logs.add('This is the first ever run of Obtainium.'); // If this is the first run, ask for notification permissions and add Obtainium to the Apps list Permission.notification.request(); appsProvider.saveApps([ @@ -236,8 +235,8 @@ class _ObtainiumState extends State { // Register the background update task according to the user's setting if (existingUpdateInterval != settingsProvider.updateInterval) { if (existingUpdateInterval != -1) { - logs.add(tr('settingUpdateCheckIntervalTo', - args: [settingsProvider.updateInterval.toString()])); + logs.add( + 'Setting update interval to ${settingsProvider.updateInterval.toString()}'); } existingUpdateInterval = settingsProvider.updateInterval; if (existingUpdateInterval == 0) { @@ -246,7 +245,8 @@ class _ObtainiumState extends State { AndroidAlarmManager.periodic( Duration(minutes: existingUpdateInterval), bgUpdateCheckAlarmId, - bgUpdateCheck, + bgUpdateCheckApps, + allowWhileIdle: true, rescheduleOnReboot: true, wakeup: true); } diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 00a6bd0..be3af8b 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -765,7 +765,7 @@ class AppsProvider with ChangeNotifier { : false; } - Future loadApps() async { + Future loadApps({String? singleId}) async { while (loadingApps) { await Future.delayed(const Duration(microseconds: 1)); } @@ -776,6 +776,10 @@ class AppsProvider with ChangeNotifier { List newApps = (await getAppsDir()) // Parse Apps from JSON .listSync() .where((item) => item.path.toLowerCase().endsWith('.json')) + .where((item) => + singleId == null || + item.path.split('/').last.toLowerCase() == + '${singleId.toLowerCase()}.json') .map((e) { try { return App.fromJson(jsonDecode(File(e.path).readAsStringSync())); @@ -986,26 +990,32 @@ class AppsProvider with ChangeNotifier { return newApp.latestVersion != currentApp.latestVersion ? newApp : null; } + List getAppsSortedByUpdateCheckTime( + {DateTime? ignoreAppsCheckedAfter}) { + List appIds = apps.values + .where((app) => + app.app.lastUpdateCheck == null || + ignoreAppsCheckedAfter == null || + app.app.lastUpdateCheck!.isBefore(ignoreAppsCheckedAfter)) + .map((e) => e.app.id) + .toList(); + appIds.sort((a, b) => + (apps[a]!.app.lastUpdateCheck ?? DateTime.fromMicrosecondsSinceEpoch(0)) + .compareTo(apps[b]!.app.lastUpdateCheck ?? + DateTime.fromMicrosecondsSinceEpoch(0))); + return appIds; + } + Future> checkUpdates( {DateTime? ignoreAppsCheckedAfter, - bool throwErrorsForRetry = false, - NotificationsProvider? notificationsProvider}) async { + bool throwErrorsForRetry = false}) async { List updates = []; MultiAppMultiError errors = MultiAppMultiError(); if (!gettingUpdates) { gettingUpdates = true; try { - List appIds = apps.values - .where((app) => - app.app.lastUpdateCheck == null || - ignoreAppsCheckedAfter == null || - app.app.lastUpdateCheck!.isBefore(ignoreAppsCheckedAfter)) - .map((e) => e.app.id) - .toList(); - appIds.sort((a, b) => (apps[a]!.app.lastUpdateCheck ?? - DateTime.fromMicrosecondsSinceEpoch(0)) - .compareTo(apps[b]!.app.lastUpdateCheck ?? - DateTime.fromMicrosecondsSinceEpoch(0))); + List appIds = getAppsSortedByUpdateCheckTime( + ignoreAppsCheckedAfter: ignoreAppsCheckedAfter); for (int i = 0; i < appIds.length; i++) { App? newApp; try { @@ -1016,14 +1026,9 @@ class AppsProvider with ChangeNotifier { rethrow; } errors.add(appIds[i], e.toString()); - notificationsProvider?.notify(ErrorCheckingUpdatesNotification( - '${appIds[i]}: ${e.toString()}', - id: appIds[i].hashCode)); } if (newApp != null) { updates.add(newApp); - notificationsProvider - ?.notify(UpdateNotification([newApp], id: newApp.id.hashCode)); } } } finally { From f5479ec82f3497cd7d248a1231eb144f7c8ebe8a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 21 Aug 2023 20:15:57 -0400 Subject: [PATCH 342/600] Max 5 attempts for bg check fail due to rate/net --- lib/main.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 4506787..1b59a7f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -105,6 +105,12 @@ Future bgUpdateCheckApp(int taskId, Map? params) async { AppsProvider appsProvider = AppsProvider(); String appId = params!['appId']; + params['attemptCount'] = (params['attemptCount'] ?? 0) + 1; + int maxAttempts = 5; + if (params['attemptCount'] > 1) { + logs.add( + 'BG update check for $appId: Note this is attempt #${params['attemptCount']} of $maxAttempts'); + } try { await appsProvider.loadApps(singleId: appId); AppInMemory app = appsProvider.apps[appId]!; @@ -117,7 +123,8 @@ Future bgUpdateCheckApp(int taskId, Map? params) async { newApp = await appsProvider.checkUpdate(appId); } catch (e) { logs.add('BG update check for $appId got error \'${e.toString()}\'.'); - if (e is RateLimitError || e is ClientException) { + if (e is RateLimitError || + e is ClientException && params['attemptCount'] < maxAttempts) { var remainingMinutes = e is RateLimitError ? e.remainingMinutes : 15; logs.add( 'BG update check for $appId will be retried in $remainingMinutes minutes.'); From d08ff3fbae774d5c30b8c3862bc908064252cbd0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 21 Aug 2023 20:32:41 -0400 Subject: [PATCH 343/600] Add BG update toggle --- assets/translations/bs.json | 2 ++ assets/translations/de.json | 2 ++ assets/translations/en.json | 3 ++ assets/translations/es.json | 2 ++ assets/translations/fa.json | 2 ++ assets/translations/fr.json | 2 ++ assets/translations/hu.json | 2 ++ assets/translations/it.json | 2 ++ assets/translations/ja.json | 2 ++ assets/translations/pl.json | 2 ++ assets/translations/ru.json | 2 ++ assets/translations/zh.json | 2 ++ lib/pages/settings.dart | 46 ++++++++++++++++++++++++++++ lib/providers/settings_provider.dart | 9 ++++++ 14 files changed, 80 insertions(+) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 7c86b74..cd14a19 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -244,6 +244,8 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 973c229..9227e9f 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -244,6 +244,8 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 7a76230..165b4ff 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -244,6 +244,9 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "enableBackgroundUpdates": "Enable background updates", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 63f9dc1..bbed509 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -244,6 +244,8 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 4342244..93caa25 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -244,6 +244,8 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 1bc1a6e..bfbbfcc 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -244,6 +244,8 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 117bd54..5c5fd49 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -243,6 +243,8 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "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 e3a5211..14586d4 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -244,6 +244,8 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index f228582..386a512 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -244,6 +244,8 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 1b5809c..327e720 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -248,6 +248,8 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 798793a..e8a2507 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -244,6 +244,8 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 05f3bc3..eac5e3e 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -244,6 +244,8 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 2ea391e..f98d8a0 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -1,3 +1,4 @@ +import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:obtainium/components/custom_app_bar.dart'; @@ -184,6 +185,10 @@ class _SettingsPageState extends State { } }); + const height8 = SizedBox( + height: 8, + ); + const height16 = SizedBox( height: 16, ); @@ -211,6 +216,47 @@ class _SettingsPageState extends State { color: Theme.of(context).colorScheme.primary), ), intervalDropdown, + FutureBuilder( + builder: (ctx, val) { + return (val.data?.version.sdkInt ?? 0) >= 30 + ? Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + height16, + Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Flexible( + child: Text(tr( + 'enableBackgroundUpdates'))), + Switch( + value: settingsProvider + .enableBackgroundUpdates, + onChanged: (value) { + settingsProvider + .enableBackgroundUpdates = + value; + }) + ], + ), + height8, + Text(tr('backgroundUpdateReqsExplanation'), + style: Theme.of(context) + .textTheme + .labelSmall), + Text(tr('backgroundUpdateLimitsExplanation'), + style: Theme.of(context) + .textTheme + .labelSmall), + height8 + ], + ) + : const SizedBox.shrink(); + }, + future: DeviceInfoPlugin().androidInfo), height16, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index ea79e38..f5aba32 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -309,4 +309,13 @@ class SettingsProvider with ChangeNotifier { prefs?.setBool('reversePageTransitions', show); notifyListeners(); } + + bool get enableBackgroundUpdates { + return prefs?.getBool('enableBackgroundUpdates') ?? true; + } + + set enableBackgroundUpdates(bool val) { + prefs?.setBool('enableBackgroundUpdates', val); + notifyListeners(); + } } From bb4f34317b6a8a6d08c7dc0a5b550321ca0c3f24 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 21 Aug 2023 23:55:54 -0400 Subject: [PATCH 344/600] Bugfix + version increment + update packages --- lib/main.dart | 17 +++++++++-------- pubspec.lock | 34 +++++++++++++++++++++------------- pubspec.yaml | 2 +- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 1b59a7f..a6130f0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -21,7 +21,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.26'; +const String currentVersion = '0.13.27'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES @@ -82,7 +82,7 @@ Future bgUpdateCheckApps(int taskId, Map? params) async { AppsProvider appsProvider = AppsProvider(); await appsProvider.loadApps(); - logs.add('BG update master task started.'); + logs.add('BG update parent task started.'); var appIds = appsProvider.getAppsSortedByUpdateCheckTime(); for (var id in appIds) { AndroidAlarmManager.oneShot( @@ -90,7 +90,8 @@ Future bgUpdateCheckApps(int taskId, Map? params) async { params: {'appId': id}); await Future.delayed(const Duration(seconds: 1)); } - logs.add('BG update master task - all $appIds child tasks started.'); + logs.add( + 'BG update parent task ended (${appIds.length} child task(s) started).'); } @pragma('vm:entry-point') @@ -107,10 +108,8 @@ Future bgUpdateCheckApp(int taskId, Map? params) async { String appId = params!['appId']; params['attemptCount'] = (params['attemptCount'] ?? 0) + 1; int maxAttempts = 5; - if (params['attemptCount'] > 1) { - logs.add( - 'BG update check for $appId: Note this is attempt #${params['attemptCount']} of $maxAttempts'); - } + logs.add( + 'BG update task for $appId started (attempt #${params['attemptCount']}).'); try { await appsProvider.loadApps(singleId: appId); AppInMemory app = appsProvider.apps[appId]!; @@ -153,6 +152,9 @@ Future bgUpdateCheckApp(int taskId, Map? params) async { notificationsProvider.notify(ErrorCheckingUpdatesNotification( '$appId: ${e.toString()}', id: appId.hashCode * 20)); + } finally { + logs.add( + 'BG update task for $appId ended (attempt #${params['attemptCount']}).'); } } @@ -253,7 +255,6 @@ class _ObtainiumState extends State { Duration(minutes: existingUpdateInterval), bgUpdateCheckAlarmId, bgUpdateCheckApps, - allowWhileIdle: true, rescheduleOnReboot: true, wakeup: true); } diff --git a/pubspec.lock b/pubspec.lock index ffb90fa..fd01871 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -111,10 +111,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" convert: dependency: transitive description: @@ -379,10 +379,10 @@ packages: dependency: transitive description: name: intl - sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.18.0" + version: "0.18.1" js: dependency: transitive description: @@ -419,18 +419,18 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: @@ -672,10 +672,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" sqflite: dependency: "direct main" description: @@ -736,10 +736,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" timezone: dependency: transitive description: @@ -836,6 +836,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" webview_flutter: dependency: "direct main" description: @@ -909,5 +917,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index 551bf12..f107cb0 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.13.26+190 # When changing this, update the tag in main() accordingly +version: 0.13.27+191 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From e956ee92544fb4150502ada174afa0f43dbd40ee Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 22 Aug 2023 12:51:55 -0400 Subject: [PATCH 345/600] Trying a new recursive BG update task due2 mem limits --- lib/main.dart | 113 ++++++++++++++++--------------- lib/providers/apps_provider.dart | 14 +--- 2 files changed, 63 insertions(+), 64 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a6130f0..1a98726 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -71,31 +71,23 @@ Future loadTranslations() async { fallbackTranslations: controller.fallbackTranslations); } -@pragma('vm:entry-point') -Future bgUpdateCheckApps(int taskId, Map? params) async { - WidgetsFlutterBinding.ensureInitialized(); - await EasyLocalization.ensureInitialized(); - await AndroidAlarmManager.initialize(); - await loadTranslations(); - - LogsProvider logs = LogsProvider(); - AppsProvider appsProvider = AppsProvider(); - await appsProvider.loadApps(); - - logs.add('BG update parent task started.'); - var appIds = appsProvider.getAppsSortedByUpdateCheckTime(); - for (var id in appIds) { - AndroidAlarmManager.oneShot( - const Duration(minutes: 0), id.hashCode, bgUpdateCheckApp, - params: {'appId': id}); - await Future.delayed(const Duration(seconds: 1)); +moveStrToEnd(List arr, String str, {String? strB}) { + String? temp; + arr.removeWhere((element) { + bool res = element == str || element == strB; + if (res) { + temp = element; + } + return res; + }); + if (temp != null) { + arr = [...arr, temp!]; } - logs.add( - 'BG update parent task ended (${appIds.length} child task(s) started).'); + return arr; } @pragma('vm:entry-point') -Future bgUpdateCheckApp(int taskId, Map? params) async { +Future bgUpdateCheck(int taskId, Map? params) async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); await AndroidAlarmManager.initialize(); @@ -104,31 +96,50 @@ Future bgUpdateCheckApp(int taskId, Map? params) async { LogsProvider logs = LogsProvider(); NotificationsProvider notificationsProvider = NotificationsProvider(); AppsProvider appsProvider = AppsProvider(); + await appsProvider.loadApps(); - String appId = params!['appId']; - params['attemptCount'] = (params['attemptCount'] ?? 0) + 1; int maxAttempts = 5; + + params ??= {}; + params['attemptCount'] = (params['attemptCount'] ?? 0) + 1; + params['toCheck'] = + params['toCheck'] ?? appsProvider.getAppsSortedByUpdateCheckTime(); + params['toInstall'] = params['toInstall'] ?? []; + + List toCheck = params['toCheck']; + List toInstall = params['toCheck']; + logs.add( - 'BG update task for $appId started (attempt #${params['attemptCount']}).'); - try { - await appsProvider.loadApps(singleId: appId); - AppInMemory app = appsProvider.apps[appId]!; - App? newApp; - if (app.app.installedVersion == app.app.latestVersion && - app.app.installedVersion != null) { + 'BG update task $taskId started - ${toCheck.length} to check and ${toInstall.length} to install${params['attemptCount'] > 1 ? ' (attempt #${params['attemptCount']})' : ''}.'); + + if (toCheck.isNotEmpty) { + String appId = toCheck.removeAt(0); + AppInMemory? app = appsProvider.apps[appId]; + if (app?.app.installedVersion != null) { try { notificationsProvider.notify(checkingUpdatesNotification, cancelExisting: true); - newApp = await appsProvider.checkUpdate(appId); + App? newApp = await appsProvider.checkUpdate(appId); + if (newApp != null) { + if (!(await appsProvider.canInstallSilently(app!.app))) { + notificationsProvider.notify( + UpdateNotification([newApp], id: newApp.id.hashCode * 10)); + } else { + toInstall.add(appId); + } + } } catch (e) { - logs.add('BG update check for $appId got error \'${e.toString()}\'.'); + logs.add( + 'BG update check got error on checking for $appId \'${e.toString()}\'.'); if (e is RateLimitError || e is ClientException && params['attemptCount'] < maxAttempts) { var remainingMinutes = e is RateLimitError ? e.remainingMinutes : 15; logs.add( - 'BG update check for $appId will be retried in $remainingMinutes minutes.'); + 'BG update task $taskId will be retried in $remainingMinutes minutes (with $appId moved to the end of the line).'); + toCheck = toInstall = []; // So the next task will not start + params['toCheck'] = moveStrToEnd(params['toCheck'], appId); AndroidAlarmManager.oneShot( - Duration(minutes: remainingMinutes), taskId, bgUpdateCheckApp, + Duration(minutes: remainingMinutes), taskId + 1, bgUpdateCheck, params: params); } else { rethrow; @@ -137,24 +148,20 @@ Future bgUpdateCheckApp(int taskId, Map? params) async { notificationsProvider.cancel(checkingUpdatesNotification.id); } } - if (newApp != null) { - var canInstallSilently = await appsProvider.canInstallSilently(app.app); - if (!canInstallSilently) { - notificationsProvider - .notify(UpdateNotification([newApp], id: newApp.id.hashCode * 10)); - } else { - logs.add('Attempting to update $appId in the background.'); - await appsProvider.downloadAndInstallLatestApps([appId], null, - notificationsProvider: notificationsProvider); - } - } - } catch (e) { - notificationsProvider.notify(ErrorCheckingUpdatesNotification( - '$appId: ${e.toString()}', - id: appId.hashCode * 20)); - } finally { - logs.add( - 'BG update task for $appId ended (attempt #${params['attemptCount']}).'); + } else if (toInstall.isNotEmpty) { + toInstall = moveStrToEnd(toInstall, obtainiumId); + String appId = toInstall.removeAt(0); + logs.add('Attempting to update $appId in the background.'); + await appsProvider.downloadAndInstallLatestApps([appId], null, + notificationsProvider: notificationsProvider); + } + + logs.add('BG update task $taskId ended.'); + + if (toCheck.isNotEmpty || toInstall.isNotEmpty) { + AndroidAlarmManager.oneShot(Duration(seconds: toCheck.isNotEmpty ? 1 : 5), + taskId + 1, bgUpdateCheck, + params: {'toCheck': toCheck, 'toInstall': toInstall}); } } @@ -254,7 +261,7 @@ class _ObtainiumState extends State { AndroidAlarmManager.periodic( Duration(minutes: existingUpdateInterval), bgUpdateCheckAlarmId, - bgUpdateCheckApps, + bgUpdateCheck, rescheduleOnReboot: true, wakeup: true); } diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index be3af8b..b9f29a7 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -15,6 +15,7 @@ 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'; import 'package:obtainium/providers/logs_provider.dart'; import 'package:obtainium/providers/notifications_provider.dart'; import 'package:obtainium/providers/settings_provider.dart'; @@ -555,17 +556,8 @@ class AppsProvider with ChangeNotifier { List installedIds = []; // Move Obtainium to the end of the line (let all other apps update first) - String? temp; - appsToInstall.removeWhere((element) { - bool res = element == obtainiumId || element == obtainiumTempId; - if (res) { - temp = element; - } - return res; - }); - if (temp != null) { - appsToInstall = [...appsToInstall, temp!]; - } + appsToInstall = + moveStrToEnd(appsToInstall, obtainiumId, strB: obtainiumTempId); for (var id in appsToInstall) { try { From 82e08150ab312d92c90f35cfb772ee0dee8a5aab Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 22 Aug 2023 16:28:22 -0400 Subject: [PATCH 346/600] bugs --- lib/main.dart | 26 ++++++++++++++------------ lib/providers/apps_provider.dart | 11 ----------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 1a98726..25ad603 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -104,13 +104,13 @@ Future bgUpdateCheck(int taskId, Map? params) async { params['attemptCount'] = (params['attemptCount'] ?? 0) + 1; params['toCheck'] = params['toCheck'] ?? appsProvider.getAppsSortedByUpdateCheckTime(); - params['toInstall'] = params['toInstall'] ?? []; + params['toInstall'] = params['toInstall'] ?? ([]); - List toCheck = params['toCheck']; - List toInstall = params['toCheck']; + List toCheck = [...params['toCheck']]; + List toInstall = [...params['toInstall']]; logs.add( - 'BG update task $taskId started - ${toCheck.length} to check and ${toInstall.length} to install${params['attemptCount'] > 1 ? ' (attempt #${params['attemptCount']})' : ''}.'); + 'BG update task $taskId: Started [${toCheck.length},${toInstall.length}]${params['attemptCount'] > 1 ? '. ${params['attemptCount'] - 1} consecutive fail(s)' : ''}.'); if (toCheck.isNotEmpty) { String appId = toCheck.removeAt(0); @@ -123,19 +123,19 @@ Future bgUpdateCheck(int taskId, Map? params) async { if (newApp != null) { if (!(await appsProvider.canInstallSilently(app!.app))) { notificationsProvider.notify( - UpdateNotification([newApp], id: newApp.id.hashCode * 10)); + UpdateNotification([newApp], id: newApp.id.hashCode - 1)); } else { toInstall.add(appId); } } } catch (e) { logs.add( - 'BG update check got error on checking for $appId \'${e.toString()}\'.'); + 'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.'); if (e is RateLimitError || e is ClientException && params['attemptCount'] < maxAttempts) { var remainingMinutes = e is RateLimitError ? e.remainingMinutes : 15; logs.add( - 'BG update task $taskId will be retried in $remainingMinutes minutes (with $appId moved to the end of the line).'); + 'BG update task $taskId: Next task will start in $remainingMinutes minutes (with $appId moved to the end of the line).'); toCheck = toInstall = []; // So the next task will not start params['toCheck'] = moveStrToEnd(params['toCheck'], appId); AndroidAlarmManager.oneShot( @@ -151,17 +151,19 @@ Future bgUpdateCheck(int taskId, Map? params) async { } else if (toInstall.isNotEmpty) { toInstall = moveStrToEnd(toInstall, obtainiumId); String appId = toInstall.removeAt(0); - logs.add('Attempting to update $appId in the background.'); + logs.add( + 'BG update task $taskId: Attempting to update $appId in the background.'); await appsProvider.downloadAndInstallLatestApps([appId], null, notificationsProvider: notificationsProvider); } - logs.add('BG update task $taskId ended.'); - if (toCheck.isNotEmpty || toInstall.isNotEmpty) { - AndroidAlarmManager.oneShot(Duration(seconds: toCheck.isNotEmpty ? 1 : 5), - taskId + 1, bgUpdateCheck, + logs.add('BG update task $taskId: Ended. Next task will start soon.'); + AndroidAlarmManager.oneShot( + const Duration(seconds: 0), taskId + 1, bgUpdateCheck, params: {'toCheck': toCheck, 'toInstall': toInstall}); + } else { + logs.add('BG update task $taskId: Ended.'); } } diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index b9f29a7..20cbbe9 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -708,17 +708,6 @@ class AppsProvider with ChangeNotifier { logs.add('Could not reconcile version formats for: ${app.id}'); modded = true; } - // if (app.installedVersion != null && - // app.additionalSettings['versionDetection'] == - // 'standardVersionDetection') { - // var correctedInstalledVersion = - // reconcileVersionDifferences(app.installedVersion!, app.latestVersion); - // if (correctedInstalledVersion == null) { - // app.additionalSettings['versionDetection'] = 'noVersionDetection'; - // logs.add('Could not reconcile version formats for: ${app.id}'); - // modded = true; - // } - // } return modded ? app : null; } From 9eb32ae55a287405d24f15545127a1f852346d37 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 22 Aug 2023 17:13:15 -0400 Subject: [PATCH 347/600] Don't reschedule bg checks if app is restarted --- lib/main.dart | 37 ++++++++++++++++++---------- lib/providers/settings_provider.dart | 12 +++++++++ 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 25ad603..165d6b1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -97,10 +97,15 @@ Future bgUpdateCheck(int taskId, Map? params) async { NotificationsProvider notificationsProvider = NotificationsProvider(); AppsProvider appsProvider = AppsProvider(); await appsProvider.loadApps(); + var settingsProvider = SettingsProvider(); + await settingsProvider.initializeSettings(); int maxAttempts = 5; params ??= {}; + if (params['toCheck'] == null) { + settingsProvider.lastBGCheckTime = DateTime.now(); + } params['attemptCount'] = (params['attemptCount'] ?? 0) + 1; params['toCheck'] = params['toCheck'] ?? appsProvider.getAppsSortedByUpdateCheckTime(); @@ -251,22 +256,28 @@ class _ObtainiumState extends State { settingsProvider.resetLocaleSafe(context); } // Register the background update task according to the user's setting - if (existingUpdateInterval != settingsProvider.updateInterval) { - if (existingUpdateInterval != -1) { - logs.add( - 'Setting update interval to ${settingsProvider.updateInterval.toString()}'); - } - existingUpdateInterval = settingsProvider.updateInterval; - if (existingUpdateInterval == 0) { + var actualUpdateInterval = settingsProvider.updateInterval; + if (existingUpdateInterval != actualUpdateInterval) { + if (actualUpdateInterval == 0) { AndroidAlarmManager.cancel(bgUpdateCheckAlarmId); } else { - AndroidAlarmManager.periodic( - Duration(minutes: existingUpdateInterval), - bgUpdateCheckAlarmId, - bgUpdateCheck, - rescheduleOnReboot: true, - wakeup: true); + var settingChanged = existingUpdateInterval != -1; + var lastCheckWasTooLongAgo = actualUpdateInterval != 0 && + settingsProvider.lastBGCheckTime + .add(Duration(seconds: actualUpdateInterval + 60)) + .isBefore(DateTime.now()); + if (settingChanged || lastCheckWasTooLongAgo) { + logs.add( + 'Update interval was set to ${actualUpdateInterval.toString()} (reason: ${settingChanged ? 'setting changed' : 'last check was too long ago or never'}).'); + AndroidAlarmManager.periodic( + Duration(minutes: actualUpdateInterval), + bgUpdateCheckAlarmId, + bgUpdateCheck, + rescheduleOnReboot: true, + wakeup: true); + } } + existingUpdateInterval = actualUpdateInterval; } } diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index f5aba32..386b267 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -318,4 +318,16 @@ class SettingsProvider with ChangeNotifier { prefs?.setBool('enableBackgroundUpdates', val); notifyListeners(); } + + DateTime get lastBGCheckTime { + int? temp = prefs?.getInt('lastBGCheckTime'); + return temp != null + ? DateTime.fromMillisecondsSinceEpoch(temp) + : DateTime.fromMillisecondsSinceEpoch(0); + } + + set lastBGCheckTime(DateTime val) { + prefs?.setInt('lastBGCheckTime', val.millisecondsSinceEpoch); + notifyListeners(); + } } From 5cfd80e510cf8691fe49518720c4f6f84627ac6a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 22 Aug 2023 17:36:13 -0400 Subject: [PATCH 348/600] Added debug menu with on-demand bg task --- lib/pages/settings.dart | 40 +++++++++++++++++++++++++++- lib/providers/settings_provider.dart | 9 +++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index f98d8a0..cd5ce5a 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -1,3 +1,4 @@ +import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -508,7 +509,44 @@ class _SettingsPageState extends State { label: Text(tr('appLogs'))), ], ), - height16, + const Divider( + height: 32, + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), + child: Column(children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Flexible(child: Text('Debug Menu')), + Switch( + value: settingsProvider.showDebugOpts, + onChanged: (value) { + settingsProvider.showDebugOpts = value; + }) + ], + ), + if (settingsProvider.showDebugOpts) + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + height16, + TextButton( + onPressed: () { + AndroidAlarmManager.oneShot( + const Duration(seconds: 0), + bgUpdateCheckAlarmId + 200, + bgUpdateCheck); + showError( + 'Background task started - check logs.', + context); + }, + child: + const Text('Run Background Update Check Now')) + ], + ), + ]), + ), ], ), ) diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 386b267..7495c9b 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -330,4 +330,13 @@ class SettingsProvider with ChangeNotifier { prefs?.setInt('lastBGCheckTime', val.millisecondsSinceEpoch); notifyListeners(); } + + bool get showDebugOpts { + return prefs?.getBool('showDebugOpts') ?? false; + } + + set showDebugOpts(bool val) { + prefs?.setBool('showDebugOpts', val); + notifyListeners(); + } } From 3f6d96289d8b30d34e2a0bf515e60dd839cb60f3 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 22 Aug 2023 18:13:28 -0400 Subject: [PATCH 349/600] Bugfix, logging --- lib/main.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 165d6b1..a670d8f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -157,9 +157,11 @@ Future bgUpdateCheck(int taskId, Map? params) async { toInstall = moveStrToEnd(toInstall, obtainiumId); String appId = toInstall.removeAt(0); logs.add( - 'BG update task $taskId: Attempting to update $appId in the background.'); + 'BG update task $taskId: Attempting to download $appId in the background.'); await appsProvider.downloadAndInstallLatestApps([appId], null, notificationsProvider: notificationsProvider); + logs.add( + 'BG update task $taskId: Attempting to update $appId in the background.'); } if (toCheck.isNotEmpty || toInstall.isNotEmpty) { @@ -264,11 +266,11 @@ class _ObtainiumState extends State { var settingChanged = existingUpdateInterval != -1; var lastCheckWasTooLongAgo = actualUpdateInterval != 0 && settingsProvider.lastBGCheckTime - .add(Duration(seconds: actualUpdateInterval + 60)) + .add(Duration(minutes: actualUpdateInterval + 60)) .isBefore(DateTime.now()); if (settingChanged || lastCheckWasTooLongAgo) { logs.add( - 'Update interval was set to ${actualUpdateInterval.toString()} (reason: ${settingChanged ? 'setting changed' : 'last check was too long ago or never'}).'); + 'Update interval was set to ${actualUpdateInterval.toString()} (reason: ${settingChanged ? 'setting changed' : 'last check was ${settingsProvider.lastBGCheckTime.toLocal().toString()}'}).'); AndroidAlarmManager.periodic( Duration(minutes: actualUpdateInterval), bgUpdateCheckAlarmId, From 788c4c79175e321857afb5560aa11e9594f8681b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 22 Aug 2023 19:14:56 -0400 Subject: [PATCH 350/600] Try less messy bg update method --- lib/main.dart | 161 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 106 insertions(+), 55 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a670d8f..ce8b3bf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -86,6 +86,24 @@ moveStrToEnd(List arr, String str, {String? strB}) { return arr; } +/// Background updater function +/// +/// @param List? toCheck: The appIds to check for updates (default to all apps sorted by last update check time) +/// +/// @param List? toInstall: The appIds to attempt to update (defaults to an empty array) +/// +/// @param int? attemptCount: The number of times the function has failed up to this point (defaults to 0) +/// +/// When toCheck is empty, the function is in "install mode" (else it is in "update mode"). +/// In update mode, all apps in toCheck are checked for updates. +/// If an update is available, the appId is either added to toInstall (if a background update is possible) or the user is notified. +/// If there is an error, the function tries to continue after a few minutes (duration depends on the error), up to a maximum of 5 tries. +/// +/// Once all update checks are complete, the function is called again in install mode. +/// In this mode, all apps in toInstall are downloaded and installed in the background (install result is unknown). +/// If there is an error, the function tries to continue after a few minutes (duration depends on the error), up to a maximum of 5 tries. +/// +/// In either mode, if the function fails after the maximum number of tries, the user is notified. @pragma('vm:entry-point') Future bgUpdateCheck(int taskId, Map? params) async { WidgetsFlutterBinding.ensureInitialized(); @@ -106,71 +124,104 @@ Future bgUpdateCheck(int taskId, Map? params) async { if (params['toCheck'] == null) { settingsProvider.lastBGCheckTime = DateTime.now(); } - params['attemptCount'] = (params['attemptCount'] ?? 0) + 1; - params['toCheck'] = - params['toCheck'] ?? appsProvider.getAppsSortedByUpdateCheckTime(); - params['toInstall'] = params['toInstall'] ?? ([]); + int attemptCount = (params['attemptCount'] ?? 0) + 1; + List toCheck = [ + ...(params['toCheck'] ?? appsProvider.getAppsSortedByUpdateCheckTime()) + ]; + List toInstall = [...(params['toInstall'] ?? ([]))]; - List toCheck = [...params['toCheck']]; - List toInstall = [...params['toInstall']]; + bool installMode = toCheck.isEmpty && toInstall.isNotEmpty; logs.add( - 'BG update task $taskId: Started [${toCheck.length},${toInstall.length}]${params['attemptCount'] > 1 ? '. ${params['attemptCount'] - 1} consecutive fail(s)' : ''}.'); + 'BG update task $taskId: Started in ${installMode ? 'install' : 'update'} mode${attemptCount > 1 ? '. ${attemptCount - 1} consecutive fail(s)' : ''}.'); - if (toCheck.isNotEmpty) { - String appId = toCheck.removeAt(0); - AppInMemory? app = appsProvider.apps[appId]; - if (app?.app.installedVersion != null) { - try { - notificationsProvider.notify(checkingUpdatesNotification, - cancelExisting: true); - App? newApp = await appsProvider.checkUpdate(appId); - if (newApp != null) { - if (!(await appsProvider.canInstallSilently(app!.app))) { - notificationsProvider.notify( - UpdateNotification([newApp], id: newApp.id.hashCode - 1)); - } else { - toInstall.add(appId); + if (!installMode) { + var didCompleteChecking = false; + for (int i = 0; i < toCheck.length; i++) { + var appId = toCheck[i]; + AppInMemory? app = appsProvider.apps[appId]; + if (app?.app.installedVersion != null) { + try { + logs.add('BG update task $taskId: Checking for updates for $appId.'); + notificationsProvider.notify(checkingUpdatesNotification, + cancelExisting: true); + App? newApp = await appsProvider.checkUpdate(appId); + if (newApp != null) { + if (!(await appsProvider.canInstallSilently(app!.app))) { + notificationsProvider.notify( + UpdateNotification([newApp], id: newApp.id.hashCode - 1)); + } else { + toInstall.add(appId); + } } - } - } catch (e) { - logs.add( - 'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.'); - if (e is RateLimitError || - e is ClientException && params['attemptCount'] < maxAttempts) { - var remainingMinutes = e is RateLimitError ? e.remainingMinutes : 15; + if (i == (toCheck.length - 1)) { + didCompleteChecking = true; + } + } catch (e) { logs.add( - 'BG update task $taskId: Next task will start in $remainingMinutes minutes (with $appId moved to the end of the line).'); - toCheck = toInstall = []; // So the next task will not start - params['toCheck'] = moveStrToEnd(params['toCheck'], appId); - AndroidAlarmManager.oneShot( - Duration(minutes: remainingMinutes), taskId + 1, bgUpdateCheck, - params: params); - } else { - rethrow; + 'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.'); + if (attemptCount < maxAttempts) { + var remainingSeconds = e is RateLimitError + ? (e.remainingMinutes * 60) + : e is ClientException + ? (15 * 60) + : 1; + logs.add( + 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); + var remainingToCheck = moveStrToEnd(toCheck.sublist(i), appId); + AndroidAlarmManager.oneShot( + Duration(seconds: remainingSeconds), taskId, bgUpdateCheck, + params: { + 'toCheck': remainingToCheck, + 'toInstall': toInstall, + 'attemptCount': attemptCount + }); + break; + } else { + notificationsProvider + .notify(ErrorCheckingUpdatesNotification(e.toString())); + } + } finally { + notificationsProvider.cancel(checkingUpdatesNotification.id); } - } finally { - notificationsProvider.cancel(checkingUpdatesNotification.id); } } - } else if (toInstall.isNotEmpty) { - toInstall = moveStrToEnd(toInstall, obtainiumId); - String appId = toInstall.removeAt(0); - logs.add( - 'BG update task $taskId: Attempting to download $appId in the background.'); - await appsProvider.downloadAndInstallLatestApps([appId], null, - notificationsProvider: notificationsProvider); - logs.add( - 'BG update task $taskId: Attempting to update $appId in the background.'); - } - - if (toCheck.isNotEmpty || toInstall.isNotEmpty) { - logs.add('BG update task $taskId: Ended. Next task will start soon.'); - AndroidAlarmManager.oneShot( - const Duration(seconds: 0), taskId + 1, bgUpdateCheck, - params: {'toCheck': toCheck, 'toInstall': toInstall}); + if (didCompleteChecking && toInstall.isNotEmpty) { + AndroidAlarmManager.oneShot( + const Duration(minutes: 0), taskId + 1, bgUpdateCheck, + params: {'toCheck': [], 'toInstall': toInstall}); + } } else { - logs.add('BG update task $taskId: Ended.'); + toInstall = moveStrToEnd(toInstall, obtainiumId); + for (var i = 0; i < toInstall.length; i++) { + String appId = toInstall[i]; + try { + logs.add( + 'BG update task $taskId: Attempting to update $appId in the background.'); + await appsProvider.downloadAndInstallLatestApps([appId], null, + notificationsProvider: notificationsProvider); + } catch (e) { + logs.add( + 'BG update task $taskId: Got error on updating $appId \'${e.toString()}\'.'); + if (attemptCount < maxAttempts) { + var remainingSeconds = 1; + logs.add( + 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); + var remainingToInstall = moveStrToEnd(toInstall.sublist(i), appId); + AndroidAlarmManager.oneShot( + Duration(seconds: remainingSeconds), taskId, bgUpdateCheck, + params: { + 'toCheck': toCheck, + 'toInstall': remainingToInstall, + 'attemptCount': attemptCount + }); + break; + } else { + notificationsProvider + .notify(ErrorCheckingUpdatesNotification(e.toString())); + } + } + } } } From 5307fd0901ca493bacf882e053e807d734832ce8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 22 Aug 2023 19:43:23 -0400 Subject: [PATCH 351/600] bug --- lib/main.dart | 2 +- lib/providers/apps_provider.dart | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index ce8b3bf..a138880 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -113,7 +113,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { LogsProvider logs = LogsProvider(); NotificationsProvider notificationsProvider = NotificationsProvider(); - AppsProvider appsProvider = AppsProvider(); + AppsProvider appsProvider = AppsProvider(isBg: true); await appsProvider.loadApps(); var settingsProvider = SettingsProvider(); await settingsProvider.initializeSettings(); diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 20cbbe9..1da2213 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -114,7 +114,7 @@ class AppsProvider with ChangeNotifier { Iterable getAppValues() => apps.values.map((a) => a.deepCopy()); - AppsProvider() { + AppsProvider({isBg = false}) { // Subscribe to changes in the app foreground status foregroundStream = FGBGEvents.stream.asBroadcastStream(); foregroundSubscription = foregroundStream?.listen((event) async { @@ -132,17 +132,21 @@ class AppsProvider with ChangeNotifier { APKDir.createSync(); } } - // Load Apps into memory (in background, this is done later instead of in the constructor) - await loadApps(); - // Delete any partial APKs - var cutoff = DateTime.now().subtract(const Duration(days: 7)); - APKDir.listSync() - .where((element) => - element.path.endsWith('.part') || - element.statSync().modified.isBefore(cutoff)) - .forEach((partialApk) { - partialApk.delete(recursive: true); - }); + if (!isBg) { + // Load Apps into memory (in background processes, this is done later instead of in the constructor) + await loadApps(); + // Delete any partial APKs (if safe to do so) + var cutoff = DateTime.now().subtract(const Duration(days: 7)); + APKDir.listSync() + .where((element) => + element.path.endsWith('.part') || + element.statSync().modified.isBefore(cutoff)) + .forEach((partialApk) { + if (!areDownloadsRunning()) { + partialApk.delete(recursive: true); + } + }); + } }(); } From 6785708661173dd72e799b448acbbb72a2644991 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 22 Aug 2023 19:57:42 -0400 Subject: [PATCH 352/600] BG update toggle has an effect --- lib/main.dart | 6 ++++-- lib/pages/app.dart | 3 ++- lib/pages/apps.dart | 8 ++++---- lib/providers/apps_provider.dart | 22 +++++++++++++--------- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a138880..1cd8d55 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -147,7 +147,8 @@ Future bgUpdateCheck(int taskId, Map? params) async { cancelExisting: true); App? newApp = await appsProvider.checkUpdate(appId); if (newApp != null) { - if (!(await appsProvider.canInstallSilently(app!.app))) { + if (!(await appsProvider.canInstallSilently( + app!.app, settingsProvider))) { notificationsProvider.notify( UpdateNotification([newApp], id: newApp.id.hashCode - 1)); } else { @@ -198,7 +199,8 @@ Future bgUpdateCheck(int taskId, Map? params) async { try { logs.add( 'BG update task $taskId: Attempting to update $appId in the background.'); - await appsProvider.downloadAndInstallLatestApps([appId], null, + await appsProvider.downloadAndInstallLatestApps( + [appId], null, settingsProvider, notificationsProvider: notificationsProvider); } catch (e) { logs.add( diff --git a/lib/pages/app.dart b/lib/pages/app.dart index de64bb3..710c3fb 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -339,7 +339,8 @@ class _AppPageState extends State { HapticFeedback.heavyImpact(); var res = await appsProvider.downloadAndInstallLatestApps( app?.app.id != null ? [app!.app.id] : [], - globalNavigatorKey.currentContext); + globalNavigatorKey.currentContext, + settingsProvider); if (res.isNotEmpty && mounted) { Navigator.of(context).pop(); } diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 516a6a6..41c0f7d 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -381,7 +381,8 @@ class AppsPageState extends State { : () { appsProvider.downloadAndInstallLatestApps( [listedApps[appIndex].app.id], - globalNavigatorKey.currentContext).catchError((e) { + globalNavigatorKey.currentContext, + settingsProvider).catchError((e) { showError(e, context); return []; }); @@ -683,9 +684,8 @@ class AppsPageState extends State { toInstall.addAll(trackOnlyUpdateIdsAllOrSelected); } appsProvider - .downloadAndInstallLatestApps( - toInstall, globalNavigatorKey.currentContext, - settingsProvider: settingsProvider) + .downloadAndInstallLatestApps(toInstall, + globalNavigatorKey.currentContext, settingsProvider) .catchError((e) { showError(e, context); return []; diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 1da2213..1ea70ce 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -328,7 +328,11 @@ class AppsProvider with ChangeNotifier { .where((element) => element.downloadProgress != null) .isNotEmpty; - Future canInstallSilently(App app) async { + Future canInstallSilently( + App app, SettingsProvider settingsProvider) async { + if (!settingsProvider.enableBackgroundUpdates) { + return false; + } if (app.apkUrls.length > 1) { // Manual API selection means silent install is not possible return false; @@ -509,10 +513,9 @@ class AppsProvider with ChangeNotifier { // If no BuildContext is provided, apps that require user interaction are ignored // 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, - {SettingsProvider? settingsProvider, - NotificationsProvider? notificationsProvider}) async { + Future> downloadAndInstallLatestApps(List appIds, + BuildContext? context, SettingsProvider settingsProvider, + {NotificationsProvider? notificationsProvider}) async { notificationsProvider = notificationsProvider ?? context?.read(); List appsToInstall = []; @@ -540,7 +543,8 @@ class AppsProvider with ChangeNotifier { apps[id]!.app.preferredApkIndex = urlInd; await saveApps([apps[id]!.app]); } - if (context != null || await canInstallSilently(apps[id]!.app)) { + if (context != null || + await canInstallSilently(apps[id]!.app, settingsProvider)) { appsToInstall.add(id); } } @@ -577,9 +581,9 @@ class AppsProvider with ChangeNotifier { downloadedDir = downloadedArtifact as DownloadedXApkDir; } var appId = downloadedFile?.appId ?? downloadedDir!.appId; - bool willBeSilent = await canInstallSilently(apps[appId]!.app); - if (!(await settingsProvider?.getInstallPermission(enforce: false) ?? - true)) { + bool willBeSilent = + await canInstallSilently(apps[appId]!.app, settingsProvider); + if (!(await settingsProvider.getInstallPermission(enforce: false))) { throw ObtainiumError(tr('cancelled')); } if (!willBeSilent && context != null) { From 0deab8296fa72e7f9f37d2a2b4709ce8d32a75c0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 23 Aug 2023 18:28:16 -0400 Subject: [PATCH 353/600] bug --- lib/main.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 1cd8d55..38668c2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -171,7 +171,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); var remainingToCheck = moveStrToEnd(toCheck.sublist(i), appId); AndroidAlarmManager.oneShot( - Duration(seconds: remainingSeconds), taskId, bgUpdateCheck, + Duration(seconds: remainingSeconds), taskId + 1, bgUpdateCheck, params: { 'toCheck': remainingToCheck, 'toInstall': toInstall, @@ -211,7 +211,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); var remainingToInstall = moveStrToEnd(toInstall.sublist(i), appId); AndroidAlarmManager.oneShot( - Duration(seconds: remainingSeconds), taskId, bgUpdateCheck, + Duration(seconds: remainingSeconds), taskId + 1, bgUpdateCheck, params: { 'toCheck': toCheck, 'toInstall': remainingToInstall, From 5eac851f8014621e18a5e7dfc440d15c97791a1d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 23 Aug 2023 19:36:24 -0400 Subject: [PATCH 354/600] Added convenience build script --- build.sh | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 build.sh diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..8193949 --- /dev/null +++ b/build.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# Convenience script + +git fetch && git merge origin/main && git push; # Typically run after a PR to main, so bring dev up to date +rm ./build/app/outputs/flutter-apk/* 2>/dev/null; # Get rid of older builds if any +flutter build apk && flutter build apk --split-per-abi # Build (both split and combined APKs) +for file in ./build/app/outputs/flutter-apk/*.sha1; do gpg --sign --detach-sig "$file"; done # Generate PGP signatures +rsync -r ./build/app/outputs/flutter-apk/ ~/Downloads/Obtainium-build/ # Dropoff in Downloads to allow for drag-drop into Flatpak Firefox \ No newline at end of file From 862bb2b2761db3ccab27cce622130129d7c1ef5f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 23 Aug 2023 19:39:23 -0400 Subject: [PATCH 355/600] chmod +x build.sh --- build.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 build.sh diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 From be0b57ac007ced3151f48c0294e03f3899679fb2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 23 Aug 2023 19:51:52 -0400 Subject: [PATCH 356/600] Added logs, BG install cooldown --- lib/main.dart | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 38668c2..297b664 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -133,7 +133,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { bool installMode = toCheck.isEmpty && toInstall.isNotEmpty; logs.add( - 'BG update task $taskId: Started in ${installMode ? 'install' : 'update'} mode${attemptCount > 1 ? '. ${attemptCount - 1} consecutive fail(s)' : ''}.'); + 'BG ${installMode ? 'install' : 'update'} task $taskId: Started${attemptCount > 1 ? '. ${attemptCount - 1} consecutive fail(s)' : ''}.'); if (!installMode) { var didCompleteChecking = false; @@ -188,6 +188,8 @@ Future bgUpdateCheck(int taskId, Map? params) async { } } if (didCompleteChecking && toInstall.isNotEmpty) { + logs.add( + 'BG update task $taskId: Scheduling install task to run immediately.'); AndroidAlarmManager.oneShot( const Duration(minutes: 0), taskId + 1, bgUpdateCheck, params: {'toCheck': [], 'toInstall': toInstall}); @@ -198,17 +200,20 @@ Future bgUpdateCheck(int taskId, Map? params) async { String appId = toInstall[i]; try { logs.add( - 'BG update task $taskId: Attempting to update $appId in the background.'); + 'BG install task $taskId: Attempting to update $appId in the background.'); await appsProvider.downloadAndInstallLatestApps( [appId], null, settingsProvider, notificationsProvider: notificationsProvider); + await Future.delayed(const Duration( + seconds: + 5)); // Just in case task ending causes install fail (not clear) } catch (e) { logs.add( - 'BG update task $taskId: Got error on updating $appId \'${e.toString()}\'.'); + 'BG install task $taskId: Got error on updating $appId \'${e.toString()}\'.'); if (attemptCount < maxAttempts) { var remainingSeconds = 1; logs.add( - 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); + 'BG install task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); var remainingToInstall = moveStrToEnd(toInstall.sublist(i), appId); AndroidAlarmManager.oneShot( Duration(seconds: remainingSeconds), taskId + 1, bgUpdateCheck, @@ -225,6 +230,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { } } } + logs.add('BG ${installMode ? 'install' : 'update'} task $taskId: Done.'); } void main() async { From 57d44c972ff8a66b5cfd12e9ff314b23cabf8971 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 23 Aug 2023 20:05:08 -0400 Subject: [PATCH 357/600] Update build script to create zips --- build.sh | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/build.sh b/build.sh index 8193949..0ad2412 100755 --- a/build.sh +++ b/build.sh @@ -1,8 +1,18 @@ #!/bin/bash # Convenience script -git fetch && git merge origin/main && git push; # Typically run after a PR to main, so bring dev up to date -rm ./build/app/outputs/flutter-apk/* 2>/dev/null; # Get rid of older builds if any -flutter build apk && flutter build apk --split-per-abi # Build (both split and combined APKs) +CURR_DIR="$(pwd)" +trap "cd "$CURR_DIR"" EXIT + +git fetch && git merge origin/main && git push # Typically run after a PR to main, so bring dev up to date +rm ./build/app/outputs/flutter-apk/* 2>/dev/null # Get rid of older builds if any +flutter build apk && flutter build apk --split-per-abi # Build (both split and combined APKs) for file in ./build/app/outputs/flutter-apk/*.sha1; do gpg --sign --detach-sig "$file"; done # Generate PGP signatures -rsync -r ./build/app/outputs/flutter-apk/ ~/Downloads/Obtainium-build/ # Dropoff in Downloads to allow for drag-drop into Flatpak Firefox \ No newline at end of file +rsync -r ./build/app/outputs/flutter-apk/ ~/Downloads/Obtainium-build/ # Dropoff in Downloads to allow for drag-drop into Flatpak Firefox +cd ~/Downloads/Obtainium-build/ # Make zips just in case (for in-comment uploads) +for apk in *.apk; do + PREFIX="$(echo "$apk" | head -c -5)" + zip "$PREFIX" "$PREFIX"* +done +mkdir -p zips +mv *.zip zips/ From 5e41d5762b0c901a3f2dc384e0ebf47a91b5bad0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 24 Aug 2023 10:46:11 -0400 Subject: [PATCH 358/600] BG task: notif, retry, log tweaks --- lib/main.dart | 27 ++++++++++++++++------- lib/providers/notifications_provider.dart | 19 +++++++++------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 297b664..ff27e29 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -118,7 +118,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { var settingsProvider = SettingsProvider(); await settingsProvider.initializeSettings(); - int maxAttempts = 5; + int maxAttempts = 4; params ??= {}; if (params['toCheck'] == null) { @@ -137,13 +137,14 @@ Future bgUpdateCheck(int taskId, Map? params) async { if (!installMode) { var didCompleteChecking = false; + CheckingUpdatesNotification? notif; for (int i = 0; i < toCheck.length; i++) { var appId = toCheck[i]; AppInMemory? app = appsProvider.apps[appId]; if (app?.app.installedVersion != null) { try { - logs.add('BG update task $taskId: Checking for updates for $appId.'); - notificationsProvider.notify(checkingUpdatesNotification, + notificationsProvider.notify( + notif = CheckingUpdatesNotification(app?.name ?? appId), cancelExisting: true); App? newApp = await appsProvider.checkUpdate(appId); if (newApp != null) { @@ -166,7 +167,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { ? (e.remainingMinutes * 60) : e is ClientException ? (15 * 60) - : 1; + : (attemptCount ^ 2); logs.add( 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); var remainingToCheck = moveStrToEnd(toCheck.sublist(i), appId); @@ -183,18 +184,23 @@ Future bgUpdateCheck(int taskId, Map? params) async { .notify(ErrorCheckingUpdatesNotification(e.toString())); } } finally { - notificationsProvider.cancel(checkingUpdatesNotification.id); + if (notif != null) { + notificationsProvider.cancel(notif.id); + } } } } if (didCompleteChecking && toInstall.isNotEmpty) { logs.add( - 'BG update task $taskId: Scheduling install task to run immediately.'); + 'BG update task $taskId: Done. Scheduling install task to run immediately.'); AndroidAlarmManager.oneShot( const Duration(minutes: 0), taskId + 1, bgUpdateCheck, params: {'toCheck': [], 'toInstall': toInstall}); + } else if (didCompleteChecking) { + logs.add('BG install task $taskId: Done.'); } } else { + var didCompleteInstalling = false; toInstall = moveStrToEnd(toInstall, obtainiumId); for (var i = 0; i < toInstall.length; i++) { String appId = toInstall[i]; @@ -207,11 +213,14 @@ Future bgUpdateCheck(int taskId, Map? params) async { await Future.delayed(const Duration( seconds: 5)); // Just in case task ending causes install fail (not clear) + if (i == (toCheck.length - 1)) { + didCompleteInstalling = true; + } } catch (e) { logs.add( 'BG install task $taskId: Got error on updating $appId \'${e.toString()}\'.'); if (attemptCount < maxAttempts) { - var remainingSeconds = 1; + var remainingSeconds = attemptCount; logs.add( 'BG install task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); var remainingToInstall = moveStrToEnd(toInstall.sublist(i), appId); @@ -228,9 +237,11 @@ Future bgUpdateCheck(int taskId, Map? params) async { .notify(ErrorCheckingUpdatesNotification(e.toString())); } } + if (didCompleteInstalling) { + logs.add('BG install task $taskId: Done.'); + } } } - logs.add('BG ${installMode ? 'install' : 'update'} task $taskId: Done.'); } void main() async { diff --git a/lib/providers/notifications_provider.dart b/lib/providers/notifications_provider.dart index 1c2ab23..452512a 100644 --- a/lib/providers/notifications_provider.dart +++ b/lib/providers/notifications_provider.dart @@ -117,14 +117,17 @@ final completeInstallationNotification = ObtainiumNotification( tr('completeAppInstallationNotifDescription'), Importance.max); -final checkingUpdatesNotification = ObtainiumNotification( - 4, - tr('checkingForUpdates'), - '', - 'BG_UPDATE_CHECK', - tr('checkingForUpdates'), - tr('checkingForUpdatesNotifDescription'), - Importance.min); +class CheckingUpdatesNotification extends ObtainiumNotification { + CheckingUpdatesNotification(String appName) + : super( + 4, + tr('checkingForUpdates'), + appName, + 'BG_UPDATE_CHECK', + tr('checkingForUpdates'), + tr('checkingForUpdatesNotifDescription'), + Importance.min); +} class NotificationsProvider { FlutterLocalNotificationsPlugin notifications = From 2504ae24fcfdbbc7cf1f4da32290b4be845f350d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 24 Aug 2023 15:05:07 -0400 Subject: [PATCH 359/600] Fix bgcheck error reporting (per-app), move code around --- lib/main.dart | 175 ----------------------- lib/providers/apps_provider.dart | 236 +++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+), 175 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index ff27e29..f70dcff 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,8 +2,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:http/http.dart'; -import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/pages/home.dart'; import 'package:obtainium/providers/apps_provider.dart'; import 'package:obtainium/providers/logs_provider.dart'; @@ -71,179 +69,6 @@ Future loadTranslations() async { fallbackTranslations: controller.fallbackTranslations); } -moveStrToEnd(List arr, String str, {String? strB}) { - String? temp; - arr.removeWhere((element) { - bool res = element == str || element == strB; - if (res) { - temp = element; - } - return res; - }); - if (temp != null) { - arr = [...arr, temp!]; - } - return arr; -} - -/// Background updater function -/// -/// @param List? toCheck: The appIds to check for updates (default to all apps sorted by last update check time) -/// -/// @param List? toInstall: The appIds to attempt to update (defaults to an empty array) -/// -/// @param int? attemptCount: The number of times the function has failed up to this point (defaults to 0) -/// -/// When toCheck is empty, the function is in "install mode" (else it is in "update mode"). -/// In update mode, all apps in toCheck are checked for updates. -/// If an update is available, the appId is either added to toInstall (if a background update is possible) or the user is notified. -/// If there is an error, the function tries to continue after a few minutes (duration depends on the error), up to a maximum of 5 tries. -/// -/// Once all update checks are complete, the function is called again in install mode. -/// In this mode, all apps in toInstall are downloaded and installed in the background (install result is unknown). -/// If there is an error, the function tries to continue after a few minutes (duration depends on the error), up to a maximum of 5 tries. -/// -/// In either mode, if the function fails after the maximum number of tries, the user is notified. -@pragma('vm:entry-point') -Future bgUpdateCheck(int taskId, Map? params) async { - WidgetsFlutterBinding.ensureInitialized(); - await EasyLocalization.ensureInitialized(); - await AndroidAlarmManager.initialize(); - await loadTranslations(); - - LogsProvider logs = LogsProvider(); - NotificationsProvider notificationsProvider = NotificationsProvider(); - AppsProvider appsProvider = AppsProvider(isBg: true); - await appsProvider.loadApps(); - var settingsProvider = SettingsProvider(); - await settingsProvider.initializeSettings(); - - int maxAttempts = 4; - - params ??= {}; - if (params['toCheck'] == null) { - settingsProvider.lastBGCheckTime = DateTime.now(); - } - int attemptCount = (params['attemptCount'] ?? 0) + 1; - List toCheck = [ - ...(params['toCheck'] ?? appsProvider.getAppsSortedByUpdateCheckTime()) - ]; - List toInstall = [...(params['toInstall'] ?? ([]))]; - - bool installMode = toCheck.isEmpty && toInstall.isNotEmpty; - - logs.add( - 'BG ${installMode ? 'install' : 'update'} task $taskId: Started${attemptCount > 1 ? '. ${attemptCount - 1} consecutive fail(s)' : ''}.'); - - if (!installMode) { - var didCompleteChecking = false; - CheckingUpdatesNotification? notif; - for (int i = 0; i < toCheck.length; i++) { - var appId = toCheck[i]; - AppInMemory? app = appsProvider.apps[appId]; - if (app?.app.installedVersion != null) { - try { - notificationsProvider.notify( - notif = CheckingUpdatesNotification(app?.name ?? appId), - cancelExisting: true); - App? newApp = await appsProvider.checkUpdate(appId); - if (newApp != null) { - if (!(await appsProvider.canInstallSilently( - app!.app, settingsProvider))) { - notificationsProvider.notify( - UpdateNotification([newApp], id: newApp.id.hashCode - 1)); - } else { - toInstall.add(appId); - } - } - if (i == (toCheck.length - 1)) { - didCompleteChecking = true; - } - } catch (e) { - logs.add( - 'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.'); - if (attemptCount < maxAttempts) { - var remainingSeconds = e is RateLimitError - ? (e.remainingMinutes * 60) - : e is ClientException - ? (15 * 60) - : (attemptCount ^ 2); - logs.add( - 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); - var remainingToCheck = moveStrToEnd(toCheck.sublist(i), appId); - AndroidAlarmManager.oneShot( - Duration(seconds: remainingSeconds), taskId + 1, bgUpdateCheck, - params: { - 'toCheck': remainingToCheck, - 'toInstall': toInstall, - 'attemptCount': attemptCount - }); - break; - } else { - notificationsProvider - .notify(ErrorCheckingUpdatesNotification(e.toString())); - } - } finally { - if (notif != null) { - notificationsProvider.cancel(notif.id); - } - } - } - } - if (didCompleteChecking && toInstall.isNotEmpty) { - logs.add( - 'BG update task $taskId: Done. Scheduling install task to run immediately.'); - AndroidAlarmManager.oneShot( - const Duration(minutes: 0), taskId + 1, bgUpdateCheck, - params: {'toCheck': [], 'toInstall': toInstall}); - } else if (didCompleteChecking) { - logs.add('BG install task $taskId: Done.'); - } - } else { - var didCompleteInstalling = false; - toInstall = moveStrToEnd(toInstall, obtainiumId); - for (var i = 0; i < toInstall.length; i++) { - String appId = toInstall[i]; - try { - logs.add( - 'BG install task $taskId: Attempting to update $appId in the background.'); - await appsProvider.downloadAndInstallLatestApps( - [appId], null, settingsProvider, - notificationsProvider: notificationsProvider); - await Future.delayed(const Duration( - seconds: - 5)); // Just in case task ending causes install fail (not clear) - if (i == (toCheck.length - 1)) { - didCompleteInstalling = true; - } - } catch (e) { - logs.add( - 'BG install task $taskId: Got error on updating $appId \'${e.toString()}\'.'); - if (attemptCount < maxAttempts) { - var remainingSeconds = attemptCount; - logs.add( - 'BG install task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); - var remainingToInstall = moveStrToEnd(toInstall.sublist(i), appId); - AndroidAlarmManager.oneShot( - Duration(seconds: remainingSeconds), taskId + 1, bgUpdateCheck, - params: { - 'toCheck': toCheck, - 'toInstall': remainingToInstall, - 'attemptCount': attemptCount - }); - break; - } else { - notificationsProvider - .notify(ErrorCheckingUpdatesNotification(e.toString())); - } - } - if (didCompleteInstalling) { - logs.add('BG install task $taskId: Done.'); - } - } - } -} - void main() async { WidgetsFlutterBinding.ensureInitialized(); try { diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 1ea70ce..5b673b6 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; import 'package:android_intent_plus/flag.dart'; import 'package:android_package_installer/android_package_installer.dart'; import 'package:android_package_manager/android_package_manager.dart'; @@ -99,6 +100,38 @@ Set findStandardFormatsForVersion(String version, bool strict) { return results; } +moveStrToEnd(List arr, String str, {String? strB}) { + String? temp; + arr.removeWhere((element) { + bool res = element == str || element == strB; + if (res) { + temp = element; + } + return res; + }); + if (temp != null) { + arr = [...arr, temp!]; + } + return arr; +} + +moveStrToEndMapEntryWithCount( + List> arr, MapEntry str, + {MapEntry? strB}) { + MapEntry? temp; + arr.removeWhere((element) { + bool res = element.key == str.key || element.key == strB?.key; + if (res) { + temp = element; + } + return res; + }); + if (temp != null) { + arr = [...arr, temp!]; + } + return arr; +} + class AppsProvider with ChangeNotifier { // In memory App state (should always be kept in sync with local storage versions) Map apps = {}; @@ -1221,3 +1254,206 @@ class _APKOriginWarningDialogState extends State { ); } } + +/// Background updater function +/// +/// @param List? toCheck: The appIds to check for updates (default to all apps sorted by last update check time) +/// +/// @param List? toInstall: The appIds to attempt to update (defaults to an empty array) +/// +/// @param int? attemptCount: The number of times the function has failed up to this point (defaults to 0) +/// +/// When toCheck is empty, the function is in "install mode" (else it is in "update mode"). +/// In update mode, all apps in toCheck are checked for updates. +/// If an update is available, the appId is either added to toInstall (if a background update is possible) or the user is notified. +/// If there is an error, the function tries to continue after a few minutes (duration depends on the error), up to a maximum of 5 tries. +/// +/// Once all update checks are complete, the function is called again in install mode. +/// In this mode, all apps in toInstall are downloaded and installed in the background (install result is unknown). +/// If there is an error, the function tries to continue after a few minutes (duration depends on the error), up to a maximum of 5 tries. +/// +/// In either mode, if the function fails after the maximum number of tries, the user is notified. +@pragma('vm:entry-point') +Future bgUpdateCheck(int taskId, Map? params) async { + WidgetsFlutterBinding.ensureInitialized(); + await EasyLocalization.ensureInitialized(); + await AndroidAlarmManager.initialize(); + await loadTranslations(); + + LogsProvider logs = LogsProvider(); + NotificationsProvider notificationsProvider = NotificationsProvider(); + AppsProvider appsProvider = AppsProvider(isBg: true); + await appsProvider.loadApps(); + var settingsProvider = SettingsProvider(); + await settingsProvider.initializeSettings(); + + int maxAttempts = 4; + + params ??= {}; + if (params['toCheck'] == null) { + settingsProvider.lastBGCheckTime = DateTime.now(); + } + List> toCheck = >[ + ...(params['toCheck'] + ?.map((entry) => MapEntry( + entry['key'] as String, entry['value'] as int)) + .toList() ?? + appsProvider + .getAppsSortedByUpdateCheckTime() + .map((e) => MapEntry(e, 0))) + ]; + List> toInstall = >[ + ...(params['toInstall'] + ?.map((entry) => MapEntry( + entry['key'] as String, entry['value'] as int)) + .toList() ?? + (>>[])) + ]; + + bool installMode = toCheck.isEmpty && + toInstall.isNotEmpty; // Task is either in update mode or install mode + + logs.add( + 'BG ${installMode ? 'install' : 'update'} task $taskId: Started (${installMode ? toInstall.length : toCheck.length}).'); + + if (!installMode) { + // If in update mode... + var didCompleteChecking = false; + CheckingUpdatesNotification? notif; + // Loop through all updates and check each + for (int i = 0; i < toCheck.length; i++) { + var appId = toCheck[i].key; + var retryCount = toCheck[i].value; + AppInMemory? app = appsProvider.apps[appId]; + if (app?.app.installedVersion != null) { + try { + notificationsProvider.notify( + notif = CheckingUpdatesNotification(app?.name ?? appId), + cancelExisting: true); + App? newApp = await appsProvider.checkUpdate(appId); + if (newApp != null) { + if (!(await appsProvider.canInstallSilently( + app!.app, settingsProvider))) { + notificationsProvider.notify( + UpdateNotification([newApp], id: newApp.id.hashCode - 1)); + } else { + toInstall.add(MapEntry(appId, 0)); + } + } + if (i == (toCheck.length - 1)) { + didCompleteChecking = true; + } + } catch (e) { + // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue checking shortly + logs.add( + 'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.'); + if (retryCount < maxAttempts) { + var remainingSeconds = e is RateLimitError + ? (i == 0 ? (e.remainingMinutes * 60) : (5 * 60)) + : e is ClientException + ? (15 * 60) + : (retryCount ^ 2); + logs.add( + 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); + var remainingToCheck = moveStrToEndMapEntryWithCount( + toCheck.sublist(i), MapEntry(appId, retryCount + 1)); + AndroidAlarmManager.oneShot( + Duration(seconds: remainingSeconds), taskId + 1, bgUpdateCheck, + params: { + 'toCheck': remainingToCheck + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + 'toInstall': toInstall + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + }); + break; + } else { + // If the offender has reached its fail limit, notify the user and remove it from the list (task can continue) + toCheck.removeAt(i); + i--; + notificationsProvider + .notify(ErrorCheckingUpdatesNotification(e.toString())); + } + } finally { + if (notif != null) { + notificationsProvider.cancel(notif.id); + } + } + } + } + // If you're done checking and found some silently installable updates, schedule another task which will run in install mode + if (didCompleteChecking && toInstall.isNotEmpty) { + logs.add( + 'BG update task $taskId: Done. Scheduling install task to run immediately.'); + AndroidAlarmManager.oneShot( + const Duration(minutes: 0), taskId + 1, bgUpdateCheck, + params: { + 'toCheck': [], + 'toInstall': toInstall + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList() + }); + } else if (didCompleteChecking) { + logs.add('BG install task $taskId: Done.'); + } + } else { + // If in install mode... + var didCompleteInstalling = false; + var tempObtArr = toInstall.where((element) => element.key == obtainiumId); + if (tempObtArr.isNotEmpty) { + // Move obtainium to the end of the list as it must always install last + var obt = tempObtArr.first; + toInstall = moveStrToEndMapEntryWithCount(toInstall, obt); + } + // Loop through all updates and install each + for (var i = 0; i < toInstall.length; i++) { + var appId = toInstall[i].key; + var retryCount = toInstall[i].value; + try { + logs.add( + 'BG install task $taskId: Attempting to update $appId in the background.'); + await appsProvider.downloadAndInstallLatestApps( + [appId], null, settingsProvider, + notificationsProvider: notificationsProvider); + await Future.delayed(const Duration( + seconds: + 5)); // Just in case task ending causes install fail (not clear) + if (i == (toCheck.length - 1)) { + didCompleteInstalling = true; + } + } catch (e) { + // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue installing shortly + logs.add( + 'BG install task $taskId: Got error on updating $appId \'${e.toString()}\'.'); + if (retryCount < maxAttempts) { + var remainingSeconds = retryCount; + logs.add( + 'BG install task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); + var remainingToInstall = moveStrToEndMapEntryWithCount( + toInstall.sublist(i), MapEntry(appId, retryCount + 1)); + AndroidAlarmManager.oneShot( + Duration(seconds: remainingSeconds), taskId + 1, bgUpdateCheck, + params: { + 'toCheck': toCheck + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + 'toInstall': remainingToInstall + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + }); + break; + } else { + // If the offender has reached its fail limit, notify the user and remove it from the list (task can continue) + toInstall.removeAt(i); + i--; + notificationsProvider + .notify(ErrorCheckingUpdatesNotification(e.toString())); + } + } + if (didCompleteInstalling) { + logs.add('BG install task $taskId: Done.'); + } + } + } +} From d6ddf8736569e0e653665c15cd7632aa369b82fd Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Fri, 25 Aug 2023 22:49:54 +0200 Subject: [PATCH 360/600] locale(pl): Update Polish translations Polish translation has been updated Signed-off-by: Daviteusz --- assets/translations/pl.json | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 327e720..b3f9d0e 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -245,11 +245,11 @@ "sortByFileNamesNotLinks": "Sortuj wg nazw plików zamiast pełnych linków", "filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego", "customLinkFilterRegex": "Niestandardowy filtr linków wg. wyrażenia regularnego (domyślnie \".apk$\")", - "appsPossiblyUpdated": "App Updates Attempted", - "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", - "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", - "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "appsPossiblyUpdated": "Informuj o próbach aktualizacji", + "appsPossiblyUpdatedNotifDescription": "Powiadamiaj o potencjalnym zastosowaniu w tle aktualizacji jednej lub większej ilości aplikacji", + "xWasPossiblyUpdatedToY": "{} mógł zostać zaktualizowany do {}.", + "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", + "backgroundUpdateLimitsExplanation": "Powodzenie instalacji w tle można określić dopiero po otwarciu Obtainium.", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" @@ -291,11 +291,12 @@ "other": "{} i {} aplik. otrzymało aktualizacje." }, "xAndNMoreUpdatesInstalled": { - "one": "Zaktualizowano {} i jeszcze 1 aplikację.", + "one": "{} i jeszcze 1 apka zostały zaktualizowane.", "other": "Zaktualizowano {} i {} aplik." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} and 1 more app may have been updated.", - "other": "{} and {} more apps may have been updated." - } + "one": "{} i jeszcze 1 apka mogły zostać zaktualizowane.", + "other": "{} i {} innych apek mogło zostać zaktualizowanych." + }, + "enableBackgroundUpdates": "Włącz aktualizacje w tle" } From 13e10692b16938a801db7ee8874c6060cac2ed33 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 25 Aug 2023 20:40:35 -0400 Subject: [PATCH 361/600] 'Verify latest tag' toggle (#798, #740) --- assets/translations/bs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/github.dart | 30 ++++++++++++++++++++++++++++++ 13 files changed, 42 insertions(+) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index cd14a19..830a3ac 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -246,6 +246,7 @@ "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 9227e9f..cd31e8a 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -246,6 +246,7 @@ "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 165b4ff..e3a7684 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -247,6 +247,7 @@ "enableBackgroundUpdates": "Enable background updates", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index bbed509..afe6e5e 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -246,6 +246,7 @@ "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 93caa25..5d7e754 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -246,6 +246,7 @@ "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index bfbbfcc..2ab4bb8 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -246,6 +246,7 @@ "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 5c5fd49..d30c802 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -245,6 +245,7 @@ "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "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 14586d4..b4d0359 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -246,6 +246,7 @@ "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 386a512..7c2e285 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -246,6 +246,7 @@ "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 327e720..8b4ed79 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -250,6 +250,7 @@ "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "removeAppQuestion": { "one": "Usunąć aplikację?", "other": "Usunąć aplikacje?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index e8a2507..703f057 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -246,6 +246,7 @@ "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index eac5e3e..48cf7b4 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -246,6 +246,7 @@ "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 608c31c..0b2f2c9 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -85,6 +85,10 @@ class GitHub extends AppSource { return regExValidator(value); } ]) + ], + [ + GeneratedFormSwitch('verifyLatestTag', + label: tr('verifyLatestTag'), defaultValue: false) ] ]; @@ -212,6 +216,21 @@ class GitHub extends AppSource { true ? additionalSettings['filterReleaseNotesByRegEx'] : null; + bool verifyLatestTag = additionalSettings['verifyLatestTag'] == true; + String? latestTag; + if (verifyLatestTag) { + var temp = requestUrl.split('?'); + Response res = await sourceRequest( + '${temp[0]}/latest${temp.length > 1 ? '?${temp.sublist(1).join('?')}' : ''}'); + if (res.statusCode != 200) { + if (onHttpErrorCode != null) { + onHttpErrorCode(res); + } + throw getObtainiumHttpError(res); + } + var jsres = jsonDecode(res.body); + latestTag = jsres['tag_name'] ?? jsres['name']; + } Response res = await sourceRequest(requestUrl); if (res.statusCode == 200) { var releases = jsonDecode(res.body) as List; @@ -258,6 +277,17 @@ class GitHub extends AppSource { } } }); + if (latestTag != null && + releases.isNotEmpty && + latestTag != + (releases[releases.length - 1]['tag_name'] ?? + releases[0]['name'])) { + var ind = releases.indexWhere( + (element) => latestTag == (element['tag_name'] ?? element['name'])); + if (ind >= 0) { + releases.add(releases.removeAt(ind)); + } + } releases = releases.reversed.toList(); dynamic targetRelease; var prerrelsSkipped = 0; From 57f499c6a5e92edd5da2eddfb223d0a875275ab5 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 25 Aug 2023 20:53:23 -0400 Subject: [PATCH 362/600] Update packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 16 ++++++++-------- pubspec.yaml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index f70dcff..9cab1de 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.13.27'; +const String currentVersion = '0.14.0'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index fd01871..0bd8a3c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -231,10 +231,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: "21145c9c268d54b1f771d8380c195d2d6f655e0567dc1ca2f9c134c02c819e0a" + sha256: bdfa035a974a0c080576c4c8ed01cdf9d1b406a04c7daa05443ef0383a97bedc url: "https://pub.dev" source: hosted - version: "5.3.3" + version: "5.3.4" flutter: dependency: "direct main" description: flutter @@ -276,10 +276,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "3cc40fe8c50ab8383f3e053a499f00f975636622ecdc8e20a77418ece3b1e975" + sha256: "3002092e5b8ce2f86c3361422e52e6db6776c23ee21e0b2f71b892bf4259ef04" url: "https://pub.dev" source: hosted - version: "15.1.0+1" + version: "15.1.1" flutter_local_notifications_linux: dependency: transitive description: @@ -848,10 +848,10 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: "789d52bd789373cc1e100fb634af2127e86c99cf9abde09499743270c5de8d00" + sha256: "04a0782fb058b7c71f2048935583488f4d32e9147ca403abc4e58f1de9964629" url: "https://pub.dev" source: hosted - version: "4.2.2" + version: "4.2.3" webview_flutter_android: dependency: transitive description: @@ -880,10 +880,10 @@ packages: dependency: transitive description: name: win32 - sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0 + sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa" url: "https://pub.dev" source: hosted - version: "5.0.6" + version: "5.0.7" win32_registry: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f107cb0..03537a2 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.13.27+191 # When changing this, update the tag in main() accordingly +version: 0.14.0+192 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From ef0b20887b2a2a5a4fcc7dc9eac7e614bc1a4d3c Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 25 Aug 2023 21:00:57 -0400 Subject: [PATCH 363/600] Update README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d0c3f1a..5d4c6d0 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,9 @@ Currently supported App sources: alt="Get it on GitHub" height="80">](https://github.com/ImranR98/Obtainium/releases) +[PGP Public Key](https://keyserver.ubuntu.com/pks/lookup?search=contact%40imranr.dev&fingerprint=on&op=index) + ## Limitations -- Auto (unattended) updates are unsupported due to a lack of any capable Flutter plugin. - For some sources, data is gathered using Web scraping and can easily break due to changes in website design. In such cases, more reliable methods may be unavailable. ## Screenshots From 1dd0392b78bea6adb21591b8279bf7a55590b04d Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Sun, 27 Aug 2023 01:15:08 +0900 Subject: [PATCH 364/600] Update ja.json --- assets/translations/ja.json | 44 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 7c2e285..44e1a57 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -241,19 +241,19 @@ "sortByFileNamesNotLinks": "フルのリンクではなくファイル名でソートする", "filterReleaseNotesByRegEx": "正規表現でリリースノートをフィルタリングする", "customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')", - "appsPossiblyUpdated": "App Updates Attempted", - "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", - "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", - "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", - "verifyLatestTag": "Verify the 'latest' tag", + "appsPossiblyUpdated": "アプリのアップデートが試みられました", + "appsPossiblyUpdatedNotifDescription": "1つまたは複数のアプリのアップデートがバックグラウンドで適用された可能性があることをユーザーに通知", + "xWasPossiblyUpdatedToY": "{} が {} にアップデートされた可能性があります", + "backgroundUpdateReqsExplanation": "バックグラウンドアップデートは、すべてのアプリで可能とは限りません。", + "backgroundUpdateLimitsExplanation": "バックグラウンドアップデートが成功したかどうかは、Obtainiumを起動したときにしか判断できません。", + "verifyLatestTag": "'latest'タグを確認する", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" }, "tooManyRequestsTryAgainInMinutes": { - "one": "リクエストが多すぎます(レート制限)- {}分後に再試行してください", - "other": "リクエストが多すぎます(レート制限)- {}分後に再試行してください" + "one": "リクエストが多すぎます(レート制限)- {} 分後に再試行してください", + "other": "リクエストが多すぎます(レート制限)- {} 分後に再試行してください" }, "bgUpdateGotErrorRetryInMinutes": { "one": "バックグラウンドでのアップデート確認で {} の問題が発生, {} 分後に再試行します", @@ -264,28 +264,28 @@ "other": "バックグラウンドでのアップデート確認で {} 個のアップデートを発見 - 必要に応じてユーザーに通知します" }, "apps": { - "one": "{}個のアプリ", - "other": "{}個のアプリ" + "one": "{} 個のアプリ", + "other": "{} 個のアプリ" }, "url": { - "one": "{}個のURL", - "other": "{}個のURL" + "one": "{} 個のURL", + "other": "{} 個のURL" }, "minute": { - "one": "{}分", - "other": "{}分" + "one": "{} 分", + "other": "{} 分" }, "hour": { - "one": "{}時間", - "other": "{}時間" + "one": "{} 時間", + "other": "{} 時間" }, "day": { - "one": "{}日", - "other": "{}日" + "one": "{} 日", + "other": "{} 日" }, "clearedNLogsBeforeXAfterY": { - "one": "{n}個のログをクリアしました (前 = {before}, 後 = {after})", - "other": "{n}個のログをクリアしました (前 = {before}, 後 = {after})" + "one": "{n} 個のログをクリアしました (前 = {before}, 後 = {after})", + "other": "{n} 個のログをクリアしました (前 = {before}, 後 = {after})" }, "xAndNMoreUpdatesAvailable": { "one": "{} とさらに {} 個のアプリのアップデートが利用可能です", @@ -296,7 +296,7 @@ "other": "{} とさらに {} 個のアプリがアップデートされました" }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} and 1 more app may have been updated.", - "other": "{} and {} more apps may have been updated." + "one": "{} とさらに 1 個のアプリがアップデートされた可能性があります", + "other": "{} とさらに {} 個のアプリがアップデートされた化膿性があります" } } From 9686d0f0ca529e0b6e9cb02816b2221f5d973f44 Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Sun, 27 Aug 2023 01:20:51 +0900 Subject: [PATCH 365/600] Added missing enableBackgroundUpdates text --- assets/translations/ja.json | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 44e1a57..8bf5bc1 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -244,6 +244,7 @@ "appsPossiblyUpdated": "アプリのアップデートが試みられました", "appsPossiblyUpdatedNotifDescription": "1つまたは複数のアプリのアップデートがバックグラウンドで適用された可能性があることをユーザーに通知", "xWasPossiblyUpdatedToY": "{} が {} にアップデートされた可能性があります", + "enableBackgroundUpdates": "バックグラウンドアップデートを有効化する", "backgroundUpdateReqsExplanation": "バックグラウンドアップデートは、すべてのアプリで可能とは限りません。", "backgroundUpdateLimitsExplanation": "バックグラウンドアップデートが成功したかどうかは、Obtainiumを起動したときにしか判断できません。", "verifyLatestTag": "'latest'タグを確認する", From ae92a459b7d13cf1a264c233240cd73fc2be6df8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 26 Aug 2023 15:35:08 -0400 Subject: [PATCH 366/600] Remove VLC (#801) --- README.md | 1 - lib/providers/source_provider.dart | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 5d4c6d0..915d851 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ Currently supported App sources: - Jenkins Jobs - [Steam](https://store.steampowered.com/mobile) - [Telegram App](https://telegram.org) -- [VLC](https://www.videolan.org/vlc/download-android.html) - [Neutron Code](https://neutroncode.com) - "HTML" (Fallback) - Any other URL that returns an HTML page with links to APK files (if multiple, the last file alphabetically is picked) diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 1fff134..3371ee4 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -25,7 +25,6 @@ import 'package:obtainium/app_sources/sourceforge.dart'; import 'package:obtainium/app_sources/sourcehut.dart'; import 'package:obtainium/app_sources/steammobile.dart'; import 'package:obtainium/app_sources/telegramapp.dart'; -import 'package:obtainium/app_sources/vlc.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart'; @@ -517,7 +516,7 @@ class SourceProvider { // APKCombo(), // Can't get past their scraping blocking yet (get 403 Forbidden) Mullvad(), Signal(), - VLC(), + // VLC(), // As of 2023-08-26 this site randomly messes up the 'latest' version (one minute it's 3.5.4, next minute back to 3.5.3) // WhatsApp(), // As of 2023-03-20 this is unusable as the version on the webpage is months out of date TelegramApp(), SteamMobile(), From d81085a9e81802bb39892d4e0f885ead564e2db1 Mon Sep 17 00:00:00 2001 From: Matsuri Date: Sun, 27 Aug 2023 15:30:01 +0800 Subject: [PATCH 367/600] Update zh.json - Translate new strings - Slight improvements Signed-off-by: Matsuri --- assets/translations/zh.json | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 48cf7b4..5ab313d 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -40,7 +40,7 @@ "appSourceURL": "来源 URL", "error": "错误", "add": "添加", - "searchSomeSourcesLabel": "搜索(仅部分来源)", + "searchSomeSourcesLabel": "搜索(仅支持部分来源)", "search": "搜索", "additionalOptsFor": "{} 的更多选项", "supportedSourcesBelow": "支持的来源:", @@ -144,16 +144,16 @@ "warning": "警告", "sourceIsXButPackageFromYPrompt": "此应用的来源是“{}”,但 APK 文件来自“{}”。是否继续?", "updatesAvailable": "更新可用", - "updatesAvailableNotifDescription": "Obtainium 追踪的应用有更新时发出通知", + "updatesAvailableNotifDescription": "Obtainium 追踪的应用有更新时发送通知", "noNewUpdates": "全部应用已是最新。", "xHasAnUpdate": "{} 可以更新了。", "appsUpdated": "应用已更新", - "appsUpdatedNotifDescription": "当应用在后台安装更新时发出通知", + "appsUpdatedNotifDescription": "当应用在后台安装更新时发送通知", "xWasUpdatedToY": "{} 已更新至 {}。", "errorCheckingUpdates": "检查更新出错", "errorCheckingUpdatesNotifDescription": "当后台检查更新失败时显示的通知", "appsRemoved": "应用已删除", - "appsRemovedNotifDescription": "当应用因加载出错而被删除时发出通知", + "appsRemovedNotifDescription": "当应用因加载出错而被删除时发送通知", "xWasRemovedDueToErrorY": "{} 由于以下错误被删除:{}", "completeAppInstallation": "完成应用安装", "obtainiumMustBeOpenToInstallApps": "必须启动 Obtainium 才能安装应用", @@ -174,7 +174,7 @@ "yesMarkUpdated": "是,标记为已更新", "fdroid": "F-Droid 官方存储库", "appIdOrName": "应用 ID 或名称", - "appId": "App ID", + "appId": "应用 ID", "appWithIdOrNameNotFound": "未找到符合此 ID 或名称的应用", "reposHaveMultipleApps": "存储库中可能包含多个应用", "fdroidThirdPartyRepo": "F-Droid 第三方存储库", @@ -238,15 +238,16 @@ "addInfoInSettings": "在“设置”中添加此凭据。", "githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。", "gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。", - "sortByFileNamesNotLinks": "根据文件名而不是完整链接来排序", - "filterReleaseNotesByRegEx": "用正则表达式筛选发布说明", - "customLinkFilterRegex": "用正则表达式自定义链接筛选(默认 '.apk$')", - "appsPossiblyUpdated": "App Updates Attempted", - "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", - "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", - "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", - "verifyLatestTag": "Verify the 'latest' tag", + "sortByFileNamesNotLinks": "使用文件名代替链接进行排序", + "filterReleaseNotesByRegEx": "使用正则表达式筛选发行说明", + "customLinkFilterRegex": "使用正则表达式自定义链接筛选(默认模式为“.apk$”)", + "appsPossiblyUpdated": "已尝试更新应用", + "appsPossiblyUpdatedNotifDescription": "当应用已尝试在后台更新时发送通知", + "xWasPossiblyUpdatedToY": "已尝试将 {} 更新至 {}。", + "enableBackgroundUpdates": "启用后台更新", + "backgroundUpdateReqsExplanation": "后台更新未必适用于所有的应用。", + "backgroundUpdateLimitsExplanation": "只有在启动 Obtainium 时才能确认安装是否成功。", + "verifyLatestTag": "验证“Latest”标签", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" @@ -260,8 +261,8 @@ "other": "后台更新检查遇到了“{}”问题,预定于 {} 分钟后重试" }, "bgCheckFoundUpdatesWillNotifyIfNeeded": { - "one": "后台检查发现 {} 个应用更新 - 如有需要将发出通知", - "other": "后台检查发现 {} 个应用更新 - 如有需要将发出通知" + "one": "后台检查发现 {} 个应用更新 - 如有需要将发送通知", + "other": "后台检查发现 {} 个应用更新 - 如有需要将发送通知" }, "apps": { "one": "{} 个应用", @@ -296,7 +297,7 @@ "other": "{} 和另外 {} 个应用已更新。" }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} and 1 more app may have been updated.", - "other": "{} and {} more apps may have been updated." + "one": "{} 和另外 1 个应用已尝试更新。", + "other": "{} 和另外 {} 个应用已尝试更新。" } } From db2476f3a5c8bdd2cc73a91cb354ce90cb87a44c Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Mon, 28 Aug 2023 01:36:14 +0900 Subject: [PATCH 368/600] Update ja.json --- assets/translations/ja.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 8bf5bc1..e2d360c 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -241,8 +241,8 @@ "sortByFileNamesNotLinks": "フルのリンクではなくファイル名でソートする", "filterReleaseNotesByRegEx": "正規表現でリリースノートをフィルタリングする", "customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')", - "appsPossiblyUpdated": "アプリのアップデートが試みられました", - "appsPossiblyUpdatedNotifDescription": "1つまたは複数のアプリのアップデートがバックグラウンドで適用された可能性があることをユーザーに通知", + "appsPossiblyUpdated": "アプリのアップデートを試行", + "appsPossiblyUpdatedNotifDescription": "1つまたは複数のアプリのアップデートがバックグラウンドで適用された可能性があることをユーザーに通知する", "xWasPossiblyUpdatedToY": "{} が {} にアップデートされた可能性があります", "enableBackgroundUpdates": "バックグラウンドアップデートを有効化する", "backgroundUpdateReqsExplanation": "バックグラウンドアップデートは、すべてのアプリで可能とは限りません。", From 1e94d716658bc1cb24a493249a760c5e18fd3eb5 Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Sun, 27 Aug 2023 18:20:46 +0200 Subject: [PATCH 369/600] locale(pl): Update Polish translations --- assets/translations/pl.json | 72 +++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index b754f7f..e6ca53d 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -4,8 +4,10 @@ "okay": "Okej", "appId": "ID aplikacji", "bgUpdateGotErrorRetryInMinutes": { - "one": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} min.", - "other": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} min." + "one": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minutę", + "few": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minuty", + "many": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minut", + "other": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minuty" }, "invalidURLForSource": "Nieprawidłowy adres URL aplikacji {}", "noReleaseFound": "Nie można znaleźć odpowiedniego wydania", @@ -247,57 +249,81 @@ "customLinkFilterRegex": "Niestandardowy filtr linków wg. wyrażenia regularnego (domyślnie \".apk$\")", "appsPossiblyUpdated": "Informuj o próbach aktualizacji", "appsPossiblyUpdatedNotifDescription": "Powiadamiaj o potencjalnym zastosowaniu w tle aktualizacji jednej lub większej ilości aplikacji", - "xWasPossiblyUpdatedToY": "{} mógł zostać zaktualizowany do {}.", + "xWasPossiblyUpdatedToY": "{} być może zaktualizowano do {}.", "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", "backgroundUpdateLimitsExplanation": "Powodzenie instalacji w tle można określić dopiero po otwarciu Obtainium.", - "verifyLatestTag": "Verify the 'latest' tag", + "verifyLatestTag": "Zweryfikuj najnowszy tag", "removeAppQuestion": { "one": "Usunąć aplikację?", + "few": "Usunąć aplikacje?", + "many": "Usunąć aplikacje?", "other": "Usunąć aplikacje?" }, "tooManyRequestsTryAgainInMinutes": { - "one": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} min.", - "other": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} min." + "one": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minutę", + "few": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minuty", + "many": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minut", + "other": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minuty" }, "bgCheckFoundUpdatesWillNotifyIfNeeded": { - "one": "Podczas sprawdzania aktualizacji w tle znaleziono {} aktualizację - w razie potrzeby użytkownik zostanie o tym powiadomiony", - "other": "Podczas sprawdzania aktualizacji w tle znaleziono {} akt. - w razie potrzeby użytkownik zostanie o tym powiadomiony" + "one": "W tle znaleziono {} aktualizację - w razie potrzeby użytkownik zostanie o tym powiadomiony", + "few": "W tle znaleziono {} aktualizacje - w razie potrzeby użytkownik zostanie o tym powiadomiony", + "many": "W tle znaleziono {} aktualizacji - w razie potrzeby użytkownik zostanie o tym powiadomiony", + "other": "W tle znaleziono {} aktualizacje - w razie potrzeby użytkownik zostanie o tym powiadomiony" }, "apps": { - "one": "{} aplik.", - "other": "{} aplik." + "one": "{} apkę", + "few": "{} apki", + "many": "{} apek", + "other": "{} apki" }, "url": { "one": "{} adres URL", - "other": "{} adr. URL" + "few": "{} adresy URL", + "many": "{} adresów URL", + "other": "{} adresy URL" }, "minute": { - "one": "{} min.", - "other": "{} min." + "one": "{} minuta", + "few": "{} minuty", + "many": "{} minut", + "other": "{} minuty" }, "hour": { - "one": "{} godz.", - "other": "{} godz." + "one": "{} godzina", + "few": "{} godziny", + "many": "{} godzin", + "other": "{} godziny" }, "day": { "one": "{} dzień", + "few": "{} dni", + "many": "{} dni", "other": "{} dni" }, "clearedNLogsBeforeXAfterY": { "one": "Wyczyszczono {n} log (przed = {before}, po = {after})", - "other": "Wyczyszczono logi: {n} (przed = {before}, po = {after})" + "few": "Wyczyszczono {n} logi (przed = {before}, po = {after})", + "many": "Wyczyszczono {n} logów (przed = {before}, po = {after})", + "other": "Wyczyszczono {n} logi (przed = {before}, po = {after})" }, "xAndNMoreUpdatesAvailable": { - "one": "{} i jeszcze 1 aplikacja mają aktualizacje.", - "other": "{} i {} aplik. otrzymało aktualizacje." + "one": "{} i 1 inna apka mają aktualizacje.", + "few": "{} i {} inne apki mają aktualizacje.", + "many": "{} i {} innych apek ma aktualizacje.", + "other": "{} i {} inne apki mają aktualizacje." }, "xAndNMoreUpdatesInstalled": { - "one": "{} i jeszcze 1 apka zostały zaktualizowane.", - "other": "Zaktualizowano {} i {} aplik." + "one": "Zaktualizowano {} i 1 inną apkę.", + "few": "{} i {} inne apki zostały zaktualizowane.", + "many": "{} i {} innych apek zostało zaktualizowanych.", + "other": "{} i {} inne apki zostały zaktualizowane." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} i jeszcze 1 apka mogły zostać zaktualizowane.", - "other": "{} i {} innych apek mogło zostać zaktualizowanych." + "one": "{} i 1 inna apka mogły zostać zaktualizowane.", + "few": "{} i {} inne apki mogły zostać zaktualizowane.", + "many": "{} i {} innych apek mogło zostać zaktualizowanych.", + "other": "{} i {} inne apki mogły zostać zaktualizowane." }, "enableBackgroundUpdates": "Włącz aktualizacje w tle" -} +} \ No newline at end of file From f7e783a5565fbba4e43ca2e313ba64ffce3ebbab Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 27 Aug 2023 14:26:37 -0400 Subject: [PATCH 370/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 9cab1de..594dc7c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.0'; +const String currentVersion = '0.14.1'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 03537a2..d388e51 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.14.0+192 # When changing this, update the tag in main() accordingly +version: 0.14.1+193 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 0a6e1f9cc6c1e56fa63d5be114c05847429de2b2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 27 Aug 2023 15:43:17 -0400 Subject: [PATCH 371/600] Switch back to upstream package manager (from custom branch) --- pubspec.lock | 11 +++++------ pubspec.yaml | 5 +---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 0bd8a3c..b717324 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -29,12 +29,11 @@ packages: android_package_manager: dependency: "direct main" description: - path: "." - ref: master - resolved-ref: c7c2f992a9dc452393c94d96cdf2b1f5a5ce7c80 - url: "https://github.com/ImranR98/android_package_manager" - source: git - version: "0.5.4" + name: android_package_manager + sha256: b873fe5856f7c442aca9751dac05d117285be9e4de08eb15d1ffb811fd1b688d + url: "https://pub.dev" + source: hosted + version: "0.6.0" animations: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index d388e51..60254c0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -55,10 +55,7 @@ dependencies: git: url: https://github.com/ImranR98/android_package_installer ref: main - android_package_manager: - git: - url: https://github.com/ImranR98/android_package_manager - ref: master + android_package_manager: ^0.6.0 share_plus: ^7.0.0 android_alarm_manager_plus: ^3.0.0 sqflite: ^2.2.0+3 From d92e8125547482c0ddddafb6b66216abe17527d7 Mon Sep 17 00:00:00 2001 From: LucasTavaresA Date: Sun, 27 Aug 2023 18:25:26 -0300 Subject: [PATCH 372/600] Add brasilian translation --- assets/translations/br.json | 303 ++++++++++++++++++++++++++++++++++++ lib/main.dart | 1 + 2 files changed, 304 insertions(+) create mode 100644 assets/translations/br.json diff --git a/assets/translations/br.json b/assets/translations/br.json new file mode 100644 index 0000000..e7e828a --- /dev/null +++ b/assets/translations/br.json @@ -0,0 +1,303 @@ +{ + "invalidURLForSource": "URL {} inválida", + "noReleaseFound": "Não foi possivel encontrar uma versão adequada", + "noVersionFound": "Não foi possivel encontrar uma versão lançada", + "urlMatchesNoSource": "URL não corresponde a uma fonte conhecida", + "cantInstallOlderVersion": "Não pode instalar uma versão anterior de um App", + "appIdMismatch": "ID do pacote baixado não é igual ao ID do App instalado", + "functionNotImplemented": "Esta classe não implementou essa função", + "placeholder": "Espaço Reservado", + "someErrors": "Alguns Erros Ocorreram", + "unexpectedError": "Erro Inesperado", + "ok": "Ok", + "and": "e", + "githubPATLabel": "Token de Acceso Pessoal do GitHub (Reduz tempos de espera)", + "githubPATHint": "O TAP deve estar nesse formato: usuario:token", + "githubPATFormat": "usuario:token", + "includePrereleases": "Incluir pré-lançamentos", + "fallbackToOlderReleases": "Retornar para versões anteriores", + "filterReleaseTitlesByRegEx": "Filtrar Titulos de Versões por Expressão Regular", + "invalidRegEx": "Expressão Regular Inválida", + "noDescription": "Sem descrição", + "cancel": "Cancelar", + "continue": "Continuar", + "requiredInBrackets": "(Necessário)", + "dropdownNoOptsError": "ERRO: O DROPDOWN DEVE TER PELO MENOS UMA OPÇÃO", + "colour": "Cor", + "githubStarredRepos": "Favoritados no GitHub", + "uname": "Nome de usuário", + "wrongArgNum": "Número de argumentos errado", + "xIsTrackOnly": "{} é 'Apenas Seguir'", + "source": "Fonte", + "app": "App", + "appsFromSourceAreTrackOnly": "Os apps desta fonte são 'Apenas Seguir'.", + "youPickedTrackOnly": "Você selecionou a opção 'Apenas Seguir'.", + "trackOnlyAppDescription": "Esse App vai ser seguido por atualizações, mais o Obtainium não poderá baixa-lo ou instala-lo.", + "cancelled": "Cancelado", + "appAlreadyAdded": "App já adicionado", + "alreadyUpToDateQuestion": "App já atualizado?", + "addApp": "Adicionar App", + "appSourceURL": "URL de origem do App", + "error": "Erro", + "add": "Adicionar", + "searchSomeSourcesLabel": "Procurar (Apenas Algumas Fontes)", + "search": "Procurar", + "additionalOptsFor": "Opções Adicionais para {}", + "supportedSourcesBelow": "Fontes Compatíveis:", + "trackOnlyInBrackets": "(Apenas Seguir)", + "searchableInBrackets": "(Pesquisável)", + "appsString": "Apps", + "noApps": "Sem Apps", + "noAppsForFilter": "Sem Apps para Filtrar", + "byX": "Por {}", + "percentProgress": "Progresso: {}%", + "pleaseWait": "Por Favor Espere", + "updateAvailable": "Atualização Disponível", + "estimateInBracketsShort": "(Aprox.)", + "notInstalled": "Não Instalado", + "estimateInBrackets": "(Aproximado)", + "selectAll": "Selecionar All", + "deselectN": "Deselecionar {}", + "xWillBeRemovedButRemainInstalled": "{} sera removido do Obtainium mais permanecerá instalado no dispositivo.", + "removeSelectedAppsQuestion": "Remover Apps Selecionados?", + "removeSelectedApps": "Remover Apps Selecionados", + "updateX": "Atualizar {}", + "installX": "Instalar {}", + "markXTrackOnlyAsUpdated": "Marcar {}\n(Apenas Seguir)\ncomo Atualizado", + "changeX": "Mudar {}", + "installUpdateApps": "Instalar/Atualizar Apps", + "installUpdateSelectedApps": "Instalar/Atualizar Apps Selecionados", + "markXSelectedAppsAsUpdated": "Marcar {} Apps Delecionados como Atualizados?", + "no": "Não", + "yes": "Sim", + "markSelectedAppsUpdated": "Marcar Apps Selecionados como Atualizados", + "pinToTop": "Fixar no topo", + "unpinFromTop": "Desafixar do topo", + "resetInstallStatusForSelectedAppsQuestion": "Reiniciar Status de Instalação para Apps Seleciondos?", + "installStatusOfXWillBeResetExplanation": "O status de instalação de qualquer app selecionado sera reiniciado.\n\nIsso pode ajudar quando uma versão de um App mostrada no Obtainium é incorreta devido a falhas ao atualizar ou outros problemas.", + "shareSelectedAppURLs": "Compartilhar URLs de Apps Selecionados", + "resetInstallStatus": "Reiniciar Status de Instalação", + "more": "Mais", + "removeOutdatedFilter": "Remover Filtro de Apps Desatualizados", + "showOutdatedOnly": "Mostrar Apenas Apps Desatualizados", + "filter": "Filtro", + "filterActive": "Filtro *", + "filterApps": "Filtrar Apps", + "appName": "Nome do App", + "author": "Autor", + "upToDateApps": "Apps Atualizados", + "nonInstalledApps": "Apps Não Instalados", + "importExport": "Importar/Exportar", + "settings": "Configurações", + "exportedTo": "Exportado para {}", + "obtainiumExport": "Exportar Obtainium", + "invalidInput": "Input Inválido", + "importedX": "Importado {}", + "obtainiumImport": "Importar Obtainium", + "importFromURLList": "Importar de Lista de URLs", + "searchQuery": "Pesquisa", + "appURLList": "Lista de URLs de Apps", + "line": "Linha", + "searchX": "Pesquisa {}", + "noResults": "Nenhum resultado encontrado", + "importX": "Importar {}", + "importedAppsIdDisclaimer": "Apps Importados podem ser mostrados incorretamente como \"Não Instalado\".\nPara consertar, reinstale-os usando o Obtainium.\nIsso não deve afetar dados do App.\n\nAfeta apenas métodos de importação de URL e de terceiros.", + "importErrors": "Erros de Importação", + "importedXOfYApps": "{} de {} Apps importados.", + "followingURLsHadErrors": "As seguintes URLs apresentaram erros:", + "okay": "Ok", + "selectURL": "Selecionar URL", + "selectURLs": "Selecionar URLs", + "pick": "Escolher", + "theme": "Tema", + "dark": "Escuro", + "light": "Claro", + "followSystem": "Seguir o Sistema", + "obtainium": "Obtainium", + "materialYou": "Material You", + "useBlackTheme": "Usar tema preto completamente escuro", + "appSortBy": "Classificar App por", + "authorName": "Autor/Nome", + "nameAuthor": "Nome/Autor", + "asAdded": "Como Adicionado", + "appSortOrder": "Ordem de classificação de Apps", + "ascending": "Ascendente", + "descending": "Descendente", + "bgUpdateCheckInterval": "Intervalo de verificação de atualizações em segundo plano", + "neverManualOnly": "Nunca - Apenas Manual", + "appearance": "Aparência", + "showWebInAppView": "Mostrar páginas da internet em App view", + "pinUpdates": "Fixar atualizações no topo da visão de Apps", + "updates": "Atualizações", + "sourceSpecific": "Específico a fonte", + "appSource": "Fonte de Apps", + "noLogs": "Sem Logs", + "appLogs": "Logs do App", + "close": "Fechar", + "share": "Compartilhar", + "appNotFound": "App não encontrado", + "obtainiumExportHyphenatedLowercase": "obtainium-export", + "pickAnAPK": "Selecionar um APK", + "appHasMoreThanOnePackage": "{} tem mais de um pacote:", + "deviceSupportsXArch": "Seu dispositivo suporta a arquitetura de CPU {}.", + "deviceSupportsFollowingArchs": "Seu dispositivo suporta as seguintes arquiteturas de CPU:", + "warning": "Aviso", + "sourceIsXButPackageFromYPrompt": "A Fonte do App é '{}' mais o pacote lançado vem de '{}'. Continuar?", + "updatesAvailable": "Atualizações Disponíveis", + "updatesAvailableNotifDescription": "Notifica o usuário quando atualizações estão disponíveis um ou mais Apps seguidos pelo Obtainium", + "noNewUpdates": "Sem novas atualizações.", + "xHasAnUpdate": "{} tem uma atualização.", + "appsUpdated": "Apps Atualizados", + "appsUpdatedNotifDescription": "Notifica o usuário quando atualizações para um ou mais Apps foram aplicadas em segundo plano", + "xWasUpdatedToY": "{} foi atualizado para {}.", + "errorCheckingUpdates": "Erro ao Procurar por Atualizações", + "errorCheckingUpdatesNotifDescription": "Uma notificação que mostra quando a checagem por atualizações em segundo plano falha", + "appsRemoved": "Apps Removidos", + "appsRemovedNotifDescription": "Notifica o usuário quando um ou mais Apps foram removidos devido a erros ao carregá-los", + "xWasRemovedDueToErrorY": "{} foi removido devido a este erro: {}", + "completeAppInstallation": "Instalação completa do App", + "obtainiumMustBeOpenToInstallApps": "Obtainium deve estar aberto para instalar Apps", + "completeAppInstallationNotifDescription": "Pede ao usuário que retorne ao Obtainium para finalizar a instalação de um App", + "checkingForUpdates": "Checando por Atualizações", + "checkingForUpdatesNotifDescription": "Notificação transiente que aparece quando checando por atualizações", + "pleaseAllowInstallPerm": "Por favor, permita o Obtainium instalar Apps", + "trackOnly": "Apenas Seguir", + "errorWithHttpStatusCode": "Erro {}", + "versionCorrectionDisabled": "Correção de versão desativada (plugin parece não funcionar)", + "unknown": "Desconhecido", + "none": "Nenhum", + "never": "Nunca", + "latestVersionX": "Última versão: {}", + "installedVersionX": "Versão Instalada: {}", + "lastUpdateCheckX": "Última Checagem por Atualização: {}", + "remove": "Remover", + "yesMarkUpdated": "Sim, Marcar como Atualizado", + "fdroid": "F-Droid Official", + "appIdOrName": "ID do App ou Nome", + "appId": "ID do App", + "appWithIdOrNameNotFound": "Nenhum App foi encontrado com esse ID ou nome", + "reposHaveMultipleApps": "Repositórios podem conter multiplos Apps", + "fdroidThirdPartyRepo": "Repositórios de terceiros F-Droid", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Chat", + "install": "Instalar", + "markInstalled": "Marcar Instalado", + "update": "Atualizar", + "markUpdated": "Marcar Atualizado", + "additionalOptions": "Opções Adicionais", + "disableVersionDetection": "Desativar Detecção de Versão", + "noVersionDetectionExplanation": "Essa opção deve apenas ser usada por Apps onde detecção de versão não funciona corretamente.", + "downloadingX": "Baixando {}", + "downloadNotifDescription": "Notifica o usuário do progresso ao baixar um App", + "noAPKFound": "APK não encontrado", + "noVersionDetection": "Sem Detecção de versão", + "categorize": "Categorizar", + "categories": "Categorias", + "category": "Categoria", + "noCategory": "Sem Categoria", + "noCategories": "Sem Categoria", + "deleteCategoriesQuestion": "Deletar Categorias?", + "categoryDeleteWarning": "Todos os Apps em categorias removidas serão descategorizados.", + "addCategory": "Adicionar Categoria", + "label": "Etiqueta", + "language": "Linguagem", + "copiedToClipboard": "Copiado para a área de transferência", + "storagePermissionDenied": "Permição ao armazenamento negada", + "selectedCategorizeWarning": "Isso vai substituir qualquer confirução de categoria para os Apps selecionados.", + "filterAPKsByRegEx": "Filtrar APKs por Expressão Regular", + "removeFromObtainium": "Remover do Obtainium", + "uninstallFromDevice": "Desinstalar do dispositivo", + "onlyWorksWithNonVersionDetectApps": "Apenas funciona para Apps com detecção de versão desativada.", + "releaseDateAsVersion": "Usar Data de Lançamento como Versão", + "releaseDateAsVersionExplanation": "Esta opção só deve ser usada para aplicativos onde a detecção de versão não funciona corretamente, mas há uma data de lançamento disponível.", + "changes": "Mudanças", + "releaseDate": "Data de Lançamento", + "importFromURLsInFile": "Importar de URLs em Arquivo (como OPML)", + "versionDetection": "Detecção de Versão", + "standardVersionDetection": "Detecção de versão padrão", + "groupByCategory": "Agroupar por Categoria", + "autoApkFilterByArch": "Tente filtrar APKs por arquitetura de CPU, se possível", + "overrideSource": "Substituir Fonte", + "dontShowAgain": "Não mostrar isso novamente", + "dontShowTrackOnlyWarnings": "Não mostrar avisos 'Apenas Seguir'", + "dontShowAPKOriginWarnings": "Não mostrar avisos de origem da APK", + "moveNonInstalledAppsToBottom": "Mover Apps não instalados para o fundo da visão de Apps", + "gitlabPATLabel": "Token de Acceso Pessoal do Gitlab\n(Ativa Pesquisa e Melhor Descoberta de APKs)", + "about": "Sobre", + "requiresCredentialsInSettings": "Isso requer credenciais adicionais (em Configurações)", + "checkOnStart": "Checar por atualizações ao iniciar ", + "tryInferAppIdFromCode": "Tente inferir o ID do App pelo código fonte", + "removeOnExternalUninstall": "Remover automaticamente Apps desinstalados externamente", + "pickHighestVersionCode": "Auto-selecionar o maior numero de versão do APK", + "checkUpdateOnDetailPage": "Checar por atualizações ao abrir a pagina de detalhes de um App", + "disablePageTransitions": "Desativar animações de transição de pagina", + "reversePageTransitions": "Reverter animações de transição de pagina", + "minStarCount": "Contagem Minima de Estrelas", + "addInfoBelow": "Adicionar essa informação abaixo.", + "addInfoInSettings": "Adicionar essa informação nas configurações.", + "githubSourceNote": "A limitação de taxa do GitHub pode ser evitada usando uma chave de API.", + "gitlabSourceNote": "A extração de APK do GitLab pode não funcionar sem uma chave de API.", + "sortByFileNamesNotLinks": "Classifique por nomes de arquivos em vez de links completos", + "filterReleaseNotesByRegEx": "Filtrar Notas de Lançamento por Expressão Regular", + "customLinkFilterRegex": "Filtro de Link Personalizado por Expressão Regular (Padrão '.apk$')", + "appsPossiblyUpdated": "Tentativas de atualização de Apps", + "appsPossiblyUpdatedNotifDescription": "Notifica o usuário de que atualizações de um ou mais Apps foram potencialmente aplicadas em segundo plano", + "xWasPossiblyUpdatedToY": "{} pode ter sido atualizado para {}.", + "enableBackgroundUpdates": "Ativar atualizações em segundo plano", + "backgroundUpdateReqsExplanation": "Atualizações em segundo plano podem não ser possíveis para todos os Apps.", + "backgroundUpdateLimitsExplanation": "O sucesso de uma instalação em segundo plano só pode ser determinado quando o Obtainium é aberto.", + "verifyLatestTag": "Verifique a 'ultima' etiqueta", + "removeAppQuestion": { + "one": "Remover App?", + "other": "Remover Apps?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Muitas solicitações (taxa limitada) - tente novamente em {} minuto", + "other": "Muitas solicitações (taxa limitada) - tente novamente em {} minutos", + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "A verificação de atualizações em segundo plano encontrou um {}, agendada uma nova verificação em {} minuto", + "other": "A verificação de atualizações em segundo plano encontrou um {}, agendada uma nova verificação em {} minutos" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "A verificação de atualizações em segundo plano encontrou {} atualização, o usuário sera notificado caso necessário", + "other": "A verificação de atualizações em segundo plano encontrou {} atualizações, o usuário sera notificado caso necessário" + }, + "apps": { + "one": "{} App", + "other": "{} Apps" + }, + "url": { + "one": "{} URL", + "other": "{} URLs" + }, + "minute": { + "one": "{} Minuto", + "other": "{} Minutos" + }, + "hour": { + "one": "{} Hora", + "other": "{} Horas" + }, + "day": { + "one": "{} Dia", + "other": "{} Dias" + }, + "clearedNLogsBeforeXAfterY": { + "one": "Limpo {n} log (antes = {antes}, depois = {depois})", + "other": "Limpados {n} logs (antes = {antes}, depois = {depois})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "{} e 1 outro app tem atualizações.", + "other": "{} e {} outros apps tem atualizações." + }, + "xAndNMoreUpdatesInstalled": { + "one": "{} e 1 outro app foi atualizado.", + "other": "{} e {} outros apps foram atualizados." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "{} e 1 outro app pode ter sido atualizado.", + "other": "{} e {} outros apps podem ter sido atualizados." + } +} diff --git a/lib/main.dart b/lib/main.dart index 594dc7c..4570ff9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,6 +38,7 @@ List> supportedLocales = const [ MapEntry(Locale('pl'), 'Polski'), MapEntry(Locale('ru'), 'Русский язык'), MapEntry(Locale('bs'), 'Bosanski'), + MapEntry(Locale('br'), 'Brasileiro'), ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; From dcb8807fa741dc57488f8a53d7867ee469f018aa Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 28 Aug 2023 19:11:22 -0400 Subject: [PATCH 373/600] Add "Intermediate Link" option to HTML Source (#820) --- assets/translations/bs.json | 2 +- assets/translations/en.json | 4 +++- assets/translations/es.json | 2 +- assets/translations/fr.json | 2 +- assets/translations/hu.json | 2 +- assets/translations/it.json | 2 +- assets/translations/ru.json | 2 +- lib/app_sources/html.dart | 24 ++++++++++++++++++++++++ lib/app_sources/huaweiappgallery.dart | 3 ++- lib/app_sources/jenkins.dart | 3 ++- lib/providers/source_provider.dart | 11 +++++++++-- 11 files changed, 46 insertions(+), 11 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 830a3ac..9590708 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -240,7 +240,7 @@ "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", diff --git a/assets/translations/en.json b/assets/translations/en.json index e3a7684..d86d9a1 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -240,7 +240,7 @@ "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", @@ -248,6 +248,8 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", + "intermediateLinkNotFound": "Intermediate link not found", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index afe6e5e..a7968a7 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -240,7 +240,7 @@ "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 2ab4bb8..4f7e585 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -240,7 +240,7 @@ "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", diff --git a/assets/translations/hu.json b/assets/translations/hu.json index d30c802..8c3a71e 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -239,7 +239,7 @@ "gitlabSourceNote": "Előfordulhat, hogy a GitLab APK kibontása nem működik API-kulcs nélkül.", "sortByFileNamesNotLinks": "Fájlnevek szerinti elrendezés teljes linkek helyett", "filterReleaseNotesByRegEx": "Kiadási megjegyzések szűrése reguláris kifejezéssel", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", diff --git a/assets/translations/it.json b/assets/translations/it.json index b4d0359..75d5778 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -240,7 +240,7 @@ "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 703f057..6c91980 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -240,7 +240,7 @@ "gitlabSourceNote": "Извлечение APK из GitLab может не работать без ключа API.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom Link Filter by Regular Expression (Default '.apk$')", + "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 8df2add..753e3f1 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -103,7 +103,16 @@ class HTML extends AppSource { } ]) ], + [ + GeneratedFormTextField('intermediateLinkRegex', + label: tr('intermediateLinkRegex'), + hint: '([0-9]+\.)*[0-9]+/\$', + required: false, + additionalValidators: [(value) => regExValidator(value)]) + ] ]; + overrideVersionDetectionFormDefault('noVersionDetection', + disableStandard: true, disableRelDate: true); } @override @@ -132,6 +141,21 @@ class HTML extends AppSource { .map((element) => element.attributes['href'] ?? '') .toList(); List links = []; + if ((additionalSettings['intermediateLinkRegex'] as String?) + ?.isNotEmpty == + true) { + var reg = RegExp(additionalSettings['intermediateLinkRegex']); + links = allLinks.where((element) => reg.hasMatch(element)).toList(); + links.sort((a, b) => compareAlphaNumeric(a, b)); + if (links.isEmpty) { + throw ObtainiumError(tr('intermediateLinkNotFound')); + } + Map additionalSettingsTemp = + Map.from(additionalSettings); + additionalSettingsTemp['intermediateLinkRegex'] = null; + return getLatestAPKDetails( + ensureAbsoluteUrl(links.last, uri), additionalSettingsTemp); + } if ((additionalSettings['customLinkFilterRegex'] as String?) ?.isNotEmpty == true) { diff --git a/lib/app_sources/huaweiappgallery.dart b/lib/app_sources/huaweiappgallery.dart index 1a97774..76388e9 100644 --- a/lib/app_sources/huaweiappgallery.dart +++ b/lib/app_sources/huaweiappgallery.dart @@ -7,7 +7,8 @@ class HuaweiAppGallery extends AppSource { HuaweiAppGallery() { name = 'Huawei AppGallery'; host = 'appgallery.huawei.com'; - overrideVersionDetectionFormDefault('releaseDateAsVersion', true); + overrideVersionDetectionFormDefault('releaseDateAsVersion', + disableStandard: true); } @override diff --git a/lib/app_sources/jenkins.dart b/lib/app_sources/jenkins.dart index 2aa8853..9e5af8d 100644 --- a/lib/app_sources/jenkins.dart +++ b/lib/app_sources/jenkins.dart @@ -6,7 +6,8 @@ import 'package:obtainium/providers/source_provider.dart'; class Jenkins extends AppSource { Jenkins() { - overrideVersionDetectionFormDefault('releaseDateAsVersion', true); + overrideVersionDetectionFormDefault('releaseDateAsVersion', + disableStandard: true); } String trimJobUrl(String url) { diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 3371ee4..3611566 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -329,16 +329,23 @@ abstract class AppSource { name = runtimeType.toString(); } - overrideVersionDetectionFormDefault(String vd, bool disableStandard) { + overrideVersionDetectionFormDefault(String vd, + {bool disableStandard = false, bool disableRelDate = false}) { additionalAppSpecificSourceAgnosticSettingFormItems = additionalAppSpecificSourceAgnosticSettingFormItems.map((e) { return e.map((e2) { if (e2.key == 'versionDetection') { var item = e2 as GeneratedFormDropdown; item.defaultValue = vd; + item.disabledOptKeys = []; if (disableStandard) { - item.disabledOptKeys = ['standardVersionDetection']; + item.disabledOptKeys?.add('standardVersionDetection'); } + if (disableRelDate) { + item.disabledOptKeys?.add('releaseDateAsVersion'); + } + item.disabledOptKeys = + item.disabledOptKeys?.where((element) => element != vd).toList(); } return e2; }).toList(); From 075ecae540c1c78019dd7e2be00a75e46a9d6e07 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 28 Aug 2023 19:36:02 -0400 Subject: [PATCH 374/600] Re-add VLC with better error messaging when no mirror available (#821) --- lib/app_sources/vlc.dart | 63 +++++++++++++++++++++++------- lib/providers/source_provider.dart | 3 +- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/lib/app_sources/vlc.dart b/lib/app_sources/vlc.dart index 6787996..51adb7f 100644 --- a/lib/app_sources/vlc.dart +++ b/lib/app_sources/vlc.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:html/parser.dart'; import 'package:http/http.dart'; import 'package:obtainium/app_sources/html.dart'; @@ -41,27 +42,59 @@ class VLC extends AppSource { String standardUrl, Map additionalSettings, ) async { - String? version = await getLatestVersion(standardUrl); - if (version == null) { - throw NoVersionError(); - } - String? targetUrl = '$dwUrlBase$version/'; - Response res = await sourceRequest(targetUrl); - List apkUrls = []; + Response res = await get( + Uri.parse('https://www.videolan.org/vlc/download-android.html')); if (res.statusCode == 200) { - apkUrls = parse(res.body) + var dwUrlBase = 'get.videolan.org/vlc-android'; + var dwLinks = parse(res.body) .querySelectorAll('a') - .map((e) => e.attributes['href']?.split('/').last) - .where((h) => - h != null && h.isNotEmpty && h.toLowerCase().endsWith('.apk')) - .map((e) => targetUrl + e!) + .where((element) => + element.attributes['href']?.contains(dwUrlBase) ?? false) .toList(); + String? version = dwLinks.isNotEmpty + ? dwLinks.first.attributes['href'] + ?.split('/') + .where((s) => s.isNotEmpty) + .last + : null; + if (version == null) { + throw NoVersionError(); + } + + String? targetUrl = 'https://$dwUrlBase/$version/'; + Response res2 = await get(Uri.parse(targetUrl)); + List apkUrls = []; + if (res2.statusCode == 200) { + apkUrls = parse(res2.body) + .querySelectorAll('a') + .map((e) => e.attributes['href']?.split('/').last) + .where((h) => + h != null && h.isNotEmpty && h.toLowerCase().endsWith('.apk')) + .map((e) => targetUrl + e!) + .toList(); + } else if (res2.statusCode == 500 && + res2.body.toLowerCase().indexOf('mirror') > 0) { + var html = parse(res2.body); + var err = ''; + html.body?.nodes.forEach((element) { + if (element.text != null) { + err += '${element.text}\n'; + } + }); + err = err.trim(); + if (err.isEmpty) { + err = tr('err'); + } + throw ObtainiumError(err); + } else { + throw getObtainiumHttpError(res2); + } + + return APKDetails( + version, getApkUrlsFromUrls(apkUrls), AppNames('VideoLAN', 'VLC')); } else { throw getObtainiumHttpError(res); } - - return APKDetails( - version, getApkUrlsFromUrls(apkUrls), AppNames('VideoLAN', 'VLC')); } @override diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 3611566..9eef449 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -25,6 +25,7 @@ import 'package:obtainium/app_sources/sourceforge.dart'; import 'package:obtainium/app_sources/sourcehut.dart'; import 'package:obtainium/app_sources/steammobile.dart'; import 'package:obtainium/app_sources/telegramapp.dart'; +import 'package:obtainium/app_sources/vlc.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart'; @@ -523,7 +524,7 @@ class SourceProvider { // APKCombo(), // Can't get past their scraping blocking yet (get 403 Forbidden) Mullvad(), Signal(), - // VLC(), // As of 2023-08-26 this site randomly messes up the 'latest' version (one minute it's 3.5.4, next minute back to 3.5.3) + VLC(), // As of 2023-08-26 this site randomly messes up the 'latest' version (one minute it's 3.5.4, next minute back to 3.5.3) // WhatsApp(), // As of 2023-03-20 this is unusable as the version on the webpage is months out of date TelegramApp(), SteamMobile(), From 551643b11cf38b54d81bc18faef1c0be0ee56844 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 28 Aug 2023 19:51:49 -0400 Subject: [PATCH 375/600] More UI feedback when app updated (#814) --- lib/pages/app.dart | 5 +++++ lib/pages/apps.dart | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 710c3fb..45812d0 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -341,10 +341,15 @@ class _AppPageState extends State { app?.app.id != null ? [app!.app.id] : [], globalNavigatorKey.currentContext, settingsProvider); + if (app?.app.installedVersion != null && !trackOnly) { + // ignore: use_build_context_synchronously + showError(tr('appsUpdated'), context); + } if (res.isNotEmpty && mounted) { Navigator.of(context).pop(); } } catch (e) { + // ignore: use_build_context_synchronously showError(e, context); } } diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 41c0f7d..835be74 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -689,6 +689,10 @@ class AppsPageState extends State { .catchError((e) { showError(e, context); return []; + }).then((value) { + if (shouldInstallUpdates) { + showError(tr('appsUpdated'), context); + } }); } }); From bd8f608ee66e30cc4f8392b2f64719ee018d7c30 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 28 Aug 2023 20:02:09 -0400 Subject: [PATCH 376/600] Allow apps to be exempted from BG updates (#822) --- assets/translations/bs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/providers/apps_provider.dart | 3 +++ lib/providers/source_provider.dart | 6 +++++- 14 files changed, 20 insertions(+), 1 deletion(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 9590708..7a928a6 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -247,6 +247,7 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index cd31e8a..1c588a6 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -247,6 +247,7 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index d86d9a1..bbebf39 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -250,6 +250,7 @@ "verifyLatestTag": "Verify the 'latest' tag", "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", "intermediateLinkNotFound": "Intermediate link not found", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index a7968a7..95626c1 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -247,6 +247,7 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 5d7e754..b2bb37a 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -247,6 +247,7 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 4f7e585..0b0a4d3 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -247,6 +247,7 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 8c3a71e..80db119 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -246,6 +246,7 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "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 75d5778..addad9e 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -247,6 +247,7 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index e2d360c..1366fd0 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -248,6 +248,7 @@ "backgroundUpdateReqsExplanation": "バックグラウンドアップデートは、すべてのアプリで可能とは限りません。", "backgroundUpdateLimitsExplanation": "バックグラウンドアップデートが成功したかどうかは、Obtainiumを起動したときにしか判断できません。", "verifyLatestTag": "'latest'タグを確認する", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index e6ca53d..eacaa63 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -253,6 +253,7 @@ "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", "backgroundUpdateLimitsExplanation": "Powodzenie instalacji w tle można określić dopiero po otwarciu Obtainium.", "verifyLatestTag": "Zweryfikuj najnowszy tag", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 6c91980..48f47f3 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -247,6 +247,7 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 5ab313d..9457fe1 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -247,6 +247,7 @@ "enableBackgroundUpdates": "启用后台更新", "backgroundUpdateReqsExplanation": "后台更新未必适用于所有的应用。", "backgroundUpdateLimitsExplanation": "只有在启动 Obtainium 时才能确认安装是否成功。", + "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "verifyLatestTag": "验证“Latest”标签", "removeAppQuestion": { "one": "是否删除应用?", diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 5b673b6..08523c4 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -366,6 +366,9 @@ class AppsProvider with ChangeNotifier { if (!settingsProvider.enableBackgroundUpdates) { return false; } + if (app.additionalSettings['examptFromBackgroundUpdates'] == true) { + return false; + } if (app.apkUrls.length > 1) { // Manual API selection means silent install is not possible return false; diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 9eef449..e0e11e7 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -425,7 +425,11 @@ abstract class AppSource { GeneratedFormSwitch('autoApkFilterByArch', label: tr('autoApkFilterByArch'), defaultValue: true) ], - [GeneratedFormTextField('appName', label: tr('appName'), required: false)] + [GeneratedFormTextField('appName', label: tr('appName'), required: false)], + [ + GeneratedFormSwitch('examptFromBackgroundUpdates', + label: tr('examptFromBackgroundUpdates')) + ] ]; // Previous 2 variables combined into one at runtime for convenient usage From 8f739d9e0b2ac3c04d3348f0238b71d22182062a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 28 Aug 2023 20:24:15 -0400 Subject: [PATCH 377/600] WiFi only BG update toggle (#819) + typo fix --- assets/translations/bs.json | 3 ++- assets/translations/de.json | 3 ++- assets/translations/en.json | 3 ++- assets/translations/es.json | 3 ++- assets/translations/fa.json | 3 ++- assets/translations/fr.json | 3 ++- assets/translations/hu.json | 3 ++- assets/translations/it.json | 3 ++- assets/translations/ja.json | 3 ++- assets/translations/pl.json | 3 ++- assets/translations/ru.json | 3 ++- assets/translations/zh.json | 3 ++- lib/pages/settings.dart | 27 ++++++++++++++++++++++++++- lib/providers/apps_provider.dart | 14 +++++++++++--- lib/providers/settings_provider.dart | 9 +++++++++ lib/providers/source_provider.dart | 4 ++-- pubspec.lock | 24 ++++++++++++++++++++++++ pubspec.yaml | 1 + 18 files changed, 97 insertions(+), 18 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 7a928a6..533ad5a 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -247,7 +247,8 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 1c588a6..2233355 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -247,7 +247,8 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index bbebf39..afb64d2 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -250,7 +250,8 @@ "verifyLatestTag": "Verify the 'latest' tag", "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", "intermediateLinkNotFound": "Intermediate link not found", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 95626c1..6c07acc 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -247,7 +247,8 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index b2bb37a..a35fb49 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -247,7 +247,8 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 0b0a4d3..83a1d60 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -247,7 +247,8 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 80db119..54ca69b 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -246,7 +246,8 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "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 addad9e..210bce0 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -247,7 +247,8 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 1366fd0..fc11db1 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -248,7 +248,8 @@ "backgroundUpdateReqsExplanation": "バックグラウンドアップデートは、すべてのアプリで可能とは限りません。", "backgroundUpdateLimitsExplanation": "バックグラウンドアップデートが成功したかどうかは、Obtainiumを起動したときにしか判断できません。", "verifyLatestTag": "'latest'タグを確認する", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index eacaa63..e3c4d34 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -253,7 +253,8 @@ "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", "backgroundUpdateLimitsExplanation": "Powodzenie instalacji w tle można określić dopiero po otwarciu Obtainium.", "verifyLatestTag": "Zweryfikuj najnowszy tag", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 48f47f3..91c5572 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -247,7 +247,8 @@ "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 9457fe1..6ab56a0 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -247,8 +247,9 @@ "enableBackgroundUpdates": "启用后台更新", "backgroundUpdateReqsExplanation": "后台更新未必适用于所有的应用。", "backgroundUpdateLimitsExplanation": "只有在启动 Obtainium 时才能确认安装是否成功。", - "examptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "verifyLatestTag": "验证“Latest”标签", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index cd5ce5a..ec19efb 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -252,7 +252,32 @@ class _SettingsPageState extends State { style: Theme.of(context) .textTheme .labelSmall), - height8 + height8, + if (settingsProvider + .enableBackgroundUpdates) + Column( + children: [ + height16, + Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Flexible( + child: Text(tr( + 'bgUpdatesOnWiFiOnly'))), + Switch( + value: settingsProvider + .bgUpdatesOnWiFiOnly, + onChanged: (value) { + settingsProvider + .bgUpdatesOnWiFiOnly = + value; + }) + ], + ), + ], + ), ], ) : const SizedBox.shrink(); diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 08523c4..5017e26 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -9,6 +9,7 @@ import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; import 'package:android_intent_plus/flag.dart'; import 'package:android_package_installer/android_package_installer.dart'; import 'package:android_package_manager/android_package_manager.dart'; +import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -366,7 +367,7 @@ class AppsProvider with ChangeNotifier { if (!settingsProvider.enableBackgroundUpdates) { return false; } - if (app.additionalSettings['examptFromBackgroundUpdates'] == true) { + if (app.additionalSettings['exemptFromBackgroundUpdates'] == true) { return false; } if (app.apkUrls.length > 1) { @@ -1323,6 +1324,12 @@ Future bgUpdateCheck(int taskId, Map? params) async { // If in update mode... var didCompleteChecking = false; CheckingUpdatesNotification? notif; + var networkRestricted = false; + if (settingsProvider.bgUpdatesOnWiFiOnly) { + var netResult = await (Connectivity().checkConnectivity()); + networkRestricted = (netResult != ConnectivityResult.wifi) && + (netResult != ConnectivityResult.ethernet); + } // Loop through all updates and check each for (int i = 0; i < toCheck.length; i++) { var appId = toCheck[i].key; @@ -1335,8 +1342,9 @@ Future bgUpdateCheck(int taskId, Map? params) async { cancelExisting: true); App? newApp = await appsProvider.checkUpdate(appId); if (newApp != null) { - if (!(await appsProvider.canInstallSilently( - app!.app, settingsProvider))) { + if (networkRestricted || + !(await appsProvider.canInstallSilently( + app!.app, settingsProvider))) { notificationsProvider.notify( UpdateNotification([newApp], id: newApp.id.hashCode - 1)); } else { diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 7495c9b..0ccae4a 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -319,6 +319,15 @@ class SettingsProvider with ChangeNotifier { notifyListeners(); } + bool get bgUpdatesOnWiFiOnly { + return prefs?.getBool('bgUpdatesOnWiFiOnly') ?? false; + } + + set bgUpdatesOnWiFiOnly(bool val) { + prefs?.setBool('bgUpdatesOnWiFiOnly', val); + notifyListeners(); + } + DateTime get lastBGCheckTime { int? temp = prefs?.getInt('lastBGCheckTime'); return temp != null diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index e0e11e7..5494362 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -427,8 +427,8 @@ abstract class AppSource { ], [GeneratedFormTextField('appName', label: tr('appName'), required: false)], [ - GeneratedFormSwitch('examptFromBackgroundUpdates', - label: tr('examptFromBackgroundUpdates')) + GeneratedFormSwitch('exemptFromBackgroundUpdates', + label: tr('exemptFromBackgroundUpdates')) ] ]; diff --git a/pubspec.lock b/pubspec.lock index b717324..a9d3711 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -114,6 +114,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.2" + connectivity_plus: + dependency: "direct main" + description: + name: connectivity_plus + sha256: "77a180d6938f78ca7d2382d2240eb626c0f6a735d0bfdce227d8ffb80f95c48b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + connectivity_plus_platform_interface: + dependency: transitive + description: + name: connectivity_plus_platform_interface + sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a + url: "https://pub.dev" + source: hosted + version: "1.2.4" convert: dependency: transitive description: @@ -454,6 +470,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + nm: + dependency: transitive + description: + name: nm + sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" + url: "https://pub.dev" + source: hosted + version: "0.5.0" path: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 60254c0..3810687 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,6 +64,7 @@ dependencies: flutter_markdown: ^0.6.14 flutter_archive: ^5.0.0 hsluv: ^1.1.3 + connectivity_plus: ^4.0.2 dev_dependencies: flutter_test: From 408c1a541f34e56ff51e940d87e04e9c0514c3cd Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 28 Aug 2023 20:26:21 -0400 Subject: [PATCH 378/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 594dc7c..6be8e29 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.1'; +const String currentVersion = '0.14.2'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 3810687..ad5c919 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.14.1+193 # When changing this, update the tag in main() accordingly +version: 0.14.2+194 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From efd55c8d3647f2c18b87304b52e09e699527bc90 Mon Sep 17 00:00:00 2001 From: LucasTavaresA Date: Mon, 28 Aug 2023 22:10:54 -0300 Subject: [PATCH 379/600] Fix and update brasilian translation --- assets/translations/br.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/assets/translations/br.json b/assets/translations/br.json index e7e828a..dac26f4 100644 --- a/assets/translations/br.json +++ b/assets/translations/br.json @@ -248,13 +248,17 @@ "backgroundUpdateReqsExplanation": "Atualizações em segundo plano podem não ser possíveis para todos os Apps.", "backgroundUpdateLimitsExplanation": "O sucesso de uma instalação em segundo plano só pode ser determinado quando o Obtainium é aberto.", "verifyLatestTag": "Verifique a 'ultima' etiqueta", + "intermediateLinkRegex": "Filtre por um Link 'Intermediário' para Visitar Primeiro", + "intermediateLinkNotFound": "Link intermediário não encontrado", + "exemptFromBackgroundUpdates": "Isento de atualizações em segundo plano (se ativadas)", + "bgUpdatesOnWiFiOnly": "Desative atualizações em segundo plano quando não estiver em WiFi", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" }, "tooManyRequestsTryAgainInMinutes": { "one": "Muitas solicitações (taxa limitada) - tente novamente em {} minuto", - "other": "Muitas solicitações (taxa limitada) - tente novamente em {} minutos", + "other": "Muitas solicitações (taxa limitada) - tente novamente em {} minutos" }, "bgUpdateGotErrorRetryInMinutes": { "one": "A verificação de atualizações em segundo plano encontrou um {}, agendada uma nova verificação em {} minuto", From 4ba3f7996ed5ae0725f6c82d7b5aa98e835b4760 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 28 Aug 2023 22:08:37 -0400 Subject: [PATCH 380/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index dbc887e..2023b17 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.2'; +const String currentVersion = '0.14.3'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index ad5c919..657fa18 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.14.2+194 # When changing this, update the tag in main() accordingly +version: 0.14.3+195 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 486f3664efddf4d0b5090760408d1c86ceaab6b4 Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Tue, 29 Aug 2023 18:57:11 +0200 Subject: [PATCH 381/600] locale(pl): Update Polish translations --- assets/translations/pl.json | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index e3c4d34..0518562 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -246,15 +246,15 @@ "gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.", "sortByFileNamesNotLinks": "Sortuj wg nazw plików zamiast pełnych linków", "filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego", - "customLinkFilterRegex": "Niestandardowy filtr linków wg. wyrażenia regularnego (domyślnie \".apk$\")", + "customLinkFilterRegex": "Filtruj linki APK według wyrażenia regularnego (domyślnie \".apk$\")", "appsPossiblyUpdated": "Informuj o próbach aktualizacji", "appsPossiblyUpdatedNotifDescription": "Powiadamiaj o potencjalnym zastosowaniu w tle aktualizacji jednej lub większej ilości aplikacji", "xWasPossiblyUpdatedToY": "{} być może zaktualizowano do {}.", "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", "backgroundUpdateLimitsExplanation": "Powodzenie instalacji w tle można określić dopiero po otwarciu Obtainium.", "verifyLatestTag": "Zweryfikuj najnowszy tag", - "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", - "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)", + "bgUpdatesOnWiFiOnly": "Wyłącz aktualizacje w tle, gdy nie ma połączenia z Wi-Fi", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", @@ -327,5 +327,7 @@ "many": "{} i {} innych apek mogło zostać zaktualizowanych.", "other": "{} i {} inne apki mogły zostać zaktualizowane." }, - "enableBackgroundUpdates": "Włącz aktualizacje w tle" + "enableBackgroundUpdates": "Włącz aktualizacje w tle", + "intermediateLinkRegex": "Filtr linków \"pośrednich\" do odwiedzenia w pierwszej kolejności", + "intermediateLinkNotFound": "Nie znaleziono linku pośredniego" } \ No newline at end of file From 7a0acaefb3ef6f7b050fad8f63e94afb5764a954 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 29 Aug 2023 13:04:58 -0400 Subject: [PATCH 382/600] Disable BR lang. to unblock users (temp.) (#830) --- lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 2023b17..b7a1010 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,7 +38,7 @@ List> supportedLocales = const [ MapEntry(Locale('pl'), 'Polski'), MapEntry(Locale('ru'), 'Русский язык'), MapEntry(Locale('bs'), 'Bosanski'), - MapEntry(Locale('br'), 'Brasileiro'), + // MapEntry(Locale('br'), 'Brasileiro'), ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; From 11ca7c3f7dac154a3753b426e8da0ac9fc8aecf2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 29 Aug 2023 13:05:17 -0400 Subject: [PATCH 383/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index b7a1010..e047aa9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.3'; +const String currentVersion = '0.14.4'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 657fa18..ed0195b 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.14.3+195 # When changing this, update the tag in main() accordingly +version: 0.14.4+196 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From db2faf6511481677c1823510ae7c2bb5befbbce3 Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Wed, 30 Aug 2023 07:01:06 +0200 Subject: [PATCH 384/600] Update de.json updated newly added strings, added "APK" for the line "customLinkFilterRegex" which was added in other languages too. --- assets/translations/de.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 2233355..7cb5b45 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -240,15 +240,15 @@ "gitlabSourceNote": "GitLab APK-Extraktion funktioniert möglicherweise nicht ohne API-Schlüssel", "sortByFileNamesNotLinks": "Sortiere nach Dateinamen, anstelle von ganzen Links", "filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck filtern", - "customLinkFilterRegex": "Benutzerdefinierter Link Filter nach Regulärem Ausdruck (Standard '.apk$')", - "appsPossiblyUpdated": "App Updates Attempted", - "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", - "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", - "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", - "verifyLatestTag": "Verify the 'latest' tag", - "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", - "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "customLinkFilterRegex": "Benutzerdefinierter APK Link Filter nach Regulärem Ausdruck (Standard '.apk$')", + "appsPossiblyUpdated": "App Aktualisierungen wurden versucht", + "appsPossiblyUpdatedNotifDescription": "Benachrichtigt den Benutzer, dass Updates für eine oder mehrere Apps möglicherweise im Hintergrund durchgeführt wurden", + "xWasPossiblyUpdatedToY": "{} wurde möglicherweise aktualisiert auf {}.", + "backgroundUpdateReqsExplanation": "Die Hintergrundaktualisierung ist möglicherweise nicht für alle Apps möglich.", + "backgroundUpdateLimitsExplanation": "Der Erfolg einer Hintergrundinstallation kann nur festgestellt werden, wenn Obtainium geöffnet wird.", + "verifyLatestTag": "Überprüfe das 'latest' Tag", + "exemptFromBackgroundUpdates": "Ausschluss von Hintergrundaktualisierungen (falls aktiviert)", + "bgUpdatesOnWiFiOnly": "Hintergrundaktualisierungen deaktivieren, wenn kein WLAN vorhanden ist", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" @@ -298,7 +298,7 @@ "other": "{} und {} weitere Anwendungen wurden aktualisiert." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} and 1 more app may have been updated.", - "other": "{} and {} more apps may have been updated." + "one": "{} und 1 weitere Anwendung wurden möglicherweise aktualisiert.", + "other": "{} und {} weitere Anwendungen wurden möglicherweise aktualisiert." } } From 101d892c7f25e453689e2f0e94e9b740b9d4fff9 Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Wed, 30 Aug 2023 14:09:11 +0900 Subject: [PATCH 385/600] Update ja.json --- assets/translations/ja.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index fc11db1..5224933 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -248,8 +248,8 @@ "backgroundUpdateReqsExplanation": "バックグラウンドアップデートは、すべてのアプリで可能とは限りません。", "backgroundUpdateLimitsExplanation": "バックグラウンドアップデートが成功したかどうかは、Obtainiumを起動したときにしか判断できません。", "verifyLatestTag": "'latest'タグを確認する", - "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", - "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "exemptFromBackgroundUpdates": "バックグラウンドアップデートを行わない (有効な場合)", + "bgUpdatesOnWiFiOnly": "WiFiを使用していない場合,バックグラウンドアップデートを無効にする", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" @@ -300,6 +300,6 @@ }, "xAndNMoreUpdatesPossiblyInstalled": { "one": "{} とさらに 1 個のアプリがアップデートされた可能性があります", - "other": "{} とさらに {} 個のアプリがアップデートされた化膿性があります" + "other": "{} とさらに {} 個のアプリがアップデートされた可能性があります" } } From f7f0332b13b6d9ef629535296835ec12407291de Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 30 Aug 2023 18:41:34 -0400 Subject: [PATCH 386/600] VLC: Postpone mirror-dependent request to download time (#821) --- lib/app_sources/vlc.dart | 46 +++++++++++++++------------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/lib/app_sources/vlc.dart b/lib/app_sources/vlc.dart index 51adb7f..1c1adb8 100644 --- a/lib/app_sources/vlc.dart +++ b/lib/app_sources/vlc.dart @@ -60,36 +60,10 @@ class VLC extends AppSource { if (version == null) { throw NoVersionError(); } - String? targetUrl = 'https://$dwUrlBase/$version/'; - Response res2 = await get(Uri.parse(targetUrl)); - List apkUrls = []; - if (res2.statusCode == 200) { - apkUrls = parse(res2.body) - .querySelectorAll('a') - .map((e) => e.attributes['href']?.split('/').last) - .where((h) => - h != null && h.isNotEmpty && h.toLowerCase().endsWith('.apk')) - .map((e) => targetUrl + e!) - .toList(); - } else if (res2.statusCode == 500 && - res2.body.toLowerCase().indexOf('mirror') > 0) { - var html = parse(res2.body); - var err = ''; - html.body?.nodes.forEach((element) { - if (element.text != null) { - err += '${element.text}\n'; - } - }); - err = err.trim(); - if (err.isEmpty) { - err = tr('err'); - } - throw ObtainiumError(err); - } else { - throw getObtainiumHttpError(res2); - } - + var apkUrls = ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'] + .map((e) => '${targetUrl}VLC-Android-$version-$e.apk') + .toList(); return APKDetails( version, getApkUrlsFromUrls(apkUrls), AppNames('VideoLAN', 'VLC')); } else { @@ -108,6 +82,20 @@ class VLC extends AppSource { throw NoAPKError(); } return apkUrl; + } else if (res.statusCode == 500 && + res.body.toLowerCase().indexOf('mirror') > 0) { + var html = parse(res.body); + var err = ''; + html.body?.nodes.forEach((element) { + if (element.text != null) { + err += '${element.text}\n'; + } + }); + err = err.trim(); + if (err.isEmpty) { + err = tr('err'); + } + throw ObtainiumError(err); } else { throw getObtainiumHttpError(res); } From 59d1d275bc429f48454de91dd82bfcf9e0c46919 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 30 Aug 2023 18:41:55 -0400 Subject: [PATCH 387/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index e047aa9..8f5c38d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.4'; +const String currentVersion = '0.14.5'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index ed0195b..c32228b 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.14.4+196 # When changing this, update the tag in main() accordingly +version: 0.14.5+197 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 3d7df604b13791f543072290d9c1e81dbe85f80e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 30 Aug 2023 18:43:03 -0400 Subject: [PATCH 388/600] Upgrade packages --- pubspec.lock | 148 +++++++++++++++++++++++++-------------------------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index a9d3711..f6ddf37 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -38,10 +38,10 @@ packages: dependency: "direct main" description: name: animations - sha256: fe8a6bdca435f718bb1dc8a11661b2c22504c6da40ef934cee8327ed77934164 + sha256: ef57563eed3620bd5d75ad96189846aca1e033c0c45fc9a7d26e80ab02b88a70 url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "2.0.8" archive: dependency: transitive description: @@ -142,10 +142,10 @@ packages: dependency: transitive description: name: cross_file - sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + sha256: fd832b5384d0d6da4f6df60b854d33accaaeb63aa9e10e736a87381f08dee2cb url: "https://pub.dev" source: hosted - version: "0.3.3+4" + version: "0.3.3+5" crypto: dependency: transitive description: @@ -166,10 +166,10 @@ packages: dependency: "direct main" description: name: cupertino_icons - sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.6" dbus: dependency: transitive description: @@ -246,10 +246,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: bdfa035a974a0c080576c4c8ed01cdf9d1b406a04c7daa05443ef0383a97bedc + sha256: be325344c1f3070354a1d84a231a1ba75ea85d413774ec4bdf444c023342e030 url: "https://pub.dev" source: hosted - version: "5.3.4" + version: "5.5.0" flutter: dependency: "direct main" description: flutter @@ -283,10 +283,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.0.3" flutter_local_notifications: dependency: "direct main" description: @@ -320,18 +320,18 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: "2b206d397dd7836ea60035b2d43825c8a303a76a5098e66f42d55a753e18d431" + sha256: d4a1cb250c4e059586af0235f32e02882860a508e189b61f2b31b8810c1e1330 url: "https://pub.dev" source: hosted - version: "0.6.17+1" + version: "0.6.17+2" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360" + sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.0.16" flutter_test: dependency: "direct dev" description: flutter @@ -490,50 +490,50 @@ packages: dependency: "direct main" description: name: path_provider - sha256: "909b84830485dbcd0308edf6f7368bc8fd76afa26a270420f34cabea2a6467a0" + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "5d44fc3314d969b84816b569070d7ace0f1dea04bd94a83f74c4829615d22ad8" + sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.2.0" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "1b744d3d774e5a879bb76d6cd1ecee2ba2c6960c03b1020cd35212f6aa267ac5" + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3 + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84 + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" permission_handler: dependency: "direct main" description: @@ -546,10 +546,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: "2ffaf52a21f64ac9b35fe7369bb9533edbd4f698e5604db8645b1064ff4cf221" + sha256: d74e77a5ecd38649905db0a7d05ef16bed42ff263b9efb73ed794317c5764ec3 url: "https://pub.dev" source: hosted - version: "10.3.3" + version: "10.3.4" permission_handler_apple: dependency: transitive description: @@ -586,18 +586,18 @@ packages: dependency: transitive description: name: platform - sha256: "57c07bf82207aee366dfaa3867b3164e4f03a238a461a11b0e8a3a510d51203d" + sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" + sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.1.6" pointycastle: dependency: transitive description: @@ -634,58 +634,58 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "0344316c947ffeb3a529eac929e1978fcd37c26be4e8468628bac399365a3ca1" + sha256: b7f41bad7e521d205998772545de63ff4e6c97714775902c199353f8bf1511ac url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: fe8401ec5b6dcd739a0fe9588802069e608c3fdbfd3c3c93e546cf2f90438076 + sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: d29753996d8eb8f7619a1f13df6ce65e34bc107bef6330739ed76f18b22310ef + sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.3.4" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "71d6806d1449b0a9d4e85e0c7a917771e672a3d5dc61149cc9fac871115018e1" + sha256: c2eb5bf57a2fe9ad6988121609e47d3e07bb3bdca5b6f8444e4cf302428a128a url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "23b052f17a25b90ff2b61aad4cc962154da76fb62848a9ce088efe30d7c50ab1" + sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "7347b194fb0bbeb4058e6a4e87ee70350b6b2b90f8ac5f8bd5b3a01548f6d33a" + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: f95e6a43162bce43c9c3405f3eb6f39e5b5d11f65fab19196cf8225e2777624d + sha256: f763a101313bd3be87edffe0560037500967de9c394a714cd598d945517f694f url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.1" sky_engine: dependency: transitive description: flutter @@ -783,66 +783,66 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e" + sha256: "38d8e783681bc342e92dc9799cbe4421d08c4d210a67ee9d61d0f7310491a465" url: "https://pub.dev" source: hosted - version: "6.1.12" + version: "6.1.13" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "3dd2388cc0c42912eee04434531a26a82512b9cb1827e0214430c9bcbddfe025" + sha256: ef7e34951ffa963fb7a65928deeb38d40fb3c5975baf93c1d631341ff7f2650a url: "https://pub.dev" source: hosted - version: "6.0.38" + version: "6.0.39" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "6.1.5" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" + sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.0.6" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1" + sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88 url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.0.7" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea + sha256: "4d0dae953f80dc06fa24c58d0f8381302139c22c2dad301417787ad96f5f73bd" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4 + sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5" url: "https://pub.dev" source: hosted - version: "2.0.18" + version: "2.0.20" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422" + sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069" url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "3.0.8" uuid: dependency: transitive description: @@ -871,34 +871,34 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: "04a0782fb058b7c71f2048935583488f4d32e9147ca403abc4e58f1de9964629" + sha256: "82f6787d5df55907aa01e49bd9644f4ed1cc82af7a8257dd9947815959d2e755" url: "https://pub.dev" source: hosted - version: "4.2.3" + version: "4.2.4" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: bca797abba472868655b5f1a6029c1132385685ee9db4713cb0e7f33076210c6 + sha256: "8545719bbf06f5c4b850f0d5f86da1fe837b1953c56b9af579a26be73627c98d" url: "https://pub.dev" source: hosted - version: "3.9.3" + version: "3.9.4" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "0ca3cfcc6781a7de701d580917af4a9efc4e3e129f8ead95a80587f0a749480a" + sha256: "9d32a63a5ee111b37482cb3eac3379b9f0992afd27a52ee30279dbf06f41918b" url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.5.1" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - sha256: ed749f94ac9e814d04a258a9255cf69cfa4cc6006ff59542aea7fb4590144972 + sha256: d2f7241849582da80b79acb03bb936422412ce5c0c79fb5f6a1de5421a5aecc4 url: "https://pub.dev" source: hosted - version: "3.7.3" + version: "3.7.4" win32: dependency: transitive description: @@ -919,10 +919,10 @@ packages: dependency: transitive description: name: xdg_directories - sha256: f0c26453a2d47aa4c2570c6a033246a3fc62da2fe23c7ffdd0a7495086dc0247 + sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.0.3" xml: dependency: transitive description: @@ -940,5 +940,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" - flutter: ">=3.10.0" + dart: ">=3.1.0 <4.0.0" + flutter: ">=3.13.0" From 370ec1432e1ceaddcb25da3c4de4022e14fa45bd Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 30 Aug 2023 21:40:05 -0400 Subject: [PATCH 389/600] Fix BG update OS requirement --- lib/providers/apps_provider.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 5017e26..febf2df 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -393,7 +393,7 @@ class AppsProvider with ChangeNotifier { (await getInstalledInfo(app.id))?.applicationInfo?.targetSdkVersion; // The OS must also be new enough and the APK should target a new enough API - return osInfo.version.sdkInt >= 30 && + return osInfo.version.sdkInt >= 31 && targetSDK != null && targetSDK >= // https://developer.android.com/reference/android/content/pm/PackageInstaller.SessionParams#setRequireUserAction(int) (osInfo.version.sdkInt - 3); From 73a3c7eb715111b177d02b3ece8786c4b756c121 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 30 Aug 2023 21:41:26 -0400 Subject: [PATCH 390/600] Temporarily exclude Obtainium from BG updates (#836) --- lib/providers/apps_provider.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index febf2df..e6b87df 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -364,6 +364,9 @@ class AppsProvider with ChangeNotifier { Future canInstallSilently( App app, SettingsProvider settingsProvider) async { + if (app.id == obtainiumId) { + return false; + } if (!settingsProvider.enableBackgroundUpdates) { return false; } From 01f9003b8df9e5f6e8be7f2a9dd68e96232c87b6 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 30 Aug 2023 22:07:30 -0400 Subject: [PATCH 391/600] Group update notifications into one (#829) --- lib/providers/apps_provider.dart | 120 ++++++++++++++++--------------- 1 file changed, 64 insertions(+), 56 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index e6b87df..057b887 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1334,67 +1334,75 @@ Future bgUpdateCheck(int taskId, Map? params) async { (netResult != ConnectivityResult.ethernet); } // Loop through all updates and check each - for (int i = 0; i < toCheck.length; i++) { - var appId = toCheck[i].key; - var retryCount = toCheck[i].value; - AppInMemory? app = appsProvider.apps[appId]; - if (app?.app.installedVersion != null) { - try { - notificationsProvider.notify( - notif = CheckingUpdatesNotification(app?.name ?? appId), - cancelExisting: true); - App? newApp = await appsProvider.checkUpdate(appId); - if (newApp != null) { - if (networkRestricted || - !(await appsProvider.canInstallSilently( - app!.app, settingsProvider))) { - notificationsProvider.notify( - UpdateNotification([newApp], id: newApp.id.hashCode - 1)); + List toNotify = []; + try { + for (int i = 0; i < toCheck.length; i++) { + var appId = toCheck[i].key; + var retryCount = toCheck[i].value; + AppInMemory? app = appsProvider.apps[appId]; + if (app?.app.installedVersion != null) { + try { + notificationsProvider.notify( + notif = CheckingUpdatesNotification(app?.name ?? appId), + cancelExisting: true); + App? newApp = await appsProvider.checkUpdate(appId); + if (newApp != null) { + if (networkRestricted || + !(await appsProvider.canInstallSilently( + app!.app, settingsProvider))) { + toNotify.add(newApp); + } else { + toInstall.add(MapEntry(appId, 0)); + } + } + if (i == (toCheck.length - 1)) { + didCompleteChecking = true; + } + } catch (e) { + // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue checking shortly + logs.add( + 'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.'); + if (retryCount < maxAttempts) { + var remainingSeconds = e is RateLimitError + ? (i == 0 ? (e.remainingMinutes * 60) : (5 * 60)) + : e is ClientException + ? (15 * 60) + : (retryCount ^ 2); + logs.add( + 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); + var remainingToCheck = moveStrToEndMapEntryWithCount( + toCheck.sublist(i), MapEntry(appId, retryCount + 1)); + AndroidAlarmManager.oneShot(Duration(seconds: remainingSeconds), + taskId + 1, bgUpdateCheck, + params: { + 'toCheck': remainingToCheck + .map( + (entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + 'toInstall': toInstall + .map( + (entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + }); + break; } else { - toInstall.add(MapEntry(appId, 0)); + // If the offender has reached its fail limit, notify the user and remove it from the list (task can continue) + toCheck.removeAt(i); + i--; + notificationsProvider + .notify(ErrorCheckingUpdatesNotification(e.toString())); + } + } finally { + if (notif != null) { + notificationsProvider.cancel(notif.id); } } - if (i == (toCheck.length - 1)) { - didCompleteChecking = true; - } - } catch (e) { - // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue checking shortly - logs.add( - 'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.'); - if (retryCount < maxAttempts) { - var remainingSeconds = e is RateLimitError - ? (i == 0 ? (e.remainingMinutes * 60) : (5 * 60)) - : e is ClientException - ? (15 * 60) - : (retryCount ^ 2); - logs.add( - 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); - var remainingToCheck = moveStrToEndMapEntryWithCount( - toCheck.sublist(i), MapEntry(appId, retryCount + 1)); - AndroidAlarmManager.oneShot( - Duration(seconds: remainingSeconds), taskId + 1, bgUpdateCheck, - params: { - 'toCheck': remainingToCheck - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - 'toInstall': toInstall - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - }); - break; - } else { - // If the offender has reached its fail limit, notify the user and remove it from the list (task can continue) - toCheck.removeAt(i); - i--; - notificationsProvider - .notify(ErrorCheckingUpdatesNotification(e.toString())); - } - } finally { - if (notif != null) { - notificationsProvider.cancel(notif.id); - } } } + } finally { + if (toNotify.isNotEmpty) { + notificationsProvider.notify(UpdateNotification(toNotify)); + } } // If you're done checking and found some silently installable updates, schedule another task which will run in install mode if (didCompleteChecking && toInstall.isNotEmpty) { From 9af2c8370d134e7dac38daeba428e802d864c92a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 30 Aug 2023 22:34:12 -0400 Subject: [PATCH 392/600] Bugfix: BG update fail leads to infinite retries (#838) --- lib/providers/apps_provider.dart | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 057b887..cad3b2f 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -4,6 +4,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'dart:math'; import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; import 'package:android_intent_plus/flag.dart'; @@ -116,16 +117,19 @@ moveStrToEnd(List arr, String str, {String? strB}) { return arr; } -moveStrToEndMapEntryWithCount( +List> moveStrToEndMapEntryWithCount( List> arr, MapEntry str, {MapEntry? strB}) { MapEntry? temp; arr.removeWhere((element) { - bool res = element.key == str.key || element.key == strB?.key; - if (res) { - temp = element; + bool resA = element.key == str.key; + bool resB = element.key == strB?.key; + if (resA) { + temp = str; + } else if (resB) { + temp = strB; } - return res; + return resA || resB; }); if (temp != null) { arr = [...arr, temp!]; @@ -1338,7 +1342,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { try { for (int i = 0; i < toCheck.length; i++) { var appId = toCheck[i].key; - var retryCount = toCheck[i].value; + var attemptCount = toCheck[i].value + 1; AppInMemory? app = appsProvider.apps[appId]; if (app?.app.installedVersion != null) { try { @@ -1362,16 +1366,16 @@ Future bgUpdateCheck(int taskId, Map? params) async { // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue checking shortly logs.add( 'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.'); - if (retryCount < maxAttempts) { + if (attemptCount < maxAttempts) { var remainingSeconds = e is RateLimitError ? (i == 0 ? (e.remainingMinutes * 60) : (5 * 60)) : e is ClientException ? (15 * 60) - : (retryCount ^ 2); + : pow(attemptCount, 2).toInt(); logs.add( 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); var remainingToCheck = moveStrToEndMapEntryWithCount( - toCheck.sublist(i), MapEntry(appId, retryCount + 1)); + toCheck.sublist(i), MapEntry(appId, attemptCount)); AndroidAlarmManager.oneShot(Duration(seconds: remainingSeconds), taskId + 1, bgUpdateCheck, params: { From 8b01fc03eccb706203354870420a4b7c521a0eac Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 30 Aug 2023 22:35:11 -0400 Subject: [PATCH 393/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8f5c38d..fb3a711 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.5'; +const String currentVersion = '0.14.6'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index c32228b..61b3d06 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.14.5+197 # When changing this, update the tag in main() accordingly +version: 0.14.6+198 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From ebe256e482708249eaa6b0e61574749fec5586ed Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:05:49 -0400 Subject: [PATCH 394/600] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..9dc3ec4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,29 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Screenshots and Logs** +If applicable, add screenshots, logs, and any other artifacts (like some/all files under `/Android/data/dev.imranr.obtainium/`) that you think may help troubleshoot the issue. + +**Please complete the following information:** + - Device: [e.g. Pixel 7] + - OS: [e.g. GrapheneOS] + - Obtainium Version [e.g. 0.14.6-beta] + +**Additional context** +Add any other context about the problem here. From f5a9eb4295755927c36348efdea15032ff2a8352 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:13:04 -0400 Subject: [PATCH 395/600] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 9dc3ec4..23aff72 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,8 +1,8 @@ --- name: Bug report -about: Create a report to help us improve +about: Something isn't working right title: '' -labels: bug +labels: bug, To Check assignees: '' --- From 9cc25fd93186a15b6f1898588d6defc0cf5dab95 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:18:42 -0400 Subject: [PATCH 396/600] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 7 +++++-- .github/ISSUE_TEMPLATE/feature_request.md | 24 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 23aff72..a464de1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,19 +1,22 @@ --- name: Bug report -about: Something isn't working right +about: Something isn't working right. title: '' labels: bug, To Check assignees: '' --- +**Prerequisites** +Please ensure your request is not part of an existing issue. + **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' -2. Click on '....' +2. Tap on '....' 3. Scroll down to '....' 4. See error diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..53baa22 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,24 @@ +--- +name: Feature request +about: Suggest a new Source, setting, or other feature. +title: '' +labels: enhancement, To Check +assignees: '' + +--- + +**Prerequisites** +Please ensure your request is not part of an existing issue. + +**Describe the feature** +A clear and concise description of what you want to happen. + +For new Sources, it's preferable (not required) if you suggest how an App ID (or any release-specific identifier), App version, and APK URL(s) could be scraped from the Source. + +**Describe alternatives you've considered (if applicable)** +A clear and concise description of any alternative solutions or features you've considered. + +Note that app-specific Sources are less likely to be added. In those cases, see if the HTML Source will work for you (if not, see if a generally-applicable enhancement to the HTML Source would work, and suggest that instead). + +**Additional context** +Add any other context or screenshots about the feature request here. From dda5619cdc3c62ba2a25e9912d739c2fbac0d310 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:25:53 -0400 Subject: [PATCH 397/600] Update issue templates --- .github/ISSUE_TEMPLATE/feature_request.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 53baa22..b106d0f 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -13,7 +13,12 @@ Please ensure your request is not part of an existing issue. **Describe the feature** A clear and concise description of what you want to happen. -For new Sources, it's preferable (not required) if you suggest how an App ID (or any release-specific identifier), App version, and APK URL(s) could be scraped from the Source. +For new Sources, it's preferable (not required) if you suggest how the following details can be extracted from the Source in a reliable way (like an API or through web scraping): +- The App version (or any release-specific identifier - a "pseudo-version") for the latest release +- One or more APK URL(s) for the latest release +- Above details for previous releases (optional) + +Note that the Web scraper cannot deal with JavaScript-enabled content. **Describe alternatives you've considered (if applicable)** A clear and concise description of any alternative solutions or features you've considered. From 8c63920ef63a8fc8561f0cd562b7ebbb2082e822 Mon Sep 17 00:00:00 2001 From: gidano Date: Sat, 2 Sep 2023 15:41:10 +0200 Subject: [PATCH 398/600] Update hu.json --- assets/translations/hu.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 54ca69b..322543a 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -87,7 +87,7 @@ "author": "Szerző", "upToDateApps": "Naprakész appok", "nonInstalledApps": "Nem telepített appok", - "importExport": "Importálás/Exportálás", + "importExport": "Import/Export", "settings": "Beállítások", "exportedTo": "Exportálva ide {}", "obtainiumExport": "Obtainium Adat Exportálás", @@ -137,7 +137,7 @@ "share": "Megosztás", "appNotFound": "App nem található", "obtainiumExportHyphenatedLowercase": "obtainium-export", - "pickAnAPK": "Válasszon egy APK-ot", + "pickAnAPK": "Válasszon egy APK-t", "appHasMoreThanOnePackage": "A(z) {} egynél több csomaggal rendelkezik:", "deviceSupportsXArch": "Eszköze támogatja a {} CPU architektúrát.", "deviceSupportsFollowingArchs": "Az eszköze a következő CPU architektúrákat támogatja:", @@ -204,7 +204,7 @@ "copiedToClipboard": "Másolva a vágólapra", "storagePermissionDenied": "Tárhely engedély megtagadva", "selectedCategorizeWarning": "Ez felváltja a kiválasztott alkalmazások meglévő kategória-beállításait.", - "filterAPKsByRegEx": "Az APK-ok szűrése reguláris kifejezéssel", + "filterAPKsByRegEx": "Az APK-k szűrése reguláris kifejezéssel", "removeFromObtainium": "Eltávolítás az Obtainiumból", "uninstallFromDevice": "Eltávolítás a készülékről", "onlyWorksWithNonVersionDetectApps": "Csak azoknál az alkalmazásoknál működik, amelyeknél a verzióérzékelés le van tiltva.", @@ -239,15 +239,15 @@ "gitlabSourceNote": "Előfordulhat, hogy a GitLab APK kibontása nem működik API-kulcs nélkül.", "sortByFileNamesNotLinks": "Fájlnevek szerinti elrendezés teljes linkek helyett", "filterReleaseNotesByRegEx": "Kiadási megjegyzések szűrése reguláris kifejezéssel", - "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", - "appsPossiblyUpdated": "App Updates Attempted", - "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", - "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", - "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", - "verifyLatestTag": "Verify the 'latest' tag", - "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", - "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "customLinkFilterRegex": "Egyéni APK hivatkozásszűrő reguláris kifejezéssel (Alapérték '.apk$')", + "appsPossiblyUpdated": "App frissítési kísérlet", + "appsPossiblyUpdatedNotifDescription": "Értesíti a felhasználót, hogy egy vagy több alkalmazás frissítése lehetséges a háttérben", + "xWasPossiblyUpdatedToY": "{} frissítve lehet erre {}.", + "backgroundUpdateReqsExplanation": "Előfordulhat, hogy nem minden appnál lehetséges a háttérbeli frissítés.", + "backgroundUpdateLimitsExplanation": "A háttérben történő telepítés sikeressége csak az Obtainium megnyitásakor állapítható meg.", + "verifyLatestTag": "Ellenőrizze a „legújabb” címkét", + "exemptFromBackgroundUpdates": "Mentes a háttérben történő frissítések alól (ha engedélyezett)", + "bgUpdatesOnWiFiOnly": "Tiltsa le a háttérben frissítéseket, ha nincs Wi-Fi-n", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" @@ -297,7 +297,7 @@ "other": "{} és {} további alkalmazás frissítve." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} and 1 more app may have been updated.", - "other": "{} and {} more apps may have been updated." + "one": "{} és 1 további alkalmazás is frissült.", + "other": "{} és {} további alkalmazás is frissült." } } From 75a8dc9ee4612f58241e9b7bce2529a3878ecdab Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 2 Sep 2023 21:28:30 -0400 Subject: [PATCH 399/600] Add Aptoide as a Source (#843) --- README.md | 1 + lib/app_sources/aptoide.dart | 104 +++++++++++++++++++++++++++++ lib/providers/source_provider.dart | 9 ++- 3 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 lib/app_sources/aptoide.dart diff --git a/README.md b/README.md index 915d851..cf57007 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Currently supported App sources: - [Signal](https://signal.org/) - [SourceForge](https://sourceforge.net/) - [SourceHut](https://git.sr.ht/) +- [Aptoide](https://aptoide.com/) - [APKMirror](https://apkmirror.com/) (Track-Only) - [APKPure](https://apkpure.com/) - [Huawei AppGallery](https://appgallery.huawei.com/) diff --git a/lib/app_sources/aptoide.dart b/lib/app_sources/aptoide.dart new file mode 100644 index 0000000..0b7f3f4 --- /dev/null +++ b/lib/app_sources/aptoide.dart @@ -0,0 +1,104 @@ +import 'dart:convert'; + +import 'package:easy_localization/easy_localization.dart'; +import 'package:html/parser.dart'; +import 'package:http/http.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class Aptoide extends AppSource { + Aptoide() { + host = 'aptoide.com'; + name = tr('Aptoide'); + allowSubDomains = true; + } + + @override + String sourceSpecificStandardizeURL(String url) { + RegExp standardUrlRegEx = RegExp('^https?://([^\\.]+\\.){2,}$host'); + RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); + if (match == null) { + throw InvalidURLError(name); + } + return url.substring(0, match.end); + } + + @override + Future tryInferringAppId(String standardUrl, + {Map additionalSettings = const {}}) async { + return (await getLatestAPKDetails(standardUrl, additionalSettings)).version; + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + var res = await sourceRequest(standardUrl); + if (res.statusCode != 200) { + throw getObtainiumHttpError(res); + } + var idMatch = RegExp('"app":{"id":[0-9]+').firstMatch(res.body); + String? id; + if (idMatch != null) { + id = res.body.substring(idMatch.start + 12, idMatch.end); + } else { + throw NoReleasesError(); + } + var res2 = + await sourceRequest('https://ws2.aptoide.com/api/7/getApp/app_id/$id'); + if (res2.statusCode != 200) { + throw getObtainiumHttpError(res); + } + var appDetails = jsonDecode(res2.body)?['nodes']?['meta']?['data']; + String appName = appDetails?['name'] ?? tr('app'); + String author = appDetails?['developer']?['name'] ?? name; + String? dateStr = appDetails?['updated']; + String? version = appDetails?['file']?['vername']; + String? apkUrl = appDetails?['file']?['path']; + if (version == null) { + throw NoVersionError(); + } + if (apkUrl == null) { + throw NoAPKError(); + } + DateTime? relDate; + if (dateStr != null) { + relDate = DateTime.parse(dateStr); + } + + return APKDetails( + version, getApkUrlsFromUrls([apkUrl]), AppNames(author, appName), + releaseDate: relDate); + } + + @override + Future>> search(String query, + {Map querySettings = const {}}) async { + Response res = await sourceRequest( + 'https://search.$host/?q=${Uri.encodeQueryComponent(query)}'); + if (res.statusCode == 200) { + Map> urlsWithDescriptions = {}; + parse(res.body).querySelectorAll('.package-header').forEach((e) { + String? url = e.attributes['href']; + if (url != null) { + try { + standardizeUrl(url); + } catch (e) { + url = null; + } + } + if (url != null) { + urlsWithDescriptions[url] = [ + e.querySelector('.package-name')?.text.trim() ?? '', + e.querySelector('.package-summary')?.text.trim() ?? + tr('noDescription') + ]; + } + }); + return urlsWithDescriptions; + } else { + throw getObtainiumHttpError(res); + } + } +} diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 5494362..c9433b7 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -9,6 +9,7 @@ import 'package:html/dom.dart'; import 'package:http/http.dart'; import 'package:obtainium/app_sources/apkmirror.dart'; import 'package:obtainium/app_sources/apkpure.dart'; +import 'package:obtainium/app_sources/aptoide.dart'; import 'package:obtainium/app_sources/codeberg.dart'; import 'package:obtainium/app_sources/fdroid.dart'; import 'package:obtainium/app_sources/fdroidrepo.dart'; @@ -325,6 +326,7 @@ abstract class AppSource { bool enforceTrackOnly = false; bool changeLogIfAnyIsMarkDown = true; bool appIdInferIsOptional = false; + bool allowSubDomains = false; AppSource() { name = runtimeType.toString(); @@ -522,13 +524,14 @@ class SourceProvider { Jenkins(), SourceForge(), SourceHut(), + Aptoide(), APKMirror(), APKPure(), HuaweiAppGallery(), // APKCombo(), // Can't get past their scraping blocking yet (get 403 Forbidden) Mullvad(), Signal(), - VLC(), // As of 2023-08-26 this site randomly messes up the 'latest' version (one minute it's 3.5.4, next minute back to 3.5.3) + VLC(), // WhatsApp(), // As of 2023-03-20 this is unusable as the version on the webpage is months out of date TelegramApp(), SteamMobile(), @@ -554,7 +557,9 @@ class SourceProvider { } AppSource? source; for (var s in sources.where((element) => element.host != null)) { - if (RegExp('://${s.host}(/|\\z)?').hasMatch(url)) { + if (RegExp( + '://${s.allowSubDomains ? '([^\\.]+\\.)*' : ''}${s.host}(/|\\z)?') + .hasMatch(url)) { source = s; break; } From 52d19f267ed57f4b7ad825153823e7590406eed6 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 3 Sep 2023 00:14:23 -0400 Subject: [PATCH 400/600] Upgrade packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 24 ++++++++++++------------ pubspec.yaml | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index fb3a711..b3fdbd7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.6'; +const String currentVersion = '0.14.7'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index f6ddf37..c394bd0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -46,10 +46,10 @@ packages: dependency: transitive description: name: archive - sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a" + sha256: "49b1fad315e57ab0bbc15bcbb874e83116a1d78f77ebd500a4af6c9407d6b28e" url: "https://pub.dev" source: hosted - version: "3.3.7" + version: "3.3.8" args: dependency: transitive description: @@ -206,10 +206,10 @@ packages: dependency: "direct main" description: name: easy_localization - sha256: "30ebf25448ffe169e0bd9bc4b5da94faa8398967a2ad2ca09f438be8b6953645" + sha256: de63e3b422adfc97f256cbb3f8cf12739b6a4993d390f3cadb3f51837afaefe5 url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" easy_logger: dependency: transitive description: @@ -783,18 +783,18 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "38d8e783681bc342e92dc9799cbe4421d08c4d210a67ee9d61d0f7310491a465" + sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27" url: "https://pub.dev" source: hosted - version: "6.1.13" + version: "6.1.14" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: ef7e34951ffa963fb7a65928deeb38d40fb3c5975baf93c1d631341ff7f2650a + sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330 url: "https://pub.dev" source: hosted - version: "6.0.39" + version: "6.1.0" url_launcher_ios: dependency: transitive description: @@ -823,10 +823,10 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "4d0dae953f80dc06fa24c58d0f8381302139c22c2dad301417787ad96f5f73bd" + sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" url_launcher_web: dependency: transitive description: @@ -879,10 +879,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "8545719bbf06f5c4b850f0d5f86da1fe837b1953c56b9af579a26be73627c98d" + sha256: "0d8f5ac96a155e672129bf94c7abf625de01241d44d269dbaff083f1b4deb1aa" url: "https://pub.dev" source: hosted - version: "3.9.4" + version: "3.9.5" webview_flutter_platform_interface: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 61b3d06..13a2449 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.14.6+198 # When changing this, update the tag in main() accordingly +version: 0.14.7+199 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 503914dbce1b28fe4f9b3d2cbc1c4fc4d831ce2e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 3 Sep 2023 15:37:26 -0400 Subject: [PATCH 401/600] Bugfix in HTML Source (#848) --- lib/app_sources/html.dart | 2 +- lib/main.dart | 2 +- pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 753e3f1..47dc5ff 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -18,7 +18,7 @@ String ensureAbsoluteUrl(String ambiguousUrl, Uri referenceAbsoluteUrl) { .toList(); if (ambiguousUrl.startsWith('/') || currPathSegments.isEmpty) { return '${referenceAbsoluteUrl.origin}/$ambiguousUrl'; - } else if (ambiguousUrl.split('/').length == 1) { + } else if (ambiguousUrl.split('/').where((e) => e.isNotEmpty).length == 1) { return '${referenceAbsoluteUrl.origin}/${currPathSegments.join('/')}/$ambiguousUrl'; } else { return '${referenceAbsoluteUrl.origin}/${currPathSegments.sublist(0, currPathSegments.length - 1).join('/')}/$ambiguousUrl'; diff --git a/lib/main.dart b/lib/main.dart index b3fdbd7..282048f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.7'; +const String currentVersion = '0.14.8'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 13a2449..b3a239d 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.14.7+199 # When changing this, update the tag in main() accordingly +version: 0.14.8+200 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 78f73a9049e5a76ebc1730d2a9e66b3e7adc7cb0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 3 Sep 2023 16:11:17 -0400 Subject: [PATCH 402/600] Auto Select Highest VersionCode APK (F-Droid) (#846) --- assets/translations/br.json | 1 + assets/translations/bs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/fdroid.dart | 22 ++++++++++++++++++---- lib/app_sources/izzyondroid.dart | 13 ++++++++++--- lib/main.dart | 2 +- pubspec.yaml | 2 +- 17 files changed, 43 insertions(+), 9 deletions(-) diff --git a/assets/translations/br.json b/assets/translations/br.json index dac26f4..7a23ea5 100644 --- a/assets/translations/br.json +++ b/assets/translations/br.json @@ -252,6 +252,7 @@ "intermediateLinkNotFound": "Link intermediário não encontrado", "exemptFromBackgroundUpdates": "Isento de atualizações em segundo plano (se ativadas)", "bgUpdatesOnWiFiOnly": "Desative atualizações em segundo plano quando não estiver em WiFi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 533ad5a..9813cd4 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -249,6 +249,7 @@ "verifyLatestTag": "Verify the 'latest' tag", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 7cb5b45..9d0de6a 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -249,6 +249,7 @@ "verifyLatestTag": "Überprüfe das 'latest' Tag", "exemptFromBackgroundUpdates": "Ausschluss von Hintergrundaktualisierungen (falls aktiviert)", "bgUpdatesOnWiFiOnly": "Hintergrundaktualisierungen deaktivieren, wenn kein WLAN vorhanden ist", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index afb64d2..c157509 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -252,6 +252,7 @@ "intermediateLinkNotFound": "Intermediate link not found", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 6c07acc..bf83959 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -249,6 +249,7 @@ "verifyLatestTag": "Verify the 'latest' tag", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index a35fb49..1866dd6 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -249,6 +249,7 @@ "verifyLatestTag": "Verify the 'latest' tag", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 83a1d60..e55ba3b 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -249,6 +249,7 @@ "verifyLatestTag": "Verify the 'latest' tag", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 322543a..b7a75d9 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -248,6 +248,7 @@ "verifyLatestTag": "Ellenőrizze a „legújabb” címkét", "exemptFromBackgroundUpdates": "Mentes a háttérben történő frissítések alól (ha engedélyezett)", "bgUpdatesOnWiFiOnly": "Tiltsa le a háttérben frissítéseket, ha nincs Wi-Fi-n", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "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 210bce0..5d43a36 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -249,6 +249,7 @@ "verifyLatestTag": "Verify the 'latest' tag", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 5224933..0119f5d 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -250,6 +250,7 @@ "verifyLatestTag": "'latest'タグを確認する", "exemptFromBackgroundUpdates": "バックグラウンドアップデートを行わない (有効な場合)", "bgUpdatesOnWiFiOnly": "WiFiを使用していない場合,バックグラウンドアップデートを無効にする", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 0518562..f2495bf 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -255,6 +255,7 @@ "verifyLatestTag": "Zweryfikuj najnowszy tag", "exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)", "bgUpdatesOnWiFiOnly": "Wyłącz aktualizacje w tle, gdy nie ma połączenia z Wi-Fi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 91c5572..e53644f 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -249,6 +249,7 @@ "verifyLatestTag": "Verify the 'latest' tag", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 6ab56a0..0837f74 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -250,6 +250,7 @@ "verifyLatestTag": "验证“Latest”标签", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 2f96fe7..ffee596 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; import 'package:html/parser.dart'; import 'package:http/http.dart'; +import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -11,6 +12,12 @@ class FDroid extends AppSource { host = 'f-droid.org'; name = tr('fdroid'); canSearch = true; + additionalSourceAppSpecificSettingFormItems = [ + [ + GeneratedFormSwitch('autoSelectHighestVersionCode', + label: tr('autoSelectHighestVersionCode')) + ] + ]; } @override @@ -37,7 +44,8 @@ class FDroid extends AppSource { } APKDetails getAPKUrlsFromFDroidPackagesAPIResponse( - Response res, String apkUrlPrefix, String standardUrl) { + Response res, String apkUrlPrefix, String standardUrl, + {bool autoSelectHighestVersionCode = false}) { if (res.statusCode == 200) { List releases = jsonDecode(res.body)['packages'] ?? []; if (releases.isEmpty) { @@ -47,8 +55,12 @@ class FDroid extends AppSource { if (latestVersion == null) { throw NoVersionError(); } - List apkUrls = releases - .where((element) => element['versionName'] == latestVersion) + Iterable latestReleases = + releases.where((element) => element['versionName'] == latestVersion); + if (latestReleases.length > 1 && autoSelectHighestVersionCode) { + latestReleases = [latestReleases.first]; + } + List apkUrls = latestReleases .map((e) => '${apkUrlPrefix}_${e['versionCode']}.apk') .toList(); return APKDetails(latestVersion, getApkUrlsFromUrls(apkUrls), @@ -68,7 +80,9 @@ class FDroid extends AppSource { return getAPKUrlsFromFDroidPackagesAPIResponse( await sourceRequest('https://$host/api/v1/packages/$appId'), 'https://$host/repo/$appId', - standardUrl); + standardUrl, + autoSelectHighestVersionCode: + additionalSettings['autoSelectHighestVersionCode'] == true); } @override diff --git a/lib/app_sources/izzyondroid.dart b/lib/app_sources/izzyondroid.dart index d0fcfe8..f145bb8 100644 --- a/lib/app_sources/izzyondroid.dart +++ b/lib/app_sources/izzyondroid.dart @@ -3,8 +3,13 @@ import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; class IzzyOnDroid extends AppSource { + late FDroid fd; + IzzyOnDroid() { host = 'android.izzysoft.de'; + fd = FDroid(); + additionalSourceAppSpecificSettingFormItems = + fd.additionalSourceAppSpecificSettingFormItems; } @override @@ -20,7 +25,7 @@ class IzzyOnDroid extends AppSource { @override Future tryInferringAppId(String standardUrl, {Map additionalSettings = const {}}) async { - return FDroid().tryInferringAppId(standardUrl); + return fd.tryInferringAppId(standardUrl); } @override @@ -29,10 +34,12 @@ class IzzyOnDroid extends AppSource { Map additionalSettings, ) async { String? appId = await tryInferringAppId(standardUrl); - return FDroid().getAPKUrlsFromFDroidPackagesAPIResponse( + return fd.getAPKUrlsFromFDroidPackagesAPIResponse( await sourceRequest( 'https://apt.izzysoft.de/fdroid/api/v1/packages/$appId'), 'https://android.izzysoft.de/frepo/$appId', - standardUrl); + standardUrl, + autoSelectHighestVersionCode: + additionalSettings['autoSelectHighestVersionCode'] == true); } } diff --git a/lib/main.dart b/lib/main.dart index 282048f..420ef9b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.8'; +const String currentVersion = '0.14.9'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index b3a239d..7bafa7f 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.14.8+200 # When changing this, update the tag in main() accordingly +version: 0.14.9+201 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From 58a378d2120d67c831cdf53cefbfd1be8c4ea8e3 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 4 Sep 2023 03:55:13 -0400 Subject: [PATCH 403/600] Fix Aptoide App ID inferral error (#851) --- lib/app_sources/aptoide.dart | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/lib/app_sources/aptoide.dart b/lib/app_sources/aptoide.dart index 0b7f3f4..e3c5548 100644 --- a/lib/app_sources/aptoide.dart +++ b/lib/app_sources/aptoide.dart @@ -26,14 +26,10 @@ class Aptoide extends AppSource { @override Future tryInferringAppId(String standardUrl, {Map additionalSettings = const {}}) async { - return (await getLatestAPKDetails(standardUrl, additionalSettings)).version; + return (await getAppDetailsJSON(standardUrl))['package']; } - @override - Future getLatestAPKDetails( - String standardUrl, - Map additionalSettings, - ) async { + Future> getAppDetailsJSON(String standardUrl) async { var res = await sourceRequest(standardUrl); if (res.statusCode != 200) { throw getObtainiumHttpError(res); @@ -50,12 +46,20 @@ class Aptoide extends AppSource { if (res2.statusCode != 200) { throw getObtainiumHttpError(res); } - var appDetails = jsonDecode(res2.body)?['nodes']?['meta']?['data']; - String appName = appDetails?['name'] ?? tr('app'); - String author = appDetails?['developer']?['name'] ?? name; - String? dateStr = appDetails?['updated']; - String? version = appDetails?['file']?['vername']; - String? apkUrl = appDetails?['file']?['path']; + return jsonDecode(res2.body)?['nodes']?['meta']?['data']; + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + var appDetails = await getAppDetailsJSON(standardUrl); + String appName = appDetails['name'] ?? tr('app'); + String author = appDetails['developer']?['name'] ?? name; + String? dateStr = appDetails['updated']; + String? version = appDetails['file']?['vername']; + String? apkUrl = appDetails['file']?['path']; if (version == null) { throw NoVersionError(); } From 73ed0cea884615ffa043c06cd40ace02a01dd2af Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 4 Sep 2023 03:56:41 -0400 Subject: [PATCH 404/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 420ef9b..91d86b5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.9'; +const String currentVersion = '0.14.10'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 7bafa7f..f643b70 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.14.9+201 # When changing this, update the tag in main() accordingly +version: 0.14.10+202 # When changing this, update the tag in main() accordingly environment: sdk: '>=2.18.2 <3.0.0' From e08ab89fd44a6589ed5a1b8e54efed730b1d9e03 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Wed, 6 Sep 2023 18:33:04 -0400 Subject: [PATCH 405/600] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 20 ++++++++++---------- .github/ISSUE_TEMPLATE/feature_request.md | 14 +++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index a464de1..5980e5f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,31 +2,31 @@ name: Bug report about: Something isn't working right. title: '' -labels: bug, To Check +labels: bug, to check assignees: '' --- **Prerequisites** -Please ensure your request is not part of an existing issue. + **Describe the bug** -A clear and concise description of what the bug is. + **To Reproduce** -Steps to reproduce the behavior: + **Screenshots and Logs** -If applicable, add screenshots, logs, and any other artifacts (like some/all files under `/Android/data/dev.imranr.obtainium/`) that you think may help troubleshoot the issue. + **Please complete the following information:** - - Device: [e.g. Pixel 7] - - OS: [e.g. GrapheneOS] - - Obtainium Version [e.g. 0.14.6-beta] + - Device: + - OS: + - Obtainium Version: **Additional context** -Add any other context about the problem here. + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index b106d0f..44e16b8 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,28 +2,28 @@ name: Feature request about: Suggest a new Source, setting, or other feature. title: '' -labels: enhancement, To Check +labels: enhancement, to check assignees: '' --- **Prerequisites** -Please ensure your request is not part of an existing issue. + **Describe the feature** -A clear and concise description of what you want to happen. + **Describe alternatives you've considered (if applicable)** -A clear and concise description of any alternative solutions or features you've considered. + **Additional context** -Add any other context or screenshots about the feature request here. + From c08e05bd6c6eb3b1a35f2ee20b0a0129bcfd154f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 6 Sep 2023 21:30:45 -0400 Subject: [PATCH 406/600] Trying to use header-based HTTP auth (not working) --- assets/translations/br.json | 2 - assets/translations/bs.json | 2 - assets/translations/de.json | 2 - assets/translations/en.json | 2 - assets/translations/es.json | 2 - assets/translations/fa.json | 2 - assets/translations/fr.json | 2 - assets/translations/hu.json | 2 - assets/translations/it.json | 2 - assets/translations/ja.json | 2 - assets/translations/pl.json | 2 - assets/translations/ru.json | 2 - assets/translations/zh.json | 2 - lib/app_sources/apkcombo.dart | 16 +++++--- lib/app_sources/github.dart | 56 +++++++++++++++++---------- lib/app_sources/html.dart | 13 ++++--- lib/app_sources/vlc.dart | 7 +++- lib/mass_app_sources/githubstars.dart | 6 ++- lib/providers/apps_provider.dart | 9 +++-- lib/providers/source_provider.dart | 14 +++++-- 20 files changed, 81 insertions(+), 66 deletions(-) diff --git a/assets/translations/br.json b/assets/translations/br.json index 7a23ea5..efe9093 100644 --- a/assets/translations/br.json +++ b/assets/translations/br.json @@ -12,8 +12,6 @@ "ok": "Ok", "and": "e", "githubPATLabel": "Token de Acceso Pessoal do GitHub (Reduz tempos de espera)", - "githubPATHint": "O TAP deve estar nesse formato: usuario:token", - "githubPATFormat": "usuario:token", "includePrereleases": "Incluir pré-lançamentos", "fallbackToOlderReleases": "Retornar para versões anteriores", "filterReleaseTitlesByRegEx": "Filtrar Titulos de Versões por Expressão Regular", diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 9813cd4..e3a4ef6 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -12,8 +12,6 @@ "ok": "Dobro", "and": "i", "githubPATLabel": "GitHub token za lični pristup (eng. PAT, povećava ograničenje stope)", - "githubPATHint": "PAT mora biti u ovom formatu: korisničko_ime:token", - "githubPATFormat": "korisničko_ime:token", "includePrereleases": "Uključi preliminarna izdanja", "fallbackToOlderReleases": "Povratak na starija izdanja", "filterReleaseTitlesByRegEx": "Filtrirajte naslove izdanja prema regularnom izrazu", diff --git a/assets/translations/de.json b/assets/translations/de.json index 9d0de6a..2e9857e 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -12,8 +12,6 @@ "ok": "Okay", "and": "und", "githubPATLabel": "GitHub Personal Access Token (Erhöht das Ratenlimit)", - "githubPATHint": "PAT muss in diesem Format sein: Benutzername:Token", - "githubPATFormat": "Benutzername:Token", "includePrereleases": "Vorabversionen einbeziehen", "fallbackToOlderReleases": "Fallback auf ältere Versionen", "filterReleaseTitlesByRegEx": "Release-Titel nach regulärem Ausdruck\nfiltern", diff --git a/assets/translations/en.json b/assets/translations/en.json index c157509..bba3367 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -12,8 +12,6 @@ "ok": "Okay", "and": "and", "githubPATLabel": "GitHub Personal Access Token (Increases Rate Limit)", - "githubPATHint": "PAT must be in this format: username:token", - "githubPATFormat": "username:token", "includePrereleases": "Include prereleases", "fallbackToOlderReleases": "Fallback to older releases", "filterReleaseTitlesByRegEx": "Filter Release Titles by Regular Expression", diff --git a/assets/translations/es.json b/assets/translations/es.json index bf83959..e4ffaa0 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -12,8 +12,6 @@ "ok": "Correcto", "and": "y", "githubPATLabel": "Token de Acceso Personal de GitHub (Reduce tiempos de espera)", - "githubPATHint": "El TAP debe tener este formato: nombre_de_usuario:token", - "githubPATFormat": "nombre_de_usuario:token", "includePrereleases": "Incluir versiones preliminares", "fallbackToOlderReleases": "Retorceder a versiones previas", "filterReleaseTitlesByRegEx": "Filtra Títulos de Versiones mediantes Expresiones Regulares", diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 1866dd6..041ce19 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -12,8 +12,6 @@ "ok": "باشه", "and": "و", "githubPATLabel": "توکن دسترسی شخصی گیت هاب(محدودیت نرخ را افزایش میدهد)", - "githubPATHint": "PAT باید در این قالب باشد: username:token", - "githubPATFormat": "username:token", "includePrereleases": "شامل نسخه های اولیه", "fallbackToOlderReleases": "بازگشت به نسخه های قدیمی تر", "filterReleaseTitlesByRegEx": "عناوین انتشار را با بیان منظم فیلتر کنید", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index e55ba3b..8b5adfc 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -12,8 +12,6 @@ "ok": "Okay", "and": "et", "githubPATLabel": "Jeton d'Accès Personnel GitHub (Augmente la limite de débit)", - "githubPATHint": "Le JAP doit être dans ce format : username:token", - "githubPATFormat": "username:token", "includePrereleases": "Inclure les avant-premières", "fallbackToOlderReleases": "Retour aux anciennes versions", "filterReleaseTitlesByRegEx": "Filtrer les titres de version par expression régulière", diff --git a/assets/translations/hu.json b/assets/translations/hu.json index b7a75d9..7c7d912 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -12,8 +12,6 @@ "ok": "Oké", "and": "és", "githubPATLabel": "GitHub Personal Access Token (megnöveli a díjkorlátot)", - "githubPATHint": "A PAT-nak a következő formátumban kell lennie: felhasználónév:token", - "githubPATFormat": "felhasználónév:token", "includePrereleases": "Tartalmazza az előzetes kiadásokat", "fallbackToOlderReleases": "Visszatérés a régebbi kiadásokhoz", "filterReleaseTitlesByRegEx": "A kiadás címeinek szűrése reguláris kifejezéssel", diff --git a/assets/translations/it.json b/assets/translations/it.json index 5d43a36..eadf90b 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -12,8 +12,6 @@ "ok": "Va bene", "and": "e", "githubPATLabel": "GitHub Personal Access Token (diminuisce limite di traffico)", - "githubPATHint": "PAT deve seguire questo formato: nomeutente:token", - "githubPATFormat": "nomeutente:token", "includePrereleases": "Includi prerelease", "fallbackToOlderReleases": "Ripiega su release precedenti", "filterReleaseTitlesByRegEx": "Filtra release con espressioni regolari", diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 0119f5d..1fa24d6 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -12,8 +12,6 @@ "ok": "OK", "and": "と", "githubPATLabel": "GitHub パーソナルアクセストークン (レート制限の引き上げ)", - "githubPATHint": "PATは次の形式でなければなりません: ユーザー名:トークン", - "githubPATFormat": "ユーザー名:トークン", "includePrereleases": "プレリリースを含む", "fallbackToOlderReleases": "旧リリースへのフォールバック", "filterReleaseTitlesByRegEx": "正規表現でリリースタイトルをフィルタリングする", diff --git a/assets/translations/pl.json b/assets/translations/pl.json index f2495bf..f56121c 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -22,8 +22,6 @@ "ok": "Okej", "and": "i", "githubPATLabel": "Osobisty token dostępu GitHub (zwiększa limit zapytań)", - "githubPATHint": "Wymagany format: użytkownik:token", - "githubPATFormat": "użytkownik:token", "includePrereleases": "Uwzględnij wersje wstępne", "fallbackToOlderReleases": "Powracaj do starszych wersji", "filterReleaseTitlesByRegEx": "Filtruj tytuły wydań wg. wyrażeń regularnych", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index e53644f..dfaeb93 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -12,8 +12,6 @@ "ok": "Окей", "and": "и", "githubPATLabel": "Персональный токен доступа GitHub (увеличивает лимит запросов)", - "githubPATHint": "Токен доступа должен быть в формате: имя_пользователя:токен", - "githubPATFormat": "имя_пользователя:токен", "includePrereleases": "Включить предварительные релизы", "fallbackToOlderReleases": "Откатиться к более старым версиям", "filterReleaseTitlesByRegEx": "Фильтровать заголовки релизов\nс помощью регулярного выражения", diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 0837f74..6f4e7a2 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -12,8 +12,6 @@ "ok": "好的", "and": "和", "githubPATLabel": "GitHub 个人访问令牌(提升 API 请求限额)", - "githubPATHint": "个人访问令牌必须为“username:token”的格式", - "githubPATFormat": "username:token", "includePrereleases": "包含预发行版", "fallbackToOlderReleases": "将旧发行版作为备选", "filterReleaseTitlesByRegEx": "使用正则表达式筛选发行标题", diff --git a/lib/app_sources/apkcombo.dart b/lib/app_sources/apkcombo.dart index c90b0cb..73c144b 100644 --- a/lib/app_sources/apkcombo.dart +++ b/lib/app_sources/apkcombo.dart @@ -25,12 +25,16 @@ class APKCombo extends AppSource { } @override - Map get requestHeaders => { - "User-Agent": "curl/8.0.1", - "Accept": "*/*", - "Connection": "keep-alive", - "Host": "$host" - }; + Future?> getRequestHeaders( + {Map additionalSettings = const {}, + bool forAPKDownload = false}) async { + return { + "User-Agent": "curl/8.0.1", + "Accept": "*/*", + "Connection": "keep-alive", + "Host": "$host" + }; + } Future>> getApkUrls(String standardUrl) async { var res = await sourceRequest('$standardUrl/download/apk'); diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 0b2f2c9..a2722b7 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart'; @@ -21,20 +22,6 @@ class GitHub extends AppSource { label: tr('githubPATLabel'), password: true, required: false, - additionalValidators: [ - (value) { - if (value != null && value.trim().isNotEmpty) { - if (value - .split(':') - .where((element) => element.trim().isNotEmpty) - .length != - 2) { - return tr('githubPATHint'); - } - } - return null; - } - ], hint: tr('githubPATFormat'), belowWidgets: [ const SizedBox( @@ -169,26 +156,53 @@ class GitHub extends AppSource { return url.substring(0, match.end); } - Future getCredentialPrefixIfAny( - Map additionalSettings) async { + @override + Future?> getRequestHeaders( + {Map additionalSettings = const {}, + bool forAPKDownload = false}) async { + var token = await getTokenIfAny(additionalSettings); + var headers = {}; + if (token != null) { + headers[HttpHeaders.authorizationHeader] = 'Token $token'; + } + if (forAPKDownload == true) { + headers[HttpHeaders.acceptHeader] = 'octet-stream'; + } + if (headers.isNotEmpty) { + return headers; + } else { + return null; + } + } + + Future getTokenIfAny(Map additionalSettings) async { SettingsProvider settingsProvider = SettingsProvider(); await settingsProvider.initializeSettings(); var sourceConfig = await getSourceConfigValues(additionalSettings, settingsProvider); String? creds = sourceConfig['github-creds']; - return creds != null && creds.isNotEmpty ? '$creds@' : ''; + if (creds != null) { + var userNameEndIndex = creds.indexOf(':'); + if (userNameEndIndex > 0) { + creds = creds.substring( + userNameEndIndex + 1); // For old username-included token inputs + } + return creds; + } else { + return null; + } } @override Future getSourceNote() async { - if (!hostChanged && (await getCredentialPrefixIfAny({})).isEmpty) { + if (!hostChanged && (await getTokenIfAny({})) == null) { return '${tr('githubSourceNote')} ${hostChanged ? tr('addInfoBelow') : tr('addInfoInSettings')}'; } return null; } Future getAPIHost(Map additionalSettings) async => - 'https://${await getCredentialPrefixIfAny(additionalSettings)}api.$host'; + 'https://api.$host'; Future convertStandardUrlToAPIUrl( String standardUrl, Map additionalSettings) async => @@ -238,7 +252,9 @@ class GitHub extends AppSource { List> getReleaseAPKUrls(dynamic release) => (release['assets'] as List?) ?.map((e) { - return e['name'] != null && e['browser_download_url'] != null + return e['name'] != null && + e['browser_download_url'] != + null // TODO: Figure out how to use 'url' here to enable private repos ? MapEntry(e['name'] as String, e['browser_download_url'] as String) : const MapEntry('', ''); diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 47dc5ff..bce8f34 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -116,11 +116,14 @@ class HTML extends AppSource { } @override - // TODO: implement requestHeaders choice, hardcoded for now - Map? get requestHeaders => { - "User-Agent": - "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36" - }; + Future?> getRequestHeaders( + {Map additionalSettings = const {}, + bool forAPKDownload = false}) async { + return { + "User-Agent": + "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36" + }; + } @override String sourceSpecificStandardizeURL(String url) { diff --git a/lib/app_sources/vlc.dart b/lib/app_sources/vlc.dart index 1c1adb8..091411a 100644 --- a/lib/app_sources/vlc.dart +++ b/lib/app_sources/vlc.dart @@ -12,7 +12,12 @@ class VLC extends AppSource { get dwUrlBase => 'https://get.$host/vlc-android/'; @override - Map? get requestHeaders => HTML().requestHeaders; + Future?> getRequestHeaders( + {Map additionalSettings = const {}, + bool forAPKDownload = false}) => + HTML().getRequestHeaders( + additionalSettings: additionalSettings, + forAPKDownload: forAPKDownload); @override String sourceSpecificStandardizeURL(String url) { diff --git a/lib/mass_app_sources/githubstars.dart b/lib/mass_app_sources/githubstars.dart index db8495b..b32cc77 100644 --- a/lib/mass_app_sources/githubstars.dart +++ b/lib/mass_app_sources/githubstars.dart @@ -15,8 +15,10 @@ class GitHubStars implements MassAppUrlSource { Future>> getOnePageOfUserStarredUrlsWithDescriptions( String username, int page) async { - Response res = await get(Uri.parse( - 'https://${await GitHub().getCredentialPrefixIfAny({})}api.github.com/users/$username/starred?per_page=100&page=$page')); + Response res = await get( + Uri.parse( + 'https://api.github.com/users/$username/starred?per_page=100&page=$page'), + headers: await GitHub().getRequestHeaders()); if (res.statusCode == 200) { Map> urlsWithDescriptions = {}; for (var e in (jsonDecode(res.body) as List)) { diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index cad3b2f..208b222 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:math'; +import 'package:http/http.dart' as http; import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; import 'package:android_intent_plus/flag.dart'; @@ -215,7 +216,7 @@ class AppsProvider with ChangeNotifier { if (headers != null) { req.headers.addAll(headers); } - var client = Client(); + var client = http.Client(); StreamedResponse response = await client.send(req); String ext = response.headers['content-disposition']?.split('.').last ?? 'apk'; @@ -298,9 +299,11 @@ class AppsProvider with ChangeNotifier { notificationsProvider?.cancel(notif.id); int? prevProg; var fileNameNoExt = '${app.id}-${downloadUrl.hashCode}'; + var headers = await source.getRequestHeaders( + additionalSettings: app.additionalSettings, forAPKDownload: true); var downloadedFile = await downloadFileWithRetry( - downloadUrl, fileNameNoExt, headers: source.requestHeaders, - (double? progress) { + downloadUrl, fileNameNoExt, + headers: headers, (double? progress) { int? prog = progress?.ceil(); if (apps[app.id] != null) { apps[app.id]!.downloadProgress = progress; diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index c9433b7..df21e57 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -363,15 +363,23 @@ abstract class AppSource { return url; } - Map? get requestHeaders => null; + Future?> getRequestHeaders( + {Map additionalSettings = const {}, + bool forAPKDownload = false}) async { + return null; + } Future sourceRequest(String url, - {bool followRedirects = true}) async { + {bool followRedirects = true, + Map additionalSettings = + const {}}) async { + var requestHeaders = + await getRequestHeaders(additionalSettings: additionalSettings); if (requestHeaders != null || followRedirects == false) { var req = Request('GET', Uri.parse(url)); req.followRedirects = followRedirects; if (requestHeaders != null) { - req.headers.addAll(requestHeaders!); + req.headers.addAll(requestHeaders); } return Response.fromStream(await Client().send(req)); } else { From d66be3ecdada47918673ea6019077733c5d22a18 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 9 Sep 2023 03:55:52 -0400 Subject: [PATCH 407/600] Private GitHub repos now work (#857) --- lib/app_sources/github.dart | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index a2722b7..9c7cb73 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -166,7 +166,7 @@ class GitHub extends AppSource { headers[HttpHeaders.authorizationHeader] = 'Token $token'; } if (forAPKDownload == true) { - headers[HttpHeaders.acceptHeader] = 'octet-stream'; + headers[HttpHeaders.acceptHeader] = 'application/octet-stream'; } if (headers.isNotEmpty) { return headers; @@ -252,11 +252,8 @@ class GitHub extends AppSource { List> getReleaseAPKUrls(dynamic release) => (release['assets'] as List?) ?.map((e) { - return e['name'] != null && - e['browser_download_url'] != - null // TODO: Figure out how to use 'url' here to enable private repos - ? MapEntry(e['name'] as String, - e['browser_download_url'] as String) + return e['name'] != null && e['url'] != null + ? MapEntry(e['name'] as String, e['url'] as String) : const MapEntry('', ''); }) .where((element) => element.key.toLowerCase().endsWith('.apk')) From 85f9336804d92fae060af510cc8bf2e2afcb1d7b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 9 Sep 2023 03:58:54 -0400 Subject: [PATCH 408/600] Re-add dl notification when adding app (#858) --- lib/pages/add_app.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 0f8095c..2438270 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -11,6 +11,7 @@ import 'package:obtainium/pages/app.dart'; import 'package:obtainium/pages/import_export.dart'; import 'package:obtainium/pages/settings.dart'; import 'package:obtainium/providers/apps_provider.dart'; +import 'package:obtainium/providers/notifications_provider.dart'; import 'package:obtainium/providers/settings_provider.dart'; import 'package:obtainium/providers/source_provider.dart'; import 'package:provider/provider.dart'; @@ -42,6 +43,8 @@ class _AddAppPageState extends State { Widget build(BuildContext context) { AppsProvider appsProvider = context.read(); SettingsProvider settingsProvider = context.watch(); + NotificationsProvider notificationsProvider = + context.read(); bool doingSomething = gettingAppInfo || searching; @@ -161,7 +164,8 @@ class _AddAppPageState extends State { app.apkUrls.map((e) => e.value).toList().indexOf(apkUrl.value); // ignore: use_build_context_synchronously var downloadedArtifact = await appsProvider.downloadApp( - app, globalNavigatorKey.currentContext); + app, globalNavigatorKey.currentContext, + notificationsProvider: notificationsProvider); DownloadedApk? downloadedFile; DownloadedXApkDir? downloadedDir; if (downloadedArtifact is DownloadedApk) { From aa7989c16d0e73ce5c20b7d63fb02154ce20e1d3 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 9 Sep 2023 04:41:44 -0400 Subject: [PATCH 409/600] Custom version extraction for HTML (#861) --- assets/translations/br.json | 2 + assets/translations/bs.json | 2 + assets/translations/de.json | 2 + assets/translations/en.json | 2 + assets/translations/es.json | 2 + assets/translations/fa.json | 2 + assets/translations/fr.json | 2 + assets/translations/hu.json | 2 + assets/translations/it.json | 2 + assets/translations/ja.json | 2 + assets/translations/pl.json | 2 + assets/translations/ru.json | 2 + assets/translations/zh.json | 2 + lib/app_sources/html.dart | 38 ++++++++++++++++- lib/components/generated_form.dart | 65 +++++++++++++++++------------- 15 files changed, 98 insertions(+), 31 deletions(-) diff --git a/assets/translations/br.json b/assets/translations/br.json index efe9093..ad6a4a5 100644 --- a/assets/translations/br.json +++ b/assets/translations/br.json @@ -251,6 +251,8 @@ "exemptFromBackgroundUpdates": "Isento de atualizações em segundo plano (se ativadas)", "bgUpdatesOnWiFiOnly": "Desative atualizações em segundo plano quando não estiver em WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/bs.json b/assets/translations/bs.json index e3a4ef6..b65d8a3 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -248,6 +248,8 @@ "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 2e9857e..d5a016b 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -248,6 +248,8 @@ "exemptFromBackgroundUpdates": "Ausschluss von Hintergrundaktualisierungen (falls aktiviert)", "bgUpdatesOnWiFiOnly": "Hintergrundaktualisierungen deaktivieren, wenn kein WLAN vorhanden ist", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index bba3367..f5473be 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -251,6 +251,8 @@ "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index e4ffaa0..62fc6e7 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -248,6 +248,8 @@ "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 041ce19..466b976 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -248,6 +248,8 @@ "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 8b5adfc..a23667b 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -248,6 +248,8 @@ "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 7c7d912..dfd1274 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -247,6 +247,8 @@ "exemptFromBackgroundUpdates": "Mentes a háttérben történő frissítések alól (ha engedélyezett)", "bgUpdatesOnWiFiOnly": "Tiltsa le a háttérben frissítéseket, ha nincs Wi-Fi-n", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "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 eadf90b..c46ddbd 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -248,6 +248,8 @@ "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 1fa24d6..741597e 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -249,6 +249,8 @@ "exemptFromBackgroundUpdates": "バックグラウンドアップデートを行わない (有効な場合)", "bgUpdatesOnWiFiOnly": "WiFiを使用していない場合,バックグラウンドアップデートを無効にする", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index f56121c..5d419ef 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -254,6 +254,8 @@ "exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)", "bgUpdatesOnWiFiOnly": "Wyłącz aktualizacje w tle, gdy nie ma połączenia z Wi-Fi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index dfaeb93..34b48f1 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -248,6 +248,8 @@ "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 6f4e7a2..902034d 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -249,6 +249,8 @@ "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index bce8f34..a2a25cc 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -1,4 +1,5 @@ import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; import 'package:html/parser.dart'; import 'package:http/http.dart'; import 'package:obtainium/components/generated_form.dart'; @@ -109,6 +110,26 @@ class HTML extends AppSource { hint: '([0-9]+\.)*[0-9]+/\$', required: false, additionalValidators: [(value) => regExValidator(value)]) + ], + [ + GeneratedFormTextField('versionExtractionRegEx', + label: tr('versionExtractionRegEx'), + required: false, + additionalValidators: [(value) => regExValidator(value)]), + GeneratedFormTextField('matchGroupToUse', + label: tr('matchGroupToUse'), + required: false, + hint: '1', + textInputType: const TextInputType.numberWithOptions(), + additionalValidators: [ + (value) { + value ??= '1'; + if (int.tryParse(value) == null) { + return tr('invalidInput'); + } + return null; + } + ]) ] ]; overrideVersionDetectionFormDefault('noVersionDetection', @@ -183,10 +204,23 @@ class HTML extends AppSource { throw NoReleasesError(); } var rel = links.last; - var version = rel.hashCode.toString(); + String? version = rel.hashCode.toString(); + var versionExtractionRegEx = + additionalSettings['versionExtractionRegEx'] as String?; + if (versionExtractionRegEx?.isNotEmpty == true) { + var match = RegExp(versionExtractionRegEx!).allMatches(rel); + if (match.isEmpty) { + throw NoVersionError(); + } + version = match.last + .group(int.parse(additionalSettings['matchGroupToUse'] as String)); + if (version?.isEmpty == true) { + throw NoVersionError(); + } + } List apkUrls = [rel].map((e) => ensureAbsoluteUrl(e, uri)).toList(); - return APKDetails(version, apkUrls.map((e) => MapEntry(e, e)).toList(), + return APKDetails(version!, apkUrls.map((e) => MapEntry(e, e)).toList(), AppNames(uri.host, tr('app'))); } else { throw getObtainiumHttpError(res); diff --git a/lib/components/generated_form.dart b/lib/components/generated_form.dart index 300b679..41e742f 100644 --- a/lib/components/generated_form.dart +++ b/lib/components/generated_form.dart @@ -25,6 +25,7 @@ class GeneratedFormTextField extends GeneratedFormItem { late int max; late String? hint; late bool password; + late TextInputType? textInputType; GeneratedFormTextField(String key, {String label = 'Input', @@ -34,7 +35,8 @@ class GeneratedFormTextField extends GeneratedFormItem { this.required = true, this.max = 1, this.hint, - this.password = false}) + this.password = false, + this.textInputType}) : super(key, label: label, belowWidgets: belowWidgets, @@ -144,7 +146,8 @@ Color generateRandomLightColor() { // Map from HPLuv color space to RGB, use constant saturation=100, lightness=70 final List rgbValuesDbl = Hsluv.hpluvToRgb([hue, 100, 70]); // Map RBG values from 0-1 to 0-255: - final List rgbValues = rgbValuesDbl.map((rgb) => (rgb * 255).toInt()).toList(); + final List rgbValues = + rgbValuesDbl.map((rgb) => (rgb * 255).toInt()).toList(); return Color.fromARGB(255, rgbValues[0], rgbValues[1], rgbValues[2]); } @@ -190,6 +193,7 @@ class _GeneratedFormState extends State { if (formItem is GeneratedFormTextField) { final formFieldKey = GlobalKey(); return TextFormField( + keyboardType: formItem.textInputType, obscureText: formItem.password, autocorrect: !formItem.password, enableSuggestions: !formItem.password, @@ -370,34 +374,37 @@ class _GeneratedFormState extends State { }) ?? [const SizedBox.shrink()], (values[widget.items[r][e].key] - as Map>?) - ?.values - .where((e) => e.value) - .length == 1 + as Map>?) + ?.values + .where((e) => e.value) + .length == + 1 ? Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: IconButton( - onPressed: () { - setState(() { - var temp = values[widget.items[r][e].key] - as Map>; - // get selected category str where bool is true - final oldEntry = temp.entries.firstWhere((entry) => entry.value.value); - // generate new color, ensure it is not the same - int newColor = oldEntry.value.key; - while(oldEntry.value.key == newColor) { - newColor = generateRandomLightColor().value; - } - // Update entry with new color, remain selected - temp.update(oldEntry.key, (old) => MapEntry(newColor, old.value)); - values[widget.items[r][e].key] = temp; - someValueChanged(); - }); - }, - icon: const Icon(Icons.format_color_fill_rounded), - visualDensity: VisualDensity.compact, - tooltip: tr('colour'), - )) + padding: const EdgeInsets.symmetric(horizontal: 4), + child: IconButton( + onPressed: () { + setState(() { + var temp = values[widget.items[r][e].key] + as Map>; + // get selected category str where bool is true + final oldEntry = temp.entries + .firstWhere((entry) => entry.value.value); + // generate new color, ensure it is not the same + int newColor = oldEntry.value.key; + while (oldEntry.value.key == newColor) { + newColor = generateRandomLightColor().value; + } + // Update entry with new color, remain selected + temp.update(oldEntry.key, + (old) => MapEntry(newColor, old.value)); + values[widget.items[r][e].key] = temp; + someValueChanged(); + }); + }, + icon: const Icon(Icons.format_color_fill_rounded), + visualDensity: VisualDensity.compact, + tooltip: tr('colour'), + )) : const SizedBox.shrink(), (values[widget.items[r][e].key] as Map>?) From cbc840378c992c1db1a6186853c918fb7b004d66 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 9 Sep 2023 05:31:04 -0400 Subject: [PATCH 410/600] Add Uptodown (#853) --- README.md | 47 +++++++++-------- lib/app_sources/apkpure.dart | 37 ++++++++------ lib/app_sources/aptoide.dart | 32 ------------ lib/app_sources/uptodown.dart | 82 ++++++++++++++++++++++++++++++ lib/providers/source_provider.dart | 10 ++-- pubspec.yaml | 2 +- 6 files changed, 137 insertions(+), 73 deletions(-) create mode 100644 lib/app_sources/uptodown.dart diff --git a/README.md b/README.md index cf57007..762d485 100644 --- a/README.md +++ b/README.md @@ -2,31 +2,36 @@ Get Android App Updates Directly From the Source. -Obtainium allows you to install and update Open-Source Apps directly from their releases pages, and receive notifications when new releases are made available. +Obtainium allows you to install and update Apps directly from their releases pages, and receive notifications when new releases are made available. Motivation: [Side Of Burritos - You should use this instead of F-Droid | How to use app RSS feed](https://youtu.be/FFz57zNR_M0) Currently supported App sources: -- [GitHub](https://github.com/) -- [GitLab](https://gitlab.com/) -- [Codeberg](https://codeberg.org/) -- [F-Droid](https://f-droid.org/) -- [IzzyOnDroid](https://android.izzysoft.de/) -- [Mullvad](https://mullvad.net/en/) -- [Signal](https://signal.org/) -- [SourceForge](https://sourceforge.net/) -- [SourceHut](https://git.sr.ht/) -- [Aptoide](https://aptoide.com/) -- [APKMirror](https://apkmirror.com/) (Track-Only) -- [APKPure](https://apkpure.com/) -- [Huawei AppGallery](https://appgallery.huawei.com/) -- Third Party F-Droid Repos -- Jenkins Jobs -- [Steam](https://store.steampowered.com/mobile) -- [Telegram App](https://telegram.org) -- [Neutron Code](https://neutroncode.com) -- "HTML" (Fallback) - - Any other URL that returns an HTML page with links to APK files (if multiple, the last file alphabetically is picked) +- Open Source - General: + - [GitHub](https://github.com/) + - [GitLab](https://gitlab.com/) + - [Codeberg](https://codeberg.org/) + - [F-Droid](https://f-droid.org/) + - Third Party F-Droid Repos + - [IzzyOnDroid](https://android.izzysoft.de/) + - [SourceForge](https://sourceforge.net/) + - [SourceHut](https://git.sr.ht/) +- Other - General: + - [APKPure](https://apkpure.com/) + - [Aptoide](https://aptoide.com/) + - [Uptodown](https://uptodown.com/) + - [APKMirror](https://apkmirror.com/) (Track-Only) + - [Huawei AppGallery](https://appgallery.huawei.com/) + - Jenkins Jobs +- Open Source - App-Specific: + - [Mullvad](https://mullvad.net/en/) + - [Signal](https://signal.org/) + - [VLC](https://videolan.org/) +- Other - App-Specific: + - [Telegram App](https://telegram.org) + - [Steam Mobile Apps](https://store.steampowered.com/mobile) + - [Neutron Code](https://neutroncode.com) +- "HTML" (Fallback): Any other URL that returns an HTML page with links to APK files ## Installation diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index ff63d2b..15ca098 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -3,6 +3,21 @@ import 'package:html/parser.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; +parseDateTimeMMMddCommayyyy(String? dateString) { + DateTime? releaseDate; + try { + releaseDate = dateString != null + ? DateFormat('MMM dd, yyyy').parse(dateString) + : null; + releaseDate = dateString != null && releaseDate == null + ? DateFormat('MMMM dd, yyyy').parse(dateString) + : releaseDate; + } catch (err) { + // ignore + } + return releaseDate; +} + class APKPure extends AppSource { APKPure() { host = 'apkpure.com'; @@ -47,17 +62,7 @@ class APKPure extends AppSource { } String? dateString = html.querySelector('span.info-other span.date')?.text.trim(); - DateTime? releaseDate; - try { - releaseDate = dateString != null - ? DateFormat('MMM dd, yyyy').parse(dateString) - : null; - releaseDate = dateString != null && releaseDate == null - ? DateFormat('MMMM dd, yyyy').parse(dateString) - : null; - } catch (err) { - // ignore - } + DateTime? releaseDate = parseDateTimeMMMddCommayyyy(dateString); String type = html.querySelector('a.info-tag')?.text.trim() ?? 'APK'; List> apkUrls = [ MapEntry('$appId.apk', 'https://d.$host/b/$type/$appId?version=latest') @@ -70,11 +75,13 @@ class APKPure extends AppSource { Uri.parse(standardUrl).pathSegments.reversed.last; String appName = html.querySelector('h1.info-title')?.text.trim() ?? appId; - String? changeLog = htmlChangelog.querySelector("div.whats-new-info p:not(.date)")?.innerHtml - .trim().replaceAll("
", " \n"); + String? changeLog = htmlChangelog + .querySelector("div.whats-new-info p:not(.date)") + ?.innerHtml + .trim() + .replaceAll("
", " \n"); return APKDetails(version, apkUrls, AppNames(author, appName), - releaseDate: releaseDate, - changeLog: changeLog); + releaseDate: releaseDate, changeLog: changeLog); } else { throw getObtainiumHttpError(res); } diff --git a/lib/app_sources/aptoide.dart b/lib/app_sources/aptoide.dart index e3c5548..9543464 100644 --- a/lib/app_sources/aptoide.dart +++ b/lib/app_sources/aptoide.dart @@ -1,8 +1,6 @@ import 'dart:convert'; import 'package:easy_localization/easy_localization.dart'; -import 'package:html/parser.dart'; -import 'package:http/http.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -75,34 +73,4 @@ class Aptoide extends AppSource { version, getApkUrlsFromUrls([apkUrl]), AppNames(author, appName), releaseDate: relDate); } - - @override - Future>> search(String query, - {Map querySettings = const {}}) async { - Response res = await sourceRequest( - 'https://search.$host/?q=${Uri.encodeQueryComponent(query)}'); - if (res.statusCode == 200) { - Map> urlsWithDescriptions = {}; - parse(res.body).querySelectorAll('.package-header').forEach((e) { - String? url = e.attributes['href']; - if (url != null) { - try { - standardizeUrl(url); - } catch (e) { - url = null; - } - } - if (url != null) { - urlsWithDescriptions[url] = [ - e.querySelector('.package-name')?.text.trim() ?? '', - e.querySelector('.package-summary')?.text.trim() ?? - tr('noDescription') - ]; - } - }); - return urlsWithDescriptions; - } else { - throw getObtainiumHttpError(res); - } - } } diff --git a/lib/app_sources/uptodown.dart b/lib/app_sources/uptodown.dart new file mode 100644 index 0000000..4075ee1 --- /dev/null +++ b/lib/app_sources/uptodown.dart @@ -0,0 +1,82 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:html/parser.dart'; +import 'package:obtainium/app_sources/apkpure.dart'; +import 'package:obtainium/custom_errors.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class Uptodown extends AppSource { + Uptodown() { + host = 'uptodown.com'; + allowSubDomains = true; + } + + @override + String sourceSpecificStandardizeURL(String url) { + RegExp standardUrlRegEx = RegExp('^https?://([^\\.]+\\.){2,}$host'); + RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); + if (match == null) { + throw InvalidURLError(name); + } + return '${url.substring(0, match.end)}/android/download'; + } + + @override + Future tryInferringAppId(String standardUrl, + {Map additionalSettings = const {}}) async { + return (await getAppDetailsFromPage(standardUrl))['appId']; + } + + Future> getAppDetailsFromPage(String standardUrl) async { + var res = await sourceRequest(standardUrl); + if (res.statusCode != 200) { + throw getObtainiumHttpError(res); + } + var html = parse(res.body); + String? version = html.querySelector('div.version')?.innerHtml; + String? apkUrl = + html.querySelector('#detail-download-button')?.attributes['data-url']; + String? name = html.querySelector('#detail-app-name')?.innerHtml; + String? author = html.querySelector('#author-link')?.innerHtml; + var detailElements = html.querySelectorAll('#technical-information td'); + String? appId = (detailElements.elementAtOrNull(2))?.innerHtml; + String? dateStr = (detailElements.elementAtOrNull(29))?.innerHtml; + return Map.fromEntries([ + MapEntry('version', version), + MapEntry('apkUrl', apkUrl), + MapEntry('appId', appId), + MapEntry('name', name), + MapEntry('author', author), + MapEntry('dateStr', dateStr) + ]); + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + var appDetails = await getAppDetailsFromPage(standardUrl); + var version = appDetails['version']; + var apkUrl = appDetails['apkUrl']; + var appId = appDetails['appId']; + if (version == null) { + throw NoVersionError(); + } + if (apkUrl == null) { + throw NoAPKError(); + } + if (appId == null) { + throw NoReleasesError(); + } + String appName = appDetails['name'] ?? tr('app'); + String author = appDetails['author'] ?? name; + String? dateStr = appDetails['dateStr']; + DateTime? relDate; + if (dateStr != null) { + relDate = parseDateTimeMMMddCommayyyy(dateStr); + } + return APKDetails( + version, getApkUrlsFromUrls([apkUrl]), AppNames(author, appName), + releaseDate: relDate); + } +} diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index df21e57..3c06be2 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -26,6 +26,7 @@ import 'package:obtainium/app_sources/sourceforge.dart'; import 'package:obtainium/app_sources/sourcehut.dart'; import 'package:obtainium/app_sources/steammobile.dart'; import 'package:obtainium/app_sources/telegramapp.dart'; +import 'package:obtainium/app_sources/uptodown.dart'; import 'package:obtainium/app_sources/vlc.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; @@ -527,15 +528,16 @@ class SourceProvider { GitLab(), Codeberg(), FDroid(), - IzzyOnDroid(), FDroidRepo(), - Jenkins(), + IzzyOnDroid(), SourceForge(), SourceHut(), - Aptoide(), - APKMirror(), APKPure(), + Aptoide(), + Uptodown(), + APKMirror(), HuaweiAppGallery(), + Jenkins(), // APKCombo(), // Can't get past their scraping blocking yet (get 403 Forbidden) Mullvad(), Signal(), diff --git a/pubspec.yaml b/pubspec.yaml index f643b70..8ed048c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,7 +20,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 0.14.10+202 # When changing this, update the tag in main() accordingly environment: - sdk: '>=2.18.2 <3.0.0' + sdk: '>=3.0.0 <4.0.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions From b178b1d780b576a648c871ce5d7a09e72b12b17d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 9 Sep 2023 05:46:56 -0400 Subject: [PATCH 411/600] Bugfix --- lib/app_sources/uptodown.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/app_sources/uptodown.dart b/lib/app_sources/uptodown.dart index 4075ee1..dd9b68a 100644 --- a/lib/app_sources/uptodown.dart +++ b/lib/app_sources/uptodown.dart @@ -35,11 +35,11 @@ class Uptodown extends AppSource { String? version = html.querySelector('div.version')?.innerHtml; String? apkUrl = html.querySelector('#detail-download-button')?.attributes['data-url']; - String? name = html.querySelector('#detail-app-name')?.innerHtml; - String? author = html.querySelector('#author-link')?.innerHtml; + String? name = html.querySelector('#detail-app-name')?.innerHtml.trim(); + String? author = html.querySelector('#author-link')?.innerHtml.trim(); var detailElements = html.querySelectorAll('#technical-information td'); - String? appId = (detailElements.elementAtOrNull(2))?.innerHtml; - String? dateStr = (detailElements.elementAtOrNull(29))?.innerHtml; + String? appId = (detailElements.elementAtOrNull(2))?.innerHtml.trim(); + String? dateStr = (detailElements.elementAtOrNull(29))?.innerHtml.trim(); return Map.fromEntries([ MapEntry('version', version), MapEntry('apkUrl', apkUrl), From 94bd0774fb24bacddc45171e07908fa74e30c3d7 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 9 Sep 2023 06:00:36 -0400 Subject: [PATCH 412/600] Make release notes tap target more obvious (#860) --- lib/pages/apps.dart | 57 +++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 835be74..ebbc272 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -449,33 +449,40 @@ class AppsPageState extends State { : const SizedBox.shrink(), GestureDetector( onTap: showChangesFn, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Row(mainAxisSize: MainAxisSize.min, children: [ - Container( - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context).size.width / 4), - child: Text(getVersionText(index), - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.end)), - ]), - Row( - mainAxisSize: MainAxisSize.min, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Theme.of(context).primaryColor.withAlpha(20)), + padding: const EdgeInsets.fromLTRB(12, 0, 12, 0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, children: [ - Text( - getChangesButtonString(index, showChangesFn != null), - style: TextStyle( - fontStyle: FontStyle.italic, - decoration: showChangesFn != null - ? TextDecoration.underline - : TextDecoration.none), - ) + Row(mainAxisSize: MainAxisSize.min, children: [ + Container( + constraints: BoxConstraints( + maxWidth: + MediaQuery.of(context).size.width / 4), + child: Text(getVersionText(index), + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.end)), + ]), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + getChangesButtonString( + index, showChangesFn != null), + style: TextStyle( + fontStyle: FontStyle.italic, + decoration: showChangesFn != null + ? TextDecoration.underline + : TextDecoration.none), + ) + ], + ), ], - ), - ], - )) + ))) ], ); From c53a15696921b486ef780e0001ae44c868085ad0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 9 Sep 2023 06:48:55 -0400 Subject: [PATCH 413/600] Slight UI tweak --- assets/translations/br.json | 2 +- assets/translations/bs.json | 2 +- assets/translations/de.json | 2 +- assets/translations/en.json | 2 +- assets/translations/es.json | 2 +- assets/translations/fa.json | 2 +- assets/translations/fr.json | 2 +- assets/translations/hu.json | 2 +- assets/translations/it.json | 2 +- assets/translations/ja.json | 2 +- assets/translations/pl.json | 2 +- assets/translations/ru.json | 2 +- assets/translations/zh.json | 2 +- lib/pages/add_app.dart | 26 +++++++++++++------------- 14 files changed, 26 insertions(+), 26 deletions(-) diff --git a/assets/translations/br.json b/assets/translations/br.json index ad6a4a5..9073850 100644 --- a/assets/translations/br.json +++ b/assets/translations/br.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "Procurar (Apenas Algumas Fontes)", "search": "Procurar", "additionalOptsFor": "Opções Adicionais para {}", - "supportedSourcesBelow": "Fontes Compatíveis:", + "supportedSources": "Fontes Compatíveis", "trackOnlyInBrackets": "(Apenas Seguir)", "searchableInBrackets": "(Pesquisável)", "appsString": "Apps", diff --git a/assets/translations/bs.json b/assets/translations/bs.json index b65d8a3..7b7d657 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "Pretraživanje (samo neki izvori)", "search": "Pretraživanje", "additionalOptsFor": "Dodatne opcije za {}", - "supportedSourcesBelow": "Podržani izvori:", + "supportedSources": "Podržani izvori", "trackOnlyInBrackets": "(Samo za praćenje)", "searchableInBrackets": "(Može se pretraživati)", "appsString": "Aplikacije", diff --git a/assets/translations/de.json b/assets/translations/de.json index d5a016b..300844d 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "Suche (nur bestimmte Quellen)", "search": "Suchen", "additionalOptsFor": "Zusatzoptionen für {}", - "supportedSourcesBelow": "Unterstützte Quellen:", + "supportedSources": "Unterstützte Quellen", "trackOnlyInBrackets": "(Nur Nachverfolgen)", "searchableInBrackets": "(Durchsuchbar)", "appsString": "Apps", diff --git a/assets/translations/en.json b/assets/translations/en.json index f5473be..abf4080 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "Search (Some Sources Only)", "search": "Search", "additionalOptsFor": "Additional Options for {}", - "supportedSourcesBelow": "Supported Sources:", + "supportedSources": "Supported Sources", "trackOnlyInBrackets": "(Track-Only)", "searchableInBrackets": "(Searchable)", "appsString": "Apps", diff --git a/assets/translations/es.json b/assets/translations/es.json index 62fc6e7..75ea294 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "Buscar (Solo Algunas Fuentes)", "search": "Buscar", "additionalOptsFor": "Opciones Adicionales para {}", - "supportedSourcesBelow": "Fuentes Soportadas:", + "supportedSources": "Fuentes Soportadas", "trackOnlyInBrackets": "(Solo Seguimiento)", "searchableInBrackets": "(Soporta Búsquedas)", "appsString": "Aplicaciones", diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 466b976..5afe7df 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "جستجو (فقط برخی منابع)", "search": "جستجو کردن", "additionalOptsFor": "گزینه های اضافی برای {}", - "supportedSourcesBelow": "منابع پشتیبانی شده:", + "supportedSources": "منابع پشتیبانی شده", "trackOnlyInBrackets": "«فقط ردیابی»", "searchableInBrackets": "(قابل جستجو)", "appsString": "برنامه ها", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index a23667b..fbd15c1 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "Rechercher (certaines sources uniquement)", "search": "Rechercher", "additionalOptsFor": "Options supplémentaires pour {}", - "supportedSourcesBelow": "Sources prises en charge :", + "supportedSources": "Sources prises en charge ", "trackOnlyInBrackets": "(Suivi uniquement)", "searchableInBrackets": "(Recherchable)", "appsString": "Applications", diff --git a/assets/translations/hu.json b/assets/translations/hu.json index dfd1274..0c5d98f 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "Keresés (csak egyes források)", "search": "Keresés", "additionalOptsFor": "További lehetőségek a következőhöz: {}", - "supportedSourcesBelow": "Támogatott források:", + "supportedSources": "Támogatott források", "trackOnlyInBrackets": "(Csak nyomonkövetés)", "searchableInBrackets": "(Kereshető)", "appsString": "Appok", diff --git a/assets/translations/it.json b/assets/translations/it.json index c46ddbd..d63547d 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "Cerca (solo per alcune fonti)", "search": "Cerca", "additionalOptsFor": "Opzioni aggiuntive per {}", - "supportedSourcesBelow": "Fonti supportate:", + "supportedSources": "Fonti supportate", "trackOnlyInBrackets": "(Solo-Monitoraggio)", "searchableInBrackets": "(ricercabile)", "appsString": "App", diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 741597e..81d0e18 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "検索 (一部ソースのみ)", "search": "検索", "additionalOptsFor": "{}の追加オプション", - "supportedSourcesBelow": "対応するソース:", + "supportedSources": "対応するソース", "trackOnlyInBrackets": "(追跡のみ)", "searchableInBrackets": "(検索可能)", "appsString": "アプリ", diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 5d419ef..bda97f1 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -50,7 +50,7 @@ "searchSomeSourcesLabel": "Szukaj (tylko niektóre źródła)", "search": "Szukaj", "additionalOptsFor": "Dodatkowe opcje dla {}", - "supportedSourcesBelow": "Obsługiwane źródła:", + "supportedSources": "Obsługiwane źródła", "trackOnlyInBrackets": "(tylko obserwowane)", "searchableInBrackets": "(Wyszukiwalne)", "appsString": "Aplikacje", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 34b48f1..98c167e 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "Поиск (только в некоторых источниках)", "search": "Поиск", "additionalOptsFor": "Дополнительные опции для {}", - "supportedSourcesBelow": "Поддерживаемые источники:", + "supportedSources": "Поддерживаемые источники", "trackOnlyInBrackets": "(Только для отслеживания)", "searchableInBrackets": "(Поиск)", "appsString": "Приложения", diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 902034d..a3024e5 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -41,7 +41,7 @@ "searchSomeSourcesLabel": "搜索(仅支持部分来源)", "search": "搜索", "additionalOptsFor": "{} 的更多选项", - "supportedSourcesBelow": "支持的来源:", + "supportedSources": "支持的来源", "trackOnlyInBrackets": "(仅追踪)", "searchableInBrackets": "(可搜索)", "appsString": "应用列表", diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 2438270..ee8099e 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -463,14 +463,12 @@ class _AddAppPageState extends State { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - const SizedBox( - height: 48, - ), Text( - tr('supportedSourcesBelow'), + tr('supportedSources'), + style: const TextStyle(fontWeight: FontWeight.bold), ), const SizedBox( - height: 8, + height: 16, ), ...sourceProvider.sources .map((e) => GestureDetector( @@ -524,15 +522,17 @@ class _AddAppPageState extends State { : const SizedBox(); }, future: pickedSource?.getSourceNote()), - const SizedBox( - height: 16, + SizedBox( + height: pickedSource != null ? 16 : 96, ), - if (pickedSource != null) - getAdditionalOptsCol() - else - getSourcesListWidget(), - const SizedBox( - height: 8, + if (pickedSource != null) getAdditionalOptsCol(), + if (pickedSource == null) + const Divider( + height: 48, + ), + if (pickedSource == null) getSourcesListWidget(), + SizedBox( + height: pickedSource != null ? 8 : 2, ), ])), ) From 4dc007a4f6c4b76b0871a64c29e73ee190f41eaf Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 9 Sep 2023 06:50:13 -0400 Subject: [PATCH 414/600] Update packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 20 ++++++++++---------- pubspec.yaml | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 91d86b5..8b21863 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.10'; +const String currentVersion = '0.14.11'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index c394bd0..04ca07a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -538,18 +538,18 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "63e5216aae014a72fe9579ccd027323395ce7a98271d9defa9d57320d001af81" + sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5 url: "https://pub.dev" source: hosted - version: "10.4.3" + version: "10.4.5" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: d74e77a5ecd38649905db0a7d05ef16bed42ff263b9efb73ed794317c5764ec3 + sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47" url: "https://pub.dev" source: hosted - version: "10.3.4" + version: "10.3.6" permission_handler_apple: dependency: transitive description: @@ -562,10 +562,10 @@ packages: dependency: transitive description: name: permission_handler_platform_interface - sha256: "7c6b1500385dd1d2ca61bb89e2488ca178e274a69144d26bbd65e33eae7c02a9" + sha256: f2343e9fa9c22ae4fd92d4732755bfe452214e7189afcc097380950cf567b4b2 url: "https://pub.dev" source: hosted - version: "3.11.3" + version: "3.11.5" permission_handler_windows: dependency: transitive description: @@ -879,18 +879,18 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "0d8f5ac96a155e672129bf94c7abf625de01241d44d269dbaff083f1b4deb1aa" + sha256: "9427774649fd3c8b7ff53523051395d13aed2ca355822b822e6493d79f5fc05a" url: "https://pub.dev" source: hosted - version: "3.9.5" + version: "3.10.0" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "9d32a63a5ee111b37482cb3eac3379b9f0992afd27a52ee30279dbf06f41918b" + sha256: "6d9213c65f1060116757a7c473247c60f3f7f332cac33dc417c9e362a9a13e4f" url: "https://pub.dev" source: hosted - version: "2.5.1" + version: "2.6.0" webview_flutter_wkwebview: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8ed048c..d3c80c3 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.14.10+202 # When changing this, update the tag in main() accordingly +version: 0.14.11+203 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 09421230f2b6fce087b7dfa821b016e07adbf0c6 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 9 Sep 2023 07:29:35 -0400 Subject: [PATCH 415/600] Make less obvious target highlighting optional --- assets/translations/br.json | 1 + assets/translations/bs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/pages/apps.dart | 6 +++++- lib/pages/settings.dart | 15 +++++++++++++++ lib/providers/settings_provider.dart | 9 +++++++++ 16 files changed, 42 insertions(+), 1 deletion(-) diff --git a/assets/translations/br.json b/assets/translations/br.json index 9073850..6a70a80 100644 --- a/assets/translations/br.json +++ b/assets/translations/br.json @@ -253,6 +253,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 7b7d657..254f11c 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -250,6 +250,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 300844d..81c2ea7 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -250,6 +250,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index abf4080..f286c68 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -253,6 +253,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 75ea294..8893461 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -250,6 +250,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 5afe7df..adf44c2 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -250,6 +250,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index fbd15c1..cfae07f 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -250,6 +250,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 0c5d98f..1913544 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -249,6 +249,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "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 d63547d..b211e4e 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -250,6 +250,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 81d0e18..1181f88 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -251,6 +251,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index bda97f1..1b43982 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -256,6 +256,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 98c167e..49bc22d 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -250,6 +250,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index a3024e5..ac43598 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -251,6 +251,7 @@ "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index ebbc272..4228be8 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -452,7 +452,11 @@ class AppsPageState extends State { child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), - color: Theme.of(context).primaryColor.withAlpha(20)), + color: Theme.of(context).primaryColor.withAlpha( + (settingsProvider.highlightTouchTargets && + showChangesFn != null) + ? 20 + : 0)), padding: const EdgeInsets.fromLTRB(12, 0, 12, 0), child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index ec19efb..ec3d1d9 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -484,6 +484,21 @@ class _SettingsPageState extends State { }) ], ), + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text(tr('highlightTouchTargets'))), + Switch( + value: + settingsProvider.highlightTouchTargets, + onChanged: (value) { + settingsProvider.highlightTouchTargets = + value; + }) + ], + ), height32, Text( tr('categories'), diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 0ccae4a..a95e2b3 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -348,4 +348,13 @@ class SettingsProvider with ChangeNotifier { prefs?.setBool('showDebugOpts', val); notifyListeners(); } + + bool get highlightTouchTargets { + return prefs?.getBool('highlightTouchTargets') ?? false; + } + + set highlightTouchTargets(bool val) { + prefs?.setBool('highlightTouchTargets', val); + notifyListeners(); + } } From e4a55abcb360a3fedc0a0b64d00e6d446967d160 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 13:49:04 -0400 Subject: [PATCH 416/600] Fix Codeberg not finding APKs (#877) --- lib/app_sources/github.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 9c7cb73..15b9831 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -252,8 +252,10 @@ class GitHub extends AppSource { List> getReleaseAPKUrls(dynamic release) => (release['assets'] as List?) ?.map((e) { - return e['name'] != null && e['url'] != null - ? MapEntry(e['name'] as String, e['url'] as String) + return (e['name'] != null) && + ((e['url'] ?? e['browser_download_url']) != null) + ? MapEntry(e['name'] as String, + (e['url'] ?? e['browser_download_url']) as String) : const MapEntry('', ''); }) .where((element) => element.key.toLowerCase().endsWith('.apk')) From 8f44338e762091b55f8bbc5a6d7a3c2a9bf6b875 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 13:56:39 -0400 Subject: [PATCH 417/600] Make touch highlight visible in dark theme (#860) --- lib/pages/apps.dart | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 4228be8..a980724 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -452,11 +452,13 @@ class AppsPageState extends State { child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), - color: Theme.of(context).primaryColor.withAlpha( - (settingsProvider.highlightTouchTargets && - showChangesFn != null) - ? 20 - : 0)), + color: settingsProvider.highlightTouchTargets && + showChangesFn != null + ? (Theme.of(context).brightness == Brightness.light + ? Theme.of(context).primaryColor + : Theme.of(context).primaryColorLight) + .withAlpha(20) + : null), padding: const EdgeInsets.fromLTRB(12, 0, 12, 0), child: Column( mainAxisAlignment: MainAxisAlignment.center, From b2af8448fd8a8d3e0cce0fd3f8974f7ede0ddb34 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 14:02:26 -0400 Subject: [PATCH 418/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8b21863..1b9fe28 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.11'; +const String currentVersion = '0.14.12'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index d3c80c3..4f48012 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.14.11+203 # When changing this, update the tag in main() accordingly +version: 0.14.12+204 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 27b1149d1cf1700582e7ad627b073f05184c4224 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 14:16:19 -0400 Subject: [PATCH 419/600] Fix padding when touch targets not highlighted --- lib/pages/apps.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index a980724..32eb8c3 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -459,7 +459,9 @@ class AppsPageState extends State { : Theme.of(context).primaryColorLight) .withAlpha(20) : null), - padding: const EdgeInsets.fromLTRB(12, 0, 12, 0), + padding: settingsProvider.highlightTouchTargets + ? const EdgeInsetsDirectional.fromSTEB(12, 0, 12, 0) + : const EdgeInsetsDirectional.fromSTEB(24, 0, 0, 0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, From 873a1a0683cf4c7df43b4094633df41374f41970 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 15:55:34 -0400 Subject: [PATCH 420/600] Allow for alternative app dirs (unfinished) --- lib/pages/app.dart | 6 ++-- lib/pages/apps.dart | 7 ++-- lib/providers/apps_provider.dart | 41 +++++++++------------ lib/providers/settings_provider.dart | 54 ++++++++++++++++++++++++++++ pubspec.lock | 8 +++++ pubspec.yaml | 1 + 6 files changed, 85 insertions(+), 32 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 45812d0..dcd52bd 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -338,9 +338,9 @@ class _AppPageState extends State { try { HapticFeedback.heavyImpact(); var res = await appsProvider.downloadAndInstallLatestApps( - app?.app.id != null ? [app!.app.id] : [], - globalNavigatorKey.currentContext, - settingsProvider); + app?.app.id != null ? [app!.app.id] : [], + globalNavigatorKey.currentContext, + ); if (app?.app.installedVersion != null && !trackOnly) { // ignore: use_build_context_synchronously showError(tr('appsUpdated'), context); diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 32eb8c3..3f4cc30 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -381,8 +381,7 @@ class AppsPageState extends State { : () { appsProvider.downloadAndInstallLatestApps( [listedApps[appIndex].app.id], - globalNavigatorKey.currentContext, - settingsProvider).catchError((e) { + globalNavigatorKey.currentContext).catchError((e) { showError(e, context); return []; }); @@ -699,8 +698,8 @@ class AppsPageState extends State { toInstall.addAll(trackOnlyUpdateIdsAllOrSelected); } appsProvider - .downloadAndInstallLatestApps(toInstall, - globalNavigatorKey.currentContext, settingsProvider) + .downloadAndInstallLatestApps( + toInstall, globalNavigatorKey.currentContext) .catchError((e) { showError(e, context); return []; diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 208b222..63a061e 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -150,6 +150,7 @@ class AppsProvider with ChangeNotifier { late Stream? foregroundStream; late StreamSubscription? foregroundSubscription; late Directory APKDir; + late SettingsProvider settingsProvider = SettingsProvider(); Iterable getAppValues() => apps.values.map((a) => a.deepCopy()); @@ -161,12 +162,12 @@ class AppsProvider with ChangeNotifier { if (isForeground) await loadApps(); }); () async { + await settingsProvider.initializeSettings(); var cacheDirs = await getExternalCacheDirectories(); if (cacheDirs?.isNotEmpty ?? false) { APKDir = cacheDirs!.first; } else { - APKDir = - Directory('${(await getExternalStorageDirectory())!.path}/apks'); + APKDir = Directory('${await settingsProvider.getAppDir()}/apks'); if (!APKDir.existsSync()) { APKDir.createSync(); } @@ -369,8 +370,7 @@ class AppsProvider with ChangeNotifier { .where((element) => element.downloadProgress != null) .isNotEmpty; - Future canInstallSilently( - App app, SettingsProvider settingsProvider) async { + Future canInstallSilently(App app) async { if (app.id == obtainiumId) { return false; } @@ -539,7 +539,6 @@ class AppsProvider with ChangeNotifier { getHost(apkUrl.value) != getHost(app.url) && context != null) { // ignore: use_build_context_synchronously - var settingsProvider = context.read(); if (!(settingsProvider.hideAPKOriginWarning) && // ignore: use_build_context_synchronously await showDialog( @@ -560,8 +559,8 @@ class AppsProvider with ChangeNotifier { // If no BuildContext is provided, apps that require user interaction are ignored // 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, SettingsProvider settingsProvider, + Future> downloadAndInstallLatestApps( + List appIds, BuildContext? context, {NotificationsProvider? notificationsProvider}) async { notificationsProvider = notificationsProvider ?? context?.read(); @@ -590,8 +589,7 @@ class AppsProvider with ChangeNotifier { apps[id]!.app.preferredApkIndex = urlInd; await saveApps([apps[id]!.app]); } - if (context != null || - await canInstallSilently(apps[id]!.app, settingsProvider)) { + if (context != null || await canInstallSilently(apps[id]!.app)) { appsToInstall.add(id); } } @@ -628,8 +626,7 @@ class AppsProvider with ChangeNotifier { downloadedDir = downloadedArtifact as DownloadedXApkDir; } var appId = downloadedFile?.appId ?? downloadedDir!.appId; - bool willBeSilent = - await canInstallSilently(apps[appId]!.app, settingsProvider); + bool willBeSilent = await canInstallSilently(apps[appId]!.app); if (!(await settingsProvider.getInstallPermission(enforce: false))) { throw ObtainiumError(tr('cancelled')); } @@ -678,8 +675,8 @@ class AppsProvider with ChangeNotifier { } Future getAppsDir() async { - Directory appsDir = Directory( - '${(await getExternalStorageDirectory())?.path as String}/app_data'); + Directory appsDir = + Directory('${await settingsProvider.getAppDir()}/app_data'); if (!appsDir.existsSync()) { appsDir.createSync(); } @@ -879,8 +876,6 @@ class AppsProvider with ChangeNotifier { .toList(); // After reconciliation, delete externally uninstalled Apps if needed if (removedAppIds.isNotEmpty) { - var settingsProvider = SettingsProvider(); - await settingsProvider.initializeSettings(); if (settingsProvider.removeOnExternalUninstall) { await removeApps(removedAppIds); } @@ -1114,8 +1109,8 @@ class AppsProvider with ChangeNotifier { logs.add('Error accessing Downloads (will use fallback): $e'); } if (!downloadsAccessible) { - exportDir = await getExternalStorageDirectory(); - path = exportDir!.path; + exportDir = Directory(await settingsProvider.getAppDir()); + path = exportDir.path; } File export = File( '${exportDir.path}/${tr('obtainiumExportHyphenatedLowercase')}-${DateTime.now().millisecondsSinceEpoch}.json'); @@ -1298,14 +1293,12 @@ Future bgUpdateCheck(int taskId, Map? params) async { NotificationsProvider notificationsProvider = NotificationsProvider(); AppsProvider appsProvider = AppsProvider(isBg: true); await appsProvider.loadApps(); - var settingsProvider = SettingsProvider(); - await settingsProvider.initializeSettings(); int maxAttempts = 4; params ??= {}; if (params['toCheck'] == null) { - settingsProvider.lastBGCheckTime = DateTime.now(); + appsProvider.settingsProvider.lastBGCheckTime = DateTime.now(); } List> toCheck = >[ ...(params['toCheck'] @@ -1335,7 +1328,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { var didCompleteChecking = false; CheckingUpdatesNotification? notif; var networkRestricted = false; - if (settingsProvider.bgUpdatesOnWiFiOnly) { + if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { var netResult = await (Connectivity().checkConnectivity()); networkRestricted = (netResult != ConnectivityResult.wifi) && (netResult != ConnectivityResult.ethernet); @@ -1355,8 +1348,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { App? newApp = await appsProvider.checkUpdate(appId); if (newApp != null) { if (networkRestricted || - !(await appsProvider.canInstallSilently( - app!.app, settingsProvider))) { + !(await appsProvider.canInstallSilently(app!.app))) { toNotify.add(newApp); } else { toInstall.add(MapEntry(appId, 0)); @@ -1442,8 +1434,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { try { logs.add( 'BG install task $taskId: Attempting to update $appId in the background.'); - await appsProvider.downloadAndInstallLatestApps( - [appId], null, settingsProvider, + await appsProvider.downloadAndInstallLatestApps([appId], null, notificationsProvider: notificationsProvider); await Future.delayed(const Duration( seconds: diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index a95e2b3..e96b5a7 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -1,6 +1,7 @@ // Exposes functions used to save/load app settings import 'dart:convert'; +import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -9,8 +10,10 @@ import 'package:obtainium/app_sources/github.dart'; import 'package:obtainium/main.dart'; import 'package:obtainium/providers/apps_provider.dart'; import 'package:obtainium/providers/source_provider.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:shared_storage/shared_storage.dart' as saf; String obtainiumTempId = 'imranr98_obtainium_${GitHub().host}'; String obtainiumId = 'dev.imranr.obtainium'; @@ -35,6 +38,7 @@ List updateIntervals = [15, 30, 60, 120, 180, 360, 720, 1440, 4320, 0] class SettingsProvider with ChangeNotifier { SharedPreferences? prefs; + String? defaultAppDir; bool justStarted = true; String sourceUrl = 'https://github.com/ImranR98/Obtainium'; @@ -42,6 +46,7 @@ class SettingsProvider with ChangeNotifier { // Not done in constructor as we want to be able to await it Future initializeSettings() async { prefs = await SharedPreferences.getInstance(); + defaultAppDir = (await getExternalStorageDirectory())!.path; notifyListeners(); } @@ -357,4 +362,53 @@ class SettingsProvider with ChangeNotifier { prefs?.setBool('highlightTouchTargets', val); notifyListeners(); } + + Future getAppDir() async { + return prefs?.getString('appDir') ?? defaultAppDir!; + } + + pickAppDir({bool useDefault = false}) async { + var existingSAFPerms = (await saf.persistedUriPermissions()) ?? []; + var currentAppDir = await getAppDir(); + if (currentAppDir != defaultAppDir) { + currentAppDir = currentAppDir.replaceFirst( + '/storage/emulated/0/', '/tree/primary%3A'); + } + String? newAppDir; + if (!useDefault) { + var target = (await saf.openDocumentTree()); + if (target != null) { + newAppDir = target.path + .replaceFirst('/tree/primary%3A', '/storage/emulated/0/'); + } + } else { + newAppDir = defaultAppDir; + } + newAppDir ??= defaultAppDir; + if (currentAppDir != newAppDir) { + moveDirectoryContents(Directory(currentAppDir), Directory(newAppDir!)); + prefs?.setString('appDir', newAppDir); + notifyListeners(); + } + for (var e in existingSAFPerms) { + await saf.releasePersistableUriPermission(e.uri); + } + } +} + +void moveDirectoryContents(Directory sourceDir, Directory destinationDir) { + if (!destinationDir.existsSync()) { + destinationDir.createSync(recursive: true); + } + List contents = sourceDir.listSync(); + for (FileSystemEntity entity in contents) { + String newPath = '${destinationDir.path}/${entity.uri.pathSegments.last}'; + if (entity is File) { + entity.renameSync(newPath); + } else if (entity is Directory) { + Directory newDestinationDir = Directory(newPath); + moveDirectoryContents(entity, newDestinationDir); + entity.deleteSync(recursive: true); + } + } } diff --git a/pubspec.lock b/pubspec.lock index 04ca07a..cdacfb5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -686,6 +686,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.1" + shared_storage: + dependency: "direct main" + description: + name: shared_storage + sha256: "7c65a9d64f0f5521256be974cfd74010af12196657cec9f9fb7b03b2f11bcaf6" + url: "https://pub.dev" + source: hosted + version: "0.8.0" sky_engine: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 4f48012..355bbd4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -65,6 +65,7 @@ dependencies: flutter_archive: ^5.0.0 hsluv: ^1.1.3 connectivity_plus: ^4.0.2 + shared_storage: ^0.8.0 dev_dependencies: flutter_test: From 6e735b17633975dfcd4161b0aab5ec3eefb0f138 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 22:24:18 -0400 Subject: [PATCH 421/600] Enable auto-export on update checks --- assets/translations/br.json | 2 + assets/translations/bs.json | 6 +- assets/translations/de.json | 2 + assets/translations/en.json | 2 + assets/translations/es.json | 2 + assets/translations/fa.json | 2 + assets/translations/fr.json | 2 + assets/translations/hu.json | 2 + assets/translations/it.json | 2 + assets/translations/ja.json | 2 + assets/translations/pl.json | 2 + assets/translations/ru.json | 2 + assets/translations/zh.json | 2 + lib/app_sources/html.dart | 5 +- lib/pages/apps.dart | 5 ++ lib/pages/import_export.dart | 57 +++++++++++++++++-- lib/providers/apps_provider.dart | 83 +++++++++++++++++++--------- lib/providers/settings_provider.dart | 58 ++++++++----------- lib/providers/source_provider.dart | 14 +++++ 19 files changed, 182 insertions(+), 70 deletions(-) diff --git a/assets/translations/br.json b/assets/translations/br.json index 6a70a80..fa734f4 100644 --- a/assets/translations/br.json +++ b/assets/translations/br.json @@ -254,6 +254,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 254f11c..a6ca2ab 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -111,7 +111,7 @@ "dark": "Tamna", "light": "Svijetla", "followSystem": "Pratite sistem", - "obtainium": "Obtainium", + "obtainium": "Obtainium", "materialYou": "Material You", "useBlackTheme": "Koristite čisto crnu tamnu temu", "appSortBy": "Aplikacije sortirane po", @@ -251,7 +251,9 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", - "removeAppQuestion": { + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" }, diff --git a/assets/translations/de.json b/assets/translations/de.json index 81c2ea7..d6a3a10 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -251,6 +251,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index f286c68..185e1e9 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -254,6 +254,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 8893461..aaf5dcd 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -251,6 +251,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index adf44c2..44b363b 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -251,6 +251,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index cfae07f..0081dbe 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -251,6 +251,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 1913544..b694f45 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -250,6 +250,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "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 b211e4e..31e4f59 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -251,6 +251,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 1181f88..33b3efa 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -252,6 +252,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 1b43982..25151f4 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -257,6 +257,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 49bc22d..3635f30 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -251,6 +251,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index ac43598..519425c 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -252,6 +252,8 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index a2a25cc..8676af9 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -124,10 +124,7 @@ class HTML extends AppSource { additionalValidators: [ (value) { value ??= '1'; - if (int.tryParse(value) == null) { - return tr('invalidInput'); - } - return null; + return intValidator(value); } ]) ] diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 3f4cc30..9eb0ff5 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -74,6 +74,11 @@ class AppsPageState extends State { setState(() { refreshingSince = null; }); + if (settingsProvider.autoExportOnUpdateCheckKeepNum > 0) { + appsProvider.exportApps(isAuto: true).then((value) { + appsProvider.trimAutoExports(); + }); + } }); } diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index e2ebdf9..8bbb09c 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -104,8 +104,12 @@ class _ImportExportPageState extends State { runObtainiumExport() { HapticFeedback.selectionClick(); - appsProvider.exportApps().then((String path) { - showError(tr('exportedTo', args: [path]), context); + appsProvider + .exportApps(pickOnly: settingsProvider.exportDir == null) + .then((String? result) { + if (result != null) { + showError(tr('exportedTo', args: [result]), context); + } }).catchError((e) { showError(e, context); }); @@ -310,7 +314,10 @@ class _ImportExportPageState extends State { importInProgress ? null : runObtainiumExport, - child: Text(tr('obtainiumExport')))), + child: Text(tr( + settingsProvider.exportDir != null + ? 'obtainiumExport' + : 'pickExportDirKeepLastN')))), const SizedBox( width: 16, ), @@ -323,6 +330,48 @@ class _ImportExportPageState extends State { child: Text(tr('obtainiumImport')))) ], ), + if (settingsProvider.exportDir != null) + Column( + children: [ + const SizedBox(height: 16), + GeneratedForm( + items: [ + [ + GeneratedFormTextField( + 'autoExportOnUpdateCheckKeepNum', + label: tr( + 'autoExportOnUpdateCheckKeepNum'), + required: false, + defaultValue: settingsProvider + .autoExportOnUpdateCheckKeepNum + .toString(), + textInputType: const TextInputType + .numberWithOptions(), + additionalValidators: [ + (value) { + value ??= settingsProvider + .autoExportOnUpdateCheckKeepNum + .toString(); + return intValidator(value, + positive: true); + } + ]) + ] + ], + onValueChanges: (value, valid, isBuilding) { + if (valid && !isBuilding) { + if (value[ + 'autoExportOnUpdateCheckKeepNum'] != + null) { + settingsProvider + .autoExportOnUpdateCheckKeepNum = + int.parse(value[ + 'autoExportOnUpdateCheckKeepNum']); + } + } + }), + ], + ), if (importInProgress) const Column( children: [ @@ -399,7 +448,7 @@ class _ImportExportPageState extends State { fontStyle: FontStyle.italic, fontSize: 12)), const SizedBox( height: 8, - ) + ), ], ))) ])); diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 63a061e..4158fb9 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -16,6 +16,7 @@ import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/components/generated_form_modal.dart'; import 'package:obtainium/custom_errors.dart'; @@ -31,6 +32,7 @@ import 'package:obtainium/providers/source_provider.dart'; import 'package:http/http.dart'; import 'package:android_intent_plus/android_intent.dart'; import 'package:flutter_archive/flutter_archive.dart'; +import 'package:shared_storage/shared_storage.dart' as saf; final pm = AndroidPackageManager(); @@ -167,7 +169,8 @@ class AppsProvider with ChangeNotifier { if (cacheDirs?.isNotEmpty ?? false) { APKDir = cacheDirs!.first; } else { - APKDir = Directory('${await settingsProvider.getAppDir()}/apks'); + APKDir = + Directory('${(await getExternalStorageDirectory())!.path}/apks'); if (!APKDir.existsSync()) { APKDir.createSync(); } @@ -676,7 +679,7 @@ class AppsProvider with ChangeNotifier { Future getAppsDir() async { Directory appsDir = - Directory('${await settingsProvider.getAppDir()}/app_data'); + Directory('${(await getExternalStorageDirectory())!.path}/app_data'); if (!appsDir.existsSync()) { appsDir.createSync(); } @@ -1091,32 +1094,58 @@ class AppsProvider with ChangeNotifier { return updateAppIds; } - Future exportApps() async { - if ((await DeviceInfoPlugin().androidInfo).version.sdkInt <= 29) { - if (await Permission.storage.isDenied) { - await Permission.storage.request(); + Future exportApps({bool pickOnly = false, isAuto = false}) async { + if (isAuto) { + logs.add('Started auto-export.'); + } + var exportDir = settingsProvider.exportDir; + if (exportDir == null || pickOnly) { + await settingsProvider.pickExportDirKeepLastN(); + exportDir = settingsProvider.exportDir; + } + if (exportDir == null) { + throw ObtainiumError(tr('unexpectedError')); + } + String? returnPath; + if (!pickOnly) { + var result = await saf.createFile(exportDir, + displayName: + '${tr('obtainiumExportHyphenatedLowercase')}-${DateTime.now().toIso8601String().replaceAll(':', '-')}${isAuto ? '-auto' : ''}.json', + mimeType: 'application/json', + content: jsonEncode(apps.values.map((e) => e.app.toJson()).toList())); + if (result == null) { + throw ObtainiumError(tr('unexpectedError')); } - if (await Permission.storage.isDenied) { - throw ObtainiumError(tr('storagePermissionDenied')); + returnPath = + exportDir.pathSegments.join('/').replaceFirst('tree/primary:', ''); + } + return returnPath; + } + + Future trimAutoExports() async { + var exportDir = settingsProvider.exportDir; + if (exportDir != null) { + var files = await saf + .listFiles(exportDir, columns: [saf.DocumentFileColumn.id]).toList(); + var maxCount = settingsProvider.autoExportOnUpdateCheckKeepNum; + if (files.length > maxCount) { + files.sort((a, b) { + if (a.name == null) { + return -1; + } else if (b.name == null) { + return 1; + } else { + return compareAlphaNumeric(a.name!, b.name!); + } + }); + files = files.reversed.toList(); + logs.add( + 'Deleting auto-exports older than ${files[maxCount - 1].uri.pathSegments.last}.'); + files.sublist(maxCount).forEach((f) { + saf.delete(f.uri); + }); } } - Directory? exportDir = Directory('/storage/emulated/0/Download'); - String path = 'Downloads'; // TODO: See if hardcoding this can be avoided - var downloadsAccessible = false; - try { - downloadsAccessible = exportDir.existsSync(); - } catch (e) { - logs.add('Error accessing Downloads (will use fallback): $e'); - } - if (!downloadsAccessible) { - exportDir = Directory(await settingsProvider.getAppDir()); - path = exportDir.path; - } - File export = File( - '${exportDir.path}/${tr('obtainiumExportHyphenatedLowercase')}-${DateTime.now().millisecondsSinceEpoch}.json'); - export.writeAsStringSync( - jsonEncode(apps.values.map((e) => e.app.toJson()).toList())); - return path; } Future importApps(String appsJSON) async { @@ -1402,6 +1431,10 @@ Future bgUpdateCheck(int taskId, Map? params) async { if (toNotify.isNotEmpty) { notificationsProvider.notify(UpdateNotification(toNotify)); } + if (appsProvider.settingsProvider.autoExportOnUpdateCheckKeepNum > 0) { + await appsProvider.exportApps(isAuto: true); + await appsProvider.trimAutoExports(); + } } // If you're done checking and found some silently installable updates, schedule another task which will run in install mode if (didCompleteChecking && toInstall.isNotEmpty) { diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index e96b5a7..984d3d9 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -1,7 +1,6 @@ // Exposes functions used to save/load app settings import 'dart:convert'; -import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -363,52 +362,41 @@ class SettingsProvider with ChangeNotifier { notifyListeners(); } - Future getAppDir() async { - return prefs?.getString('appDir') ?? defaultAppDir!; + Uri? get exportDir { + var uriString = prefs?.getString('exportDir'); + if (uriString != null) { + return Uri.parse(uriString); + } else { + return null; + } } - pickAppDir({bool useDefault = false}) async { + Future pickExportDirKeepLastN({bool remove = false}) async { var existingSAFPerms = (await saf.persistedUriPermissions()) ?? []; - var currentAppDir = await getAppDir(); - if (currentAppDir != defaultAppDir) { - currentAppDir = currentAppDir.replaceFirst( - '/storage/emulated/0/', '/tree/primary%3A'); + var currentOneWayDataSyncDir = exportDir; + Uri? newOneWayDataSyncDir; + if (!remove) { + newOneWayDataSyncDir = (await saf.openDocumentTree()); } - String? newAppDir; - if (!useDefault) { - var target = (await saf.openDocumentTree()); - if (target != null) { - newAppDir = target.path - .replaceFirst('/tree/primary%3A', '/storage/emulated/0/'); + if (currentOneWayDataSyncDir?.path != newOneWayDataSyncDir?.path) { + if (newOneWayDataSyncDir == null) { + prefs?.remove('exportDir'); + } else { + prefs?.setString('exportDir', newOneWayDataSyncDir.toString()); } - } else { - newAppDir = defaultAppDir; - } - newAppDir ??= defaultAppDir; - if (currentAppDir != newAppDir) { - moveDirectoryContents(Directory(currentAppDir), Directory(newAppDir!)); - prefs?.setString('appDir', newAppDir); notifyListeners(); } for (var e in existingSAFPerms) { await saf.releasePersistableUriPermission(e.uri); } } -} -void moveDirectoryContents(Directory sourceDir, Directory destinationDir) { - if (!destinationDir.existsSync()) { - destinationDir.createSync(recursive: true); + int get autoExportOnUpdateCheckKeepNum { + return prefs?.getInt('autoExportOnUpdateCheckKeepNum') ?? 0; } - List contents = sourceDir.listSync(); - for (FileSystemEntity entity in contents) { - String newPath = '${destinationDir.path}/${entity.uri.pathSegments.last}'; - if (entity is File) { - entity.renameSync(newPath); - } else if (entity is Directory) { - Directory newDestinationDir = Directory(newPath); - moveDirectoryContents(entity, newDestinationDir); - entity.deleteSync(recursive: true); - } + + set autoExportOnUpdateCheckKeepNum(int val) { + prefs?.setInt('autoExportOnUpdateCheckKeepNum', val); + notifyListeners(); } } diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 3c06be2..43a0f1e 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -521,6 +521,20 @@ regExValidator(String? value) { return null; } +intValidator(String? value, {bool positive = false}) { + if (value == null) { + return tr('invalidInput'); + } + var num = int.tryParse(value); + if (num == null) { + return tr('invalidInput'); + } + if (positive && num <= 0) { + return tr('invalidInput'); + } + return null; +} + class SourceProvider { // Add more source classes here so they are available via the service List get sources => [ From 53cf4d0234d410f481e6d3632e405b924696c6d2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 22:35:28 -0400 Subject: [PATCH 422/600] Pick export dir + auto-export (#283, #600) --- assets/translations/br.json | 2 +- assets/translations/bs.json | 2 +- assets/translations/de.json | 2 +- assets/translations/en.json | 2 +- assets/translations/es.json | 2 +- assets/translations/fa.json | 2 +- assets/translations/fr.json | 2 +- assets/translations/hu.json | 2 +- assets/translations/it.json | 2 +- assets/translations/ja.json | 2 +- assets/translations/pl.json | 2 +- assets/translations/ru.json | 2 +- assets/translations/zh.json | 2 +- lib/main.dart | 2 +- lib/pages/apps.dart | 5 ---- lib/pages/import_export.dart | 35 ++++++---------------- lib/providers/apps_provider.dart | 44 ++++++++-------------------- lib/providers/settings_provider.dart | 8 ++--- pubspec.yaml | 2 +- 19 files changed, 41 insertions(+), 81 deletions(-) diff --git a/assets/translations/br.json b/assets/translations/br.json index fa734f4..96e9e7d 100644 --- a/assets/translations/br.json +++ b/assets/translations/br.json @@ -255,7 +255,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/bs.json b/assets/translations/bs.json index a6ca2ab..01d0d2b 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -252,7 +252,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index d6a3a10..f6f9d0e 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -252,7 +252,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 185e1e9..4395c68 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -255,7 +255,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index aaf5dcd..b662041 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -252,7 +252,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 44b363b..c3f5274 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -252,7 +252,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 0081dbe..8576909 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -252,7 +252,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index b694f45..845e313 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -251,7 +251,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "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 31e4f59..7fec3c8 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -252,7 +252,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 33b3efa..541da17 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -253,7 +253,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 25151f4..04f8322 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -258,7 +258,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 3635f30..690cd53 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -252,7 +252,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 519425c..66fc426 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -253,7 +253,7 @@ "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", - "autoExportOnUpdateCheckKeepNum": "Auto-export on update check (keep last N auto-exports)", + "autoExportOnChanges": "Auto-export on changes", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/main.dart b/lib/main.dart index 1b9fe28..0b2338d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.12'; +const String currentVersion = '0.14.13'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 9eb0ff5..3f4cc30 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -74,11 +74,6 @@ class AppsPageState extends State { setState(() { refreshingSince = null; }); - if (settingsProvider.autoExportOnUpdateCheckKeepNum > 0) { - appsProvider.exportApps(isAuto: true).then((value) { - appsProvider.trimAutoExports(); - }); - } }); } diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index 8bbb09c..c398532 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -337,36 +337,19 @@ class _ImportExportPageState extends State { GeneratedForm( items: [ [ - GeneratedFormTextField( - 'autoExportOnUpdateCheckKeepNum', - label: tr( - 'autoExportOnUpdateCheckKeepNum'), - required: false, - defaultValue: settingsProvider - .autoExportOnUpdateCheckKeepNum - .toString(), - textInputType: const TextInputType - .numberWithOptions(), - additionalValidators: [ - (value) { - value ??= settingsProvider - .autoExportOnUpdateCheckKeepNum - .toString(); - return intValidator(value, - positive: true); - } - ]) + GeneratedFormSwitch( + 'autoExportOnChanges', + label: tr('autoExportOnChanges'), + defaultValue: + settingsProvider.autoExportOnChanges, + ) ] ], onValueChanges: (value, valid, isBuilding) { if (valid && !isBuilding) { - if (value[ - 'autoExportOnUpdateCheckKeepNum'] != - null) { - settingsProvider - .autoExportOnUpdateCheckKeepNum = - int.parse(value[ - 'autoExportOnUpdateCheckKeepNum']); + if (value['autoExportOnChanges'] != null) { + settingsProvider.autoExportOnChanges = + value['autoExportOnChanges'] == true; } } }), diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 4158fb9..fd10a09 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -16,7 +16,6 @@ import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/components/generated_form_modal.dart'; import 'package:obtainium/custom_errors.dart'; @@ -917,6 +916,7 @@ class AppsProvider with ChangeNotifier { } } notifyListeners(); + await exportApps(isAuto: true); } Future removeApps(List appIds) async { @@ -938,6 +938,7 @@ class AppsProvider with ChangeNotifier { } if (appIds.isNotEmpty) { notifyListeners(); + await exportApps(isAuto: true); } } @@ -1097,6 +1098,17 @@ class AppsProvider with ChangeNotifier { Future exportApps({bool pickOnly = false, isAuto = false}) async { if (isAuto) { logs.add('Started auto-export.'); + var exportDir = settingsProvider.exportDir; + if (exportDir != null) { + var files = await saf.listFiles(exportDir, + columns: [saf.DocumentFileColumn.id]).toList(); + if (files.isNotEmpty) { + for (var f in files) { + saf.delete(f.uri); + } + logs.add('Previous auto-export deleted.'); + } + } } var exportDir = settingsProvider.exportDir; if (exportDir == null || pickOnly) { @@ -1122,32 +1134,6 @@ class AppsProvider with ChangeNotifier { return returnPath; } - Future trimAutoExports() async { - var exportDir = settingsProvider.exportDir; - if (exportDir != null) { - var files = await saf - .listFiles(exportDir, columns: [saf.DocumentFileColumn.id]).toList(); - var maxCount = settingsProvider.autoExportOnUpdateCheckKeepNum; - if (files.length > maxCount) { - files.sort((a, b) { - if (a.name == null) { - return -1; - } else if (b.name == null) { - return 1; - } else { - return compareAlphaNumeric(a.name!, b.name!); - } - }); - files = files.reversed.toList(); - logs.add( - 'Deleting auto-exports older than ${files[maxCount - 1].uri.pathSegments.last}.'); - files.sublist(maxCount).forEach((f) { - saf.delete(f.uri); - }); - } - } - } - Future importApps(String appsJSON) async { List importedApps = (jsonDecode(appsJSON) as List) .map((e) => App.fromJson(e)) @@ -1431,10 +1417,6 @@ Future bgUpdateCheck(int taskId, Map? params) async { if (toNotify.isNotEmpty) { notificationsProvider.notify(UpdateNotification(toNotify)); } - if (appsProvider.settingsProvider.autoExportOnUpdateCheckKeepNum > 0) { - await appsProvider.exportApps(isAuto: true); - await appsProvider.trimAutoExports(); - } } // If you're done checking and found some silently installable updates, schedule another task which will run in install mode if (didCompleteChecking && toInstall.isNotEmpty) { diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 984d3d9..c1ee5f5 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -391,12 +391,12 @@ class SettingsProvider with ChangeNotifier { } } - int get autoExportOnUpdateCheckKeepNum { - return prefs?.getInt('autoExportOnUpdateCheckKeepNum') ?? 0; + bool get autoExportOnChanges { + return prefs?.getBool('autoExportOnChanges') ?? false; } - set autoExportOnUpdateCheckKeepNum(int val) { - prefs?.setInt('autoExportOnUpdateCheckKeepNum', val); + set autoExportOnChanges(bool val) { + prefs?.setBool('autoExportOnChanges', val); notifyListeners(); } } diff --git a/pubspec.yaml b/pubspec.yaml index 355bbd4..09d66b8 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.14.12+204 # When changing this, update the tag in main() accordingly +version: 0.14.13+205 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 05f497787ee87aec018a230bee84616ee721864e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 22:37:32 -0400 Subject: [PATCH 423/600] Build script tweak --- build.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 0ad2412..76fcdde 100755 --- a/build.sh +++ b/build.sh @@ -4,7 +4,9 @@ CURR_DIR="$(pwd)" trap "cd "$CURR_DIR"" EXIT -git fetch && git merge origin/main && git push # Typically run after a PR to main, so bring dev up to date +if [ -z "$1" ]; then + git fetch && git merge origin/main && git push # Typically run after a PR to main, so bring dev up to date +fi rm ./build/app/outputs/flutter-apk/* 2>/dev/null # Get rid of older builds if any flutter build apk && flutter build apk --split-per-abi # Build (both split and combined APKs) for file in ./build/app/outputs/flutter-apk/*.sha1; do gpg --sign --detach-sig "$file"; done # Generate PGP signatures From 118e05a0fa3550ffe441b15cc16f65b3241161fa Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 22:47:04 -0400 Subject: [PATCH 424/600] Bugfix --- lib/providers/apps_provider.dart | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index fd10a09..9cf0eca 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1096,21 +1096,23 @@ class AppsProvider with ChangeNotifier { } Future exportApps({bool pickOnly = false, isAuto = false}) async { + var exportDir = settingsProvider.exportDir; if (isAuto) { + if (exportDir == null) { + logs.add('Skipping auto-export as dir is not set.'); + return null; + } logs.add('Started auto-export.'); - var exportDir = settingsProvider.exportDir; - if (exportDir != null) { - var files = await saf.listFiles(exportDir, - columns: [saf.DocumentFileColumn.id]).toList(); - if (files.isNotEmpty) { - for (var f in files) { - saf.delete(f.uri); - } - logs.add('Previous auto-export deleted.'); + var files = await saf + .listFiles(exportDir, columns: [saf.DocumentFileColumn.id]).toList(); + if (files.isNotEmpty) { + for (var f in files) { + saf.delete(f.uri); } + logs.add('Previous auto-export deleted.'); } } - var exportDir = settingsProvider.exportDir; + exportDir = settingsProvider.exportDir; if (exportDir == null || pickOnly) { await settingsProvider.pickExportDirKeepLastN(); exportDir = settingsProvider.exportDir; From 2aea1d263171f587e976365ab79669fe73a2ebc6 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 23:11:06 -0400 Subject: [PATCH 425/600] Bugfixes --- lib/pages/import_export.dart | 121 +++++++++++++++------------ lib/providers/apps_provider.dart | 13 +-- lib/providers/settings_provider.dart | 15 +++- 3 files changed, 86 insertions(+), 63 deletions(-) diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index c398532..159d38a 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -28,8 +28,8 @@ class _ImportExportPageState extends State { @override Widget build(BuildContext context) { SourceProvider sourceProvider = SourceProvider(); - var appsProvider = context.read(); - var settingsProvider = context.read(); + var appsProvider = context.watch(); + var settingsProvider = context.watch(); var outlineButtonStyle = ButtonStyle( shape: MaterialStateProperty.all( @@ -102,10 +102,12 @@ class _ImportExportPageState extends State { }); } - runObtainiumExport() { + runObtainiumExport() async { HapticFeedback.selectionClick(); appsProvider - .exportApps(pickOnly: settingsProvider.exportDir == null) + .exportApps( + pickOnly: (await settingsProvider.getExportDir()) == null, + sp: settingsProvider) .then((String? result) { if (result != null) { showError(tr('exportedTo', args: [result]), context); @@ -305,56 +307,69 @@ class _ImportExportPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Row( - children: [ - Expanded( - child: TextButton( - style: outlineButtonStyle, - onPressed: appsProvider.apps.isEmpty || - importInProgress - ? null - : runObtainiumExport, - child: Text(tr( - settingsProvider.exportDir != null - ? 'obtainiumExport' - : 'pickExportDirKeepLastN')))), - const SizedBox( - width: 16, - ), - Expanded( - child: TextButton( - style: outlineButtonStyle, - onPressed: importInProgress - ? null - : runObtainiumImport, - child: Text(tr('obtainiumImport')))) - ], - ), - if (settingsProvider.exportDir != null) - Column( - children: [ - const SizedBox(height: 16), - GeneratedForm( - items: [ - [ - GeneratedFormSwitch( - 'autoExportOnChanges', - label: tr('autoExportOnChanges'), - defaultValue: - settingsProvider.autoExportOnChanges, - ) - ] + FutureBuilder( + future: settingsProvider.getExportDir(), + builder: (context, snapshot) { + return Column( + children: [ + Row( + children: [ + Expanded( + child: TextButton( + style: outlineButtonStyle, + onPressed: appsProvider.apps.isEmpty || + importInProgress + ? null + : runObtainiumExport, + child: Text(tr(snapshot.data != null + ? 'obtainiumExport' + : 'pickExportDir')), + )), + const SizedBox( + width: 16, + ), + Expanded( + child: TextButton( + style: outlineButtonStyle, + onPressed: importInProgress + ? null + : runObtainiumImport, + child: Text(tr('obtainiumImport')))) ], - onValueChanges: (value, valid, isBuilding) { - if (valid && !isBuilding) { - if (value['autoExportOnChanges'] != null) { - settingsProvider.autoExportOnChanges = - value['autoExportOnChanges'] == true; - } - } - }), - ], - ), + ), + if (snapshot.data != null) + Column( + children: [ + const SizedBox(height: 16), + GeneratedForm( + items: [ + [ + GeneratedFormSwitch( + 'autoExportOnChanges', + label: tr('autoExportOnChanges'), + defaultValue: settingsProvider + .autoExportOnChanges, + ) + ] + ], + onValueChanges: + (value, valid, isBuilding) { + if (valid && !isBuilding) { + if (value['autoExportOnChanges'] != + null) { + settingsProvider + .autoExportOnChanges = value[ + 'autoExportOnChanges'] == + true; + } + } + }), + ], + ), + ], + ); + }, + ), if (importInProgress) const Column( children: [ diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 9cf0eca..3776018 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1095,8 +1095,10 @@ class AppsProvider with ChangeNotifier { return updateAppIds; } - Future exportApps({bool pickOnly = false, isAuto = false}) async { - var exportDir = settingsProvider.exportDir; + Future exportApps( + {bool pickOnly = false, isAuto = false, SettingsProvider? sp}) async { + SettingsProvider settingsProvider = sp ?? this.settingsProvider; + var exportDir = await settingsProvider.getExportDir(); if (isAuto) { if (exportDir == null) { logs.add('Skipping auto-export as dir is not set.'); @@ -1112,13 +1114,12 @@ class AppsProvider with ChangeNotifier { logs.add('Previous auto-export deleted.'); } } - exportDir = settingsProvider.exportDir; if (exportDir == null || pickOnly) { - await settingsProvider.pickExportDirKeepLastN(); - exportDir = settingsProvider.exportDir; + await settingsProvider.pickExportDir(); + exportDir = await settingsProvider.getExportDir(); } if (exportDir == null) { - throw ObtainiumError(tr('unexpectedError')); + return null; } String? returnPath; if (!pickOnly) { diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index c1ee5f5..2085168 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -362,18 +362,25 @@ class SettingsProvider with ChangeNotifier { notifyListeners(); } - Uri? get exportDir { + Future getExportDir() async { var uriString = prefs?.getString('exportDir'); if (uriString != null) { - return Uri.parse(uriString); + Uri? uri = Uri.parse(uriString); + if (!(await saf.canRead(uri) ?? false) || + !(await saf.canWrite(uri) ?? false)) { + uri = null; + prefs?.remove('exportDir'); + notifyListeners(); + } + return uri; } else { return null; } } - Future pickExportDirKeepLastN({bool remove = false}) async { + Future pickExportDir({bool remove = false}) async { var existingSAFPerms = (await saf.persistedUriPermissions()) ?? []; - var currentOneWayDataSyncDir = exportDir; + var currentOneWayDataSyncDir = await getExportDir(); Uri? newOneWayDataSyncDir; if (!remove) { newOneWayDataSyncDir = (await saf.openDocumentTree()); From 9c56a4d1fc63e19758af4a092f06ad77015b4c8a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 23:15:16 -0400 Subject: [PATCH 426/600] Bugs --- lib/providers/apps_provider.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 3776018..715a558 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1106,7 +1106,9 @@ class AppsProvider with ChangeNotifier { } logs.add('Started auto-export.'); var files = await saf - .listFiles(exportDir, columns: [saf.DocumentFileColumn.id]).toList(); + .listFiles(exportDir, columns: [saf.DocumentFileColumn.id]) + .where((f) => f.uri.pathSegments.last.endsWith('-auto.json')) + .toList(); if (files.isNotEmpty) { for (var f in files) { saf.delete(f.uri); @@ -1132,7 +1134,7 @@ class AppsProvider with ChangeNotifier { throw ObtainiumError(tr('unexpectedError')); } returnPath = - exportDir.pathSegments.join('/').replaceFirst('tree/primary:', ''); + exportDir.pathSegments.join('/').replaceFirst('tree/primary:', '/'); } return returnPath; } From 13de0437b83fbfdc13f47bbc4549ca82cf6283e8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 23:23:35 -0400 Subject: [PATCH 427/600] Bugfix --- lib/providers/apps_provider.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 715a558..1467e7b 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1100,6 +1100,9 @@ class AppsProvider with ChangeNotifier { SettingsProvider settingsProvider = sp ?? this.settingsProvider; var exportDir = await settingsProvider.getExportDir(); if (isAuto) { + if (settingsProvider.autoExportOnChanges != true) { + return null; + } if (exportDir == null) { logs.add('Skipping auto-export as dir is not set.'); return null; From fdb6eed6d003184701990cc4b44eff8094ef3cbf Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 10 Sep 2023 23:28:37 -0400 Subject: [PATCH 428/600] Slight tweak --- lib/providers/apps_provider.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 1467e7b..9dff5ff 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -916,7 +916,7 @@ class AppsProvider with ChangeNotifier { } } notifyListeners(); - await exportApps(isAuto: true); + exportApps(isAuto: true); } Future removeApps(List appIds) async { @@ -938,7 +938,7 @@ class AppsProvider with ChangeNotifier { } if (appIds.isNotEmpty) { notifyListeners(); - await exportApps(isAuto: true); + exportApps(isAuto: true); } } From 5cfddd807a234076be74cdd08b798e57cf348385 Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Mon, 11 Sep 2023 21:58:06 +0200 Subject: [PATCH 429/600] locale(pl): Update Polish translations --- assets/translations/pl.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 04f8322..b2027a8 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -253,12 +253,12 @@ "verifyLatestTag": "Zweryfikuj najnowszy tag", "exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)", "bgUpdatesOnWiFiOnly": "Wyłącz aktualizacje w tle, gdy nie ma połączenia z Wi-Fi", - "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", - "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", - "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", - "autoExportOnChanges": "Auto-export on changes", + "autoSelectHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", + "versionExtractionRegEx": "Wyrażenie regularne wyodrębniające wersję", + "matchGroupToUse": "Dopasuj grupę do użycia", + "highlightTouchTargets": "Wyróżnij mniej oczywiste elementy dotykowe", + "pickExportDir": "Wybierz katalog eksportu", + "autoExportOnChanges": "Automatyczny eksport po wprowadzeniu zmian", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", From acc6a780fa14a432ccb31d41dda76cc0ee2e5a0d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 13 Sep 2023 21:01:39 -0400 Subject: [PATCH 430/600] Fix export encoding (#887) --- lib/providers/apps_provider.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 9dff5ff..e7b79ce 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1132,7 +1132,8 @@ class AppsProvider with ChangeNotifier { displayName: '${tr('obtainiumExportHyphenatedLowercase')}-${DateTime.now().toIso8601String().replaceAll(':', '-')}${isAuto ? '-auto' : ''}.json', mimeType: 'application/json', - content: jsonEncode(apps.values.map((e) => e.app.toJson()).toList())); + bytes: Uint8List.fromList(utf8.encode( + jsonEncode(apps.values.map((e) => e.app.toJson()).toList())))); if (result == null) { throw ObtainiumError(tr('unexpectedError')); } From 7d9571cfddf189a7bd10aa12ba66631332237f25 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 13 Sep 2023 21:24:25 -0400 Subject: [PATCH 431/600] Fix repeating background install for some apps (#886) --- lib/providers/apps_provider.dart | 35 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index e7b79ce..a9b5edd 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -430,7 +430,8 @@ class AppsProvider with ChangeNotifier { zipFile: File(filePath), destinationDir: Directory(destinationPath)); } - Future installXApkDir(DownloadedXApkDir dir) async { + Future installXApkDir( + DownloadedXApkDir dir, BuildContext? context) async { // We don't know which APKs in an XAPK are supported by the user's device // So we try installing all of them and assume success if at least one installed // If 0 APKs installed, throw the first install error encountered @@ -443,7 +444,7 @@ class AppsProvider with ChangeNotifier { if (file.path.toLowerCase().endsWith('.apk')) { try { somethingInstalled = somethingInstalled || - await installApk(DownloadedApk(dir.appId, file)); + await installApk(DownloadedApk(dir.appId, file), context); } catch (e) { logs.add( 'Could not install APK from XAPK \'${file.path}\': ${e.toString()}'); @@ -463,7 +464,7 @@ class AppsProvider with ChangeNotifier { } } - Future installApk(DownloadedApk file) async { + Future installApk(DownloadedApk file, BuildContext? context) async { var newInfo = await pm.getPackageArchiveInfo(archiveFilePath: file.file.path); PackageInfo? appInfo = await getInstalledInfo(apps[file.appId]!.app.id); @@ -472,8 +473,16 @@ class AppsProvider with ChangeNotifier { !(await canDowngradeApps())) { throw DowngradeError(); } - int? code = - await AndroidPackageInstaller.installApk(apkFilePath: file.file.path); + int? code; + if (context == null) { + // In background installs, 'installApk' never returns so don't wait for it + // TODO: Find a fix to make this work synchronously without context + AndroidPackageInstaller.installApk(apkFilePath: file.file.path); + code = 0; // Be optimistic (ver. det. will get most wrong ones anyways) + } else { + code = + await AndroidPackageInstaller.installApk(apkFilePath: file.file.path); + } bool installed = false; if (code != null && code != 0 && code != 3) { throw InstallError(code); @@ -640,19 +649,11 @@ class AppsProvider with ChangeNotifier { notifyListeners(); try { if (downloadedFile != null) { - if (willBeSilent && context == null) { - // Would await forever - workaround - TODO - installApk(downloadedFile); - } else { - await installApk(downloadedFile); - } + // ignore: use_build_context_synchronously + await installApk(downloadedFile, context); } else { - if (willBeSilent && context == null) { - // Would await forever - workaround - TODO - installXApkDir(downloadedDir!); - } else { - await installXApkDir(downloadedDir!); - } + // ignore: use_build_context_synchronously + await installXApkDir(downloadedDir!, context); } if (willBeSilent && context == null) { notificationsProvider?.notify(SilentUpdateAttemptNotification( From 2d5a9bec84c139405bac07747912b29c6dbef647 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 13 Sep 2023 21:27:18 -0400 Subject: [PATCH 432/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 16 ++++++++-------- pubspec.yaml | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 0b2338d..14276a1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.13'; +const String currentVersion = '0.14.14'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index cdacfb5..ef2647c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -46,10 +46,10 @@ packages: dependency: transitive description: name: archive - sha256: "49b1fad315e57ab0bbc15bcbb874e83116a1d78f77ebd500a4af6c9407d6b28e" + sha256: e0902a06f0e00414e4e3438a084580161279f137aeb862274710f29ec10cf01e url: "https://pub.dev" source: hosted - version: "3.3.8" + version: "3.3.9" args: dependency: transitive description: @@ -320,10 +320,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: d4a1cb250c4e059586af0235f32e02882860a508e189b61f2b31b8810c1e1330 + sha256: a10979814c5f4ddbe2b6143fba25d927599e21e3ba65b3862995960606fae78f url: "https://pub.dev" source: hosted - version: "0.6.17+2" + version: "0.6.17+3" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -538,18 +538,18 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5 + sha256: ad65ba9af42a3d067203641de3fd9f547ded1410bad3b84400c2b4899faede70 url: "https://pub.dev" source: hosted - version: "10.4.5" + version: "11.0.0" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47" + sha256: f23cfe9af0d49c6b9fd8a8b09f7b3301ca7e346204939b5afef4404d36d2608f url: "https://pub.dev" source: hosted - version: "10.3.6" + version: "11.0.1" permission_handler_apple: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 09d66b8..db5c5ca 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.14.13+205 # When changing this, update the tag in main() accordingly +version: 0.14.14+206 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' @@ -46,7 +46,7 @@ dependencies: html: ^0.15.0 shared_preferences: ^2.0.15 url_launcher: ^6.1.5 - permission_handler: ^10.0.0 + permission_handler: ^11.0.0 fluttertoast: ^8.0.9 device_info_plus: ^9.0.0 file_picker: ^5.2.10 From a2e494b2bae8d2e96c3902ef7b866529162e66d7 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 13 Sep 2023 22:15:10 -0400 Subject: [PATCH 433/600] More version filtering options for F-Droid (#885) --- assets/translations/br.json | 2 + assets/translations/bs.json | 2 + assets/translations/de.json | 2 + assets/translations/en.json | 2 + assets/translations/es.json | 2 + assets/translations/fa.json | 2 + assets/translations/fr.json | 2 + assets/translations/hu.json | 2 + assets/translations/it.json | 2 + assets/translations/ja.json | 2 + assets/translations/pl.json | 2 + assets/translations/ru.json | 2 + assets/translations/zh.json | 2 + lib/app_sources/fdroid.dart | 94 ++++++++++++++++++++++++++++---- lib/app_sources/izzyondroid.dart | 5 +- 15 files changed, 112 insertions(+), 13 deletions(-) diff --git a/assets/translations/br.json b/assets/translations/br.json index 96e9e7d..a083e20 100644 --- a/assets/translations/br.json +++ b/assets/translations/br.json @@ -256,6 +256,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 01d0d2b..7352027 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -253,6 +253,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/de.json b/assets/translations/de.json index f6f9d0e..5ab4801 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -253,6 +253,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 4395c68..6e782f9 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -256,6 +256,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index b662041..aefea28 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -253,6 +253,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index c3f5274..9c62c43 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -253,6 +253,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 8576909..33e9fb6 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -253,6 +253,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 845e313..164cd9a 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -252,6 +252,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "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 7fec3c8..b805fc5 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -253,6 +253,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 541da17..9093e15 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -254,6 +254,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 04f8322..205d716 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -259,6 +259,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 690cd53..9db80ce 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -253,6 +253,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 66fc426..1057515 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -254,6 +254,8 @@ "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index ffee596..f2dd3f9 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -13,10 +13,24 @@ class FDroid extends AppSource { name = tr('fdroid'); canSearch = true; additionalSourceAppSpecificSettingFormItems = [ + [ + GeneratedFormTextField('filterVersionsByRegEx', + label: tr('filterVersionsByRegEx'), + required: false, + additionalValidators: [ + (value) { + return regExValidator(value); + } + ]) + ], + [ + GeneratedFormSwitch('trySelectingSuggestedVersionCode', + label: tr('trySelectingSuggestedVersionCode'), defaultValue: true) + ], [ GeneratedFormSwitch('autoSelectHighestVersionCode', label: tr('autoSelectHighestVersionCode')) - ] + ], ]; } @@ -45,25 +59,73 @@ class FDroid extends AppSource { APKDetails getAPKUrlsFromFDroidPackagesAPIResponse( Response res, String apkUrlPrefix, String standardUrl, - {bool autoSelectHighestVersionCode = false}) { + {bool autoSelectHighestVersionCode = false, + bool trySelectingSuggestedVersionCode = false, + String? filterVersionsByRegEx}) { if (res.statusCode == 200) { - List releases = jsonDecode(res.body)['packages'] ?? []; + var response = jsonDecode(res.body); + List releases = response['packages'] ?? []; if (releases.isEmpty) { throw NoReleasesError(); } - String? latestVersion = releases[0]['versionName']; - if (latestVersion == null) { + String? version; + Iterable releaseChoices = []; + // Grab the versionCode suggested if the user chose to do that + // Only do so at this stage if the user has no release filter + if (trySelectingSuggestedVersionCode && + response['suggestedVersionCode'] != null && + filterVersionsByRegEx == null) { + var suggestedReleases = releases.where((element) => + element['versionCode'] == response['suggestedVersionCode']); + if (suggestedReleases.isNotEmpty) { + releaseChoices = suggestedReleases; + version = suggestedReleases.first['versionName']; + } + } + // Apply the release filter if any + if (filterVersionsByRegEx != null) { + version = null; + releaseChoices = []; + for (var i = 0; i < releases.length; i++) { + if (RegExp(filterVersionsByRegEx) + .hasMatch(releases[i]['versionName'])) { + version = releases[i]['versionName']; + } + } + if (version == null) { + throw NoVersionError(); + } + } + // Default to the highest version + version ??= releases[0]['versionName']; + if (version == null) { throw NoVersionError(); } - Iterable latestReleases = - releases.where((element) => element['versionName'] == latestVersion); - if (latestReleases.length > 1 && autoSelectHighestVersionCode) { - latestReleases = [latestReleases.first]; + // If a suggested release was not already picked, pick all those with the selected version + if (releaseChoices.isEmpty) { + releaseChoices = + releases.where((element) => element['versionName'] == version); } - List apkUrls = latestReleases + // For the remaining releases, use the toggles to auto-select one if possible + if (releaseChoices.length > 1) { + if (autoSelectHighestVersionCode) { + releaseChoices = [releaseChoices.first]; + } else if (trySelectingSuggestedVersionCode && + response['suggestedVersionCode'] != null) { + var suggestedReleases = releaseChoices.where((element) => + element['versionCode'] == response['suggestedVersionCode']); + if (suggestedReleases.isNotEmpty) { + releaseChoices = suggestedReleases; + } + } + } + if (releaseChoices.isEmpty) { + throw NoReleasesError(); + } + List apkUrls = releaseChoices .map((e) => '${apkUrlPrefix}_${e['versionCode']}.apk') .toList(); - return APKDetails(latestVersion, getApkUrlsFromUrls(apkUrls), + return APKDetails(version, getApkUrlsFromUrls(apkUrls), AppNames(name, Uri.parse(standardUrl).pathSegments.last)); } else { throw getObtainiumHttpError(res); @@ -82,7 +144,15 @@ class FDroid extends AppSource { 'https://$host/repo/$appId', standardUrl, autoSelectHighestVersionCode: - additionalSettings['autoSelectHighestVersionCode'] == true); + additionalSettings['autoSelectHighestVersionCode'] == true, + trySelectingSuggestedVersionCode: + additionalSettings['trySelectingSuggestedVersionCode'] == true, + filterVersionsByRegEx: + (additionalSettings['filterVersionsByRegEx'] as String?) + ?.isNotEmpty == + true + ? additionalSettings['filterVersionsByRegEx'] + : null); } @override diff --git a/lib/app_sources/izzyondroid.dart b/lib/app_sources/izzyondroid.dart index f145bb8..8f801db 100644 --- a/lib/app_sources/izzyondroid.dart +++ b/lib/app_sources/izzyondroid.dart @@ -40,6 +40,9 @@ class IzzyOnDroid extends AppSource { 'https://android.izzysoft.de/frepo/$appId', standardUrl, autoSelectHighestVersionCode: - additionalSettings['autoSelectHighestVersionCode'] == true); + additionalSettings['autoSelectHighestVersionCode'] == true, + trySelectingSuggestedVersionCode: + additionalSettings['trySelectingSuggestedVersionCode'] == true, + filterVersionsByRegEx: additionalSettings['filterVersionsByRegEx']); } } From 4c0c4b70104b2226198127712797aa2b7a99974e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 13 Sep 2023 22:19:09 -0400 Subject: [PATCH 434/600] Trim user URL input --- lib/pages/add_app.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index ee8099e..c792a2a 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -148,7 +148,7 @@ class _AddAppPageState extends State { userPickedTrackOnly))) { var trackOnly = pickedSource!.enforceTrackOnly || userPickedTrackOnly; app = await sourceProvider.getApp( - pickedSource!, userInput, additionalSettings, + pickedSource!, userInput.trim(), additionalSettings, trackOnlyOverride: trackOnly, overrideSource: pickedSourceOverride, inferAppIdIfOptional: inferAppIdIfOptional); From 5cf4c21ce391b243ea1b5222a502ba9c0f0dfb4d Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Thu, 14 Sep 2023 08:37:46 +0200 Subject: [PATCH 435/600] Update de.json Translated latest strings --- assets/translations/de.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 5ab4801..3c11e3d 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -247,14 +247,14 @@ "verifyLatestTag": "Überprüfe das 'latest' Tag", "exemptFromBackgroundUpdates": "Ausschluss von Hintergrundaktualisierungen (falls aktiviert)", "bgUpdatesOnWiFiOnly": "Hintergrundaktualisierungen deaktivieren, wenn kein WLAN vorhanden ist", - "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", - "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", - "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", - "autoExportOnChanges": "Auto-export on changes", - "filterVersionsByRegEx": "Filter Versions by Regular Expression", - "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "autoSelectHighestVersionCode": "Automatische Auswahl der höchsten APK Version", + "versionExtractionRegEx": "Versionsextrahierung mit Regulärem Ausdruck", + "matchGroupToUse": "Zu verwendende Gruppe abgleichen", + "highlightTouchTargets": "Weniger offensichtliche Touch-Ziele hervorheben", + "pickExportDir": "Wähle Export Verzeichnis", + "autoExportOnChanges": "Automatischer Export bei Änderungen", + "filterVersionsByRegEx": "Versionen nach Regulärem Ausdruck filtern", + "trySelectingSuggestedVersionCode": "Versuchen die vorgeschlagene APK-Version auszuwählen", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" From 8c82f53dd271462dcc549f16a75208f77d47895b Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Thu, 14 Sep 2023 15:44:27 +0900 Subject: [PATCH 436/600] Update ja.json --- assets/translations/ja.json | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 9093e15..be3e9c8 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -144,7 +144,7 @@ "updatesAvailable": "アップデートが利用可能", "updatesAvailableNotifDescription": "Obtainiumが追跡している1つまたは複数のアプリのアップデートが利用可能であることをユーザーに通知する", "noNewUpdates": "新しいアップデートはありません", - "xHasAnUpdate": "{} のアップデートが利用可能です", + "xHasAnUpdate": "{} のアップデートが利用可能です。", "appsUpdated": "アプリをアップデートしました", "appsUpdatedNotifDescription": "1つまたは複数のAppのアップデートがバックグラウンドで適用されたことをユーザーに通知する", "xWasUpdatedToY": "{} が {} にアップデートされました", @@ -241,21 +241,23 @@ "customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')", "appsPossiblyUpdated": "アプリのアップデートを試行", "appsPossiblyUpdatedNotifDescription": "1つまたは複数のアプリのアップデートがバックグラウンドで適用された可能性があることをユーザーに通知する", - "xWasPossiblyUpdatedToY": "{} が {} にアップデートされた可能性があります", + "xWasPossiblyUpdatedToY": "{} が {} にアップデートされた可能性があります。", "enableBackgroundUpdates": "バックグラウンドアップデートを有効化する", "backgroundUpdateReqsExplanation": "バックグラウンドアップデートは、すべてのアプリで可能とは限りません。", "backgroundUpdateLimitsExplanation": "バックグラウンドアップデートが成功したかどうかは、Obtainiumを起動したときにしか判断できません。", "verifyLatestTag": "'latest'タグを確認する", + "intermediateLinkRegex": "最初にアクセスする「中間」リンクをフィルタリングする", + "intermediateLinkNotFound": "中間リンクが見つかりませんでした", "exemptFromBackgroundUpdates": "バックグラウンドアップデートを行わない (有効な場合)", "bgUpdatesOnWiFiOnly": "WiFiを使用していない場合,バックグラウンドアップデートを無効にする", - "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", - "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", - "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", - "autoExportOnChanges": "Auto-export on changes", - "filterVersionsByRegEx": "Filter Versions by Regular Expression", - "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "autoSelectHighestVersionCode": "最も高いバージョンコードのAPKを自動で選択する", + "versionExtractionRegEx": "バージョン抽出の正規表現", + "matchGroupToUse": "使用するマッチしたグループ", + "highlightTouchTargets": "目立たないタップ可能な対象をハイライトする", + "pickExportDir": "エクスポートディレクトリを選択", + "autoExportOnChanges": "変更があった際に自動でエクスポートする", + "filterVersionsByRegEx": "正規表現でバージョンをフィルタリングする", + "trySelectingSuggestedVersionCode": "提案されたバージョンコードのAPKを選択する", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" @@ -297,15 +299,15 @@ "other": "{n} 個のログをクリアしました (前 = {before}, 後 = {after})" }, "xAndNMoreUpdatesAvailable": { - "one": "{} とさらに {} 個のアプリのアップデートが利用可能です", - "other": "{} とさらに {} 個のアプリのアップデートが利用可能です" + "one": "{} とさらに {} 個のアプリのアップデートが利用可能です。", + "other": "{} とさらに {} 個のアプリのアップデートが利用可能です。" }, "xAndNMoreUpdatesInstalled": { - "one": "{} とさらに {} 個のアプリがアップデートされました", - "other": "{} とさらに {} 個のアプリがアップデートされました" + "one": "{} とさらに {} 個のアプリがアップデートされました。", + "other": "{} とさらに {} 個のアプリがアップデートされました。" }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} とさらに 1 個のアプリがアップデートされた可能性があります", - "other": "{} とさらに {} 個のアプリがアップデートされた可能性があります" + "one": "{} とさらに 1 個のアプリがアップデートされた可能性があります。", + "other": "{} とさらに {} 個のアプリがアップデートされた可能性があります。" } } From 9862c22fdbeb55c4ee6b0831a57035da38a500df Mon Sep 17 00:00:00 2001 From: Markus <82206269+markus-gitdev@users.noreply.github.com> Date: Thu, 14 Sep 2023 09:27:36 +0200 Subject: [PATCH 437/600] Update de.json --- assets/translations/de.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 5ab4801..e35c97c 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -247,14 +247,14 @@ "verifyLatestTag": "Überprüfe das 'latest' Tag", "exemptFromBackgroundUpdates": "Ausschluss von Hintergrundaktualisierungen (falls aktiviert)", "bgUpdatesOnWiFiOnly": "Hintergrundaktualisierungen deaktivieren, wenn kein WLAN vorhanden ist", - "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", - "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", - "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", - "autoExportOnChanges": "Auto-export on changes", - "filterVersionsByRegEx": "Filter Versions by Regular Expression", - "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "autoSelectHighestVersionCode": "Automatisch höchste APK-Code-Version auswählen", + "versionExtractionRegEx": "Versions-Extraktion RegEx", + "matchGroupToUse": "Zu verwendende Gruppe abgleichen", + "highlightTouchTargets": "Weniger offensichtliche Ziele hervorheben", + "pickExportDir": "Export-Verzeichnis wählen", + "autoExportOnChanges": "Automatischer Export bei Änderung", + "filterVersionsByRegEx": "Versionen nach regulären Ausdrücken filtern", + "trySelectingSuggestedVersionCode": "Versuchen, die vorgeschlagene APK-Code-Version auszuwählen", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" From 84d8ff8b0be465fece8390876f51d46496f0fe6c Mon Sep 17 00:00:00 2001 From: DwainZwerg <97027379+DwainZwerg@users.noreply.github.com> Date: Thu, 14 Sep 2023 08:46:51 +0000 Subject: [PATCH 438/600] Small improvement of the previous translation (especially "" instead of the English ''; my translations of the new features to be translated are mostly based on iDazai (https://github.com/ImranR98/Obtainium/pull/892/files) and markus-gitdev (https://github.com/ImranR98/Obtainium/pull/894/files)) --- assets/translations/de.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 5ab4801..4b340ee 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -28,8 +28,8 @@ "xIsTrackOnly": "{} ist nur zur Nachverfolgung", "source": "Quelle", "app": "App", - "appsFromSourceAreTrackOnly": "Apps aus dieser Quelle sind 'Nur Nachverfolgen'.", - "youPickedTrackOnly": "Sie haben die Option 'Nur Nachverfolgen' gewählt.", + "appsFromSourceAreTrackOnly": "Apps aus dieser Quelle sind nur zum Nachverfolgen.", + "youPickedTrackOnly": "Sie haben die Option „Nur Nachverfolgen“ gewählt.", "trackOnlyAppDescription": "Die App wird auf Updates überwacht, aber Obtainium wird sie nicht herunterladen oder installieren.", "cancelled": "Abgebrochen", "appAlreadyAdded": "App bereits hinzugefügt", @@ -38,7 +38,7 @@ "appSourceURL": "Quell-URL der App", "error": "Fehler", "add": "Hinzufügen", - "searchSomeSourcesLabel": "Suche (nur bestimmte Quellen)", + "searchSomeSourcesLabel": "Suche (nur für bestimmte Quellen)", "search": "Suchen", "additionalOptsFor": "Zusatzoptionen für {}", "supportedSources": "Unterstützte Quellen", @@ -70,7 +70,7 @@ "yes": "Ja", "markSelectedAppsUpdated": "Markiere ausgewählte Apps als aktuell", "pinToTop": "Oben anheften", - "unpinFromTop": "'Oben anheften' aufheben", + "unpinFromTop": "„Oben anheften“ aufheben", "resetInstallStatusForSelectedAppsQuestion": "Installationsstatus für ausgewählte Apps zurücksetzen?", "installStatusOfXWillBeResetExplanation": "Der Installationsstatus der ausgewählten Apps wird zurückgesetzt. Dies kann hilfreich sein, wenn die in Obtainium angezeigte App-Version aufgrund fehlgeschlagener Aktualisierungen oder anderer Probleme falsch ist.", "shareSelectedAppURLs": "Ausgewählte App-URLs teilen", @@ -175,7 +175,7 @@ "appId": "App ID", "appWithIdOrNameNotFound": "Es wurde keine App mit dieser ID oder diesem Namen gefunden", "reposHaveMultipleApps": "Repos können mehrere Apps enthalten", - "fdroidThirdPartyRepo": "F-Droid Third-Party Repo", + "fdroidThirdPartyRepo": "F-Droid Drittparteienrepo", "steam": "Steam", "steamMobile": "Steam Mobile", "steamChat": "Steam Chat", @@ -244,17 +244,17 @@ "xWasPossiblyUpdatedToY": "{} wurde möglicherweise aktualisiert auf {}.", "backgroundUpdateReqsExplanation": "Die Hintergrundaktualisierung ist möglicherweise nicht für alle Apps möglich.", "backgroundUpdateLimitsExplanation": "Der Erfolg einer Hintergrundinstallation kann nur festgestellt werden, wenn Obtainium geöffnet wird.", - "verifyLatestTag": "Überprüfe das 'latest' Tag", + "verifyLatestTag": "Überprüfe das „latest“ Tag", "exemptFromBackgroundUpdates": "Ausschluss von Hintergrundaktualisierungen (falls aktiviert)", "bgUpdatesOnWiFiOnly": "Hintergrundaktualisierungen deaktivieren, wenn kein WLAN vorhanden ist", - "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "autoSelectHighestVersionCode": "Automatisch höchste APK-Version auswählen", "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", - "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", - "autoExportOnChanges": "Auto-export on changes", - "filterVersionsByRegEx": "Filter Versions by Regular Expression", - "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "matchGroupToUse": "zu verwendende Gruppe abgleichen", + "highlightTouchTargets": "Weniger offensichtliche Touch-Ziele hervorheben", + "pickExportDir": "Export-Verzeichnis wählen", + "autoExportOnChanges": "Automatischer Export bei Änderung(en)", + "filterVersionsByRegEx": "Versionsextrahierung mit Regulärem Ausdruck", + "trySelectingSuggestedVersionCode": "Versuchen, den vorgeschlagenen APK-Versionscode auszuwählen", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" From e1f2baeeda640982b7b84a25e201d228d9daa855 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 16 Sep 2023 04:31:03 -0400 Subject: [PATCH 439/600] Fix background update issue (#896) --- lib/main.dart | 2 +- lib/providers/apps_provider.dart | 45 ++++++++++++++++++++------------ pubspec.lock | 8 +++--- pubspec.yaml | 2 +- 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 14276a1..e9a4888 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.14'; +const String currentVersion = '0.14.15'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index a9b5edd..7d08656 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -430,8 +430,8 @@ class AppsProvider with ChangeNotifier { zipFile: File(filePath), destinationDir: Directory(destinationPath)); } - Future installXApkDir( - DownloadedXApkDir dir, BuildContext? context) async { + Future installXApkDir(DownloadedXApkDir dir, + {bool needsBGWorkaround = false}) async { // We don't know which APKs in an XAPK are supported by the user's device // So we try installing all of them and assume success if at least one installed // If 0 APKs installed, throw the first install error encountered @@ -444,7 +444,8 @@ class AppsProvider with ChangeNotifier { if (file.path.toLowerCase().endsWith('.apk')) { try { somethingInstalled = somethingInstalled || - await installApk(DownloadedApk(dir.appId, file), context); + await installApk(DownloadedApk(dir.appId, file), + needsBGWorkaround: needsBGWorkaround); } catch (e) { logs.add( 'Could not install APK from XAPK \'${file.path}\': ${e.toString()}'); @@ -464,7 +465,8 @@ class AppsProvider with ChangeNotifier { } } - Future installApk(DownloadedApk file, BuildContext? context) async { + Future installApk(DownloadedApk file, + {bool needsBGWorkaround = false}) async { var newInfo = await pm.getPackageArchiveInfo(archiveFilePath: file.file.path); PackageInfo? appInfo = await getInstalledInfo(apps[file.appId]!.app.id); @@ -473,16 +475,19 @@ class AppsProvider with ChangeNotifier { !(await canDowngradeApps())) { throw DowngradeError(); } - int? code; - if (context == null) { - // In background installs, 'installApk' never returns so don't wait for it - // TODO: Find a fix to make this work synchronously without context - AndroidPackageInstaller.installApk(apkFilePath: file.file.path); - code = 0; // Be optimistic (ver. det. will get most wrong ones anyways) - } else { - code = - await AndroidPackageInstaller.installApk(apkFilePath: file.file.path); + if (needsBGWorkaround) { + // The below 'await' will never return if we are in a background process + // To work around this, we should assume the install will be successful + // So we update the app's installed version first as we will never get to the later code + // We can't conditionally get rid of the 'await' as this causes install fails (BG process times out) - see #896 + // TODO: When fixed, update this function and the calls to it accordingly + apps[file.appId]!.app.installedVersion = + apps[file.appId]!.app.latestVersion; + await saveApps([apps[file.appId]!.app], + attemptToCorrectInstallStatus: false); } + int? code = + await AndroidPackageInstaller.installApk(apkFilePath: file.file.path); bool installed = false; if (code != null && code != 0 && code != 3) { throw InstallError(code); @@ -649,11 +654,17 @@ class AppsProvider with ChangeNotifier { notifyListeners(); try { if (downloadedFile != null) { - // ignore: use_build_context_synchronously - await installApk(downloadedFile, context); + if (willBeSilent && context == null) { + installApk(downloadedFile, needsBGWorkaround: true); + } else { + await installApk(downloadedFile); + } } else { - // ignore: use_build_context_synchronously - await installXApkDir(downloadedDir!, context); + if (willBeSilent && context == null) { + installXApkDir(downloadedDir!, needsBGWorkaround: true); + } else { + await installXApkDir(downloadedDir!); + } } if (willBeSilent && context == null) { notificationsProvider?.notify(SilentUpdateAttemptNotification( diff --git a/pubspec.lock b/pubspec.lock index ef2647c..33758ce 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -198,10 +198,10 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: de4798a7069121aee12d5895315680258415de9b00e717723a1bd73d58f0126d + sha256: "96bff3df72e3d428bda2b874c7a521e8c86f592cae626ea594922fcc8d166e0c" url: "https://pub.dev" source: hosted - version: "1.6.6" + version: "1.6.7" easy_localization: dependency: "direct main" description: @@ -887,10 +887,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "9427774649fd3c8b7ff53523051395d13aed2ca355822b822e6493d79f5fc05a" + sha256: ddc167c6676f57c8b367d19fcbee267d6dc6adf81bd6c3cb87981d30746e0a6d url: "https://pub.dev" source: hosted - version: "3.10.0" + version: "3.10.1" webview_flutter_platform_interface: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index db5c5ca..66170d7 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.14.14+206 # When changing this, update the tag in main() accordingly +version: 0.14.15+207 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 2cec5f7934cfba782f3f2b91ecf025721a630628 Mon Sep 17 00:00:00 2001 From: gidano Date: Sat, 16 Sep 2023 11:28:36 +0200 Subject: [PATCH 440/600] Update hu.json --- assets/translations/hu.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 164cd9a..1a8ee3e 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -246,14 +246,14 @@ "verifyLatestTag": "Ellenőrizze a „legújabb” címkét", "exemptFromBackgroundUpdates": "Mentes a háttérben történő frissítések alól (ha engedélyezett)", "bgUpdatesOnWiFiOnly": "Tiltsa le a háttérben frissítéseket, ha nincs Wi-Fi-n", - "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", - "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", - "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", - "autoExportOnChanges": "Auto-export on changes", - "filterVersionsByRegEx": "Filter Versions by Regular Expression", - "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "autoSelectHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", + "versionExtractionRegEx": "Verzió kibontása reguláris kifejezéssel", + "matchGroupToUse": "Párosítsa a csoportot a használathoz", + "highlightTouchTargets": "Emelje ki a kevésbé nyilvánvaló érintési célokat", + "pickExportDir": "Válassza az Exportálási könyvtárat", + "autoExportOnChanges": "Auto-exportálás a változások után", + "filterVersionsByRegEx": "Verziók szűrése reguláris kifejezéssel", + "trySelectingSuggestedVersionCode": "Próbálja ki a javasolt verziókódú APK-t", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From 93e03601169688187bb888b6bd586bc6a9a4e906 Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Sat, 16 Sep 2023 12:43:05 +0200 Subject: [PATCH 441/600] locale(pl): Update Polish translations --- assets/translations/pl.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 3436f45..661a85b 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -259,8 +259,8 @@ "highlightTouchTargets": "Wyróżnij mniej oczywiste elementy dotykowe", "pickExportDir": "Wybierz katalog eksportu", "autoExportOnChanges": "Automatyczny eksport po wprowadzeniu zmian", - "filterVersionsByRegEx": "Filter Versions by Regular Expression", - "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "filterVersionsByRegEx": "Filtruj wersje według wyrażenia regularnego", + "trySelectingSuggestedVersionCode": "Spróbuj wybierać sugerowany kod wersji APK", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", From 61d66e80d8cda7769afdcd8a6dad8ff37db1ddd1 Mon Sep 17 00:00:00 2001 From: Sayman Rifat <98202630+saymanrifat@users.noreply.github.com> Date: Sat, 16 Sep 2023 18:31:57 +0600 Subject: [PATCH 442/600] Add back button to app detail page (#721) --- lib/pages/app.dart | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index dcd52bd..a5c2a57 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -463,9 +463,18 @@ class _AppPageState extends State { : null)) ], )); + + appScreenAppBar() => AppBar( + leading: IconButton( + icon: const Icon(Icons.arrow_back), + onPressed: () { + Navigator.pop(context); + }, + ), + ); return Scaffold( - appBar: settingsProvider.showAppWebpage ? AppBar() : null, + appBar: settingsProvider.showAppWebpage ? AppBar() : appScreenAppBar(), backgroundColor: Theme.of(context).colorScheme.surface, body: RefreshIndicator( child: settingsProvider.showAppWebpage From f9df3ac0e28cbcd53499f4d2a3f69422141b78b0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 16 Sep 2023 09:25:26 -0400 Subject: [PATCH 443/600] Reduce top padding as we no longer need it --- lib/pages/app.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index a5c2a57..b49deb4 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -152,7 +152,7 @@ class _AppPageState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - const SizedBox(height: 125), + const SizedBox(height: 20), app?.icon != null ? Row(mainAxisAlignment: MainAxisAlignment.center, children: [ Image.memory( From 591973d97f3648613bb7d34e12b840426f4c8db8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 16 Sep 2023 09:28:45 -0400 Subject: [PATCH 444/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index e9a4888..743ac01 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.15'; +const String currentVersion = '0.14.16'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 66170d7..e9b2153 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.14.15+207 # When changing this, update the tag in main() accordingly +version: 0.14.16+208 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 298ff190eca6b82fca869ed441d942a0b4c4d947 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 16 Sep 2023 15:26:35 -0400 Subject: [PATCH 445/600] Bugfix: HTML Source was broken (could not add apps) --- lib/app_sources/html.dart | 3 +++ lib/main.dart | 2 +- pubspec.yaml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 8676af9..c2ff364 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -123,6 +123,9 @@ class HTML extends AppSource { textInputType: const TextInputType.numberWithOptions(), additionalValidators: [ (value) { + if (value?.isEmpty == true) { + value = null; + } value ??= '1'; return intValidator(value); } diff --git a/lib/main.dart b/lib/main.dart index 743ac01..ad48463 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.16'; +const String currentVersion = '0.14.17'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index e9b2153..25f11d0 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.14.16+208 # When changing this, update the tag in main() accordingly +version: 0.14.17+209 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 8bcb10b281b60a4cb994868efc56fc8a94cd98a3 Mon Sep 17 00:00:00 2001 From: zenobit Date: Sat, 16 Sep 2023 20:50:16 +0200 Subject: [PATCH 446/600] Add Czech translation --- assets/translations/cs.json | 314 ++++++++++++++++++++++++++++++++++++ lib/main.dart | 1 + 2 files changed, 315 insertions(+) create mode 100644 assets/translations/cs.json diff --git a/assets/translations/cs.json b/assets/translations/cs.json new file mode 100644 index 0000000..88fb2e7 --- /dev/null +++ b/assets/translations/cs.json @@ -0,0 +1,314 @@ +{ + "invalidURLForSource": "Žádná platná {} adresa URL aplikace", + "noReleaseFound": "Nebyla nalezena odpovídající verze", + "noVersionFound": "Nelze určit verzi vydání", + "urlMatchesNoSource": "URL neodpovídá žádnému známému zdroji", + "cantInstallOlderVersion": "Nelze nainstalovat starší verzi aplikace", + "appIdMismatch": "ID staženého balíčku neodpovídá ID existující aplikace", + "functionNotImplemented": "Tato třída nemá implementovánu tuto funkci", + "placeholder": "Zástupce", + "someErrors": "Vyskytly se nějaké chyby", + "unexpectedError": "Neočekávaná chyba", + "ok": "Okay", + "and": "a", + "githubPATLabel": "GitHub Personal Access Token (Raises Rate Limit)", + "includePrereleases": "includepreleases", + "fallbackToOlderReleases": "Fallback to older releases", + "filterReleaseTitlesByRegEx": "Názvy vydání podle regulárního výrazu\filtr", + "invalidRegEx": "Neplatný regulární výraz", + "noDescription": "Žádný popis", + "cancel": "Zrušit", + "continue": "Pokračovat", + "requiredInBracets": "(Required)", + "dropdownNoOptsError": "ERROR: DROPDOWN MUSÍ MÍT AŽ JEDNU MOŽNOST", + "color": "barva", + "githubStarredRepos": "GitHub Starred Repos", + "uname": "username", + "wrongArgNum": "Špatný počet předložených argumentů", + "xIsTrackOnly":"{} je určeno pouze pro sledování", + "source": "zdroj", + "app": "App", + "appsFromSourceAreTrackOnly": "Aplikace z tohoto zdroje jsou 'Jen sledovány'.", + "youPickedTrackOnly": "Vybrali jste možnost 'Jen sledovat'.", + "trackOnlyAppDescription": "Aplikace je sledována kvůli aktualizacím, ale Obtainium ji nebude stahovat ani instalovat.", + "cancelled": "Zrušeno", + "appAlreadyAdded": "Aplikace již přidána", + "alreadyUpToDateQuestion": "App already up to date?", + "addApp": "Přidat aplikaci", + "appSourceURL": "zdrojová adresa URL aplikace", + "error": "Chyba", + "add": "Přidat", + "searchSomeSourcesLabel": "Vyhledávání (pouze konkrétní zdroje)", + "search": "Hledat", + "additionalOptsFor": "Další možnosti pro {}", + "supportedSources": "Podporované zdroje", + "trackOnlyInBrackets": "(Pouze stopy)", + "searchableInBrackets": "(s možností vyhledávání)", + "appsString": "Apky", + "noApps": "Žádné aplikace", + "noAppsForFilter": "žádné aplikace pro vybraný filtr", + "byX": "By {}", + "percentProgress": "Pokrok: {}%", + "pleaseWait": "Počkejte prosím", + "updateAvailable": "Aktualizace je k dispozici", + "estimateInBracketsShort": "(approx.)", + "notInstalled": "Není nainstalováno", + "estimateInBrackets": "(přibližně)", + "selectAll": "Vybrat Vše", + "deselectN": "{} deselected", + "xWillBeRemovedButRemainInstalled":"{} bude odstraněn z Obtainium, ale zůstane nainstalován v zařízení.", + "removeSelectedAppsQuestion": "Odebrat vybrané aplikace?", + "removeSelectedApps": "Odebrat vybrané aplikace", + "updateX": "Aktualizovat {}", + "installX": "Instalovat {}", + "markXTrackOnlyAsUpdated": "Označit {}\n(Track-Only)\njako aktualizované", + "changeX": "Změnit {}", + "installUpdateApps": "Instalovat/aktualizovat aplikace", + "installUpdateSelectedApps": "Instalovat/aktualizovat vybrané aplikace", + "markXSelectedAppsAsUpdated": "označit {} vybrané aplikace jako aktuální?", + "no": "Ne", + "yes": "ano", + "markSelectedAppsUpdated": "označit vybrané aplikace jako aktuální", + "pinToTop": "Připnout nahoru", + "unpinFromTop": "'Unpin Top'", + "resetInstallStatusForSelectedAppsQuestion": "Obnovit stav instalace vybraných aplikací?", + "installStatusOfXWillBeResetExplanation": "Stav instalace vybraných aplikací bude resetován. To může být užitečné, pokud je verze aplikace zobrazená v Obtainium nesprávná z důvodu neúspěšných aktualizací nebo jiných problémů.", + "shareSelectedAppURLs": "Sdílet adresy URL vybraných aplikací", + "resetInstallStatus": "Obnovení stavu instalace", + "more": "more", + "removeOutdatedFilter": "Odstranit filtr aplikace 'Not Current'", + "showOutdatedOnly": "Zobrazit pouze aplikace, které nejsou aktuální", + "filter": "Filtr", + "filterActive": "Filtr *", + "filterApps": "Filtrovat aplikace", + "appName": "název aplikace", + "author": "Autor", + "upToDateApps": "Apps with current version", + "nonInstalledApps": "Apps not installed", + "importExport": "Import/Export", + "settings": "Nastavení", + "exportedTo": "Exportováno do {}", + "obtainiumExport": "Obtainium Export", + "invalidInput": "Neplatný vstup", + "importedX": "Importováno {}", + "obtainiumImport": "Obtainium Import", + "importFromURLList": "Import ze seznamu URL", + "searchQuery": "Search Query", + "appURLList": "App URL List", + "line": "line", + "searchX": "Search {}", + "noResults": "Nebyly nalezeny žádné výsledky", + "importX": "Import {}", + "importedAppsIdDisclaimer": "Importované aplikace mohou být nesprávně zobrazeny jako \"Neinstalované\". Chcete-li to opravit, nainstalujte je znovu prostřednictvím Obtainium. To nemá vliv na data aplikací. Ovlivňuje pouze metody importu URL a třetích stran.", + "importErrors": "Import Errors", + "importedXOfYApps":"{}importováno {}aplikací.", + "followingURLsHadErrors": "U následujících adres URL došlo k chybám:", + "okay": "Okay", + "selectURL": "Select URL", + "selectURLs": "Select URLs", + "pick": "Vybrat", + "theme": "Téma", + "dark": "Tmavé", + "light": "Světlé", + "followSystem": "Follow System", + "obtainium": "Obtainium", + "materialYou": "Material You", + "useBlackTheme": "Použít čistě černé tmavé téma", + "appSortBy": "Seřadit aplikaci podle", + "authorName": "autor/jméno", + "nameAuthor": "jméno/autor", + "asAdded": "AsAdded", + "appSortOrder": "Sort App By", + "ascending": "Vzestupně", + "descending": "Sestupně", + "bgUpdateCheckInterval": "Background Update Check Interval", + "neverManualOnly": "Nikdy - pouze ručně", + "appearance": "Vzhled", + "showWebInAppView": "Zobrazit zdrojové webové stránky v zobrazení aplikace", + "pinUpdates": "Připnout aplikace s aktualizacemi nahoře", + "updates": "Updates", + "sourceSpecific": "source specific", + "appSource": "zdroj aplikace", + "noLogs": "Žádné protokoly", + "appLogs": "App Logs", + "close": "Zavřít", + "share": "Sdílet", + "appNotFound": "App not found", + "obtainiumExportHyphenatedLowercase": "obtainium-export", + "pickAnAPK": "Vybrat APK", + "appHasMoreThanOnePackage":"{} má více než jeden balíček:", + "deviceSupportsXArch": "Vaše zařízení podporuje architekturu CPU {}.", + "deviceSupportsFollowingArchs": "Vaše zařízení podporuje následující architektury CPU:", + "warning": "Varování", + "sourceIsXButPackageFromYPrompt": "The app source is '{}' but the release package is from '{}'. Pokračovat?", + "updatesAvailable": "dostupné aktualizace", + "updatesAvailableNotifDescription": "Upozorňuje uživatele, že jsou k dispozici aktualizace pro jednu nebo více aplikací sledovaných Obtainium", + "noNewUpdates": "Žádné nové aktualizace.", + "xHasAnUpdate":"{} má aktualizaci.", + "appsUpdated": "Aplikace aktualizovány", + "appsUpdatedNotifDescription": "Upozorňuje uživatele, že byly provedeny aktualizace jedné nebo více aplikací na pozadí", + "xWasUpdatedToY":"{} byl aktualizován na {}", + "errorCheckingUpdates": "Chybová kontrola aktualizací", + "errorCheckingUpdatesNotifDescription": "Oznámení zobrazené při neúspěšné kontrole aktualizací na pozadí", + "appsRemoved": "Odstraněné aplikace", + "appsRemovedNotifDescription": "Oznámení uživateli, že jedna nebo více aplikací byly odstraněny z důvodu chyb při načítání", + "xWasRemovedDueToErrorY":"{} byla odstraněna z důvodu následující chyby: {}", + "completeAppInstallation": "Dokončit instalaci aplikace", + "obtainiumMustBeOpenToInstallApps": "Obtainium musí být otevřeno, aby bylo možné instalovat aplikace", + "completeAppInstallationNotifDescription": "Vyzvat uživatele k návratu do Obtainium pro dokončení instalace aplikací", + "checkingForUpdates": "Zkontrolovat aktualizace", + "checkingForUpdatesNotifDescription": "Dočasné oznámení zobrazené při kontrole aktualizací", + "pleaseAllowInstallPerm": "Povolte prosím Obtainium instalovat aplikace", + "trackOnly": "Jen sledovat", + "errorWithHttpStatusCode": "error {}", + "versionCorrectionDisabled": "Oprava verze zakázána (zásuvný modul zřejmě nefunguje)", + "unknown": "Unknown", + "none": "None", + "never": "Nikdy", + "latestVersionX": "Nejnovější verze: {}", + "installedVersionX": "Nainstalovaná verze: {}", + "lastUpdateCheckX": "Poslední kontrola aktualizace: {}", + "remove": "Odebrat", + "yesMarkUpdated": "Ano, označit jako aktualizované", + "fdroid": "F-Droid Official", + "appIdOrName": "App ID or Name", + "appId": "App ID", + "appWithIdOrNameNotFound": "Žádná aplikace s tímto ID nebo názvem nebyla nalezena", + "reposHaveMultipleApps": "Repozitáře mohou obsahovat více aplikací", + "fdroidThirdPartyRepo": "F-Droid Third-Party Repo", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Chat", + "install": "Install", + "markInstalled": "Označit jako nainstalovaný", + "update": "Aktualizovat", + "markUpdated": "Označit jako aktuální", + "additionalOptions": "Additional Options", + "disableVersionDetection": "Zakázat detekci verze", + "noVersionDetectionExplanation": "Tato volba by měla být použita pouze u aplikací, kde detekce verzí nefunguje správně.", + "downloadingX": "download {}", + "downloadNotifDescription": "Informuje uživatele o průběhu stahování aplikace", + "noAPKFound": "Žádná APK nebyla nalezena", + "noVersionDetection": "Žádná detekce verze", + "categorize": "Kategorizovat", + "categories": "Kategorie", + "category": "kategorie", + "noCategory": "Žádná kategorie", + "noCategories": "Žádné kategorie", + "deleteCategoriesQuestion": "Smazat kategorie?", + "categoryDeleteWarning": "Všechny aplikace v odstraněných kategoriích budou nastaveny na nekategorizované.", + "addCategory": "přidat kategorii", + "label": "štítek", + "language": "Jazyk", + "copiedToClipboard": "zkopírováno do schránky", + "storagePermissionDenied": "povolení k ukládání odepřeno", + "selectedCategorizeWarning": "Toto nahradí všechna stávající nastavení kategorií pro vybrané aplikace.", + "filterAPKsByRegEx": "Filtrovat APK podle regulárního výrazu", + "removeFromObtainium": "Odebrat z Obtainium", + "uninstallFromDevice": "Odinstalovat ze zařízení", + "onlyWorksWithNonVersionDetectApps": "Funguje pouze pro aplikace s vypnutou detekcí verze.", + "releaseDateAsVersion": "Použít datum vydání jako verzi", + "releaseDateAsVersionExplanation": "Tato možnost by měla být použita pouze u aplikací, u kterých detekce verze nefunguje správně, ale je k dispozici datum vydání.", + "changes": "Změny", + "releaseDate": "datum vydání", + "importFromURLsInFile": "Importovat adresy URL ze souboru (např. OPML)", + "versionDetection": "detekce verze", + "standardVersionDetection": "standardní detekce verze", + "groupByCategory": "Seskupit podle kategorie", + "autoApkFilterByArch": "Pokud je to možné, pokuste se filtrovat soubory APK podle architektury procesoru", + "overrideSource": "Přepsat zdroj", + "dontShowAgain": "Nezobrazovat znovu", + "dontShowTrackOnlyWarnings": "Nezobrazovat varování pro 'Track Only'", + "dontShowAPKOriginWarnings": "Nezobrazovat varování pro původ APK", + "moveNonInstalledAppsToBottom": "Přesunout nenainstalované aplikace na konec zobrazení Aplikace", + "gitlabPATLabel": "GitLab Personal Access Token\n(Umožňuje vyhledávání a lepší zjišťování APK)", + "about": "About", + "requiresCredentialsInSettings": "Vyžaduje další pověření (v nastavení)", + "checkOnStart": "Zkontrolovat jednou při spuštění", + "tryInferAppIdFromCode": "Pokusit se určit ID aplikace ze zdrojového kódu", + "removeOnExternalUninstall": "Automaticky odstranit externě odinstalované aplikace", + "pickHighestVersionCode": "Automaticky vybrat APK s kódem nejvyšší verze", + "checkUpdateOnDetailPage": "Zkontrolovat aktualizace při otevření stránky s podrobnostmi aplikace", + "disablePageTransitions": "Zakázat animace pro přechody stránek", + "reversePageTransitions": "Obrátit animace pro přechody stránek", + "minStarCount": "Minimální počet hvězdiček", + "addInfoBelow": "Přidat tuto informaci na konec stránky", + "addInfoInSettings": "Přidat tuto informaci do nastavení.", + "githubSourceNote": "Omezení rychlosti GitHub lze obejít pomocí klíče API.", + "gitlabSourceNote": "Extrakce GitLab APK nemusí fungovat bez klíče API", + "sortByFileNamesNotLinks": "Řadit podle názvů souborů místo celých odkazů", + "filterReleaseNotesByRegEx": "Filtrovat poznámky k vydání podle regulárního výrazu", + "customLinkFilterRegex": "Vlastní filtr odkazů APK podle regulárního výrazu (výchozí '.apk$')", + "appsPossiblyUpdated": "Byly provedeny pokusy o aktualizaci aplikací", + "appsPossiblyUpdatedNotifDescription": "Upozorňuje uživatele, že na pozadí mohly být provedeny aktualizace jedné nebo více aplikací", + "xWasPossiblyUpdatedToY":"{} mohlo být aktualizováno na {}.", + "enableBackgroundUpdates": "Povolit aktualizace na pozadí", + "backgroundUpdateReqsExplanation": "Aktualizace na pozadí nemusí být možné pro všechny aplikace.", + "backgroundUpdateLimitsExplanation": "Úspěšnost instalace na pozadí lze určit pouze v případě, že je otevřen Obtainium.", + "verifyLatestTag": "Ověřit značku 'latest'", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", + "intermediateLinkNotFound": "Intermediate link not found", + "exemptFromBackgroundUpdates": "Vyloučit aktualizace na pozadí (pokud jsou povoleny)", + "bgUpdatesOnWiFiOnly": "Zakázat aktualizace na pozadí, pokud není přítomna Wi-Fi", + "autoSelectHighestVersionCode": "Automatický výběr nejvyššího kódu verze APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Zvýraznit méně zjevné cíle dotyku", + "pickExportDir": "Vybrat adresář pro export", + "autoExportOnChanges": "Automatický export při změnách", + "filterVersionsByRegEx": "Filtrovat verze podle regulárního výrazu", + "trySelectingSuggestedVersionCode": "Zkusit vybrat navrhovaný kód verze APK", + "removeAppQuestion": { + "one": "Odstranit Apku?", + "other": "Odstranit Apky?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Příliš mnoho požadavků (omezená rychlost) - zkuste to znovu za {} minutu", + "other": "Příliš mnoho požadavků (omezená rychlost) - zkuste to znovu za {} minut" + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "Při kontrole aktualizace na pozadí byla zjištěna chyba {}, opakování pokusu bude naplánováno za {} minut", + "other": "Během kontroly aktualizace na pozadí byla zjištěna chyba {}, opakování bude naplánováno za {} minut" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "Při kontrole aktualizací na pozadí nalezena {}aktualizace - v případě potřeby upozorní uživatele", + "other": "Kontrola aktualizací na pozadí našla {} aktualizací - v případě potřeby upozorní uživatele" + }, + "apps": { + "one":"{} App", + "other":"{} apps" + }, + "url": { + "jedna": "{} URL", + "other": "{} URLs" + }, + "minute": { + "one":"{} minute", + "other": "{} minutes" + }, + "hour": { + "jedna": "{} hodina", + "other": "{} hours" + }, + "day": { + "jedna": "{} den", + "other": "{} dny" + }, + "clearedNLogsBeforeXAfterY": { + "one":"{n} log vymazán (před = {před}, po = {po})", + "other": "{n} logů vymazáno (před = {před}, po = {po})" + }, + "xAndNMoreUpdatesAvailable": { + "one":"{} a 1 další aplikace mají aktualizace.", + "other":"{} a {} další aplikace mají aktualizace." + }, + "xAndNMoreUpdatesInstalled": { + "one":"{} a {} další aplikace mají aktualizace.", + "další":"{} a {} další aplikace byly aktualizovány." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one":"{} a {} další aplikace byly možná aktualizovány", + "other":"{} a {} další aplikace mohly být aktualizovány." + } +} + diff --git a/lib/main.dart b/lib/main.dart index ad48463..e15aa29 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,6 +38,7 @@ List> supportedLocales = const [ MapEntry(Locale('pl'), 'Polski'), MapEntry(Locale('ru'), 'Русский язык'), MapEntry(Locale('bs'), 'Bosanski'), + MapEntry(Locale('cs'), 'Česky'), // MapEntry(Locale('br'), 'Brasileiro'), ]; const fallbackLocale = Locale('en'); From ae7d5546aec8536d39da8b3006a3f3bf278903cc Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 16 Sep 2023 16:34:15 -0400 Subject: [PATCH 447/600] Remove nonsense hint --- lib/app_sources/github.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 15b9831..e3ceb41 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -22,7 +22,6 @@ class GitHub extends AppSource { label: tr('githubPATLabel'), password: true, required: false, - hint: tr('githubPATFormat'), belowWidgets: [ const SizedBox( height: 4, From c4a3f7333d7a43bb73866da036db97977cd5af93 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 16 Sep 2023 16:45:06 -0400 Subject: [PATCH 448/600] Enable Brazil translation (#830) --- assets/translations/{br.json => pt.json} | 0 lib/main.dart | 4 ++-- pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename assets/translations/{br.json => pt.json} (100%) diff --git a/assets/translations/br.json b/assets/translations/pt.json similarity index 100% rename from assets/translations/br.json rename to assets/translations/pt.json diff --git a/lib/main.dart b/lib/main.dart index e15aa29..22b9f36 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.17'; +const String currentVersion = '0.14.18'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES @@ -38,8 +38,8 @@ List> supportedLocales = const [ MapEntry(Locale('pl'), 'Polski'), MapEntry(Locale('ru'), 'Русский язык'), MapEntry(Locale('bs'), 'Bosanski'), + MapEntry(Locale('pt'), 'Brasileiro'), MapEntry(Locale('cs'), 'Česky'), - // MapEntry(Locale('br'), 'Brasileiro'), ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; diff --git a/pubspec.yaml b/pubspec.yaml index 25f11d0..15efb86 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.14.17+209 # When changing this, update the tag in main() accordingly +version: 0.14.18+210 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 6e1767730bcccd98e702d6fd901fb118cd8f1270 Mon Sep 17 00:00:00 2001 From: YGXB_net Date: Mon, 18 Sep 2023 00:45:45 +0800 Subject: [PATCH 449/600] Update zh.json --- assets/translations/zh.json | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 1057515..7fb0b27 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -246,16 +246,18 @@ "backgroundUpdateReqsExplanation": "后台更新未必适用于所有的应用。", "backgroundUpdateLimitsExplanation": "只有在启动 Obtainium 时才能确认安装是否成功。", "verifyLatestTag": "验证“Latest”标签", - "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", - "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", - "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", - "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", - "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", - "autoExportOnChanges": "Auto-export on changes", - "filterVersionsByRegEx": "Filter Versions by Regular Expression", - "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "intermediateLinkRegex": "首先访问“中间”链接的过滤器", + "intermediateLinkNotFound": "中间链接未找到", + "exemptFromBackgroundUpdates": "免除后台更新 (如果启用)", + "bgUpdatesOnWiFiOnly": "不在连接 WiFi 时禁用后台更新", + "autoSelectHighestVersionCode": "自动选择最高版本号 APK", + "versionExtractionRegEx": "版本提取正则表达式", + "matchGroupToUse": "匹配要使用的组", + "highlightTouchTargets": "突出显示不明显的触摸目标", + "pickExportDir": "选择导出目录", + "autoExportOnChanges": "修改时自动导出", + "filterVersionsByRegEx": "使用正则表达式筛选版本", + "trySelectingSuggestedVersionCode": "尝试选择推荐版本 APK", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" From ea205c1acb7fd51e6aae63ffab6873055df2671d Mon Sep 17 00:00:00 2001 From: YGXB_net Date: Tue, 19 Sep 2023 00:32:20 +0800 Subject: [PATCH 450/600] Update zh.json --- assets/translations/zh.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 7fb0b27..781ca62 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -51,9 +51,9 @@ "percentProgress": "进度:{}%", "pleaseWait": "请稍候", "updateAvailable": "更新可用", - "estimateInBracketsShort": "(推测)", + "estimateInBracketsShort": "(推测)", "notInstalled": "未安装", - "estimateInBrackets": "(推测)", + "estimateInBrackets": "(推测)", "selectAll": "全选", "deselectN": "取消选择 {}", "xWillBeRemovedButRemainInstalled": "{} 将从 Obtainium 中删除,但仍安装在您的设备中。", @@ -248,7 +248,7 @@ "verifyLatestTag": "验证“Latest”标签", "intermediateLinkRegex": "首先访问“中间”链接的过滤器", "intermediateLinkNotFound": "中间链接未找到", - "exemptFromBackgroundUpdates": "免除后台更新 (如果启用)", + "exemptFromBackgroundUpdates": "禁用后台更新(如果全局设置启用)", "bgUpdatesOnWiFiOnly": "不在连接 WiFi 时禁用后台更新", "autoSelectHighestVersionCode": "自动选择最高版本号 APK", "versionExtractionRegEx": "版本提取正则表达式", From 2a94c1f33a860354bafd06b889c2ee66e22ea17c Mon Sep 17 00:00:00 2001 From: YGXB_net Date: Tue, 19 Sep 2023 00:51:58 +0800 Subject: [PATCH 451/600] Update main.dart --- lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/main.dart b/lib/main.dart index 22b9f36..a650348 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -27,7 +27,7 @@ const int bgUpdateCheckAlarmId = 666; List> supportedLocales = const [ MapEntry(Locale('en'), 'English'), - MapEntry(Locale('zh'), '汉语'), + MapEntry(Locale('zh'), '简体中文'), MapEntry(Locale('it'), 'Italiano'), MapEntry(Locale('ja'), '日本語'), MapEntry(Locale('hu'), 'Magyar'), From b423a2af521d605a1fe8280d4e85a159cd36e4a7 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 22 Sep 2023 00:22:54 -0400 Subject: [PATCH 452/600] Change a default F-Droid Source option --- lib/app_sources/fdroid.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index f2dd3f9..13f5006 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -25,7 +25,7 @@ class FDroid extends AppSource { ], [ GeneratedFormSwitch('trySelectingSuggestedVersionCode', - label: tr('trySelectingSuggestedVersionCode'), defaultValue: true) + label: tr('trySelectingSuggestedVersionCode')) ], [ GeneratedFormSwitch('autoSelectHighestVersionCode', From c10a63e76e81772854303e39582b2360b6e05efc Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 23 Sep 2023 12:48:21 -0400 Subject: [PATCH 453/600] Add GitHub "don't sort" toggle (#925) --- assets/translations/bs.json | 1 + assets/translations/cs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/pt.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/github.dart | 57 ++++++++++++++++++++----------------- lib/app_sources/html.dart | 2 +- 16 files changed, 46 insertions(+), 27 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 7352027..b6c60be 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -255,6 +255,7 @@ "autoExportOnChanges": "Auto-export on changes", "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index 88fb2e7..bf1d18a 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -258,6 +258,7 @@ "autoExportOnChanges": "Automatický export při změnách", "filterVersionsByRegEx": "Filtrovat verze podle regulárního výrazu", "trySelectingSuggestedVersionCode": "Zkusit vybrat navrhovaný kód verze APK", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 33975f8..b21756f 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -255,6 +255,7 @@ "autoExportOnChanges": "Automatischer Export bei Änderung", "filterVersionsByRegEx": "Versionen nach regulären Ausdrücken filtern", "trySelectingSuggestedVersionCode": "Versuchen, die vorgeschlagene APK-Code-Version auszuwählen", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 6e782f9..a496fa1 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -258,6 +258,7 @@ "autoExportOnChanges": "Auto-export on changes", "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index aefea28..3689bbf 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -255,6 +255,7 @@ "autoExportOnChanges": "Auto-export on changes", "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 9c62c43..6a15b9d 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -255,6 +255,7 @@ "autoExportOnChanges": "Auto-export on changes", "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 33e9fb6..7bf0e32 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -255,6 +255,7 @@ "autoExportOnChanges": "Auto-export on changes", "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 1a8ee3e..bab012d 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -254,6 +254,7 @@ "autoExportOnChanges": "Auto-exportálás a változások után", "filterVersionsByRegEx": "Verziók szűrése reguláris kifejezéssel", "trySelectingSuggestedVersionCode": "Próbálja ki a javasolt verziókódú APK-t", + "dontSortReleasesList": "Retain release order from API", "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 b805fc5..fad6392 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -255,6 +255,7 @@ "autoExportOnChanges": "Auto-export on changes", "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index be3e9c8..ec91884 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -258,6 +258,7 @@ "autoExportOnChanges": "変更があった際に自動でエクスポートする", "filterVersionsByRegEx": "正規表現でバージョンをフィルタリングする", "trySelectingSuggestedVersionCode": "提案されたバージョンコードのAPKを選択する", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 661a85b..4e8bd5c 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -261,6 +261,7 @@ "autoExportOnChanges": "Automatyczny eksport po wprowadzeniu zmian", "filterVersionsByRegEx": "Filtruj wersje według wyrażenia regularnego", "trySelectingSuggestedVersionCode": "Spróbuj wybierać sugerowany kod wersji APK", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index a083e20..d0e9809 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -258,6 +258,7 @@ "autoExportOnChanges": "Auto-export on changes", "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 9db80ce..982641a 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -255,6 +255,7 @@ "autoExportOnChanges": "Auto-export on changes", "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 1057515..cea5130 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -256,6 +256,7 @@ "autoExportOnChanges": "Auto-export on changes", "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "dontSortReleasesList": "Retain release order from API", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index e3ceb41..56a31fd 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -72,9 +72,10 @@ class GitHub extends AppSource { } ]) ], + [GeneratedFormSwitch('verifyLatestTag', label: tr('verifyLatestTag'))], [ - GeneratedFormSwitch('verifyLatestTag', - label: tr('verifyLatestTag'), defaultValue: false) + GeneratedFormSwitch('dontSortReleasesList', + label: tr('dontSortReleasesList')) ] ]; @@ -230,6 +231,8 @@ class GitHub extends AppSource { ? additionalSettings['filterReleaseNotesByRegEx'] : null; bool verifyLatestTag = additionalSettings['verifyLatestTag'] == true; + bool dontSortReleasesList = + additionalSettings['dontSortReleasesList'] == true; String? latestTag; if (verifyLatestTag) { var temp = requestUrl.split('?'); @@ -265,32 +268,34 @@ class GitHub extends AppSource { rel?['published_at'] != null ? DateTime.parse(rel['published_at']) : null; - releases.sort((a, b) { - // See #478 and #534 - if (a == b) { - return 0; - } else if (a == null) { - return -1; - } else if (b == null) { - return 1; - } else { - var nameA = a['tag_name'] ?? a['name']; - var nameB = b['tag_name'] ?? b['name']; - var stdFormats = findStandardFormatsForVersion(nameA, true) - .intersection(findStandardFormatsForVersion(nameB, true)); - if (stdFormats.isNotEmpty) { - var reg = RegExp(stdFormats.first); - var matchA = reg.firstMatch(nameA); - var matchB = reg.firstMatch(nameB); - return compareAlphaNumeric( - (nameA as String).substring(matchA!.start, matchA.end), - (nameB as String).substring(matchB!.start, matchB.end)); + if (dontSortReleasesList) { + releases.sort((a, b) { + // See #478 and #534 + if (a == b) { + return 0; + } else if (a == null) { + return -1; + } else if (b == null) { + return 1; } else { - return (getReleaseDateFromRelease(a) ?? DateTime(1)) - .compareTo(getReleaseDateFromRelease(b) ?? DateTime(0)); + var nameA = a['tag_name'] ?? a['name']; + var nameB = b['tag_name'] ?? b['name']; + var stdFormats = findStandardFormatsForVersion(nameA, true) + .intersection(findStandardFormatsForVersion(nameB, true)); + if (stdFormats.isNotEmpty) { + var reg = RegExp(stdFormats.first); + var matchA = reg.firstMatch(nameA); + var matchB = reg.firstMatch(nameB); + return compareAlphaNumeric( + (nameA as String).substring(matchA!.start, matchA.end), + (nameB as String).substring(matchB!.start, matchB.end)); + } else { + return (getReleaseDateFromRelease(a) ?? DateTime(1)) + .compareTo(getReleaseDateFromRelease(b) ?? DateTime(0)); + } } - } - }); + }); + } if (latestTag != null && releases.isNotEmpty && latestTag != diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index c2ff364..5522c62 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -107,7 +107,7 @@ class HTML extends AppSource { [ GeneratedFormTextField('intermediateLinkRegex', label: tr('intermediateLinkRegex'), - hint: '([0-9]+\.)*[0-9]+/\$', + hint: '([0-9]+.)*[0-9]+/\$', required: false, additionalValidators: [(value) => regExValidator(value)]) ], From 6ac8ad543c179b1f8bf64caa323efc5e84b69174 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 23 Sep 2023 13:16:51 -0400 Subject: [PATCH 454/600] Better IzzyOnDroid support (#926) --- lib/app_sources/fdroid.dart | 151 ++++++++++++++++--------------- lib/app_sources/izzyondroid.dart | 15 ++- 2 files changed, 87 insertions(+), 79 deletions(-) diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 13f5006..1201062 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -57,81 +57,6 @@ class FDroid extends AppSource { return Uri.parse(standardUrl).pathSegments.last; } - APKDetails getAPKUrlsFromFDroidPackagesAPIResponse( - Response res, String apkUrlPrefix, String standardUrl, - {bool autoSelectHighestVersionCode = false, - bool trySelectingSuggestedVersionCode = false, - String? filterVersionsByRegEx}) { - if (res.statusCode == 200) { - var response = jsonDecode(res.body); - List releases = response['packages'] ?? []; - if (releases.isEmpty) { - throw NoReleasesError(); - } - String? version; - Iterable releaseChoices = []; - // Grab the versionCode suggested if the user chose to do that - // Only do so at this stage if the user has no release filter - if (trySelectingSuggestedVersionCode && - response['suggestedVersionCode'] != null && - filterVersionsByRegEx == null) { - var suggestedReleases = releases.where((element) => - element['versionCode'] == response['suggestedVersionCode']); - if (suggestedReleases.isNotEmpty) { - releaseChoices = suggestedReleases; - version = suggestedReleases.first['versionName']; - } - } - // Apply the release filter if any - if (filterVersionsByRegEx != null) { - version = null; - releaseChoices = []; - for (var i = 0; i < releases.length; i++) { - if (RegExp(filterVersionsByRegEx) - .hasMatch(releases[i]['versionName'])) { - version = releases[i]['versionName']; - } - } - if (version == null) { - throw NoVersionError(); - } - } - // Default to the highest version - version ??= releases[0]['versionName']; - if (version == null) { - throw NoVersionError(); - } - // If a suggested release was not already picked, pick all those with the selected version - if (releaseChoices.isEmpty) { - releaseChoices = - releases.where((element) => element['versionName'] == version); - } - // For the remaining releases, use the toggles to auto-select one if possible - if (releaseChoices.length > 1) { - if (autoSelectHighestVersionCode) { - releaseChoices = [releaseChoices.first]; - } else if (trySelectingSuggestedVersionCode && - response['suggestedVersionCode'] != null) { - var suggestedReleases = releaseChoices.where((element) => - element['versionCode'] == response['suggestedVersionCode']); - if (suggestedReleases.isNotEmpty) { - releaseChoices = suggestedReleases; - } - } - } - if (releaseChoices.isEmpty) { - throw NoReleasesError(); - } - List apkUrls = releaseChoices - .map((e) => '${apkUrlPrefix}_${e['versionCode']}.apk') - .toList(); - return APKDetails(version, getApkUrlsFromUrls(apkUrls), - AppNames(name, Uri.parse(standardUrl).pathSegments.last)); - } else { - throw getObtainiumHttpError(res); - } - } - @override Future getLatestAPKDetails( String standardUrl, @@ -143,6 +68,7 @@ class FDroid extends AppSource { await sourceRequest('https://$host/api/v1/packages/$appId'), 'https://$host/repo/$appId', standardUrl, + name, autoSelectHighestVersionCode: additionalSettings['autoSelectHighestVersionCode'] == true, trySelectingSuggestedVersionCode: @@ -185,3 +111,78 @@ class FDroid extends AppSource { } } } + +APKDetails getAPKUrlsFromFDroidPackagesAPIResponse( + Response res, String apkUrlPrefix, String standardUrl, String sourceName, + {bool autoSelectHighestVersionCode = false, + bool trySelectingSuggestedVersionCode = false, + String? filterVersionsByRegEx}) { + if (res.statusCode == 200) { + var response = jsonDecode(res.body); + List releases = response['packages'] ?? []; + if (releases.isEmpty) { + throw NoReleasesError(); + } + String? version; + Iterable releaseChoices = []; + // Grab the versionCode suggested if the user chose to do that + // Only do so at this stage if the user has no release filter + if (trySelectingSuggestedVersionCode && + response['suggestedVersionCode'] != null && + filterVersionsByRegEx == null) { + var suggestedReleases = releases.where((element) => + element['versionCode'] == response['suggestedVersionCode']); + if (suggestedReleases.isNotEmpty) { + releaseChoices = suggestedReleases; + version = suggestedReleases.first['versionName']; + } + } + // Apply the release filter if any + if (filterVersionsByRegEx != null) { + version = null; + releaseChoices = []; + for (var i = 0; i < releases.length; i++) { + if (RegExp(filterVersionsByRegEx) + .hasMatch(releases[i]['versionName'])) { + version = releases[i]['versionName']; + } + } + if (version == null) { + throw NoVersionError(); + } + } + // Default to the highest version + version ??= releases[0]['versionName']; + if (version == null) { + throw NoVersionError(); + } + // If a suggested release was not already picked, pick all those with the selected version + if (releaseChoices.isEmpty) { + releaseChoices = + releases.where((element) => element['versionName'] == version); + } + // For the remaining releases, use the toggles to auto-select one if possible + if (releaseChoices.length > 1) { + if (autoSelectHighestVersionCode) { + releaseChoices = [releaseChoices.first]; + } else if (trySelectingSuggestedVersionCode && + response['suggestedVersionCode'] != null) { + var suggestedReleases = releaseChoices.where((element) => + element['versionCode'] == response['suggestedVersionCode']); + if (suggestedReleases.isNotEmpty) { + releaseChoices = suggestedReleases; + } + } + } + if (releaseChoices.isEmpty) { + throw NoReleasesError(); + } + List apkUrls = releaseChoices + .map((e) => '${apkUrlPrefix}_${e['versionCode']}.apk') + .toList(); + return APKDetails(version, getApkUrlsFromUrls(apkUrls), + AppNames(sourceName, Uri.parse(standardUrl).pathSegments.last)); + } else { + throw getObtainiumHttpError(res); + } +} diff --git a/lib/app_sources/izzyondroid.dart b/lib/app_sources/izzyondroid.dart index 8f801db..66624bc 100644 --- a/lib/app_sources/izzyondroid.dart +++ b/lib/app_sources/izzyondroid.dart @@ -6,16 +6,22 @@ class IzzyOnDroid extends AppSource { late FDroid fd; IzzyOnDroid() { - host = 'android.izzysoft.de'; + host = 'izzysoft.de'; fd = FDroid(); additionalSourceAppSpecificSettingFormItems = fd.additionalSourceAppSpecificSettingFormItems; + allowSubDomains = true; } @override String sourceSpecificStandardizeURL(String url) { - RegExp standardUrlRegEx = RegExp('^https?://$host/repo/apk/[^/]+'); - RegExpMatch? match = standardUrlRegEx.firstMatch(url.toLowerCase()); + RegExp standardUrlRegExA = RegExp('^https?://android.$host/repo/apk/[^/]+'); + RegExpMatch? match = standardUrlRegExA.firstMatch(url.toLowerCase()); + if (match == null) { + RegExp standardUrlRegExB = + RegExp('^https?://apt.$host/fdroid/index/apk/[^/]+'); + match = standardUrlRegExB.firstMatch(url.toLowerCase()); + } if (match == null) { throw InvalidURLError(name); } @@ -34,11 +40,12 @@ class IzzyOnDroid extends AppSource { Map additionalSettings, ) async { String? appId = await tryInferringAppId(standardUrl); - return fd.getAPKUrlsFromFDroidPackagesAPIResponse( + return getAPKUrlsFromFDroidPackagesAPIResponse( await sourceRequest( 'https://apt.izzysoft.de/fdroid/api/v1/packages/$appId'), 'https://android.izzysoft.de/frepo/$appId', standardUrl, + name, autoSelectHighestVersionCode: additionalSettings['autoSelectHighestVersionCode'] == true, trySelectingSuggestedVersionCode: From af5377d2eba2aeaf4d127a2ed89952667d51526b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 23 Sep 2023 13:21:48 -0400 Subject: [PATCH 455/600] Allow 'm.' subdomain for APKPure --- lib/app_sources/apkpure.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index 15ca098..b40d39f 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -21,6 +21,7 @@ parseDateTimeMMMddCommayyyy(String? dateString) { class APKPure extends AppSource { APKPure() { host = 'apkpure.com'; + allowSubDomains = true; } @override @@ -28,7 +29,7 @@ class APKPure extends AppSource { RegExp standardUrlRegExB = RegExp('^https?://m.$host/+[^/]+/+[^/]+'); RegExpMatch? match = standardUrlRegExB.firstMatch(url.toLowerCase()); if (match != null) { - url = 'https://$host/${Uri.parse(url).path}'; + url = 'https://$host${Uri.parse(url).path}'; } RegExp standardUrlRegExA = RegExp('^https?://$host/+[^/]+/+[^/]+'); match = standardUrlRegExA.firstMatch(url.toLowerCase()); From 68d4083708007f18cc533b969c0eddffd42d543e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 23 Sep 2023 13:31:27 -0400 Subject: [PATCH 456/600] Added HTML reverse sorting (#915) + translatable strings (#916) --- assets/translations/bs.json | 4 ++++ assets/translations/cs.json | 4 ++++ assets/translations/de.json | 4 ++++ assets/translations/en.json | 4 ++++ assets/translations/es.json | 4 ++++ 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/pl.json | 4 ++++ assets/translations/pt.json | 4 ++++ assets/translations/ru.json | 4 ++++ assets/translations/zh.json | 4 ++++ lib/app_sources/html.dart | 4 ++++ lib/pages/settings.dart | 9 +++------ 16 files changed, 63 insertions(+), 6 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index b6c60be..5ddd49f 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -256,6 +256,10 @@ "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index bf1d18a..0aceed9 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -259,6 +259,10 @@ "filterVersionsByRegEx": "Filtrovat verze podle regulárního výrazu", "trySelectingSuggestedVersionCode": "Zkusit vybrat navrhovaný kód verze APK", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/de.json b/assets/translations/de.json index b21756f..462f3a4 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -256,6 +256,10 @@ "filterVersionsByRegEx": "Versionen nach regulären Ausdrücken filtern", "trySelectingSuggestedVersionCode": "Versuchen, die vorgeschlagene APK-Code-Version auszuwählen", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index a496fa1..a283052 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -259,6 +259,10 @@ "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 3689bbf..c1231fe 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -256,6 +256,10 @@ "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 6a15b9d..c35bc60 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -256,6 +256,10 @@ "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 7bf0e32..7e0d414 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -256,6 +256,10 @@ "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index bab012d..ff1c68f 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -255,6 +255,10 @@ "filterVersionsByRegEx": "Verziók szűrése reguláris kifejezéssel", "trySelectingSuggestedVersionCode": "Próbálja ki a javasolt verziókódú APK-t", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "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 fad6392..3f3fc40 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -256,6 +256,10 @@ "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index ec91884..4f6c398 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -259,6 +259,10 @@ "filterVersionsByRegEx": "正規表現でバージョンをフィルタリングする", "trySelectingSuggestedVersionCode": "提案されたバージョンコードのAPKを選択する", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 4e8bd5c..6001dbc 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -262,6 +262,10 @@ "filterVersionsByRegEx": "Filtruj wersje według wyrażenia regularnego", "trySelectingSuggestedVersionCode": "Spróbuj wybierać sugerowany kod wersji APK", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index d0e9809..6e26a2e 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -259,6 +259,10 @@ "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 982641a..f9b78c0 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -256,6 +256,10 @@ "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index cea5130..fc8a11d 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -257,6 +257,10 @@ "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 5522c62..60fc32d 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -93,6 +93,7 @@ class HTML extends AppSource { GeneratedFormSwitch('sortByFileNamesNotLinks', label: tr('sortByFileNamesNotLinks')) ], + [GeneratedFormSwitch('reverseSort', label: tr('reverseSort'))], [ GeneratedFormTextField('customLinkFilterRegex', label: tr('customLinkFilterRegex'), @@ -195,6 +196,9 @@ class HTML extends AppSource { ? compareAlphaNumeric(a.split('/').where((e) => e.isNotEmpty).last, b.split('/').where((e) => e.isNotEmpty).last) : compareAlphaNumeric(a, b)); + if (additionalSettings['reverseSort'] == true) { + links = links.reversed.toList(); + } if ((additionalSettings['apkFilterRegEx'] as String?)?.isNotEmpty == true) { var reg = RegExp(additionalSettings['apkFilterRegEx']); diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index ec3d1d9..02237de 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -558,7 +558,7 @@ class _SettingsPageState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const Flexible(child: Text('Debug Menu')), + Flexible(child: Text(tr('debugMenu'))), Switch( value: settingsProvider.showDebugOpts, onChanged: (value) { @@ -577,12 +577,9 @@ class _SettingsPageState extends State { const Duration(seconds: 0), bgUpdateCheckAlarmId + 200, bgUpdateCheck); - showError( - 'Background task started - check logs.', - context); + showError(tr('bgTaskStarted'), context); }, - child: - const Text('Run Background Update Check Now')) + child: Text(tr('runBgCheckNow'))) ], ), ]), From 9658a65661e6bcd6bd22c6025b34e5c6387e8a8e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 23 Sep 2023 13:36:46 -0400 Subject: [PATCH 457/600] Upgrade packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 24 ++++++++++++------------ pubspec.yaml | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 22b9f36..2012280 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.18'; +const String currentVersion = '0.14.19'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 33758ce..a027ead 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -46,10 +46,10 @@ packages: dependency: transitive description: name: archive - sha256: e0902a06f0e00414e4e3438a084580161279f137aeb862274710f29ec10cf01e + sha256: "20071638cbe4e5964a427cfa0e86dce55d060bc7d82d56f3554095d7239a8765" url: "https://pub.dev" source: hosted - version: "3.3.9" + version: "3.4.2" args: dependency: transitive description: @@ -386,10 +386,10 @@ packages: dependency: transitive description: name: image - sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf + sha256: "6e703d5e2f8c63fb31a77753915c1ec8baebde8088844e0d29f71b8f0b108888" url: "https://pub.dev" source: hosted - version: "4.0.17" + version: "4.1.0" intl: dependency: transitive description: @@ -546,10 +546,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: f23cfe9af0d49c6b9fd8a8b09f7b3301ca7e346204939b5afef4404d36d2608f + sha256: f2543a236584a5e8be79076f858022f100ce690e31530e6fa4c32ac94f276d3a url: "https://pub.dev" source: hosted - version: "11.0.1" + version: "11.0.3" permission_handler_apple: dependency: transitive description: @@ -903,26 +903,26 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: d2f7241849582da80b79acb03bb936422412ce5c0c79fb5f6a1de5421a5aecc4 + sha256: "485af05f2c5f83c7f78c20e236b170ad02df7153b299ae9917345be43871d29f" url: "https://pub.dev" source: hosted - version: "3.7.4" + version: "3.8.0" win32: dependency: transitive description: name: win32 - sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa" + sha256: c97defd418eef4ec88c0d1652cdce84b9f7b63dd7198e266d06ac1710d527067 url: "https://pub.dev" source: hosted - version: "5.0.7" + version: "5.0.8" win32_registry: dependency: transitive description: name: win32_registry - sha256: e4506d60b7244251bc59df15656a3093501c37fb5af02105a944d73eb95be4c9 + sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 15efb86..1a1b034 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.14.18+210 # When changing this, update the tag in main() accordingly +version: 0.14.19+211 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From a83211f2607dc482e5059cd742b37241d3b9cca8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 23 Sep 2023 13:43:04 -0400 Subject: [PATCH 458/600] Fix version number --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a1b8837..a650348 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.19'; +const String currentVersion = '0.14.18'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 1a1b034..15efb86 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.14.19+211 # When changing this, update the tag in main() accordingly +version: 0.14.18+210 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 7789e3f3a7433adbb62401dd8a1f2d2aaec9f657 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 23 Sep 2023 14:02:55 -0400 Subject: [PATCH 459/600] Removed excessive logs --- lib/providers/apps_provider.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 7d08656..a8c6fdf 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1119,7 +1119,6 @@ class AppsProvider with ChangeNotifier { logs.add('Skipping auto-export as dir is not set.'); return null; } - logs.add('Started auto-export.'); var files = await saf .listFiles(exportDir, columns: [saf.DocumentFileColumn.id]) .where((f) => f.uri.pathSegments.last.endsWith('-auto.json')) @@ -1128,7 +1127,6 @@ class AppsProvider with ChangeNotifier { for (var f in files) { saf.delete(f.uri); } - logs.add('Previous auto-export deleted.'); } } if (exportDir == null || pickOnly) { From 3878c287be1c70bd9875389086b576424818ebe8 Mon Sep 17 00:00:00 2001 From: gidano Date: Sat, 23 Sep 2023 20:23:25 +0200 Subject: [PATCH 460/600] Update hu.json --- assets/translations/hu.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index ff1c68f..9ef04d2 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -254,11 +254,11 @@ "autoExportOnChanges": "Auto-exportálás a változások után", "filterVersionsByRegEx": "Verziók szűrése reguláris kifejezéssel", "trySelectingSuggestedVersionCode": "Próbálja ki a javasolt verziókódú APK-t", - "dontSortReleasesList": "Retain release order from API", - "reverseSort": "Reverse sorting", - "debugMenu": "Debug Menu", - "bgTaskStarted": "Background task started - check logs.", - "runBgCheckNow": "Run Background Update Check Now", + "dontSortReleasesList": "Az API-ból származó kiadási sorrend megőrzése", + "reverseSort": "Fordított rendezés", + "debugMenu": "Hibakereső menü", + "bgTaskStarted": "A háttérfeladat elindult – ellenőrizze a naplókat.", + "runBgCheckNow": "Futtassa a Háttérben frissítés ellenőrzését most", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" From 8c4509f255fba9d0df5d30a62343eba7c4460537 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 23 Sep 2023 14:31:52 -0400 Subject: [PATCH 461/600] Fix major GitHub bug (#929) --- lib/app_sources/github.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 56a31fd..700fa06 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -269,6 +269,8 @@ class GitHub extends AppSource { ? DateTime.parse(rel['published_at']) : null; if (dontSortReleasesList) { + releases = releases.reversed.toList(); + } else { releases.sort((a, b) { // See #478 and #534 if (a == b) { From b57e523a0723aa63cd31f7e79f73e564e9cddb6a Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 23 Sep 2023 14:32:13 -0400 Subject: [PATCH 462/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a650348..a1b8837 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.18'; +const String currentVersion = '0.14.19'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 15efb86..1a1b034 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.14.18+210 # When changing this, update the tag in main() accordingly +version: 0.14.19+211 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 1f6701b1831a3acc3dc58be59c3660979ed92f14 Mon Sep 17 00:00:00 2001 From: gidano Date: Sat, 23 Sep 2023 20:36:00 +0200 Subject: [PATCH 463/600] Update hu.json --- assets/translations/hu.json | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 9ef04d2..363d691 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -258,6 +258,7 @@ "reverseSort": "Fordított rendezés", "debugMenu": "Hibakereső menü", "bgTaskStarted": "A háttérfeladat elindult – ellenőrizze a naplókat.", + "enableBackgroundUpdates": "Frissítések a háttérben", "runBgCheckNow": "Futtassa a Háttérben frissítés ellenőrzését most", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", From 3ea8dc598c33ecadd8b4acc816757ee97bbe81cd Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 23 Sep 2023 17:18:12 -0400 Subject: [PATCH 464/600] Downgrade permission handler to fix #932 + APKPure improvement --- lib/app_sources/apkpure.dart | 6 ++++-- lib/main.dart | 2 +- pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index b40d39f..d22e9a6 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -26,12 +26,14 @@ class APKPure extends AppSource { @override String sourceSpecificStandardizeURL(String url) { - RegExp standardUrlRegExB = RegExp('^https?://m.$host/+[^/]+/+[^/]+'); + RegExp standardUrlRegExB = + RegExp('^https?://m.$host/+[^/]+/+[^/]+(/+[^/]+)?'); RegExpMatch? match = standardUrlRegExB.firstMatch(url.toLowerCase()); if (match != null) { url = 'https://$host${Uri.parse(url).path}'; } - RegExp standardUrlRegExA = RegExp('^https?://$host/+[^/]+/+[^/]+'); + RegExp standardUrlRegExA = + RegExp('^https?://$host/+[^/]+/+[^/]+(/+[^/]+)?'); match = standardUrlRegExA.firstMatch(url.toLowerCase()); if (match == null) { throw InvalidURLError(name); diff --git a/lib/main.dart b/lib/main.dart index a1b8837..114dae6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.19'; +const String currentVersion = '0.14.20'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index a027ead..fc2bdb5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -546,10 +546,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: f2543a236584a5e8be79076f858022f100ce690e31530e6fa4c32ac94f276d3a + sha256: f23cfe9af0d49c6b9fd8a8b09f7b3301ca7e346204939b5afef4404d36d2608f url: "https://pub.dev" source: hosted - version: "11.0.3" + version: "11.0.1" permission_handler_apple: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 1a1b034..17d8771 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.14.19+211 # When changing this, update the tag in main() accordingly +version: 0.14.20+212 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From f3632a403310e7e50cad051675737651668af7d2 Mon Sep 17 00:00:00 2001 From: LucasTavaresA Date: Sat, 23 Sep 2023 19:18:54 +0000 Subject: [PATCH 465/600] Update pt.json --- assets/translations/pt.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/assets/translations/pt.json b/assets/translations/pt.json index 6e26a2e..1271fc5 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -128,7 +128,7 @@ "pinUpdates": "Fixar atualizações no topo da visão de Apps", "updates": "Atualizações", "sourceSpecific": "Específico a fonte", - "appSource": "Fonte de Apps", + "appSource": "Fonte do App", "noLogs": "Sem Logs", "appLogs": "Logs do App", "close": "Fechar", @@ -250,19 +250,19 @@ "intermediateLinkNotFound": "Link intermediário não encontrado", "exemptFromBackgroundUpdates": "Isento de atualizações em segundo plano (se ativadas)", "bgUpdatesOnWiFiOnly": "Desative atualizações em segundo plano quando não estiver em WiFi", - "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", - "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", - "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", - "autoExportOnChanges": "Auto-export on changes", - "filterVersionsByRegEx": "Filter Versions by Regular Expression", - "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", - "dontSortReleasesList": "Retain release order from API", - "reverseSort": "Reverse sorting", - "debugMenu": "Debug Menu", - "bgTaskStarted": "Background task started - check logs.", - "runBgCheckNow": "Run Background Update Check Now", + "autoSelectHighestVersionCode": "Auto-selecionar o maior codigo de versão", + "versionExtractionRegEx": "RegEx para Extração de Versão", + "matchGroupToUse": "Grupo de Seleção para Usar", + "highlightTouchTargets": "Destaque areas de toque menos óbvias", + "pickExportDir": "Escolher Diretorio de Exportação", + "autoExportOnChanges": "Auto-exportar em mudanças", + "filterVersionsByRegEx": "Filtrar Versões por Expressão Regular", + "trySelectingSuggestedVersionCode": "Tente selecionar a versão sugerida", + "dontSortReleasesList": "Reter a ordem de lançamento da API", + "reverseSort": "Ordenação reversa", + "debugMenu": "Menu Debug", + "bgTaskStarted": "Tarefa em segundo plano iniciada - verifique os logs.", + "runBgCheckNow": "Execute a verificação de atualização em segundo plano agora", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" From 70162da491d8267c53e72019fc998e218d4b0ae6 Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Tue, 26 Sep 2023 01:09:19 +0300 Subject: [PATCH 466/600] Update ru.json --- assets/translations/ru.json | 59 +++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index f9b78c0..ee96354 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -236,30 +236,33 @@ "addInfoInSettings": "Добавьте эту информацию в Настройки.", "githubSourceNote": "Лимит запросов GitHub можно обойти, используя ключ API.", "gitlabSourceNote": "Извлечение APK из GitLab может не работать без ключа API.", - "sortByFileNamesNotLinks": "Sort by file names instead of full links", - "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", - "appsPossiblyUpdated": "App Updates Attempted", - "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", - "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", - "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", - "verifyLatestTag": "Verify the 'latest' tag", - "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", - "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", - "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", - "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", - "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", - "autoExportOnChanges": "Auto-export on changes", - "filterVersionsByRegEx": "Filter Versions by Regular Expression", - "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", - "dontSortReleasesList": "Retain release order from API", - "reverseSort": "Reverse sorting", - "debugMenu": "Debug Menu", - "bgTaskStarted": "Background task started - check logs.", - "runBgCheckNow": "Run Background Update Check Now", + "sortByFileNamesNotLinks": "Сортировать по именам файлов, а не по полным ссылкам", + "filterReleaseNotesByRegEx": "Фильтровать примечания к выпуску по регулярному выражению", + "customLinkFilterRegex": "Пользовательский фильтр ссылок APK по регулярному выражению (по умолчанию '.apk$')", + "appsPossiblyUpdated": "Попытки обновления приложений", + "appsPossiblyUpdatedNotifDescription": "Уведомляет пользователя о возможных обновлениях одного или нескольких приложений в фоновом режиме", + "xWasPossiblyUpdatedToY": "{} возможно был обновлен до {}.", + "enableBackgroundUpdates": "Включить обновления в фоне", + "backgroundUpdateReqsExplanation": "Фоновые обновления могут быть невозможны для всех приложений.", + "backgroundUpdateLimitsExplanation": "Успех фоновой установки можно определить только после открытия Obtainium.", + "verifyLatestTag": "Проверьте тег 'последний'", + "intermediateLinkRegex": "Фильтр ссылок 'промежуточного' типа для приоритетного посещения", + "intermediateLinkNotFound": "Промежуточная ссылка не найдена", + "exemptFromBackgroundUpdates": "Исключить из фоновых обновлений (если включено)", + "bgUpdatesOnWiFiOnly": "Отключить фоновые обновления, если нет соединения с Wi-Fi", + "autoSelectHighestVersionCode": "Автоматически выбирать APK с наивысшим кодом версии", + "versionExtractionRegEx": "Регулярное выражение для извлечения версии", + "matchGroupToUse": "Выберите группу для использования", + "highlightTouchTargets": "Выделить менее очевидные элементы управления касанием", + "pickExportDir": "Выбрать каталог для экспорта", + "autoExportOnChanges": "Автоэкспорт при изменениях", + "filterVersionsByRegEx": "Фильтровать версии по регулярному выражению", + "trySelectingSuggestedVersionCode": "Попробуйте выбрать предложенный код версии APK", + "dontSortReleasesList": "Сохранить порядок выпусков от API", + "reverseSort": "Обратная сортировка", + "debugMenu": "Меню Отладки", + "bgTaskStarted": "Фоновая задача начата - проверьте журналы.", + "runBgCheckNow": "Запустить проверку фонового обновления сейчас", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" @@ -305,11 +308,11 @@ "other": "У {} и ещё {} приложений есть обновления." }, "xAndNMoreUpdatesInstalled": { - "one": "{} и еще 1 приложение были обновлены.", - "other": "{} и еще {} приложений были обновлены." + "one": "{} и ещё 1 приложение были обновлены.", + "other": "{} и ещё {} приложений были обновлены." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} and 1 more app may have been updated.", - "other": "{} and {} more apps may have been updated." + "one": "{} и ещё 1 приложение могли быть обновлены.", + "other": "{} и ещё {} приложений могли быть обновлены." } } From db3a262410236bb61e3b7bef509d86cd58150f34 Mon Sep 17 00:00:00 2001 From: Tangy Wrecker <86275501+TangyWrecker@users.noreply.github.com> Date: Tue, 26 Sep 2023 01:13:01 +0300 Subject: [PATCH 467/600] Update ru.json oops --- assets/translations/ru.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index ee96354..8ea5c0f 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -242,12 +242,12 @@ "appsPossiblyUpdated": "Попытки обновления приложений", "appsPossiblyUpdatedNotifDescription": "Уведомляет пользователя о возможных обновлениях одного или нескольких приложений в фоновом режиме", "xWasPossiblyUpdatedToY": "{} возможно был обновлен до {}.", - "enableBackgroundUpdates": "Включить обновления в фоне", + "enableBackgroundUpdates": "Включить обновления в фоне", "backgroundUpdateReqsExplanation": "Фоновые обновления могут быть невозможны для всех приложений.", "backgroundUpdateLimitsExplanation": "Успех фоновой установки можно определить только после открытия Obtainium.", "verifyLatestTag": "Проверьте тег 'последний'", "intermediateLinkRegex": "Фильтр ссылок 'промежуточного' типа для приоритетного посещения", - "intermediateLinkNotFound": "Промежуточная ссылка не найдена", + "intermediateLinkNotFound": "Промежуточная ссылка не найдена", "exemptFromBackgroundUpdates": "Исключить из фоновых обновлений (если включено)", "bgUpdatesOnWiFiOnly": "Отключить фоновые обновления, если нет соединения с Wi-Fi", "autoSelectHighestVersionCode": "Автоматически выбирать APK с наивысшим кодом версии", From 7e85ccaf285d4bd1c0370535e3ae3dda7c0ea1c6 Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Fri, 29 Sep 2023 02:36:17 +0200 Subject: [PATCH 468/600] locale(pl): Update Polish translations --- assets/translations/pl.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 6001dbc..0cf28fd 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -34,10 +34,10 @@ "githubStarredRepos": "Repozytoria GitHub oznaczone gwiazdką", "uname": "Nazwa użytkownika", "wrongArgNum": "Nieprawidłowa liczba podanych argumentów", - "xIsTrackOnly": "{} jest tylko obserwowana", + "xIsTrackOnly": "{} jest tylko obserwowane", "source": "Źródło", "app": "Aplikacja", - "appsFromSourceAreTrackOnly": "Aplikacje z tego źródła są „Obserwowane”.", + "appsFromSourceAreTrackOnly": "Aplikacje z tego źródła są „tylko obserwowane”.", "youPickedTrackOnly": "Wybrano opcję „Tylko obserwuj”.", "trackOnlyAppDescription": "Aplikacja będzie obserwowana pod kątem aktualizacji, ale Obtainium nie będzie w stanie jej pobrać ani zainstalować.", "cancelled": "Anulowano", @@ -52,7 +52,7 @@ "additionalOptsFor": "Dodatkowe opcje dla {}", "supportedSources": "Obsługiwane źródła", "trackOnlyInBrackets": "(tylko obserwowane)", - "searchableInBrackets": "(Wyszukiwalne)", + "searchableInBrackets": "(wyszukiwalne)", "appsString": "Aplikacje", "noApps": "Brak aplikacji", "noAppsForFilter": "Brak aplikacji dla filtra", @@ -70,7 +70,7 @@ "removeSelectedApps": "Usuń wybrane aplikacje", "updateX": "Zaktualizuj {}", "installX": "Zainstaluj {}", - "markXTrackOnlyAsUpdated": "Oznacz {}\n(Tylko obserwowana)\njako zaktualizowaną", + "markXTrackOnlyAsUpdated": "Oznacz {}\n(tylko obserwowana)\njako zaktualizowaną", "changeX": "Zmień {}", "installUpdateApps": "Instaluj/aktualizuj aplikacje", "installUpdateSelectedApps": "Zainstaluj/zaktualizuj wybrane aplikacje", @@ -261,11 +261,11 @@ "autoExportOnChanges": "Automatyczny eksport po wprowadzeniu zmian", "filterVersionsByRegEx": "Filtruj wersje według wyrażenia regularnego", "trySelectingSuggestedVersionCode": "Spróbuj wybierać sugerowany kod wersji APK", - "dontSortReleasesList": "Retain release order from API", - "reverseSort": "Reverse sorting", - "debugMenu": "Debug Menu", - "bgTaskStarted": "Background task started - check logs.", - "runBgCheckNow": "Run Background Update Check Now", + "dontSortReleasesList": "Utrzymaj kolejność wydań z interfejsu API", + "reverseSort": "Odwrotne sortowanie", + "debugMenu": "Menu debugowania", + "bgTaskStarted": "Uruchomiono zadanie w tle - sprawdź logi.", + "runBgCheckNow": "Wymuś sprawdzenie aktualizacji w tle", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", From 6c30bd36d18025567e47ddeb9fc6b1b944dddd7a Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Fri, 29 Sep 2023 14:54:39 +0000 Subject: [PATCH 469/600] Create sv.json --- assets/translations/sv.json | 318 ++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 assets/translations/sv.json diff --git a/assets/translations/sv.json b/assets/translations/sv.json new file mode 100644 index 0000000..dc2666c --- /dev/null +++ b/assets/translations/sv.json @@ -0,0 +1,318 @@ +{ + "invalidURLForSource": "Inte giltig {} App-URL", + "noReleaseFound": "Kunde inte hitta en lämplig releaseversion", + "noVersionFound": "Kunde inte bestämma releaseversion", + "urlMatchesNoSource": "URL matchar inte känd källa", + "cantInstallOlderVersion": "Kan inte installera en äldre version av en app", + "appIdMismatch": "Nerladdat paket-ID matchar inte nuvarande App-ID", + "functionNotImplemented": "This class has not implemented this function", + "placeholder": "Placeholder", + "someErrors": "Några fel uppstod", + "unexpectedError": "Oväntat fel", + "ok": "Okej", + "and": "och", + "githubPATLabel": "GitHub Personal Access Token (Increases Rate Limit)", + "includePrereleases": "Inkludera förreleaser", + "fallbackToOlderReleases": "Fallback to older releases", + "filterReleaseTitlesByRegEx": "Filter Release Titles by Regular Expression", + "invalidRegEx": "Invalid regular expression", + "noDescription": "Ingen beskrivning", + "cancel": "Avbryt", + "continue": "Fortsätt", + "requiredInBrackets": "(Kräver)", + "dropdownNoOptsError": "ERROR: DROPDOWN MUST HAVE AT LEAST ONE OPT", + "colour": "Färg", + "githubStarredRepos": "GitHub Starred Repos", + "uname": "Användarnamn", + "wrongArgNum": "Wrong number of arguments provided", + "xIsTrackOnly": "{} is Track-Only", + "source": "Källa", + "app": "App", + "appsFromSourceAreTrackOnly": "Apps from this source are 'Track-Only'.", + "youPickedTrackOnly": "You have selected the 'Track-Only' option.", + "trackOnlyAppDescription": "The App will be tracked for updates, but Obtainium will not be able to download or install it.", + "cancelled": "Avbruten", + "appAlreadyAdded": "App already added", + "alreadyUpToDateQuestion": "App Already up to Date?", + "addApp": "Add App", + "appSourceURL": "App Source URL", + "error": "Fel", + "add": "Lägg till", + "searchSomeSourcesLabel": "Sök (Bara några källor)", + "search": "Sök", + "additionalOptsFor": "Additional Options for {}", + "supportedSources": "Supported Sources", + "trackOnlyInBrackets": "(Track-Only)", + "searchableInBrackets": "(Searchable)", + "appsString": "Appar", + "noApps": "Inga Appar", + "noAppsForFilter": "No Apps for Filter", + "byX": "Av {}", + "percentProgress": "Progress: {}%", + "pleaseWait": "Vänta", + "updateAvailable": "Update Available", + "estimateInBracketsShort": "(Est.)", + "notInstalled": "Not Installed", + "estimateInBrackets": "(Estimate)", + "selectAll": "Välj Alla", + "deselectN": "Deselect {}", + "xWillBeRemovedButRemainInstalled": "{} will be removed from Obtainium but remain installed on device.", + "removeSelectedAppsQuestion": "Remove Selected Apps?", + "removeSelectedApps": "Remove Selected Apps", + "updateX": "Uppdatera {}", + "installX": "Installera {}", + "markXTrackOnlyAsUpdated": "Mark {}\n(Track-Only)\nas Updated", + "changeX": "Byt {}", + "installUpdateApps": "Install/Update Apps", + "installUpdateSelectedApps": "Install/Update Selected Apps", + "markXSelectedAppsAsUpdated": "Mark {} Selected Apps as Updated?", + "no": "Nej", + "yes": "Ja", + "markSelectedAppsUpdated": "Mark Selected Apps as Updated", + "pinToTop": "Pin to top", + "unpinFromTop": "Unpin from top", + "resetInstallStatusForSelectedAppsQuestion": "Reset Install Status for Selected Apps?", + "installStatusOfXWillBeResetExplanation": "The install status of any selected Apps will be reset.\n\nThis can help when the App version shown in Obtainium is incorrect due to failed updates or other issues.", + "shareSelectedAppURLs": "Share Selected App URLs", + "resetInstallStatus": "Reset Install Status", + "more": "More", + "removeOutdatedFilter": "Remove Out-of-Date App Filter", + "showOutdatedOnly": "Show Out-of-Date Apps Only", + "filter": "Filter", + "filterActive": "Filter *", + "filterApps": "Filter Apps", + "appName": "App Name", + "author": "Author", + "upToDateApps": "Up to Date Apps", + "nonInstalledApps": "Non-Installed Apps", + "importExport": "Import/Export", + "settings": "Settings", + "exportedTo": "Exported to {}", + "obtainiumExport": "Obtainium Export", + "invalidInput": "Invalid input", + "importedX": "Imported {}", + "obtainiumImport": "Obtainium Import", + "importFromURLList": "Import from URL List", + "searchQuery": "Search Query", + "appURLList": "App URL List", + "line": "Line", + "searchX": "Search {}", + "noResults": "No results found", + "importX": "Import {}", + "importedAppsIdDisclaimer": "Imported Apps may incorrectly show as \"Not Installed\".\nTo fix this, re-install them through Obtainium.\nThis should not affect App data.\n\nOnly affects URL and third-party import methods.", + "importErrors": "Import Errors", + "importedXOfYApps": "{} of {} Apps imported.", + "followingURLsHadErrors": "The following URLs had errors:", + "okay": "Okay", + "selectURL": "Välj URL", + "selectURLs": "Välj URL:er", + "pick": "Pick", + "theme": "Tema", + "dark": "Mörkt", + "light": "Ljust", + "followSystem": "Följ System", + "obtainium": "Obtainium", + "materialYou": "Material You", + "useBlackTheme": "Use pure black dark theme", + "appSortBy": "App Sort By", + "authorName": "Author/Name", + "nameAuthor": "Name/Author", + "asAdded": "As Added", + "appSortOrder": "App Sort Order", + "ascending": "Ascending", + "descending": "Descending", + "bgUpdateCheckInterval": "Background Update Checking Interval", + "neverManualOnly": "Never - Manual Only", + "appearance": "Appearance", + "showWebInAppView": "Show Source webpage in App view", + "pinUpdates": "Pin updates to top of Apps view", + "updates": "Updates", + "sourceSpecific": "Source-Specific", + "appSource": "App Source", + "noLogs": "No Logs", + "appLogs": "App Logs", + "close": "Stäng", + "share": "Dela", + "appNotFound": "App ej funnen", + "obtainiumExportHyphenatedLowercase": "obtainium-export", + "pickAnAPK": "Pick an APK", + "appHasMoreThanOnePackage": "{} has more than one package:", + "deviceSupportsXArch": "Your device supports the {} CPU architecture.", + "deviceSupportsFollowingArchs": "Your device supports the following CPU architectures:", + "warning": "Warning", + "sourceIsXButPackageFromYPrompt": "The App source is '{}' but the release package comes from '{}'. Continue?", + "updatesAvailable": "Updates Available", + "updatesAvailableNotifDescription": "Notifies the user that updates are available for one or more Apps tracked by Obtainium", + "noNewUpdates": "Inga nya uppdateringar.", + "xHasAnUpdate": "{} har en uppdatering.", + "appsUpdated": "Appar Uppdaterade", + "appsUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were applied in the background", + "xWasUpdatedToY": "{} was updated to {}.", + "errorCheckingUpdates": "Error Checking for Updates", + "errorCheckingUpdatesNotifDescription": "A notification that shows when background update checking fails", + "appsRemoved": "Apps Removed", + "appsRemovedNotifDescription": "Notifies the user that one or more Apps were removed due to errors while loading them", + "xWasRemovedDueToErrorY": "{} was removed due to this error: {}", + "completeAppInstallation": "Complete App Installation", + "obtainiumMustBeOpenToInstallApps": "Obtainium must be open to install Apps", + "completeAppInstallationNotifDescription": "Asks the user to return to Obtainium to finish installing an App", + "checkingForUpdates": "Checking for Updates", + "checkingForUpdatesNotifDescription": "Transient notification that appears when checking for updates", + "pleaseAllowInstallPerm": "Please allow Obtainium to install Apps", + "trackOnly": "Track-Only", + "errorWithHttpStatusCode": "Error {}", + "versionCorrectionDisabled": "Version correction disabled (plugin doesn't seem to work)", + "unknown": "Unknown", + "none": "None", + "never": "Aldrig", + "latestVersionX": "Latest Version: {}", + "installedVersionX": "Installed Version: {}", + "lastUpdateCheckX": "Last Update Check: {}", + "remove": "Remove", + "yesMarkUpdated": "Yes, Mark as Updated", + "fdroid": "F-Droid Official", + "appIdOrName": "App-ID eller Namn", + "appId": "App-ID", + "appWithIdOrNameNotFound": "No App was found with that ID or Name", + "reposHaveMultipleApps": "Repos may contain multiple Apps", + "fdroidThirdPartyRepo": "F-Droid Third-Party Repo", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Chat", + "install": "Installera", + "markInstalled": "Mark Installed", + "update": "Update", + "markUpdated": "Mark Updated", + "additionalOptions": "Additional Options", + "disableVersionDetection": "Disable Version Detection", + "noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.", + "downloadingX": "Downloading {}", + "downloadNotifDescription": "Notifies the user of the progress in downloading an App", + "noAPKFound": "No APK found", + "noVersionDetection": "No version detection", + "categorize": "Categorize", + "categories": "Categories", + "category": "Category", + "noCategory": "No Category", + "noCategories": "No Categories", + "deleteCategoriesQuestion": "Delete Categories?", + "categoryDeleteWarning": "All Apps in deleted categories will be set to uncategorized.", + "addCategory": "Add Category", + "label": "Label", + "language": "Språk", + "copiedToClipboard": "Kopierat till Urklipp", + "storagePermissionDenied": "Storage permission denied", + "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", + "filterAPKsByRegEx": "Filter APKs by Regular Expression", + "removeFromObtainium": "Remove from Obtainium", + "uninstallFromDevice": "Uninstall from Device", + "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", + "releaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", + "changes": "Changes", + "releaseDate": "Release Date", + "importFromURLsInFile": "Import from URLs in File (like OPML)", + "versionDetection": "Version Detection", + "standardVersionDetection": "Standard version detection", + "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", + "moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view", + "gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)", + "about": "About", + "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", + "checkOnStart": "Check for updates on startup", + "tryInferAppIdFromCode": "Try inferring App ID from source code", + "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", + "pickHighestVersionCode": "Auto-select highest version code APK", + "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", + "disablePageTransitions": "Disable page transition animations", + "reversePageTransitions": "Reverse page transition animations", + "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "enableBackgroundUpdates": "Enable background updates", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", + "intermediateLinkNotFound": "Intermediate link not found", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", + "removeAppQuestion": { + "one": "Remove App?", + "other": "Remove Apps?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Too many requests (rate limited) - try again in {} minute", + "other": "Too many requests (rate limited) - try again in {} minutes" + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "BG update checking encountered a {}, will schedule a retry check in {} minute", + "other": "BG update checking encountered a {}, will schedule a retry check in {} minutes" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "BG update checking found {} update - will notify user if needed", + "other": "BG update checking found {} updates - will notify user if needed" + }, + "apps": { + "one": "{} App", + "other": "{} Apps" + }, + "url": { + "one": "{} URL", + "other": "{} URLs" + }, + "minute": { + "one": "{} Minute", + "other": "{} Minutes" + }, + "hour": { + "one": "{} Hour", + "other": "{} Hours" + }, + "day": { + "one": "{} Day", + "other": "{} Days" + }, + "clearedNLogsBeforeXAfterY": { + "one": "Cleared {n} log (before = {before}, after = {after})", + "other": "Cleared {n} logs (before = {before}, after = {after})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "{} and 1 more app have updates.", + "other": "{} and {} more apps have updates." + }, + "xAndNMoreUpdatesInstalled": { + "one": "{} and 1 more app was updated.", + "other": "{} and {} more apps were updated." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." + } +} From c9cb865c9c77a9f800d343353ac1af1bee636e75 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 29 Sep 2023 12:13:11 -0400 Subject: [PATCH 470/600] Add export dir pick button + update packages --- lib/main.dart | 2 +- lib/pages/import_export.dart | 32 +++++++++++++++++++++++++------- pubspec.lock | 16 ++++++++-------- pubspec.yaml | 2 +- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 114dae6..dfca6a9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.20'; +const String currentVersion = '0.14.21'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index 159d38a..264f3a9 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -102,11 +102,12 @@ class _ImportExportPageState extends State { }); } - runObtainiumExport() async { + runObtainiumExport({bool pickOnly = false}) async { HapticFeedback.selectionClick(); appsProvider .exportApps( - pickOnly: (await settingsProvider.getExportDir()) == null, + pickOnly: + pickOnly || (await settingsProvider.getExportDir()) == null, sp: settingsProvider) .then((String? result) { if (result != null) { @@ -320,21 +321,38 @@ class _ImportExportPageState extends State { onPressed: appsProvider.apps.isEmpty || importInProgress ? null - : runObtainiumExport, - child: Text(tr(snapshot.data != null - ? 'obtainiumExport' - : 'pickExportDir')), + : () { + runObtainiumExport(pickOnly: true); + }, + child: Text(tr('pickExportDir')), )), const SizedBox( width: 16, ), + Expanded( + child: TextButton( + style: outlineButtonStyle, + onPressed: appsProvider.apps.isEmpty || + importInProgress || + snapshot.data == null + ? null + : runObtainiumExport, + child: Text(tr('obtainiumExport')), + )), + ], + ), + const SizedBox( + height: 8, + ), + Row( + children: [ Expanded( child: TextButton( style: outlineButtonStyle, onPressed: importInProgress ? null : runObtainiumImport, - child: Text(tr('obtainiumImport')))) + child: Text(tr('obtainiumImport')))), ], ), if (snapshot.data != null) diff --git a/pubspec.lock b/pubspec.lock index fc2bdb5..ec8571d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -46,10 +46,10 @@ packages: dependency: transitive description: name: archive - sha256: "20071638cbe4e5964a427cfa0e86dce55d060bc7d82d56f3554095d7239a8765" + sha256: d4dc11707abb32ef756ab95678c0d6df54003d98277f7c9aeda14c48e7a38c2f url: "https://pub.dev" source: hosted - version: "3.4.2" + version: "3.4.3" args: dependency: transitive description: @@ -386,10 +386,10 @@ packages: dependency: transitive description: name: image - sha256: "6e703d5e2f8c63fb31a77753915c1ec8baebde8088844e0d29f71b8f0b108888" + sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271" url: "https://pub.dev" source: hosted - version: "4.1.0" + version: "4.1.3" intl: dependency: transitive description: @@ -546,10 +546,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: f23cfe9af0d49c6b9fd8a8b09f7b3301ca7e346204939b5afef4404d36d2608f + sha256: ace7d15a3d1a4a0b91c041d01e5405df221edb9de9116525efc773c74e6fc790 url: "https://pub.dev" source: hosted - version: "11.0.1" + version: "11.0.5" permission_handler_apple: dependency: transitive description: @@ -911,10 +911,10 @@ packages: dependency: transitive description: name: win32 - sha256: c97defd418eef4ec88c0d1652cdce84b9f7b63dd7198e266d06ac1710d527067 + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" url: "https://pub.dev" source: hosted - version: "5.0.8" + version: "5.0.9" win32_registry: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 17d8771..0c648ab 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.14.20+212 # When changing this, update the tag in main() accordingly +version: 0.14.21+213 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 4bc9f5826eba3b0940045bfe53f1d6b914e679e6 Mon Sep 17 00:00:00 2001 From: Matsuri Date: Sat, 30 Sep 2023 20:30:00 +0800 Subject: [PATCH 471/600] Update zh.json - Translate new strings - Slight improvements Signed-off-by: Matsuri --- assets/translations/zh.json | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 81a2007..69954f9 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -238,31 +238,31 @@ "gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。", "sortByFileNamesNotLinks": "使用文件名代替链接进行排序", "filterReleaseNotesByRegEx": "使用正则表达式筛选发行说明", - "customLinkFilterRegex": "使用正则表达式自定义链接筛选(默认模式为“.apk$”)", + "customLinkFilterRegex": "使用正则表达式筛选自定义来源 APK 文件链接\n(未填写时,默认匹配模式为“.apk$”)", "appsPossiblyUpdated": "已尝试更新应用", "appsPossiblyUpdatedNotifDescription": "当应用已尝试在后台更新时发送通知", - "xWasPossiblyUpdatedToY": "已尝试将 {} 更新至 {}。", + "xWasPossiblyUpdatedToY": "已尝试将“{}”更新至 {}。", "enableBackgroundUpdates": "启用后台更新", "backgroundUpdateReqsExplanation": "后台更新未必适用于所有的应用。", "backgroundUpdateLimitsExplanation": "只有在启动 Obtainium 时才能确认安装是否成功。", "verifyLatestTag": "验证“Latest”标签", - "intermediateLinkRegex": "首先访问“中间”链接的过滤器", - "intermediateLinkNotFound": "中间链接未找到", - "exemptFromBackgroundUpdates": "禁用后台更新(如果全局设置启用)", - "bgUpdatesOnWiFiOnly": "不在连接 WiFi 时禁用后台更新", - "autoSelectHighestVersionCode": "自动选择最高版本号 APK", - "versionExtractionRegEx": "版本提取正则表达式", - "matchGroupToUse": "匹配要使用的组", - "highlightTouchTargets": "突出显示不明显的触摸目标", - "pickExportDir": "选择导出目录", - "autoExportOnChanges": "修改时自动导出", - "filterVersionsByRegEx": "使用正则表达式筛选版本", - "trySelectingSuggestedVersionCode": "尝试选择推荐版本 APK", - "dontSortReleasesList": "Retain release order from API", - "reverseSort": "Reverse sorting", - "debugMenu": "Debug Menu", - "bgTaskStarted": "Background task started - check logs.", - "runBgCheckNow": "Run Background Update Check Now", + "intermediateLinkRegex": "筛选一个首先访问的“中转”链接(正则表达式)", + "intermediateLinkNotFound": "未找到“中转”链接", + "exemptFromBackgroundUpdates": "单独禁用后台更新(若已经全局启用)", + "bgUpdatesOnWiFiOnly": "未连接 Wi-Fi 时禁用后台更新", + "autoSelectHighestVersionCode": "自动选择版本号最高的 APK 文件", + "versionExtractionRegEx": "获取版本号的正则表达式", + "matchGroupToUse": "引用的捕获组", + "highlightTouchTargets": "突出展示不明显的触摸区域", + "pickExportDir": "选择导出文件夹", + "autoExportOnChanges": "数据变更时自动导出", + "filterVersionsByRegEx": "使用正则表达式筛选版本号", + "trySelectingSuggestedVersionCode": "尝试选择推荐版本的 APK 文件", + "dontSortReleasesList": "保持来自 API 的发行顺序", + "reverseSort": "反转排序", + "debugMenu": "调试选项", + "bgTaskStarted": "后台任务已启动 - 详见日志", + "runBgCheckNow": "立即进行后台更新检查", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" From 4c811c9c04d6f185f02f46dc70e08843cf3136b8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 30 Sep 2023 10:12:49 -0400 Subject: [PATCH 472/600] "Naive" version detection for some Sources (#946) --- lib/app_sources/apkpure.dart | 1 + lib/app_sources/aptoide.dart | 1 + lib/app_sources/uptodown.dart | 1 + lib/providers/apps_provider.dart | 40 ++++++++++++++++++++---------- lib/providers/source_provider.dart | 1 + 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index d22e9a6..a86fa0d 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -22,6 +22,7 @@ class APKPure extends AppSource { APKPure() { host = 'apkpure.com'; allowSubDomains = true; + naiveStandardVersionDetection = true; } @override diff --git a/lib/app_sources/aptoide.dart b/lib/app_sources/aptoide.dart index 9543464..5b92b33 100644 --- a/lib/app_sources/aptoide.dart +++ b/lib/app_sources/aptoide.dart @@ -9,6 +9,7 @@ class Aptoide extends AppSource { host = 'aptoide.com'; name = tr('Aptoide'); allowSubDomains = true; + naiveStandardVersionDetection = true; } @override diff --git a/lib/app_sources/uptodown.dart b/lib/app_sources/uptodown.dart index dd9b68a..7b36cc3 100644 --- a/lib/app_sources/uptodown.dart +++ b/lib/app_sources/uptodown.dart @@ -8,6 +8,7 @@ class Uptodown extends AppSource { Uptodown() { host = 'uptodown.com'; allowSubDomains = true; + naiveStandardVersionDetection = true; } @override diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index a8c6fdf..2dc7498 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -709,14 +709,21 @@ class AppsProvider with ChangeNotifier { } bool isVersionDetectionPossible(AppInMemory? app) { - return app?.app.additionalSettings['trackOnly'] != true && - app?.app.additionalSettings['versionDetection'] != + if (app?.app == null) { + return false; + } + var naiveStandardVersionDetection = SourceProvider() + .getSource(app!.app.url, overrideSource: app.app.overrideSource) + .naiveStandardVersionDetection; + return app.app.additionalSettings['trackOnly'] != true && + app.app.additionalSettings['versionDetection'] != 'releaseDateAsVersion' && - app?.installedInfo?.versionName != null && - app?.app.installedVersion != null && - reconcileVersionDifferences( - app!.installedInfo!.versionName!, app.app.installedVersion!) != - null; + app.installedInfo?.versionName != null && + app.app.installedVersion != null && + (reconcileVersionDifferences(app.installedInfo!.versionName!, + app.app.installedVersion!) != + null || + naiveStandardVersionDetection); } // Given an App and it's on-device info... @@ -725,8 +732,13 @@ class AppsProvider with ChangeNotifier { App app, PackageInfo? installedInfo) { var modded = false; var trackOnly = app.additionalSettings['trackOnly'] == true; - var noVersionDetection = app.additionalSettings['versionDetection'] != - 'standardVersionDetection'; + var versionDetectionIsStandard = + app.additionalSettings['versionDetection'] == + 'standardVersionDetection'; + var naiveStandardVersionDetection = SourceProvider() + .getSource(app.url, overrideSource: app.overrideSource) + .naiveStandardVersionDetection; + ; // FIRST, COMPARE THE APP'S REPORTED AND REAL INSTALLED VERSIONS, WHERE ONE IS NULL if (installedInfo == null && app.installedVersion != null && !trackOnly) { // App says it's installed but isn't really (and isn't track only) - set to not installed @@ -741,7 +753,7 @@ class AppsProvider with ChangeNotifier { // SECOND, RECONCILE DIFFERENCES BETWEEN THE APP'S REPORTED AND REAL INSTALLED VERSIONS, WHERE NEITHER IS NULL if (installedInfo?.versionName != null && installedInfo!.versionName != app.installedVersion && - !noVersionDetection) { + versionDetectionIsStandard) { // App's reported version and real version don't match (and it uses standard version detection) // If they share a standard format (and are still different under it), update the reported version accordingly var correctedInstalledVersion = reconcileVersionDifferences( @@ -749,12 +761,15 @@ class AppsProvider with ChangeNotifier { if (correctedInstalledVersion?.key == false) { app.installedVersion = correctedInstalledVersion!.value; modded = true; + } else if (naiveStandardVersionDetection) { + app.installedVersion = installedInfo.versionName; + modded = true; } } // THIRD, RECONCILE THE APP'S REPORTED INSTALLED AND LATEST VERSIONS if (app.installedVersion != null && app.installedVersion != app.latestVersion && - !noVersionDetection) { + versionDetectionIsStandard) { // App's reported installed and latest versions don't match (and it uses standard version detection) // If they share a standard format, make sure the App's reported installed version uses that format var correctedInstalledVersion = @@ -766,8 +781,7 @@ class AppsProvider with ChangeNotifier { } // FOURTH, DISABLE VERSION DETECTION IF ENABLED AND THE REPORTED/REAL INSTALLED VERSIONS ARE NOT STANDARDIZED if (installedInfo != null && - app.additionalSettings['versionDetection'] == - 'standardVersionDetection' && + versionDetectionIsStandard && !isVersionDetectionPossible( AppInMemory(app, null, installedInfo, null))) { app.additionalSettings['versionDetection'] = 'noVersionDetection'; diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 43a0f1e..b4b732f 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -328,6 +328,7 @@ abstract class AppSource { bool changeLogIfAnyIsMarkDown = true; bool appIdInferIsOptional = false; bool allowSubDomains = false; + bool naiveStandardVersionDetection = false; AppSource() { name = runtimeType.toString(); From e3baf91037f401b59992eee7b9d6733f77d19a77 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 30 Sep 2023 10:16:10 -0400 Subject: [PATCH 473/600] Increment version, upgrade packages --- lib/main.dart | 2 +- pubspec.lock | 12 ++++++------ pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index dfca6a9..1f2815e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.21'; +const String currentVersion = '0.14.22'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index ec8571d..51a04bc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -879,18 +879,18 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: "82f6787d5df55907aa01e49bd9644f4ed1cc82af7a8257dd9947815959d2e755" + sha256: "053d454c9475546b4382e9498601fb46293cdac9b3ca93f1a738375bc9a1eee4" url: "https://pub.dev" source: hosted - version: "4.2.4" + version: "4.3.0" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: ddc167c6676f57c8b367d19fcbee267d6dc6adf81bd6c3cb87981d30746e0a6d + sha256: b0cd33dd7d3dd8e5f664e11a19e17ba12c352647269921a3b568406b001f1dff url: "https://pub.dev" source: hosted - version: "3.10.1" + version: "3.12.0" webview_flutter_platform_interface: dependency: transitive description: @@ -903,10 +903,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "485af05f2c5f83c7f78c20e236b170ad02df7153b299ae9917345be43871d29f" + sha256: "3c7d56ca4b82654ad1f58aeefb8d593a59224f26d6b2bf8feed074361eb34c86" url: "https://pub.dev" source: hosted - version: "3.8.0" + version: "3.9.0" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 0c648ab..af466c0 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.14.21+213 # When changing this, update the tag in main() accordingly +version: 0.14.22+214 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From c72a41db9d20abc977466a5c2228bbcfd8e7904b Mon Sep 17 00:00:00 2001 From: DwainZwerg <97027379+DwainZwerg@users.noreply.github.com> Date: Sun, 1 Oct 2023 12:05:49 +0000 Subject: [PATCH 474/600] Update de.json and small improvements --- assets/translations/de.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 462f3a4..bf8198f 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -122,15 +122,15 @@ "ascending": "Aufsteigend", "descending": "Absteigend", "bgUpdateCheckInterval": "Prüfintervall für Hintergrundaktualisierung", - "neverManualOnly": "Nie - nur manuell", + "neverManualOnly": "Nie – nur manuell", "appearance": "Aussehen", "showWebInAppView": "Quellwebseite in der App-Ansicht anzeigen", "pinUpdates": "Apps mit Aktualisierungen oben anheften", "updates": "Aktualisierungen", "sourceSpecific": "Quellenspezifisch", "appSource": "App-Quelle", - "noLogs": "Keine Protokolle", - "appLogs": "App Protokolle", + "noLogs": "Keine Logs", + "appLogs": "App-Logs", "close": "Schließen", "share": "Teilen", "appNotFound": "App nicht gefunden", @@ -256,25 +256,25 @@ "filterVersionsByRegEx": "Versionen nach regulären Ausdrücken filtern", "trySelectingSuggestedVersionCode": "Versuchen, die vorgeschlagene APK-Code-Version auszuwählen", "dontSortReleasesList": "Retain release order from API", - "reverseSort": "Reverse sorting", - "debugMenu": "Debug Menu", - "bgTaskStarted": "Background task started - check logs.", - "runBgCheckNow": "Run Background Update Check Now", + "reverseSort": "Umgekehrtes Sortieren", + "debugMenu": "Debug Menü", + "bgTaskStarted": "Hintergrundaufgabe gestartet – Logs prüfen.", + "runBgCheckNow": "Hintergrundaktualisierungsprüfung jetzt durchführen", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" }, "tooManyRequestsTryAgainInMinutes": { - "one": "Zu viele Anfragen (Rate begrenzt) - versuchen Sie es in {} Minute erneut", - "other": "Zu viele Anfragen (Rate begrenzt) - versuchen Sie es in {} Minuten erneut" + "one": "Zu viele Anfragen (Rate begrenzt) – versuchen Sie es in {} Minute erneut", + "other": "Zu viele Anfragen (Rate begrenzt) – versuchen Sie es in {} Minuten erneut" }, "bgUpdateGotErrorRetryInMinutes": { "one": "Bei der Aktualisierungsprüfung im Hintergrund wurde ein {} festgestellt, eine erneute Prüfung wird in {} Minute geplant", "other": "Bei der Aktualisierungsprüfung im Hintergrund wurde ein {} festgestellt, eine erneute Prüfung wird in {} Minuten geplant" }, "bgCheckFoundUpdatesWillNotifyIfNeeded": { - "one": "Hintergrundaktualisierungsprüfung fand {} Aktualisierung - benachrichtigt den Benutzer, falls erforderlich", - "other": "Hintergrundaktualisierungsprüfung fand {} Aktualisierungen - benachrichtigt den Benutzer, falls erforderlich" + "one": "Die Hintergrundaktualisierungsprüfung fand {} Aktualisierung – benachrichtigt den Benutzer, falls erforderlich", + "other": "Die Hintergrundaktualisierungsprüfung fand {} Aktualisierungen – benachrichtigt den Benutzer, falls erforderlich" }, "apps": { "one": "{} App", @@ -297,8 +297,8 @@ "other": "{} Tage" }, "clearedNLogsBeforeXAfterY": { - "one": "{n} Protokoll gelöscht (vorher = {vorher}, nachher = {nachher})", - "other": "{n} Protokolle gelöscht (vorher = {vorher}, nachher = {nachher})" + "one": "{n} Log gelöscht (vorher = {vorher}, nachher = {nachher})", + "other": "{n} Logs gelöscht (vorher = {vorher}, nachher = {nachher})" }, "xAndNMoreUpdatesAvailable": { "one": "{} und 1 weitere App haben Aktualisierungen.", From 7bfc5ae0a85fdf9dac8562d4530e814435b5a9a4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 3 Oct 2023 21:34:24 -0400 Subject: [PATCH 475/600] Bugfix (#954) --- lib/app_sources/html.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 60fc32d..4cb9b26 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -120,14 +120,14 @@ class HTML extends AppSource { GeneratedFormTextField('matchGroupToUse', label: tr('matchGroupToUse'), required: false, - hint: '1', + hint: '0', textInputType: const TextInputType.numberWithOptions(), additionalValidators: [ (value) { if (value?.isEmpty == true) { value = null; } - value ??= '1'; + value ??= '0'; return intValidator(value); } ]) @@ -216,8 +216,12 @@ class HTML extends AppSource { if (match.isEmpty) { throw NoVersionError(); } - version = match.last - .group(int.parse(additionalSettings['matchGroupToUse'] as String)); + String matchGroupString = + (additionalSettings['matchGroupToUse'] as String).trim(); + if (matchGroupString.isEmpty) { + matchGroupString = "0"; + } + version = match.last.group(int.parse(matchGroupString)); if (version?.isEmpty == true) { throw NoVersionError(); } From 8bd0d185aeb1aa1edf1e8d4697d769a9f49df2de Mon Sep 17 00:00:00 2001 From: John Betaro <114379310+JohnBetaro@users.noreply.github.com> Date: Thu, 5 Oct 2023 11:16:42 +0100 Subject: [PATCH 476/600] Create android.yml --- .github/workflows/android.yml | 76 +++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .github/workflows/android.yml diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 0000000..3f81740 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,76 @@ +name: android + +on: + workflow_dispatch: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + + - uses: actions/checkout@v3 + + - uses: subosito/flutter-action@v2 + + - name: Build APKs + run: | + sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle + flutter build apk && flutter build apk --split-per-abi + + - name: Sign APKs + env: + KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} + KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }} + run: | + echo "${KEYSTORE_BASE64}" | base64 -d > apksign.keystore + for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do + out=${apk/-release/-release-signed} + ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass env:KEYSTORE_PASS --out "${out}" "${apk}" + echo "$(sha256sum ${out})" + done + rm apksign.keystore + + - name: Create Release And Upload APKs + uses: ncipollo/release-action@v1 + with: + token: ${{ secrets.GAT }} + tag: "v${{ steps.compare_versions.outputs.version }}-beta" + artifacts: ./build/app/outputs/flutter-apk/*-signed*.apk + continue-on-error: true + + - name: Wait For 10 Seconds + run: sleep 10 + + - name: Verify If APKs Have Been Uploaded + id: check_for_apk + run: | + release_info=$(curl -s "https://api.github.com/repos/ImranR98/Obtainium/releases/latest" -H "Authorization: Bearer ${{ secrets.GAT }}") + apk_asset_count=$(echo $release_info | jq '.assets | length') + release_id=$(echo $release_info | jq -r '.id') + if [[ $apk_asset_count -eq 0 ]]; then + echo "Deleting the release $release_id" + echo "::set-output name=delete_latest_release::true" + else + echo "APK found. Not deleting the release $release_id" + echo "::set-output name=delete_latest_release::false" + fi + + - name: Delete The Latest Release If No APKs Found + uses: ClementTsang/delete-tag-and-release@v0.3.1 + with: + delete_release: true + tag_name: "v${{ steps.compare_versions.outputs.version }}-beta" + env: + GITHUB_TOKEN: ${{ secrets.GAT }} + if: steps.check_for_apk.outputs.delete_latest_release == 'true' + + - name: Archive Reports For Job + uses: actions/upload-artifact@v3 + with: + name: reports + path: '*/build/reports' + if: ${{ always() }} From 102b9da617c80ff9aaf2713ac5edf41e6c0b556a Mon Sep 17 00:00:00 2001 From: John Betaro <114379310+JohnBetaro@users.noreply.github.com> Date: Thu, 5 Oct 2023 11:19:46 +0100 Subject: [PATCH 477/600] Update android.yml --- .github/workflows/android.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 3f81740..608c64a 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -34,11 +34,17 @@ jobs: done rm apksign.keystore + - name: Extract Version + id: extract_version + run: | + VERSION=$(grep -oP "currentVersion = '\K[^']+" lib/main.dart) + echo "::set-output name=version::$VERSION" + - name: Create Release And Upload APKs uses: ncipollo/release-action@v1 with: token: ${{ secrets.GAT }} - tag: "v${{ steps.compare_versions.outputs.version }}-beta" + tag: "v${{ steps.extract_version.outputs.version }}-beta" artifacts: ./build/app/outputs/flutter-apk/*-signed*.apk continue-on-error: true From 6935bff244d98876f46c919b9bacb0e2b48b7b37 Mon Sep 17 00:00:00 2001 From: John Betaro <114379310+JohnBetaro@users.noreply.github.com> Date: Thu, 5 Oct 2023 11:22:29 +0100 Subject: [PATCH 478/600] Update android.yml --- .github/workflows/android.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 608c64a..5ad5a55 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -45,6 +45,7 @@ jobs: with: token: ${{ secrets.GAT }} tag: "v${{ steps.extract_version.outputs.version }}-beta" + prerelease: true artifacts: ./build/app/outputs/flutter-apk/*-signed*.apk continue-on-error: true From ae0cd74b0e59bebeb2f4e54fc4ab6c44e14fd651 Mon Sep 17 00:00:00 2001 From: John Betaro <114379310+JohnBetaro@users.noreply.github.com> Date: Thu, 5 Oct 2023 11:29:03 +0100 Subject: [PATCH 479/600] Update android.yml --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 5ad5a55..b494ac7 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -70,7 +70,7 @@ jobs: uses: ClementTsang/delete-tag-and-release@v0.3.1 with: delete_release: true - tag_name: "v${{ steps.compare_versions.outputs.version }}-beta" + tag_name: "v${{ steps.extract_version.outputs.version }}-beta" env: GITHUB_TOKEN: ${{ secrets.GAT }} if: steps.check_for_apk.outputs.delete_latest_release == 'true' From 4304251e1e1b0ac66ffcd0c7e0e1bcd9c6d87924 Mon Sep 17 00:00:00 2001 From: John Betaro <114379310+JohnBetaro@users.noreply.github.com> Date: Thu, 5 Oct 2023 11:31:42 +0100 Subject: [PATCH 480/600] Remove checking for APKs This is because I couldn't check for prereleases because I don't know how, maybe you can. --- .github/workflows/android.yml | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index b494ac7..9ccee7f 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -47,34 +47,7 @@ jobs: tag: "v${{ steps.extract_version.outputs.version }}-beta" prerelease: true artifacts: ./build/app/outputs/flutter-apk/*-signed*.apk - continue-on-error: true - - - name: Wait For 10 Seconds - run: sleep 10 - - - name: Verify If APKs Have Been Uploaded - id: check_for_apk - run: | - release_info=$(curl -s "https://api.github.com/repos/ImranR98/Obtainium/releases/latest" -H "Authorization: Bearer ${{ secrets.GAT }}") - apk_asset_count=$(echo $release_info | jq '.assets | length') - release_id=$(echo $release_info | jq -r '.id') - if [[ $apk_asset_count -eq 0 ]]; then - echo "Deleting the release $release_id" - echo "::set-output name=delete_latest_release::true" - else - echo "APK found. Not deleting the release $release_id" - echo "::set-output name=delete_latest_release::false" - fi - - - name: Delete The Latest Release If No APKs Found - uses: ClementTsang/delete-tag-and-release@v0.3.1 - with: - delete_release: true - tag_name: "v${{ steps.extract_version.outputs.version }}-beta" - env: - GITHUB_TOKEN: ${{ secrets.GAT }} - if: steps.check_for_apk.outputs.delete_latest_release == 'true' - + - name: Archive Reports For Job uses: actions/upload-artifact@v3 with: From 21fdfc1eef72462e4a9fe4ada9869de0f87dcca7 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 6 Oct 2023 19:23:18 -0400 Subject: [PATCH 481/600] Attempting to parallelize update checks --- lib/custom_errors.dart | 5 +- lib/pages/apps.dart | 2 +- lib/providers/apps_provider.dart | 194 ++++++++++++++++++------------- 3 files changed, 115 insertions(+), 86 deletions(-) diff --git a/lib/custom_errors.dart b/lib/custom_errors.dart index 6343c87..4d807c5 100644 --- a/lib/custom_errors.dart +++ b/lib/custom_errors.dart @@ -65,11 +65,14 @@ class NotImplementedError extends ObtainiumError { } class MultiAppMultiError extends ObtainiumError { + Map rawErrors = {}; Map> content = {}; MultiAppMultiError() : super(tr('placeholder'), unexpected: true); - add(String appId, String string) { + add(String appId, dynamic error) { + rawErrors[appId] = error; + var string = error.toString(); var tempIds = content.remove(string); tempIds ??= []; tempIds.add(appId); diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 3f4cc30..cb7ce46 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -68,7 +68,7 @@ class AppsPageState extends State { refreshingSince = DateTime.now(); }); return appsProvider.checkUpdates().catchError((e) { - showError(e, context); + showError(e is Map ? e['errors'] : e, context); return []; }).whenComplete(() { setState(() { diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 2dc7498..1a9e052 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -449,7 +449,7 @@ class AppsProvider with ChangeNotifier { } catch (e) { logs.add( 'Could not install APK from XAPK \'${file.path}\': ${e.toString()}'); - errors.add(dir.appId, e.toString()); + errors.add(dir.appId, e); } } else if (file.path.toLowerCase().endsWith('.obb')) { await moveObbFile(file, dir.appId); @@ -677,7 +677,7 @@ class AppsProvider with ChangeNotifier { } installedIds.add(id); } catch (e) { - errors.add(id, e.toString()); + errors.add(id, e); } } @@ -1069,7 +1069,8 @@ class AppsProvider with ChangeNotifier { Future> checkUpdates( {DateTime? ignoreAppsCheckedAfter, - bool throwErrorsForRetry = false}) async { + bool throwErrorsForRetry = false, + List? specificIds}) async { List updates = []; MultiAppMultiError errors = MultiAppMultiError(); if (!gettingUpdates) { @@ -1077,27 +1078,33 @@ class AppsProvider with ChangeNotifier { try { List appIds = getAppsSortedByUpdateCheckTime( ignoreAppsCheckedAfter: ignoreAppsCheckedAfter); - for (int i = 0; i < appIds.length; i++) { + if (specificIds != null) { + appIds = appIds.where((aId) => specificIds.contains(aId)).toList(); + } + await Future.wait(appIds.map((appId) async { App? newApp; try { - newApp = await checkUpdate(appIds[i]); + newApp = await checkUpdate(appId); } catch (e) { if ((e is RateLimitError || e is SocketException) && throwErrorsForRetry) { rethrow; } - errors.add(appIds[i], e.toString()); + errors.add(appId, e); } if (newApp != null) { updates.add(newApp); } - } + }), eagerError: true); } finally { gettingUpdates = false; } } if (errors.content.isNotEmpty) { - throw errors; + var res = Map(); + res['errors'] = errors; + res['updates'] = updates; + throw res; } return updates; } @@ -1314,18 +1321,16 @@ class _APKOriginWarningDialogState extends State { /// Background updater function /// -/// @param List? toCheck: The appIds to check for updates (default to all apps sorted by last update check time) +/// @param List>? toCheck: The appIds to check for updates (with the number of previous attempts made per appid) (defaults to all apps) /// /// @param List? toInstall: The appIds to attempt to update (defaults to an empty array) /// -/// @param int? attemptCount: The number of times the function has failed up to this point (defaults to 0) -/// /// When toCheck is empty, the function is in "install mode" (else it is in "update mode"). /// In update mode, all apps in toCheck are checked for updates. /// If an update is available, the appId is either added to toInstall (if a background update is possible) or the user is notified. -/// If there is an error, the function tries to continue after a few minutes (duration depends on the error), up to a maximum of 5 tries. +/// If there are errors, the task is run again for the remaining apps after a few minutes (duration depends on the errors), up to a maximum of 5 tries for any app. /// -/// Once all update checks are complete, the function is called again in install mode. +/// Once all update checks are complete, the task is run again in install mode. /// In this mode, all apps in toInstall are downloaded and installed in the background (install result is unknown). /// If there is an error, the function tries to continue after a few minutes (duration depends on the error), up to a maximum of 5 tries. /// @@ -1372,87 +1377,105 @@ Future bgUpdateCheck(int taskId, Map? params) async { 'BG ${installMode ? 'install' : 'update'} task $taskId: Started (${installMode ? toInstall.length : toCheck.length}).'); if (!installMode) { - // If in update mode... - var didCompleteChecking = false; - CheckingUpdatesNotification? notif; + // If in update mode, we check for updates. + // We divide the results into 4 groups: + // - toNotify - Apps with updates that the user will be notified about (can't be silently installed) + // - toRetry - Apps with update check errors that will be retried in a while + // - toThrow - Apps with update check errors that the user will be notified about (no retry) + // - toInstall - Apps with updates that will be installed silently + // After grouping the updates, we take care of toNotify and toThrow first + // Then if toRetry is not empty, we schedule another update task to run in a while (toInstall is retained) + // If toRetry is empty, we take care of toInstall + + // Init. vars. + List updates = []; + List toNotify = []; + List> toRetry = []; + var retryAfterXSeconds = 0; + List> toThrow = []; var networkRestricted = false; if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { var netResult = await (Connectivity().checkConnectivity()); networkRestricted = (netResult != ConnectivityResult.wifi) && (netResult != ConnectivityResult.ethernet); } - // Loop through all updates and check each - List toNotify = []; + CheckingUpdatesNotification notif = + CheckingUpdatesNotification(plural('app', toCheck.length)); + try { - for (int i = 0; i < toCheck.length; i++) { - var appId = toCheck[i].key; - var attemptCount = toCheck[i].value + 1; - AppInMemory? app = appsProvider.apps[appId]; - if (app?.app.installedVersion != null) { - try { - notificationsProvider.notify( - notif = CheckingUpdatesNotification(app?.name ?? appId), - cancelExisting: true); - App? newApp = await appsProvider.checkUpdate(appId); - if (newApp != null) { - if (networkRestricted || - !(await appsProvider.canInstallSilently(app!.app))) { - toNotify.add(newApp); - } else { - toInstall.add(MapEntry(appId, 0)); - } - } - if (i == (toCheck.length - 1)) { - didCompleteChecking = true; - } - } catch (e) { - // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue checking shortly - logs.add( - 'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.'); - if (attemptCount < maxAttempts) { - var remainingSeconds = e is RateLimitError - ? (i == 0 ? (e.remainingMinutes * 60) : (5 * 60)) - : e is ClientException - ? (15 * 60) - : pow(attemptCount, 2).toInt(); - logs.add( - 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); - var remainingToCheck = moveStrToEndMapEntryWithCount( - toCheck.sublist(i), MapEntry(appId, attemptCount)); - AndroidAlarmManager.oneShot(Duration(seconds: remainingSeconds), - taskId + 1, bgUpdateCheck, - params: { - 'toCheck': remainingToCheck - .map( - (entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - 'toInstall': toInstall - .map( - (entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - }); - break; - } else { - // If the offender has reached its fail limit, notify the user and remove it from the list (task can continue) - toCheck.removeAt(i); - i--; - notificationsProvider - .notify(ErrorCheckingUpdatesNotification(e.toString())); - } - } finally { - if (notif != null) { - notificationsProvider.cancel(notif.id); + // Check for updates + notificationsProvider.notify(notif, cancelExisting: true); + updates = await appsProvider.checkUpdates( + specificIds: toCheck.map((e) => e.key).toList()); + } catch (e) { + // If there were errors, group them into toRetry and toThrow + if (e is Map) { + updates = e['updates']; + MultiAppMultiError errors = e['errors']; + errors.rawErrors.forEach((key, err) { + logs.add( + 'BG update task $taskId: Got error on checking for $key \'${err.toString()}\'.'); + var toCheckApp = toCheck.where((element) => element.key == key).first; + if (toCheckApp.value < maxAttempts) { + toRetry.add(MapEntry(toCheckApp.key, toCheckApp.value + 1)); + var minRetryIntervalForThisApp = err is RateLimitError + ? (err.remainingMinutes * 60) + : e is ClientException + ? (15 * 60) + : pow(toCheckApp.value, 2).toInt(); + if (minRetryIntervalForThisApp > retryAfterXSeconds) { + retryAfterXSeconds = minRetryIntervalForThisApp; } + } else { + toThrow.add(MapEntry(key, err)); } - } + }); + } else { + // We don't expect to ever get here in any situation so no need to catch + logs.add('Fatal error in BG update task: ${e.toString()}'); + rethrow; } } finally { - if (toNotify.isNotEmpty) { - notificationsProvider.notify(UpdateNotification(toNotify)); + notificationsProvider.cancel(notif.id); + } + + // Group the updates into toNotify and toInstall + for (var i = 0; i < updates.length; i++) { + if (networkRestricted || + !(await appsProvider.canInstallSilently(updates[i]))) { + toNotify.add(updates[i]); + } else { + toInstall.add(MapEntry(updates[i].id, 0)); } } - // If you're done checking and found some silently installable updates, schedule another task which will run in install mode - if (didCompleteChecking && toInstall.isNotEmpty) { + + // Send the update notification + if (toNotify.isNotEmpty) { + notificationsProvider.notify(UpdateNotification(toNotify)); + } + + // Send the error notifications + if (toThrow.isNotEmpty) { + for (var element in toThrow) { + notificationsProvider.notify(ErrorCheckingUpdatesNotification( + '${element.key}: ${element.value.toString()}')); + } + } + + // if there are update checks to retry, schedule a retry task + if (toRetry.isNotEmpty) { + logs.add( + 'BG update task $taskId: Will retry in $retryAfterXSeconds seconds.'); + AndroidAlarmManager.oneShot( + Duration(seconds: retryAfterXSeconds), taskId + 1, bgUpdateCheck, + params: { + 'toCheck': toRetry, + 'toInstall': toInstall + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + }); + } else if (toInstall.isNotEmpty) { + // If there are no more update checks, schedule an install task logs.add( 'BG update task $taskId: Done. Scheduling install task to run immediately.'); AndroidAlarmManager.oneShot( @@ -1463,11 +1486,14 @@ Future bgUpdateCheck(int taskId, Map? params) async { .map((entry) => {'key': entry.key, 'value': entry.value}) .toList() }); - } else if (didCompleteChecking) { + } else { logs.add('BG install task $taskId: Done.'); } - } else { - // If in install mode... + } + + if (installMode) { + // If in install mode, we install silent updates. + var didCompleteInstalling = false; var tempObtArr = toInstall.where((element) => element.key == obtainiumId); if (tempObtArr.isNotEmpty) { From e9e9adb1744eeaff9d5cf3a1ccf6c668378287e2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 6 Oct 2023 19:34:08 -0400 Subject: [PATCH 482/600] Tweaks --- lib/providers/apps_provider.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 1a9e052..31824c2 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1458,7 +1458,8 @@ Future bgUpdateCheck(int taskId, Map? params) async { if (toThrow.isNotEmpty) { for (var element in toThrow) { notificationsProvider.notify(ErrorCheckingUpdatesNotification( - '${element.key}: ${element.value.toString()}')); + '${element.key}: ${element.value.toString()}', + id: Random().nextInt(10000))); } } @@ -1469,7 +1470,9 @@ Future bgUpdateCheck(int taskId, Map? params) async { AndroidAlarmManager.oneShot( Duration(seconds: retryAfterXSeconds), taskId + 1, bgUpdateCheck, params: { - 'toCheck': toRetry, + 'toCheck': toRetry + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), 'toInstall': toInstall .map((entry) => {'key': entry.key, 'value': entry.value}) .toList(), From 8163cd5c8f7ab9706d4711d64e553007b82e73a2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 6 Oct 2023 19:58:46 -0400 Subject: [PATCH 483/600] Improvements, bugfixes --- lib/custom_errors.dart | 24 +++++++++++++----------- lib/pages/apps.dart | 2 +- lib/pages/import_export.dart | 5 +++-- lib/providers/apps_provider.dart | 29 +++++++++++++++-------------- 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/lib/custom_errors.dart b/lib/custom_errors.dart index 4d807c5..04e6104 100644 --- a/lib/custom_errors.dart +++ b/lib/custom_errors.dart @@ -66,27 +66,29 @@ class NotImplementedError extends ObtainiumError { class MultiAppMultiError extends ObtainiumError { Map rawErrors = {}; - Map> content = {}; + Map> idsByErrorString = {}; + Map appIdNames = {}; MultiAppMultiError() : super(tr('placeholder'), unexpected: true); - add(String appId, dynamic error) { + add(String appId, dynamic error, {String? appName}) { rawErrors[appId] = error; var string = error.toString(); - var tempIds = content.remove(string); + var tempIds = idsByErrorString.remove(string); tempIds ??= []; tempIds.add(appId); - content.putIfAbsent(string, () => tempIds!); + idsByErrorString.putIfAbsent(string, () => tempIds!); + if (appName != null) { + appIdNames[appId] = appName; + } } + String errorString(String appId) => + '${appIdNames.containsKey(appId) ? '${appIdNames[appId]} ($appId)' : appId}: ${rawErrors[appId].toString()}'; + @override - String toString() { - String finalString = ''; - for (var e in content.keys) { - finalString += '$e: ${content[e].toString()}\n\n'; - } - return finalString; - } + String toString() => + idsByErrorString.keys.map((e) => errorString(e)).join('\n\n'); } showError(dynamic e, BuildContext context) { diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index cb7ce46..fe98aa9 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -833,7 +833,7 @@ class AppsPageState extends State { items: const [], initValid: true, message: tr('installStatusOfXWillBeResetExplanation', - args: [plural('app', selectedAppIds.length)]), + args: [plural('apps', selectedAppIds.length)]), ); }); if (values != null) { diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index 264f3a9..68de7f5 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -217,7 +217,8 @@ class _ImportExportPageState extends State { if (errors.isEmpty) { // ignore: use_build_context_synchronously showError( - tr('importedX', args: [plural('app', selectedUrls.length)]), + tr('importedX', + args: [plural('apps', selectedUrls.length)]), context); } else { // ignore: use_build_context_synchronously @@ -274,7 +275,7 @@ class _ImportExportPageState extends State { if (errors.isEmpty) { // ignore: use_build_context_synchronously showError( - tr('importedX', args: [plural('app', selectedUrls.length)]), + tr('importedX', args: [plural('apps', selectedUrls.length)]), context); } else { // ignore: use_build_context_synchronously diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 31824c2..7c150c6 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -449,7 +449,7 @@ class AppsProvider with ChangeNotifier { } catch (e) { logs.add( 'Could not install APK from XAPK \'${file.path}\': ${e.toString()}'); - errors.add(dir.appId, e); + errors.add(dir.appId, e, appName: apps[dir.appId]?.name); } } else if (file.path.toLowerCase().endsWith('.obb')) { await moveObbFile(file, dir.appId); @@ -457,7 +457,7 @@ class AppsProvider with ChangeNotifier { } if (somethingInstalled) { dir.file.delete(recursive: true); - } else if (errors.content.isNotEmpty) { + } else if (errors.idsByErrorString.isNotEmpty) { throw errors; } } finally { @@ -677,11 +677,11 @@ class AppsProvider with ChangeNotifier { } installedIds.add(id); } catch (e) { - errors.add(id, e); + errors.add(id, e, appName: apps[id]?.name); } } - if (errors.content.isNotEmpty) { + if (errors.idsByErrorString.isNotEmpty) { throw errors; } @@ -1090,7 +1090,7 @@ class AppsProvider with ChangeNotifier { throwErrorsForRetry) { rethrow; } - errors.add(appId, e); + errors.add(appId, e, appName: apps[appId]?.name); } if (newApp != null) { updates.add(newApp); @@ -1100,7 +1100,7 @@ class AppsProvider with ChangeNotifier { gettingUpdates = false; } } - if (errors.content.isNotEmpty) { + if (errors.idsByErrorString.isNotEmpty) { var res = Map(); res['errors'] = errors; res['updates'] = updates; @@ -1392,15 +1392,16 @@ Future bgUpdateCheck(int taskId, Map? params) async { List toNotify = []; List> toRetry = []; var retryAfterXSeconds = 0; - List> toThrow = []; + List toThrow = []; var networkRestricted = false; if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { var netResult = await (Connectivity().checkConnectivity()); networkRestricted = (netResult != ConnectivityResult.wifi) && (netResult != ConnectivityResult.ethernet); } + MultiAppMultiError? errors; CheckingUpdatesNotification notif = - CheckingUpdatesNotification(plural('app', toCheck.length)); + CheckingUpdatesNotification(plural('apps', toCheck.length)); try { // Check for updates @@ -1411,8 +1412,8 @@ Future bgUpdateCheck(int taskId, Map? params) async { // If there were errors, group them into toRetry and toThrow if (e is Map) { updates = e['updates']; - MultiAppMultiError errors = e['errors']; - errors.rawErrors.forEach((key, err) { + errors = e['errors']; + errors!.rawErrors.forEach((key, err) { logs.add( 'BG update task $taskId: Got error on checking for $key \'${err.toString()}\'.'); var toCheckApp = toCheck.where((element) => element.key == key).first; @@ -1422,12 +1423,12 @@ Future bgUpdateCheck(int taskId, Map? params) async { ? (err.remainingMinutes * 60) : e is ClientException ? (15 * 60) - : pow(toCheckApp.value, 2).toInt(); + : pow(toCheckApp.value + 1, 2).toInt(); if (minRetryIntervalForThisApp > retryAfterXSeconds) { retryAfterXSeconds = minRetryIntervalForThisApp; } } else { - toThrow.add(MapEntry(key, err)); + toThrow.add(key); } }); } else { @@ -1456,9 +1457,9 @@ Future bgUpdateCheck(int taskId, Map? params) async { // Send the error notifications if (toThrow.isNotEmpty) { - for (var element in toThrow) { + for (var appId in toThrow) { notificationsProvider.notify(ErrorCheckingUpdatesNotification( - '${element.key}: ${element.value.toString()}', + errors!.errorString(appId), id: Random().nextInt(10000))); } } From df93cbde8f7aef0ce4b72e437a1bfb819da7662b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 6 Oct 2023 20:37:14 -0400 Subject: [PATCH 484/600] Fix UpToDown (#962) --- lib/app_sources/uptodown.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/app_sources/uptodown.dart b/lib/app_sources/uptodown.dart index 7b36cc3..86b640c 100644 --- a/lib/app_sources/uptodown.dart +++ b/lib/app_sources/uptodown.dart @@ -80,4 +80,20 @@ class Uptodown extends AppSource { version, getApkUrlsFromUrls([apkUrl]), AppNames(author, appName), releaseDate: relDate); } + + @override + Future apkUrlPrefetchModifier( + String apkUrl, String standardUrl) async { + var res = await sourceRequest(apkUrl); + if (res.statusCode != 200) { + throw getObtainiumHttpError(res); + } + var html = parse(res.body); + var finalUrl = + (html.querySelector('.post-download')?.attributes['data-url']); + if (finalUrl == null) { + throw NoAPKError(); + } + return finalUrl; + } } From f34ffe18a8db70b56cc3e753cda36b9a6c7b9240 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 6 Oct 2023 20:42:09 -0400 Subject: [PATCH 485/600] Update packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 24 ++++++++++++------------ pubspec.yaml | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 1f2815e..d3343ea 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.22'; +const String currentVersion = '0.14.23'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 51a04bc..fe8eaa3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -46,10 +46,10 @@ packages: dependency: transitive description: name: archive - sha256: d4dc11707abb32ef756ab95678c0d6df54003d98277f7c9aeda14c48e7a38c2f + sha256: "06a96f1249f38a00435b3b0c9a3246d934d7dbc8183fc7c9e56989860edb99d4" url: "https://pub.dev" source: hosted - version: "3.4.3" + version: "3.4.4" args: dependency: transitive description: @@ -291,10 +291,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "3002092e5b8ce2f86c3361422e52e6db6776c23ee21e0b2f71b892bf4259ef04" + sha256: "6d11ea777496061e583623aaf31923f93a9409ef8fcaeeefdd6cd78bf4fe5bb3" url: "https://pub.dev" source: hosted - version: "15.1.1" + version: "16.1.0" flutter_local_notifications_linux: dependency: transitive description: @@ -320,10 +320,10 @@ packages: dependency: "direct main" description: name: flutter_markdown - sha256: a10979814c5f4ddbe2b6143fba25d927599e21e3ba65b3862995960606fae78f + sha256: "8afc9a6aa6d8e8063523192ba837149dbf3d377a37c0b0fc579149a1fbd4a619" url: "https://pub.dev" source: hosted - version: "0.6.17+3" + version: "0.6.18" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -538,10 +538,10 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: ad65ba9af42a3d067203641de3fd9f547ded1410bad3b84400c2b4899faede70 + sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8" url: "https://pub.dev" source: hosted - version: "11.0.0" + version: "11.0.1" permission_handler_android: dependency: transitive description: @@ -879,10 +879,10 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: "053d454c9475546b4382e9498601fb46293cdac9b3ca93f1a738375bc9a1eee4" + sha256: c1ab9b81090705c6069197d9fdc1625e587b52b8d70cdde2339d177ad0dbb98e url: "https://pub.dev" source: hosted - version: "4.3.0" + version: "4.4.1" webview_flutter_android: dependency: transitive description: @@ -903,10 +903,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "3c7d56ca4b82654ad1f58aeefb8d593a59224f26d6b2bf8feed074361eb34c86" + sha256: "30b9af6bdd457b44c08748b9190d23208b5165357cc2eb57914fee1366c42974" url: "https://pub.dev" source: hosted - version: "3.9.0" + version: "3.9.1" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index af466c0..5c82b0f 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.14.22+214 # When changing this, update the tag in main() accordingly +version: 0.14.23+215 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' @@ -38,7 +38,7 @@ dependencies: cupertino_icons: ^1.0.5 path_provider: ^2.0.11 flutter_fgbg: ^0.3.0 # Try removing reliance on this - flutter_local_notifications: ^15.1.0+1 + flutter_local_notifications: ^16.1.0 provider: ^6.0.3 http: ^1.0.0 webview_flutter: ^4.0.0 From 33caf4644e82040a1dd910bc9ce50c741f8df946 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 6 Oct 2023 20:43:06 -0400 Subject: [PATCH 486/600] Ran dart fix --- lib/providers/apps_provider.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 7c150c6..9acd085 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -738,7 +738,6 @@ class AppsProvider with ChangeNotifier { var naiveStandardVersionDetection = SourceProvider() .getSource(app.url, overrideSource: app.overrideSource) .naiveStandardVersionDetection; - ; // FIRST, COMPARE THE APP'S REPORTED AND REAL INSTALLED VERSIONS, WHERE ONE IS NULL if (installedInfo == null && app.installedVersion != null && !trackOnly) { // App says it's installed but isn't really (and isn't track only) - set to not installed @@ -1101,7 +1100,7 @@ class AppsProvider with ChangeNotifier { } } if (errors.idsByErrorString.isNotEmpty) { - var res = Map(); + var res = {}; res['errors'] = errors; res['updates'] = updates; throw res; From 4e5a9b2af5099f70f21f6b1e26134e05df28a48d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 6 Oct 2023 21:19:46 -0400 Subject: [PATCH 487/600] Updated GitHub actions --- .../workflows/{android.yml => release.yml} | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) rename .github/workflows/{android.yml => release.yml} (59%) diff --git a/.github/workflows/android.yml b/.github/workflows/release.yml similarity index 59% rename from .github/workflows/android.yml rename to .github/workflows/release.yml index 9ccee7f..ed76aa5 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: android +name: Release (Manual/Draft) on: workflow_dispatch: @@ -25,12 +25,16 @@ jobs: env: KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }} + GPG_KEY: ${{ secrets.GPG_KEY }} run: | echo "${KEYSTORE_BASE64}" | base64 -d > apksign.keystore + echo "$GPG_KEY" | gpg --import for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do - out=${apk/-release/-release-signed} - ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass env:KEYSTORE_PASS --out "${out}" "${apk}" - echo "$(sha256sum ${out})" + unsignedFn=${apk/-release/-unsigned} + mv "$apk" "$unsignedFn" + ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass env:KEYSTORE_PASS --out "${apk}" "${unsignedFn}" + sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 + gpg --sign --detach-sig "$apk".sha256 done rm apksign.keystore @@ -39,14 +43,19 @@ jobs: run: | VERSION=$(grep -oP "currentVersion = '\K[^']+" lib/main.dart) echo "::set-output name=version::$VERSION" + TAG=$(grep -oP "'.*\\\$currentVersion.*'" lib/main.dart | head -c -2 | tail -c +2 | sed "s/\$currentVersion/$VERSION/g") + echo "::set-output name=tag::$TAG" + if [ -n "$(echo $TAG | grep -oP '\-beta$')" ]; then BETA=true; else BETA=false; fi + echo "::set-output name=beta::$BETA" - name: Create Release And Upload APKs uses: ncipollo/release-action@v1 with: token: ${{ secrets.GAT }} - tag: "v${{ steps.extract_version.outputs.version }}-beta" - prerelease: true - artifacts: ./build/app/outputs/flutter-apk/*-signed*.apk + tag: "${{ steps.extract_version.outputs.tag }}" + prerelease: "${{ steps.extract_version.outputs.beta }}" + artifacts: ./build/app/outputs/flutter-apk/*-release*.apk* + draft: true - name: Archive Reports For Job uses: actions/upload-artifact@v3 From ba1db88c8d4257c901a575d1911b99902a58f9db Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 6 Oct 2023 21:21:26 -0400 Subject: [PATCH 488/600] Run GH action manually only --- .github/workflows/release.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ed76aa5..ead8289 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,9 +2,6 @@ name: Release (Manual/Draft) on: workflow_dispatch: - push: - branches: - - main jobs: build: From 8f25245ad1efe774c42048ed898b86e133e6cd32 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 21:47:25 -0400 Subject: [PATCH 489/600] Update release.yml --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ead8289..216740c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,10 +22,10 @@ jobs: env: KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }} - GPG_KEY: ${{ secrets.GPG_KEY }} + GPG_KEY: ${{ secrets.PGP_KEY_BASE64 }} run: | echo "${KEYSTORE_BASE64}" | base64 -d > apksign.keystore - echo "$GPG_KEY" | gpg --import + echo "$GPG_KEY" | base64 -d | gpg --import for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do unsignedFn=${apk/-release/-unsigned} mv "$apk" "$unsignedFn" From 65187cb17bec81d3be7b096cb9b7af5b56bc7444 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:04:55 -0400 Subject: [PATCH 490/600] Update release.yml --- .github/workflows/release.yml | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 216740c..a438fb5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,16 @@ jobs: - uses: subosito/flutter-action@v2 + - name: Temp + env: + PGP_KEY_BASE64: ${{ secrets.PGP_KEY_BASE64 }} + PGP_KEY_PASSPHRASE: ${{ secrets.PGP_KEY_PASSPHRASE }} + run: | + echo "$PGP_KEY_BASE64" | base64 -d | gpg --import --passphrase "$PGP_KEY_PASSPHRASE" + PGP_KEY_FINGERPRINT="$(gpg --list-keys --with-colon "$(echo "$PGP_KEY_BASE64" | base64 -d | gpg --with-fingerprint --list-packets | grep 'user ID' | awk -F'"' '{print $2}')" | awk -F: '/^pub:/ { print $5 }')" + gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" + gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" + - name: Build APKs run: | sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle @@ -22,10 +32,12 @@ jobs: env: KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }} - GPG_KEY: ${{ secrets.PGP_KEY_BASE64 }} + PGP_KEY_BASE64: ${{ secrets.PGP_KEY_BASE64 }} + PGP_KEY_PASSPHRASE: ${{ secrets.PGP_KEY_PASSPHRASE }} run: | echo "${KEYSTORE_BASE64}" | base64 -d > apksign.keystore - echo "$GPG_KEY" | base64 -d | gpg --import + echo "$PGP_KEY_BASE64" | base64 -d | gpg --import --passphrase "$PGP_KEY_PASSPHRASE" + PGP_KEY_FINGERPRINT="$(gpg --list-keys --with-colon "$(echo "$PGP_KEY_BASE64" | base64 -d | gpg --with-fingerprint --list-packets | grep 'user ID' | awk -F'"' '{print $2}')" | awk -F: '/^pub:/ { print $5 }')" for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do unsignedFn=${apk/-release/-unsigned} mv "$apk" "$unsignedFn" @@ -34,6 +46,8 @@ jobs: gpg --sign --detach-sig "$apk".sha256 done rm apksign.keystore + gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" + gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" - name: Extract Version id: extract_version @@ -48,7 +62,7 @@ jobs: - name: Create Release And Upload APKs uses: ncipollo/release-action@v1 with: - token: ${{ secrets.GAT }} + token: ${{ secrets.GITHUB_ACCESS_TOKEN }} tag: "${{ steps.extract_version.outputs.tag }}" prerelease: "${{ steps.extract_version.outputs.beta }}" artifacts: ./build/app/outputs/flutter-apk/*-release*.apk* From ce259764a885fea6c52a51f41ed312fa9a51c4fc Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:09:33 -0400 Subject: [PATCH 491/600] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a438fb5..faafc38 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,9 +16,9 @@ jobs: - name: Temp env: PGP_KEY_BASE64: ${{ secrets.PGP_KEY_BASE64 }} - PGP_KEY_PASSPHRASE: ${{ secrets.PGP_KEY_PASSPHRASE }} run: | echo "$PGP_KEY_BASE64" | base64 -d | gpg --import --passphrase "$PGP_KEY_PASSPHRASE" + echo A PGP_KEY_FINGERPRINT="$(gpg --list-keys --with-colon "$(echo "$PGP_KEY_BASE64" | base64 -d | gpg --with-fingerprint --list-packets | grep 'user ID' | awk -F'"' '{print $2}')" | awk -F: '/^pub:/ { print $5 }')" gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From ef40f3900fecb12a10f7f5d628927d706c292109 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:11:25 -0400 Subject: [PATCH 492/600] Update release.yml --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index faafc38..67a996d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,6 +17,7 @@ jobs: env: PGP_KEY_BASE64: ${{ secrets.PGP_KEY_BASE64 }} run: | + export GPG_TTY=$(tty) echo "$PGP_KEY_BASE64" | base64 -d | gpg --import --passphrase "$PGP_KEY_PASSPHRASE" echo A PGP_KEY_FINGERPRINT="$(gpg --list-keys --with-colon "$(echo "$PGP_KEY_BASE64" | base64 -d | gpg --with-fingerprint --list-packets | grep 'user ID' | awk -F'"' '{print $2}')" | awk -F: '/^pub:/ { print $5 }')" From 66446cbffc3a9258d0c4a1dfed409b7d8de6b0a0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:16:41 -0400 Subject: [PATCH 493/600] Update release.yml --- .github/workflows/release.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 67a996d..c83aeb3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,14 +13,17 @@ jobs: - uses: subosito/flutter-action@v2 + - name: Import GPG key + id: import_pgp_key + uses: crazy-max/ghaction-import-gpg@v6 + with: + gpg_private_key: ${{ secrets.PGP_KEY_BASE64 }} + - name: Temp env: PGP_KEY_BASE64: ${{ secrets.PGP_KEY_BASE64 }} run: | - export GPG_TTY=$(tty) - echo "$PGP_KEY_BASE64" | base64 -d | gpg --import --passphrase "$PGP_KEY_PASSPHRASE" - echo A - PGP_KEY_FINGERPRINT="$(gpg --list-keys --with-colon "$(echo "$PGP_KEY_BASE64" | base64 -d | gpg --with-fingerprint --list-packets | grep 'user ID' | awk -F'"' '{print $2}')" | awk -F: '/^pub:/ { print $5 }')" + PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.tag }}" gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From 01385991200723e07c13caea7c4bd8ee624e5839 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:23:45 -0400 Subject: [PATCH 494/600] Update release.yml --- .github/workflows/release.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c83aeb3..dfa2716 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,10 +20,9 @@ jobs: gpg_private_key: ${{ secrets.PGP_KEY_BASE64 }} - name: Temp - env: - PGP_KEY_BASE64: ${{ secrets.PGP_KEY_BASE64 }} run: | - PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.tag }}" + echo -n "Hello, World!" | gpg --clearsign + PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" @@ -36,12 +35,8 @@ jobs: env: KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }} - PGP_KEY_BASE64: ${{ secrets.PGP_KEY_BASE64 }} - PGP_KEY_PASSPHRASE: ${{ secrets.PGP_KEY_PASSPHRASE }} run: | echo "${KEYSTORE_BASE64}" | base64 -d > apksign.keystore - echo "$PGP_KEY_BASE64" | base64 -d | gpg --import --passphrase "$PGP_KEY_PASSPHRASE" - PGP_KEY_FINGERPRINT="$(gpg --list-keys --with-colon "$(echo "$PGP_KEY_BASE64" | base64 -d | gpg --with-fingerprint --list-packets | grep 'user ID' | awk -F'"' '{print $2}')" | awk -F: '/^pub:/ { print $5 }')" for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do unsignedFn=${apk/-release/-unsigned} mv "$apk" "$unsignedFn" @@ -50,6 +45,7 @@ jobs: gpg --sign --detach-sig "$apk".sha256 done rm apksign.keystore + PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From df7b74e727b09d2980ad9c9175d0327fcdb9e06e Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:28:02 -0400 Subject: [PATCH 495/600] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dfa2716..9b56fd0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,7 @@ jobs: - name: Temp run: | - echo -n "Hello, World!" | gpg --clearsign + echo -n "Hello, World!" | gpg --batch --pinentry-mode loopback --clearsign PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From 3d5411ef28fe423dce8d2b8d6f437f483cd2bfd8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:32:23 -0400 Subject: [PATCH 496/600] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9b56fd0..9401d94 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,8 +21,8 @@ jobs: - name: Temp run: | - echo -n "Hello, World!" | gpg --batch --pinentry-mode loopback --clearsign PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" + echo -n "Hello, World!" | gpg --batch --clearsign --local-user "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From 36a8b04c4f0788fd7459b04728809f5833b804e6 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:35:40 -0400 Subject: [PATCH 497/600] Update release.yml --- .github/workflows/release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9401d94..056cb75 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,7 +22,8 @@ jobs: - name: Temp run: | PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" - echo -n "Hello, World!" | gpg --batch --clearsign --local-user "$PGP_KEY_FINGERPRINT" + export GPG_TTY=$(tty) + echo -n "Hello, World!" | gpg --batch --clearsign --pinentry-mode loopback --passphrase "" --local-user "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From 035df1f33841eb095433d991e8d462ccdb045356 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:38:01 -0400 Subject: [PATCH 498/600] Update release.yml --- .github/workflows/release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 056cb75..70eb0d1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,8 @@ jobs: run: | PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" export GPG_TTY=$(tty) - echo -n "Hello, World!" | gpg --batch --clearsign --pinentry-mode loopback --passphrase "" --local-user "$PGP_KEY_FINGERPRINT" + echo abc > abc + gpg --sign --detach-sig ./abc gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From 5735293efb8386814b5c5bd7ea6daf824ca27725 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:40:27 -0400 Subject: [PATCH 499/600] Update release.yml --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 70eb0d1..c57175b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,8 +22,8 @@ jobs: - name: Temp run: | PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" - export GPG_TTY=$(tty) - echo abc > abc + # export GPG_TTY=$(tty) + echo 'abc' > ./abc gpg --sign --detach-sig ./abc gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From 95cb8ca4935e9e3ef82d692d82b73f811fa0ac96 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:41:47 -0400 Subject: [PATCH 500/600] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c57175b..127e952 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,7 +22,7 @@ jobs: - name: Temp run: | PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" - # export GPG_TTY=$(tty) + export GPG_TTY=$(tty) echo 'abc' > ./abc gpg --sign --detach-sig ./abc gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" From e95230859efe381340bebf93bc7744d5fe8866e0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:43:41 -0400 Subject: [PATCH 501/600] Update release.yml --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 127e952..41b12c9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,9 +9,9 @@ jobs: steps: - - uses: actions/checkout@v3 + #- uses: actions/checkout@v3 - - uses: subosito/flutter-action@v2 + #- uses: subosito/flutter-action@v2 - name: Import GPG key id: import_pgp_key @@ -22,9 +22,9 @@ jobs: - name: Temp run: | PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" - export GPG_TTY=$(tty) + # export GPG_TTY=$(tty) echo 'abc' > ./abc - gpg --sign --detach-sig ./abc + gpg --batch --sign --detach-sig --pinentry-mode loopback ./abc gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From 827e2b161cbb1a92c79db36f50132de78cd16329 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:45:20 -0400 Subject: [PATCH 502/600] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 41b12c9..fdcffeb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" # export GPG_TTY=$(tty) echo 'abc' > ./abc - gpg --batch --sign --detach-sig --pinentry-mode loopback ./abc + gpg --sign --detach-sig ./abc gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From 15a1f1e6e09f2baaac8b2a24de3405387cc1f4c2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:46:11 -0400 Subject: [PATCH 503/600] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fdcffeb..faddc61 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" # export GPG_TTY=$(tty) echo 'abc' > ./abc - gpg --sign --detach-sig ./abc + gpg --batch --pinentry-mode loopback --passphrase "ABCDFML" --sign --detach-sig ./abc gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From 30a9e1ee4b360c7215be0f792fd94f6765e18ada Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:48:21 -0400 Subject: [PATCH 504/600] Update release.yml --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index faddc61..3dca8bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,6 +18,7 @@ jobs: uses: crazy-max/ghaction-import-gpg@v6 with: gpg_private_key: ${{ secrets.PGP_KEY_BASE64 }} + passphrase: "ABCDFML" - name: Temp run: | From 6c0459c2ae8e9a7a9ae5b18501eae70daf56dd05 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:51:30 -0400 Subject: [PATCH 505/600] Update release.yml --- .github/workflows/release.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3dca8bc..5699983 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,14 +18,16 @@ jobs: uses: crazy-max/ghaction-import-gpg@v6 with: gpg_private_key: ${{ secrets.PGP_KEY_BASE64 }} - passphrase: "ABCDFML" + passphrase: ${{ secrets.PGP_PASSPHRASE }} - name: Temp + env: + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} run: | PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" # export GPG_TTY=$(tty) echo 'abc' > ./abc - gpg --batch --pinentry-mode loopback --passphrase "ABCDFML" --sign --detach-sig ./abc + gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig ./abc gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" From 96fb97f4ef5993dc7c64410c9b8a9de2a3aab050 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:53:13 -0400 Subject: [PATCH 506/600] Update release.yml --- .github/workflows/release.yml | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5699983..3dda30e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,17 +20,6 @@ jobs: gpg_private_key: ${{ secrets.PGP_KEY_BASE64 }} passphrase: ${{ secrets.PGP_PASSPHRASE }} - - name: Temp - env: - PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} - run: | - PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" - # export GPG_TTY=$(tty) - echo 'abc' > ./abc - gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig ./abc - gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" - gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" - - name: Build APKs run: | sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle @@ -40,6 +29,7 @@ jobs: env: KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }} + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} run: | echo "${KEYSTORE_BASE64}" | base64 -d > apksign.keystore for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do @@ -47,7 +37,7 @@ jobs: mv "$apk" "$unsignedFn" ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass env:KEYSTORE_PASS --out "${apk}" "${unsignedFn}" sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 - gpg --sign --detach-sig "$apk".sha256 + gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha256 done rm apksign.keystore PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" From ddb50940ce3881bd51e3a838636f6f871aea741a Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:55:50 -0400 Subject: [PATCH 507/600] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3dda30e..dd68aed 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -57,7 +57,7 @@ jobs: - name: Create Release And Upload APKs uses: ncipollo/release-action@v1 with: - token: ${{ secrets.GITHUB_ACCESS_TOKEN }} + token: ${{ secrets.GH_ACCESS_TOKEN }} tag: "${{ steps.extract_version.outputs.tag }}" prerelease: "${{ steps.extract_version.outputs.beta }}" artifacts: ./build/app/outputs/flutter-apk/*-release*.apk* From 818dc230891920d1a982f40d9e008af0befbabab Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:55:59 -0400 Subject: [PATCH 508/600] Update release.yml --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dd68aed..1e7b6e0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,9 +9,9 @@ jobs: steps: - #- uses: actions/checkout@v3 + - uses: actions/checkout@v3 - #- uses: subosito/flutter-action@v2 + - uses: subosito/flutter-action@v2 - name: Import GPG key id: import_pgp_key From 238d43f9162a5e041e90ccecdacf8bf16139c913 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:18:25 -0400 Subject: [PATCH 509/600] Update release.yml --- .github/workflows/release.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1e7b6e0..6d478be 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,14 +28,13 @@ jobs: - name: Sign APKs env: KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} - KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASS }} PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} run: | echo "${KEYSTORE_BASE64}" | base64 -d > apksign.keystore for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do unsignedFn=${apk/-release/-unsigned} mv "$apk" "$unsignedFn" - ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass env:KEYSTORE_PASS --out "${apk}" "${unsignedFn}" + ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --out "${apk}" "${unsignedFn}" sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha256 done From 5c562a6bdb143d5f274b57ffaa562ccdd486a93e Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:45:00 -0400 Subject: [PATCH 510/600] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d478be..a85ec7b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,7 +34,7 @@ jobs: for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do unsignedFn=${apk/-release/-unsigned} mv "$apk" "$unsignedFn" - ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --out "${apk}" "${unsignedFn}" + ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass "" --out "${apk}" "${unsignedFn}" sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha256 done From b38f6d058122e9702659c21be5fea07f8c2464a0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Fri, 6 Oct 2023 23:58:33 -0400 Subject: [PATCH 511/600] Update release.yml --- .github/workflows/release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a85ec7b..9b1f7cf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,13 +28,14 @@ jobs: - name: Sign APKs env: KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} + KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} run: | echo "${KEYSTORE_BASE64}" | base64 -d > apksign.keystore for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do unsignedFn=${apk/-release/-unsigned} mv "$apk" "$unsignedFn" - ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass "" --out "${apk}" "${unsignedFn}" + ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass "${KEYSTORE_PASSWORD}" --out "${apk}" "${unsignedFn}" sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha256 done From b40a4dd243b5bccfe2bd71b65797f35c09310979 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 7 Oct 2023 00:09:18 -0400 Subject: [PATCH 512/600] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9b1f7cf..b0ca8a0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,7 @@ jobs: for apk in ./build/app/outputs/flutter-apk/*-release*.apk; do unsignedFn=${apk/-release/-unsigned} mv "$apk" "$unsignedFn" - ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass "${KEYSTORE_PASSWORD}" --out "${apk}" "${unsignedFn}" + ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass pass:"${KEYSTORE_PASSWORD}" --out "${apk}" "${unsignedFn}" sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha256 done From 290a78acb55113dd578dde2abd4f4a2ed75332e4 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 7 Oct 2023 00:30:09 -0400 Subject: [PATCH 513/600] Update release.yml --- .github/workflows/release.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b0ca8a0..f63320a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,8 +36,9 @@ jobs: unsignedFn=${apk/-release/-unsigned} mv "$apk" "$unsignedFn" ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass pass:"${KEYSTORE_PASSWORD}" --out "${apk}" "${unsignedFn}" - sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 - gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha256 + ls -l + # sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 + gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha1 done rm apksign.keystore PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" From e314717a3e59e409b27944ce1659662d44a5451d Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 7 Oct 2023 00:33:50 -0400 Subject: [PATCH 514/600] Update release.yml --- .github/workflows/release.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f63320a..e817961 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: Release (Manual/Draft) +name: Release (as Draft) on: workflow_dispatch: @@ -10,7 +10,6 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: subosito/flutter-action@v2 - name: Import GPG key @@ -54,6 +53,12 @@ jobs: echo "::set-output name=tag::$TAG" if [ -n "$(echo $TAG | grep -oP '\-beta$')" ]; then BETA=true; else BETA=false; fi echo "::set-output name=beta::$BETA" + + - name: Create Tag + uses: laputansoft/github-tag-action@v4.6 + with: + github_token: ${{ secrets.GH_ACCESS_TOKEN }} + tag: "${{ steps.extract_version.outputs.tag }}" - name: Create Release And Upload APKs uses: ncipollo/release-action@v1 From abfec51964ef1b03cac7040a99af3fcaf2a98702 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 7 Oct 2023 00:40:34 -0400 Subject: [PATCH 515/600] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e817961..b0450f8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,7 @@ jobs: unsignedFn=${apk/-release/-unsigned} mv "$apk" "$unsignedFn" ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass pass:"${KEYSTORE_PASSWORD}" --out "${apk}" "${unsignedFn}" - ls -l + ls -l ./build/app/outputs/flutter-apk/ # sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha1 done From 2cb750a7b045a8c523803174b6e15b5fd8d7321b Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 7 Oct 2023 00:56:27 -0400 Subject: [PATCH 516/600] Update release.yml --- .github/workflows/release.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b0450f8..ce5f6a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,6 +23,8 @@ jobs: run: | sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle flutter build apk && flutter build apk --split-per-abi + rm ./build/app/outputs/flutter-apk/*.sha1 + ls -l ./build/app/outputs/flutter-apk/ - name: Sign APKs env: @@ -35,9 +37,9 @@ jobs: unsignedFn=${apk/-release/-unsigned} mv "$apk" "$unsignedFn" ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass pass:"${KEYSTORE_PASSWORD}" --out "${apk}" "${unsignedFn}" - ls -l ./build/app/outputs/flutter-apk/ - # sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 - gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha1 + rm "$apk".idsig + sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 + gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha256 done rm apksign.keystore PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" From c75416f9be32539c3c3f7c9768247b7461031a29 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 7 Oct 2023 01:02:53 -0400 Subject: [PATCH 517/600] Update release.yml --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ce5f6a2..cbdf064 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,7 +37,6 @@ jobs: unsignedFn=${apk/-release/-unsigned} mv "$apk" "$unsignedFn" ${ANDROID_HOME}/build-tools/30.0.2/apksigner sign --ks apksign.keystore --ks-pass pass:"${KEYSTORE_PASSWORD}" --out "${apk}" "${unsignedFn}" - rm "$apk".idsig sha256sum ${apk} | cut -d " " -f 1 > "$apk".sha256 gpg --batch --pinentry-mode loopback --passphrase "${PGP_PASSPHRASE}" --sign --detach-sig "$apk".sha256 done From 9bbff1f4360a3e0c855c4e711187f9b97206cf37 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 7 Oct 2023 01:08:43 -0400 Subject: [PATCH 518/600] Update release.yml --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cbdf064..39def93 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,10 +56,10 @@ jobs: echo "::set-output name=beta::$BETA" - name: Create Tag - uses: laputansoft/github-tag-action@v4.6 + uses: mathieudutour/github-tag-action@v6.1 with: github_token: ${{ secrets.GH_ACCESS_TOKEN }} - tag: "${{ steps.extract_version.outputs.tag }}" + custom_tag: "${{ steps.extract_version.outputs.tag }}" - name: Create Release And Upload APKs uses: ncipollo/release-action@v1 From 2c006748351aa4e1a1586d88d13256357263c26d Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 7 Oct 2023 01:20:03 -0400 Subject: [PATCH 519/600] Update release.yml --- .github/workflows/release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 39def93..3886b94 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -60,6 +60,7 @@ jobs: with: github_token: ${{ secrets.GH_ACCESS_TOKEN }} custom_tag: "${{ steps.extract_version.outputs.tag }}" + tag_prefix: "" - name: Create Release And Upload APKs uses: ncipollo/release-action@v1 @@ -68,6 +69,7 @@ jobs: tag: "${{ steps.extract_version.outputs.tag }}" prerelease: "${{ steps.extract_version.outputs.beta }}" artifacts: ./build/app/outputs/flutter-apk/*-release*.apk* + body: ${{ steps.tag_version.outputs.changelog }} draft: true - name: Archive Reports For Job From a5b2d06742bba73ebb7ce9f3d865725ae44d717a Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 7 Oct 2023 01:33:34 -0400 Subject: [PATCH 520/600] Update release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3886b94..fda3b76 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -69,7 +69,7 @@ jobs: tag: "${{ steps.extract_version.outputs.tag }}" prerelease: "${{ steps.extract_version.outputs.beta }}" artifacts: ./build/app/outputs/flutter-apk/*-release*.apk* - body: ${{ steps.tag_version.outputs.changelog }} + generateReleaseNotes: true draft: true - name: Archive Reports For Job From 811bc6434b019ffddbf4ba296c5981a3fa64418f Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 7 Oct 2023 02:00:13 -0400 Subject: [PATCH 521/600] Update release.yml --- .github/workflows/release.yml | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fda3b76..2235561 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,18 +42,16 @@ jobs: done rm apksign.keystore PGP_KEY_FINGERPRINT="${{ steps.import_pgp_key.outputs.fingerprint }}" - gpg --batch --yes --delete-secret-keys "$PGP_KEY_FINGERPRINT" - gpg --batch --yes --delete-keys "$PGP_KEY_FINGERPRINT" - name: Extract Version id: extract_version run: | VERSION=$(grep -oP "currentVersion = '\K[^']+" lib/main.dart) - echo "::set-output name=version::$VERSION" + echo "version=$VERSION" >> $GITHUB_OUTPUT TAG=$(grep -oP "'.*\\\$currentVersion.*'" lib/main.dart | head -c -2 | tail -c +2 | sed "s/\$currentVersion/$VERSION/g") - echo "::set-output name=tag::$TAG" + echo "tag=$TAG" >> $GITHUB_OUTPUT if [ -n "$(echo $TAG | grep -oP '\-beta$')" ]; then BETA=true; else BETA=false; fi - echo "::set-output name=beta::$BETA" + echo "beta=$BETA" >> $GITHUB_OUTPUT - name: Create Tag uses: mathieudutour/github-tag-action@v6.1 @@ -71,10 +69,3 @@ jobs: artifacts: ./build/app/outputs/flutter-apk/*-release*.apk* generateReleaseNotes: true draft: true - - - name: Archive Reports For Job - uses: actions/upload-artifact@v3 - with: - name: reports - path: '*/build/reports' - if: ${{ always() }} From 1e009e2211f3b6e2cdcff45d99e987fa4f1ef5f9 Mon Sep 17 00:00:00 2001 From: Imran Remtulla <30463115+ImranR98@users.noreply.github.com> Date: Sat, 7 Oct 2023 02:03:18 -0400 Subject: [PATCH 522/600] Update release.yml --- .github/workflows/release.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2235561..7ac5e34 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: Release (as Draft) +name: Build and Release on: workflow_dispatch: @@ -68,4 +68,3 @@ jobs: prerelease: "${{ steps.extract_version.outputs.beta }}" artifacts: ./build/app/outputs/flutter-apk/*-release*.apk* generateReleaseNotes: true - draft: true From 5aabcccfd40580391bd0f945e7f821b7ad24527a Mon Sep 17 00:00:00 2001 From: John Betaro <114379310+JohnBetaro@users.noreply.github.com> Date: Sat, 7 Oct 2023 09:53:34 +0100 Subject: [PATCH 523/600] Update fdroid.dart --- lib/app_sources/fdroid.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 1201062..c7b2dda 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -11,6 +11,7 @@ class FDroid extends AppSource { FDroid() { host = 'f-droid.org'; name = tr('fdroid'); + naiveStandardVersionDetection = true; canSearch = true; additionalSourceAppSpecificSettingFormItems = [ [ From 71755763b9a50fade54de91c911e3ea086a0eb38 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 7 Oct 2023 13:15:22 -0400 Subject: [PATCH 524/600] Enabled WhatsApp Source (#357) --- lib/app_sources/whatsapp.dart | 48 ++++++++---------------------- lib/providers/source_provider.dart | 3 +- 2 files changed, 15 insertions(+), 36 deletions(-) diff --git a/lib/app_sources/whatsapp.dart b/lib/app_sources/whatsapp.dart index f17d8a0..ff295b4 100644 --- a/lib/app_sources/whatsapp.dart +++ b/lib/app_sources/whatsapp.dart @@ -16,14 +16,13 @@ class WhatsApp extends AppSource { @override Future apkUrlPrefetchModifier( String apkUrl, String standardUrl) async { - Response res = await sourceRequest('https://www.whatsapp.com/android'); + Response res = await sourceRequest('$standardUrl/android'); if (res.statusCode == 200) { var targetLinks = parse(res.body) .querySelectorAll('a') .map((e) => e.attributes['href'] ?? '') .where((e) => e.isNotEmpty) - .where((e) => - e.contains('content.whatsapp.net') && e.contains('WhatsApp.apk')) + .where((e) => e.contains('WhatsApp.apk')) .toList(); if (targetLinks.isEmpty) { throw NoAPKError(); @@ -39,37 +38,16 @@ class WhatsApp extends AppSource { String standardUrl, Map additionalSettings, ) async { - Response res = await sourceRequest('https://www.whatsapp.com/android'); - if (res.statusCode == 200) { - var targetElements = parse(res.body) - .querySelectorAll('p') - .where((element) => element.innerHtml.contains('Version ')) - .toList(); - if (targetElements.isEmpty) { - throw NoVersionError(); - } - var vLines = targetElements[0] - .innerHtml - .split('\n') - .where((element) => element.contains('Version ')) - .toList(); - if (vLines.isEmpty) { - throw NoVersionError(); - } - var versionMatch = RegExp('[0-9]+(\\.[0-9]+)+').firstMatch(vLines[0]); - if (versionMatch == null) { - throw NoVersionError(); - } - String version = - vLines[0].substring(versionMatch.start, versionMatch.end); - return APKDetails( - version, - getApkUrlsFromUrls([ - 'https://www.whatsapp.com/android?v=$version&=thisIsaPlaceholder&a=realURLPrefetchedAtDownloadTime' - ]), - AppNames('Meta', 'WhatsApp')); - } else { - throw getObtainiumHttpError(res); - } + // This is a CDN link that is consistent per version + // But it has query params that change constantly + Uri apkUri = + Uri.parse(await apkUrlPrefetchModifier(standardUrl, standardUrl)); + var unusableApkUrl = '${apkUri.origin}/${apkUri.path}'; + // So we use the param-less URL is a pseudo-version to add the app and check for updates + // See #357 for why we can't scrape the version number directly + // But we re-fetch the URL again with its latest query params at the actual download time + String version = unusableApkUrl.hashCode.toString(); + return APKDetails(version, getApkUrlsFromUrls([unusableApkUrl]), + AppNames('Meta', 'WhatsApp')); } } diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index b4b732f..958f8e9 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -28,6 +28,7 @@ import 'package:obtainium/app_sources/steammobile.dart'; import 'package:obtainium/app_sources/telegramapp.dart'; import 'package:obtainium/app_sources/uptodown.dart'; import 'package:obtainium/app_sources/vlc.dart'; +import 'package:obtainium/app_sources/whatsapp.dart'; import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/mass_app_sources/githubstars.dart'; @@ -557,7 +558,7 @@ class SourceProvider { Mullvad(), Signal(), VLC(), - // WhatsApp(), // As of 2023-03-20 this is unusable as the version on the webpage is months out of date + WhatsApp(), // As of 2023-03-20 this is unusable as the version on the webpage is months out of date TelegramApp(), SteamMobile(), NeutronCode(), From 3536dcd775449ad97d9963e19a49e7c1cdb2750c Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 7 Oct 2023 13:31:02 -0400 Subject: [PATCH 525/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index d3343ea..76fb6c2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.23'; +const String currentVersion = '0.14.24'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index 5c82b0f..4b672df 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.14.23+215 # When changing this, update the tag in main() accordingly +version: 0.14.24+216 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 2a0b68d63764b37bf4c0eaa8323afe654f410aff Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 8 Oct 2023 17:30:08 -0400 Subject: [PATCH 526/600] Less notif spam, no check in aeroplane mode (#974) --- lib/custom_errors.dart | 18 +++++++++++++---- lib/providers/apps_provider.dart | 34 +++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/lib/custom_errors.dart b/lib/custom_errors.dart index 04e6104..657a82a 100644 --- a/lib/custom_errors.dart +++ b/lib/custom_errors.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:android_package_installer/android_package_installer.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -72,6 +74,9 @@ class MultiAppMultiError extends ObtainiumError { MultiAppMultiError() : super(tr('placeholder'), unexpected: true); add(String appId, dynamic error, {String? appName}) { + if (error is SocketException) { + error = error.message; + } rawErrors[appId] = error; var string = error.toString(); var tempIds = idsByErrorString.remove(string); @@ -83,12 +88,17 @@ class MultiAppMultiError extends ObtainiumError { } } - String errorString(String appId) => - '${appIdNames.containsKey(appId) ? '${appIdNames[appId]} ($appId)' : appId}: ${rawErrors[appId].toString()}'; + String errorString(String appId, {bool includeIdsWithNames = false}) => + '${appIdNames.containsKey(appId) ? '${appIdNames[appId]}${includeIdsWithNames ? ' ($appId)' : ''}' : appId}: ${rawErrors[appId].toString()}'; + + String errorsAppsString(String errString, List appIds, + {bool includeIdsWithNames = false}) => + '$errString [${list2FriendlyString(appIds.map((id) => appIdNames.containsKey(id) == true ? '${appIdNames[id]}${includeIdsWithNames ? ' ($id)' : ''}' : id).toList())}]'; @override - String toString() => - idsByErrorString.keys.map((e) => errorString(e)).join('\n\n'); + String toString() => idsByErrorString.entries + .map((e) => errorsAppsString(e.key, e.value)) + .join('\n\n'); } showError(dynamic e, BuildContext context) { diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 9acd085..330a605 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1375,6 +1375,30 @@ Future bgUpdateCheck(int taskId, Map? params) async { logs.add( 'BG ${installMode ? 'install' : 'update'} task $taskId: Started (${installMode ? toInstall.length : toCheck.length}).'); + var netResult = await (Connectivity().checkConnectivity()); + + if (netResult == ConnectivityResult.none) { + var networkBasedRetryInterval = 15; + var nextRegularCheck = appsProvider.settingsProvider.lastBGCheckTime + .add(Duration(minutes: appsProvider.settingsProvider.updateInterval)); + var potentialNetworkRetryCheck = + DateTime.now().add(Duration(minutes: networkBasedRetryInterval)); + var shouldRetry = potentialNetworkRetryCheck.isBefore(nextRegularCheck); + logs.add( + 'BG update task $taskId: No network. Will ${shouldRetry ? 'retry in $networkBasedRetryInterval minutes' : 'not retry'}.'); + AndroidAlarmManager.oneShot( + const Duration(minutes: 15), taskId + 1, bgUpdateCheck, + params: { + 'toCheck': toCheck + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + 'toInstall': toInstall + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + }); + return; + } + if (!installMode) { // If in update mode, we check for updates. // We divide the results into 4 groups: @@ -1391,7 +1415,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { List toNotify = []; List> toRetry = []; var retryAfterXSeconds = 0; - List toThrow = []; + MultiAppMultiError toThrow = MultiAppMultiError(); var networkRestricted = false; if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { var netResult = await (Connectivity().checkConnectivity()); @@ -1427,7 +1451,7 @@ Future bgUpdateCheck(int taskId, Map? params) async { retryAfterXSeconds = minRetryIntervalForThisApp; } } else { - toThrow.add(key); + toThrow.add(key, err, appName: errors?.appIdNames[key]); } }); } else { @@ -1455,10 +1479,10 @@ Future bgUpdateCheck(int taskId, Map? params) async { } // Send the error notifications - if (toThrow.isNotEmpty) { - for (var appId in toThrow) { + if (toThrow.rawErrors.isNotEmpty) { + for (var element in toThrow.idsByErrorString.entries) { notificationsProvider.notify(ErrorCheckingUpdatesNotification( - errors!.errorString(appId), + errors!.errorsAppsString(element.key, element.value), id: Random().nextInt(10000))); } } From 7453d19d27b4d4861bd66f2bed29c522af01d4bc Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 8 Oct 2023 17:32:41 -0400 Subject: [PATCH 527/600] Increment version, update packages --- lib/main.dart | 2 +- pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 76fb6c2..a9170e5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.24'; +const String currentVersion = '0.14.25'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index fe8eaa3..2b5884c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -46,10 +46,10 @@ packages: dependency: transitive description: name: archive - sha256: "06a96f1249f38a00435b3b0c9a3246d934d7dbc8183fc7c9e56989860edb99d4" + sha256: ca12e6c9ac022f33fd89128e7007fb5e97ab6e814d4fa05dd8d4f2db1e3c69cb url: "https://pub.dev" source: hosted - version: "3.4.4" + version: "3.4.5" args: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4b672df..2e43923 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.14.24+216 # When changing this, update the tag in main() accordingly +version: 0.14.25+217 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From f4a902ee474cc86d1a7a8883250d344dc384a8dc Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Mon, 9 Oct 2023 14:52:50 +0200 Subject: [PATCH 528/600] Update de.json added three missing lines and translated them, reverted translation of variables so log function can work again. --- assets/translations/de.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index bf8198f..a554cd6 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -242,9 +242,12 @@ "appsPossiblyUpdated": "App Aktualisierungen wurden versucht", "appsPossiblyUpdatedNotifDescription": "Benachrichtigt den Benutzer, dass Updates für eine oder mehrere Apps möglicherweise im Hintergrund durchgeführt wurden", "xWasPossiblyUpdatedToY": "{} wurde möglicherweise aktualisiert auf {}.", + "enableBackgroundUpdates": "Aktiviere Hintergrundaktualisierungen", "backgroundUpdateReqsExplanation": "Die Hintergrundaktualisierung ist möglicherweise nicht für alle Apps möglich.", "backgroundUpdateLimitsExplanation": "Der Erfolg einer Hintergrundinstallation kann nur festgestellt werden, wenn Obtainium geöffnet wird.", "verifyLatestTag": "Überprüfe das „latest“ Tag", + "intermediateLinkRegex": "Filter für einen \"Zwischen\"-Link, der zuerst besucht werden soll", + "intermediateLinkNotFound": "Zwischenlink nicht gefunden", "exemptFromBackgroundUpdates": "Ausschluss von Hintergrundaktualisierungen (falls aktiviert)", "bgUpdatesOnWiFiOnly": "Hintergrundaktualisierungen deaktivieren, wenn kein WLAN vorhanden ist", "autoSelectHighestVersionCode": "Automatisch höchste APK-Code-Version auswählen", @@ -297,8 +300,8 @@ "other": "{} Tage" }, "clearedNLogsBeforeXAfterY": { - "one": "{n} Log gelöscht (vorher = {vorher}, nachher = {nachher})", - "other": "{n} Logs gelöscht (vorher = {vorher}, nachher = {nachher})" + "one": "{n} Log gelöscht (vorher = {before}, nachher = {after})", + "other": "{n} Logs gelöscht (vorher = {before}, nachher = {after})" }, "xAndNMoreUpdatesAvailable": { "one": "{} und 1 weitere App haben Aktualisierungen.", From 95f19208adac3c8297d0a1ab37debdae69fae7d5 Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Mon, 9 Oct 2023 14:54:24 +0200 Subject: [PATCH 529/600] Update bs.json added three missing lines, no translation --- assets/translations/bs.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 5ddd49f..c28637b 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -242,9 +242,12 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "enableBackgroundUpdates": "Enable background updates", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", + "intermediateLinkNotFound": "Intermediate link not found", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", @@ -312,4 +315,4 @@ "one": "{} and 1 more app may have been updated.", "other": "{} and {} more apps may have been updated." } -} \ No newline at end of file +} From 63b76a249f86ddd6fff17683ef41a3a7f4a77e39 Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Mon, 9 Oct 2023 14:57:52 +0200 Subject: [PATCH 530/600] Update es.json added three missing lines, no translation --- assets/translations/es.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assets/translations/es.json b/assets/translations/es.json index c1231fe..b835405 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -242,9 +242,12 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "enableBackgroundUpdates": "Enable background updates", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", + "intermediateLinkNotFound": "Intermediate link not found", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", From c26649d5f2d1bbfbacb0d37fb0819a431efd3bdb Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Mon, 9 Oct 2023 14:58:42 +0200 Subject: [PATCH 531/600] Update fa.json added three missing lines, no translation --- assets/translations/fa.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assets/translations/fa.json b/assets/translations/fa.json index c35bc60..e2c51a3 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -242,9 +242,12 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "enableBackgroundUpdates": "Enable background updates", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", + "intermediateLinkNotFound": "Intermediate link not found", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", From 00854abd1a006efccab755106f5548328401635f Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Mon, 9 Oct 2023 14:59:14 +0200 Subject: [PATCH 532/600] Update fr.json added three missing lines, no translation --- assets/translations/fr.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 7e0d414..c057e28 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -242,9 +242,12 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "enableBackgroundUpdates": "Enable background updates", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", + "intermediateLinkNotFound": "Intermediate link not found", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", From a7a26037aef9d56124792b1baef9ef3b51645b21 Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:02:51 +0200 Subject: [PATCH 533/600] Update hu.json added four missing lines, no translation --- assets/translations/hu.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 363d691..828bc7f 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -194,6 +194,7 @@ "categories": "Kategóriák", "category": "Kategória", "noCategory": "Nincs kategória", + "noCategories": "No Categories", "deleteCategoryQuestion": "Törli a kategóriát?", "categoryDeleteWarning": "A(z) {} összes app kategorizálatlan állapotba kerül.", "addCategory": "Új kategória", @@ -241,9 +242,12 @@ "appsPossiblyUpdated": "App frissítési kísérlet", "appsPossiblyUpdatedNotifDescription": "Értesíti a felhasználót, hogy egy vagy több alkalmazás frissítése lehetséges a háttérben", "xWasPossiblyUpdatedToY": "{} frissítve lehet erre {}.", + "enableBackgroundUpdates": "Enable background updates", "backgroundUpdateReqsExplanation": "Előfordulhat, hogy nem minden appnál lehetséges a háttérbeli frissítés.", "backgroundUpdateLimitsExplanation": "A háttérben történő telepítés sikeressége csak az Obtainium megnyitásakor állapítható meg.", "verifyLatestTag": "Ellenőrizze a „legújabb” címkét", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", + "intermediateLinkNotFound": "Intermediate link not found", "exemptFromBackgroundUpdates": "Mentes a háttérben történő frissítések alól (ha engedélyezett)", "bgUpdatesOnWiFiOnly": "Tiltsa le a háttérben frissítéseket, ha nincs Wi-Fi-n", "autoSelectHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", From ce6e51128d2fef563728391e2725341ac7139c72 Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:04:45 +0200 Subject: [PATCH 534/600] Update it.json added three missing lines, no translation --- assets/translations/it.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assets/translations/it.json b/assets/translations/it.json index 3f3fc40..8818644 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -242,9 +242,12 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "enableBackgroundUpdates": "Enable background updates", "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", "verifyLatestTag": "Verify the 'latest' tag", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", + "intermediateLinkNotFound": "Intermediate link not found", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", From ba59693d9082fc4f5a661d95297275fe4a9d3567 Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:17:52 +0200 Subject: [PATCH 535/600] Update pl.json Changed order of the lines so it's the same order for every language and better to compare --- assets/translations/pl.json | 39 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 0cf28fd..8519fa2 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -1,14 +1,4 @@ { - "noDescription": "Brak opisu", - "no": "Nie", - "okay": "Okej", - "appId": "ID aplikacji", - "bgUpdateGotErrorRetryInMinutes": { - "one": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minutę", - "few": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minuty", - "many": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minut", - "other": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minuty" - }, "invalidURLForSource": "Nieprawidłowy adres URL aplikacji {}", "noReleaseFound": "Nie można znaleźć odpowiedniego wydania", "noVersionFound": "Nie można określić wersji wydania", @@ -26,6 +16,7 @@ "fallbackToOlderReleases": "Powracaj do starszych wersji", "filterReleaseTitlesByRegEx": "Filtruj tytuły wydań wg. wyrażeń regularnych", "invalidRegEx": "Nieprawidłowe wyrażenie regularne", + "noDescription": "Brak opisu", "cancel": "Anuluj", "continue": "Kontynuuj", "requiredInBrackets": "(Wymagane)", @@ -75,6 +66,7 @@ "installUpdateApps": "Instaluj/aktualizuj aplikacje", "installUpdateSelectedApps": "Zainstaluj/zaktualizuj wybrane aplikacje", "markXSelectedAppsAsUpdated": "Oznaczyć {} wybranych aplikacji jako zaktualizowane?", + "no": "Nie", "yes": "Tak", "markSelectedAppsUpdated": "Oznacz wybrane aplikacje jako zaktualizowane", "pinToTop": "Przypnij", @@ -111,7 +103,8 @@ "importErrors": "Błędy importowania", "importedXOfYApps": "Zaimportowano {} z {} aplikacji.", "followingURLsHadErrors": "Następujące adresy URL zawierały błędy:", - "selectURL": "Wybierz adres URL", + "okay": "Okej", + "selectURL": "Wybierz adres URL", "selectURLs": "Wybierz adresy URL", "pick": "Wybierz", "theme": "Motyw", @@ -179,6 +172,7 @@ "yesMarkUpdated": "Tak, oznacz jako zaktualizowane", "fdroid": "Oficjalny F-Droid", "appIdOrName": "ID aplikacji lub nazwa", + "appId": "ID aplikacji", "appWithIdOrNameNotFound": "Nie znaleziono aplikacji o tym identyfikatorze lub nazwie", "reposHaveMultipleApps": "Repozytoria mogą zawierać wiele aplikacji", "fdroidThirdPartyRepo": "Zewnętrzne repo F-Droid", @@ -248,12 +242,15 @@ "appsPossiblyUpdated": "Informuj o próbach aktualizacji", "appsPossiblyUpdatedNotifDescription": "Powiadamiaj o potencjalnym zastosowaniu w tle aktualizacji jednej lub większej ilości aplikacji", "xWasPossiblyUpdatedToY": "{} być może zaktualizowano do {}.", - "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", + "enableBackgroundUpdates": "Włącz aktualizacje w tle", + "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", "backgroundUpdateLimitsExplanation": "Powodzenie instalacji w tle można określić dopiero po otwarciu Obtainium.", "verifyLatestTag": "Zweryfikuj najnowszy tag", - "exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)", + "intermediateLinkRegex": "Filtr linków \"pośrednich\" do odwiedzenia w pierwszej kolejności", + "intermediateLinkNotFound": "Nie znaleziono linku pośredniego" + "exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)", "bgUpdatesOnWiFiOnly": "Wyłącz aktualizacje w tle, gdy nie ma połączenia z Wi-Fi", - "autoSelectHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", + "autoSelectHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", "versionExtractionRegEx": "Wyrażenie regularne wyodrębniające wersję", "matchGroupToUse": "Dopasuj grupę do użycia", "highlightTouchTargets": "Wyróżnij mniej oczywiste elementy dotykowe", @@ -276,7 +273,13 @@ "one": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minutę", "few": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minuty", "many": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minut", - "other": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minuty" + "other": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minuty" + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minutę", + "few": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minuty", + "many": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minut", + "other": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minuty" }, "bgCheckFoundUpdatesWillNotifyIfNeeded": { "one": "W tle znaleziono {} aktualizację - w razie potrzeby użytkownik zostanie o tym powiadomiony", @@ -337,8 +340,4 @@ "few": "{} i {} inne apki mogły zostać zaktualizowane.", "many": "{} i {} innych apek mogło zostać zaktualizowanych.", "other": "{} i {} inne apki mogły zostać zaktualizowane." - }, - "enableBackgroundUpdates": "Włącz aktualizacje w tle", - "intermediateLinkRegex": "Filtr linków \"pośrednich\" do odwiedzenia w pierwszej kolejności", - "intermediateLinkNotFound": "Nie znaleziono linku pośredniego" -} \ No newline at end of file + } From 6955191fddfb3441d1300a8df97519f1d4eec5d7 Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:22:32 +0200 Subject: [PATCH 536/600] Update pl.json fixed line breaks --- assets/translations/pl.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 8519fa2..08bf2c2 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -16,7 +16,7 @@ "fallbackToOlderReleases": "Powracaj do starszych wersji", "filterReleaseTitlesByRegEx": "Filtruj tytuły wydań wg. wyrażeń regularnych", "invalidRegEx": "Nieprawidłowe wyrażenie regularne", - "noDescription": "Brak opisu", + "noDescription": "Brak opisu", "cancel": "Anuluj", "continue": "Kontynuuj", "requiredInBrackets": "(Wymagane)", @@ -66,7 +66,7 @@ "installUpdateApps": "Instaluj/aktualizuj aplikacje", "installUpdateSelectedApps": "Zainstaluj/zaktualizuj wybrane aplikacje", "markXSelectedAppsAsUpdated": "Oznaczyć {} wybranych aplikacji jako zaktualizowane?", - "no": "Nie", + "no": "Nie", "yes": "Tak", "markSelectedAppsUpdated": "Oznacz wybrane aplikacje jako zaktualizowane", "pinToTop": "Przypnij", @@ -104,7 +104,7 @@ "importedXOfYApps": "Zaimportowano {} z {} aplikacji.", "followingURLsHadErrors": "Następujące adresy URL zawierały błędy:", "okay": "Okej", - "selectURL": "Wybierz adres URL", + "selectURL": "Wybierz adres URL", "selectURLs": "Wybierz adresy URL", "pick": "Wybierz", "theme": "Motyw", @@ -172,7 +172,7 @@ "yesMarkUpdated": "Tak, oznacz jako zaktualizowane", "fdroid": "Oficjalny F-Droid", "appIdOrName": "ID aplikacji lub nazwa", - "appId": "ID aplikacji", + "appId": "ID aplikacji", "appWithIdOrNameNotFound": "Nie znaleziono aplikacji o tym identyfikatorze lub nazwie", "reposHaveMultipleApps": "Repozytoria mogą zawierać wiele aplikacji", "fdroidThirdPartyRepo": "Zewnętrzne repo F-Droid", @@ -243,12 +243,12 @@ "appsPossiblyUpdatedNotifDescription": "Powiadamiaj o potencjalnym zastosowaniu w tle aktualizacji jednej lub większej ilości aplikacji", "xWasPossiblyUpdatedToY": "{} być może zaktualizowano do {}.", "enableBackgroundUpdates": "Włącz aktualizacje w tle", - "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", + "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", "backgroundUpdateLimitsExplanation": "Powodzenie instalacji w tle można określić dopiero po otwarciu Obtainium.", "verifyLatestTag": "Zweryfikuj najnowszy tag", "intermediateLinkRegex": "Filtr linków \"pośrednich\" do odwiedzenia w pierwszej kolejności", "intermediateLinkNotFound": "Nie znaleziono linku pośredniego" - "exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)", + "exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)", "bgUpdatesOnWiFiOnly": "Wyłącz aktualizacje w tle, gdy nie ma połączenia z Wi-Fi", "autoSelectHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", "versionExtractionRegEx": "Wyrażenie regularne wyodrębniające wersję", From fc7408a8f8aabb251cb7640b2cd6d9029d06d39d Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Mon, 9 Oct 2023 20:11:12 +0200 Subject: [PATCH 537/600] locale(pl): Update Polish translations --- assets/translations/pl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 0cf28fd..74b159e 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -245,7 +245,7 @@ "sortByFileNamesNotLinks": "Sortuj wg nazw plików zamiast pełnych linków", "filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego", "customLinkFilterRegex": "Filtruj linki APK według wyrażenia regularnego (domyślnie \".apk$\")", - "appsPossiblyUpdated": "Informuj o próbach aktualizacji", + "appsPossiblyUpdated": "Próbowano zaktualizować aplikację", "appsPossiblyUpdatedNotifDescription": "Powiadamiaj o potencjalnym zastosowaniu w tle aktualizacji jednej lub większej ilości aplikacji", "xWasPossiblyUpdatedToY": "{} być może zaktualizowano do {}.", "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", From 488049821e85bd73c2dfc555fe9fb5ace86f0141 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 11 Oct 2023 20:42:33 -0400 Subject: [PATCH 538/600] Switch back to serial BG installs (#984) --- lib/providers/apps_provider.dart | 198 ++++++++++++++----------------- 1 file changed, 91 insertions(+), 107 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 330a605..614d5a0 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1369,12 +1369,6 @@ Future bgUpdateCheck(int taskId, Map? params) async { (>>[])) ]; - bool installMode = toCheck.isEmpty && - toInstall.isNotEmpty; // Task is either in update mode or install mode - - logs.add( - 'BG ${installMode ? 'install' : 'update'} task $taskId: Started (${installMode ? toInstall.length : toCheck.length}).'); - var netResult = await (Connectivity().checkConnectivity()); if (netResult == ConnectivityResult.none) { @@ -1399,110 +1393,103 @@ Future bgUpdateCheck(int taskId, Map? params) async { return; } - if (!installMode) { - // If in update mode, we check for updates. - // We divide the results into 4 groups: - // - toNotify - Apps with updates that the user will be notified about (can't be silently installed) - // - toRetry - Apps with update check errors that will be retried in a while - // - toThrow - Apps with update check errors that the user will be notified about (no retry) - // - toInstall - Apps with updates that will be installed silently - // After grouping the updates, we take care of toNotify and toThrow first - // Then if toRetry is not empty, we schedule another update task to run in a while (toInstall is retained) - // If toRetry is empty, we take care of toInstall + var networkRestricted = false; + if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { + networkRestricted = (netResult != ConnectivityResult.wifi) && + (netResult != ConnectivityResult.ethernet); + } - // Init. vars. - List updates = []; - List toNotify = []; - List> toRetry = []; - var retryAfterXSeconds = 0; - MultiAppMultiError toThrow = MultiAppMultiError(); - var networkRestricted = false; - if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { - var netResult = await (Connectivity().checkConnectivity()); - networkRestricted = (netResult != ConnectivityResult.wifi) && - (netResult != ConnectivityResult.ethernet); + bool installMode = + toCheck.isEmpty; // Task is either in update mode or install mode + + // In install mode, grab all available silent updates unless explicitly told otherwise + if (installMode && toInstall.isEmpty && !networkRestricted) { + var temp = appsProvider.findExistingUpdates(installedOnly: true); + for (var i = 0; i < temp.length; i++) { + if (await appsProvider + .canInstallSilently(appsProvider.apps[temp[i]]!.app)) { + toInstall.add(MapEntry(temp[i], 0)); + } } - MultiAppMultiError? errors; - CheckingUpdatesNotification notif = - CheckingUpdatesNotification(plural('apps', toCheck.length)); + } + logs.add( + 'BG ${installMode ? 'install' : 'update'} task $taskId: Started (${installMode ? toInstall.length : toCheck.length}).'); + + if (!installMode) { + // If in update mode... + var didCompleteChecking = false; + CheckingUpdatesNotification? notif; + // Loop through all updates and check each + List toNotify = []; try { - // Check for updates - notificationsProvider.notify(notif, cancelExisting: true); - updates = await appsProvider.checkUpdates( - specificIds: toCheck.map((e) => e.key).toList()); - } catch (e) { - // If there were errors, group them into toRetry and toThrow - if (e is Map) { - updates = e['updates']; - errors = e['errors']; - errors!.rawErrors.forEach((key, err) { - logs.add( - 'BG update task $taskId: Got error on checking for $key \'${err.toString()}\'.'); - var toCheckApp = toCheck.where((element) => element.key == key).first; - if (toCheckApp.value < maxAttempts) { - toRetry.add(MapEntry(toCheckApp.key, toCheckApp.value + 1)); - var minRetryIntervalForThisApp = err is RateLimitError - ? (err.remainingMinutes * 60) - : e is ClientException - ? (15 * 60) - : pow(toCheckApp.value + 1, 2).toInt(); - if (minRetryIntervalForThisApp > retryAfterXSeconds) { - retryAfterXSeconds = minRetryIntervalForThisApp; + for (int i = 0; i < toCheck.length; i++) { + var appId = toCheck[i].key; + var attemptCount = toCheck[i].value + 1; + AppInMemory? app = appsProvider.apps[appId]; + if (app?.app.installedVersion != null) { + try { + notificationsProvider.notify( + notif = CheckingUpdatesNotification(app?.name ?? appId), + cancelExisting: true); + App? newApp = await appsProvider.checkUpdate(appId); + if (newApp != null) { + if (networkRestricted || + !(await appsProvider.canInstallSilently(app!.app))) { + toNotify.add(newApp); + } + } + if (i == (toCheck.length - 1)) { + didCompleteChecking = true; + } + } catch (e) { + // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue checking shortly + logs.add( + 'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.'); + if (attemptCount < maxAttempts) { + var remainingSeconds = e is RateLimitError + ? (i == 0 ? (e.remainingMinutes * 60) : (5 * 60)) + : e is ClientException + ? (15 * 60) + : pow(attemptCount, 2).toInt(); + logs.add( + 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); + var remainingToCheck = moveStrToEndMapEntryWithCount( + toCheck.sublist(i), MapEntry(appId, attemptCount)); + AndroidAlarmManager.oneShot(Duration(seconds: remainingSeconds), + taskId + 1, bgUpdateCheck, + params: { + 'toCheck': remainingToCheck + .map( + (entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + 'toInstall': toInstall + .map( + (entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + }); + break; + } else { + // If the offender has reached its fail limit, notify the user and remove it from the list (task can continue) + toCheck.removeAt(i); + i--; + notificationsProvider + .notify(ErrorCheckingUpdatesNotification(e.toString())); + } + } finally { + if (notif != null) { + notificationsProvider.cancel(notif.id); } - } else { - toThrow.add(key, err, appName: errors?.appIdNames[key]); } - }); - } else { - // We don't expect to ever get here in any situation so no need to catch - logs.add('Fatal error in BG update task: ${e.toString()}'); - rethrow; + } } } finally { - notificationsProvider.cancel(notif.id); - } - - // Group the updates into toNotify and toInstall - for (var i = 0; i < updates.length; i++) { - if (networkRestricted || - !(await appsProvider.canInstallSilently(updates[i]))) { - toNotify.add(updates[i]); - } else { - toInstall.add(MapEntry(updates[i].id, 0)); + if (toNotify.isNotEmpty) { + notificationsProvider.notify(UpdateNotification(toNotify)); } } - - // Send the update notification - if (toNotify.isNotEmpty) { - notificationsProvider.notify(UpdateNotification(toNotify)); - } - - // Send the error notifications - if (toThrow.rawErrors.isNotEmpty) { - for (var element in toThrow.idsByErrorString.entries) { - notificationsProvider.notify(ErrorCheckingUpdatesNotification( - errors!.errorsAppsString(element.key, element.value), - id: Random().nextInt(10000))); - } - } - - // if there are update checks to retry, schedule a retry task - if (toRetry.isNotEmpty) { - logs.add( - 'BG update task $taskId: Will retry in $retryAfterXSeconds seconds.'); - AndroidAlarmManager.oneShot( - Duration(seconds: retryAfterXSeconds), taskId + 1, bgUpdateCheck, - params: { - 'toCheck': toRetry - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - 'toInstall': toInstall - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - }); - } else if (toInstall.isNotEmpty) { - // If there are no more update checks, schedule an install task + // If you're done checking and found some silently installable updates, schedule another task which will run in install mode + if (didCompleteChecking) { logs.add( 'BG update task $taskId: Done. Scheduling install task to run immediately.'); AndroidAlarmManager.oneShot( @@ -1513,14 +1500,11 @@ Future bgUpdateCheck(int taskId, Map? params) async { .map((entry) => {'key': entry.key, 'value': entry.value}) .toList() }); - } else { - logs.add('BG install task $taskId: Done.'); + } else if (didCompleteChecking) { + logs.add('BG update task $taskId: Done.'); } - } - - if (installMode) { - // If in install mode, we install silent updates. - + } else { + // If in install mode... var didCompleteInstalling = false; var tempObtArr = toInstall.where((element) => element.key == obtainiumId); if (tempObtArr.isNotEmpty) { From 81ea67afa85d0d46602242f1c7c25f4c96997cdf Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 11 Oct 2023 20:43:27 -0400 Subject: [PATCH 539/600] Remove unnecessary log --- lib/providers/apps_provider.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 614d5a0..a46a175 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1136,7 +1136,6 @@ class AppsProvider with ChangeNotifier { return null; } if (exportDir == null) { - logs.add('Skipping auto-export as dir is not set.'); return null; } var files = await saf From c908a710de4791ad19dd9943015e6645b578728b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 11 Oct 2023 20:55:09 -0400 Subject: [PATCH 540/600] Fix UpToDown again (#982) --- lib/app_sources/uptodown.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app_sources/uptodown.dart b/lib/app_sources/uptodown.dart index 86b640c..c764b7c 100644 --- a/lib/app_sources/uptodown.dart +++ b/lib/app_sources/uptodown.dart @@ -35,7 +35,7 @@ class Uptodown extends AppSource { var html = parse(res.body); String? version = html.querySelector('div.version')?.innerHtml; String? apkUrl = - html.querySelector('#detail-download-button')?.attributes['data-url']; + '${standardUrl.split('/').reversed.toList().sublist(1).reversed.join('/')}/post-download'; String? name = html.querySelector('#detail-app-name')?.innerHtml.trim(); String? author = html.querySelector('#author-link')?.innerHtml.trim(); var detailElements = html.querySelectorAll('#technical-information td'); From 89e44d581f0a93da14bfc1ffb98b623227abcecd Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 11 Oct 2023 20:56:26 -0400 Subject: [PATCH 541/600] Update packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 28 ++++++++++++++-------------- pubspec.yaml | 4 ++-- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a9170e5..bb0ac3a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.25'; +const String currentVersion = '0.14.26'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 2b5884c..a51aef1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: "direct main" description: name: android_alarm_manager_plus - sha256: c20d91a9096596f66274bf8172321c278f9cba8091638f80205fe66d31587fa5 + sha256: "82fb28c867c4b3dd7e9157728e46426b8916362f977dbba46b949210f00099f4" url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.0.3" android_intent_plus: dependency: "direct main" description: name: android_intent_plus - sha256: f72ae20bb37108694f442e7ae6acbd28b453ca62ce86842f6787b784355abfe6 + sha256: e1c62bb41c90e15083b7fb84dc327fe90396cc9c1445b55ff1082144fabfb4d9 url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.0.3" android_package_installer: dependency: "direct main" description: @@ -46,10 +46,10 @@ packages: dependency: transitive description: name: archive - sha256: ca12e6c9ac022f33fd89128e7007fb5e97ab6e814d4fa05dd8d4f2db1e3c69cb + sha256: "7e0d52067d05f2e0324268097ba723b71cb41ac8a6a2b24d1edf9c536b987b03" url: "https://pub.dev" source: hosted - version: "3.4.5" + version: "3.4.6" args: dependency: transitive description: @@ -118,10 +118,10 @@ packages: dependency: "direct main" description: name: connectivity_plus - sha256: "77a180d6938f78ca7d2382d2240eb626c0f6a735d0bfdce227d8ffb80f95c48b" + sha256: "94d51c6f1299133a2baa4c5c3d2c11ec7d7fb4768dee5c52a56f7d7522fcf70e" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "5.0.0" connectivity_plus_platform_interface: dependency: transitive description: @@ -562,10 +562,10 @@ packages: dependency: transitive description: name: permission_handler_platform_interface - sha256: f2343e9fa9c22ae4fd92d4732755bfe452214e7189afcc097380950cf567b4b2 + sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4" url: "https://pub.dev" source: hosted - version: "3.11.5" + version: "3.12.0" permission_handler_windows: dependency: transitive description: @@ -586,10 +586,10 @@ packages: dependency: transitive description: name: platform - sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 + sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" plugin_platform_interface: dependency: transitive description: @@ -634,10 +634,10 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: b7f41bad7e521d205998772545de63ff4e6c97714775902c199353f8bf1511ac + sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" shared_preferences_android: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2e43923..a860b55 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.14.25+217 # When changing this, update the tag in main() accordingly +version: 0.14.26+218 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' @@ -64,7 +64,7 @@ dependencies: flutter_markdown: ^0.6.14 flutter_archive: ^5.0.0 hsluv: ^1.1.3 - connectivity_plus: ^4.0.2 + connectivity_plus: ^5.0.0 shared_storage: ^0.8.0 dev_dependencies: From d800d3ba4169cda2526cda0268cf462c863da872 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 11 Oct 2023 21:03:23 -0400 Subject: [PATCH 542/600] Fix issues with last conflit resolution commit --- lib/providers/apps_provider.dart | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index cdc1052..a46a175 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1415,30 +1415,6 @@ Future bgUpdateCheck(int taskId, Map? params) async { logs.add( 'BG ${installMode ? 'install' : 'update'} task $taskId: Started (${installMode ? toInstall.length : toCheck.length}).'); - var netResult = await (Connectivity().checkConnectivity()); - - if (netResult == ConnectivityResult.none) { - var networkBasedRetryInterval = 15; - var nextRegularCheck = appsProvider.settingsProvider.lastBGCheckTime - .add(Duration(minutes: appsProvider.settingsProvider.updateInterval)); - var potentialNetworkRetryCheck = - DateTime.now().add(Duration(minutes: networkBasedRetryInterval)); - var shouldRetry = potentialNetworkRetryCheck.isBefore(nextRegularCheck); - logs.add( - 'BG update task $taskId: No network. Will ${shouldRetry ? 'retry in $networkBasedRetryInterval minutes' : 'not retry'}.'); - AndroidAlarmManager.oneShot( - const Duration(minutes: 15), taskId + 1, bgUpdateCheck, - params: { - 'toCheck': toCheck - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - 'toInstall': toInstall - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - }); - return; - } - if (!installMode) { // If in update mode... var didCompleteChecking = false; @@ -1503,8 +1479,6 @@ Future bgUpdateCheck(int taskId, Map? params) async { if (notif != null) { notificationsProvider.cancel(notif.id); } - } else { - toThrow.add(key, err, appName: errors?.appIdNames[key]); } } } From 910ed265256902a4e8c8a2e5335486886a2a765b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 12 Oct 2023 18:31:31 -0400 Subject: [PATCH 543/600] Fixed issues in some translation files --- assets/translations/hu.json | 1 - assets/translations/pl.json | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 828bc7f..c0cd3b3 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -242,7 +242,6 @@ "appsPossiblyUpdated": "App frissítési kísérlet", "appsPossiblyUpdatedNotifDescription": "Értesíti a felhasználót, hogy egy vagy több alkalmazás frissítése lehetséges a háttérben", "xWasPossiblyUpdatedToY": "{} frissítve lehet erre {}.", - "enableBackgroundUpdates": "Enable background updates", "backgroundUpdateReqsExplanation": "Előfordulhat, hogy nem minden appnál lehetséges a háttérbeli frissítés.", "backgroundUpdateLimitsExplanation": "A háttérben történő telepítés sikeressége csak az Obtainium megnyitásakor állapítható meg.", "verifyLatestTag": "Ellenőrizze a „legújabb” címkét", diff --git a/assets/translations/pl.json b/assets/translations/pl.json index c0cbb3a..21db5f1 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -247,7 +247,7 @@ "backgroundUpdateLimitsExplanation": "Powodzenie instalacji w tle można określić dopiero po otwarciu Obtainium.", "verifyLatestTag": "Zweryfikuj najnowszy tag", "intermediateLinkRegex": "Filtr linków \"pośrednich\" do odwiedzenia w pierwszej kolejności", - "intermediateLinkNotFound": "Nie znaleziono linku pośredniego" + "intermediateLinkNotFound": "Nie znaleziono linku pośredniego", "exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)", "bgUpdatesOnWiFiOnly": "Wyłącz aktualizacje w tle, gdy nie ma połączenia z Wi-Fi", "autoSelectHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", @@ -341,3 +341,4 @@ "many": "{} i {} innych apek mogło zostać zaktualizowanych.", "other": "{} i {} inne apki mogły zostać zaktualizowane." } +} \ No newline at end of file From 7ff6916e5fa41896e193408541fadc5d1994e3af Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 12 Oct 2023 18:57:47 -0400 Subject: [PATCH 544/600] Better relative link resolution (#989) --- lib/app_sources/html.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 4cb9b26..ee1593a 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -22,7 +22,7 @@ String ensureAbsoluteUrl(String ambiguousUrl, Uri referenceAbsoluteUrl) { } else if (ambiguousUrl.split('/').where((e) => e.isNotEmpty).length == 1) { return '${referenceAbsoluteUrl.origin}/${currPathSegments.join('/')}/$ambiguousUrl'; } else { - return '${referenceAbsoluteUrl.origin}/${currPathSegments.sublist(0, currPathSegments.length - 1).join('/')}/$ambiguousUrl'; + return '${referenceAbsoluteUrl.origin}/${currPathSegments.sublist(0, currPathSegments.length - (currPathSegments.last.contains('.') ? 1 : 0)).join('/')}/$ambiguousUrl'; } } From 723f7e63e977b280336db5dc50a480c37773b56b Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 12 Oct 2023 19:06:59 -0400 Subject: [PATCH 545/600] Add whole-page version extraction for HTML (#989) --- assets/translations/bs.json | 1 + assets/translations/cs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 3 ++- assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/pt.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/html.dart | 9 ++++++++- 15 files changed, 23 insertions(+), 2 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index c28637b..56191e8 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -263,6 +263,7 @@ "debugMenu": "Debug Menu", "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index 0aceed9..b8c9e9a 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -263,6 +263,7 @@ "debugMenu": "Debug Menu", "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/de.json b/assets/translations/de.json index a554cd6..124e759 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -263,6 +263,7 @@ "debugMenu": "Debug Menü", "bgTaskStarted": "Hintergrundaufgabe gestartet – Logs prüfen.", "runBgCheckNow": "Hintergrundaktualisierungsprüfung jetzt durchführen", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index a283052..d790e89 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -252,7 +252,7 @@ "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", + "matchGroupToUse": "Match Group to Use for Version Extraction Regex", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", @@ -263,6 +263,7 @@ "debugMenu": "Debug Menu", "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index b835405..df72937 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -263,6 +263,7 @@ "debugMenu": "Debug Menu", "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index e2c51a3..2f78a02 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -263,6 +263,7 @@ "debugMenu": "Debug Menu", "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index c057e28..43bf149 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -263,6 +263,7 @@ "debugMenu": "Debug Menu", "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index c0cd3b3..5402c95 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -263,6 +263,7 @@ "bgTaskStarted": "A háttérfeladat elindult – ellenőrizze a naplókat.", "enableBackgroundUpdates": "Frissítések a háttérben", "runBgCheckNow": "Futtassa a Háttérben frissítés ellenőrzését most", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "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 8818644..62a5911 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -263,6 +263,7 @@ "debugMenu": "Debug Menu", "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 4f6c398..55d9a4d 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -263,6 +263,7 @@ "debugMenu": "Debug Menu", "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 21db5f1..ef4d950 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -263,6 +263,7 @@ "debugMenu": "Menu debugowania", "bgTaskStarted": "Uruchomiono zadanie w tle - sprawdź logi.", "runBgCheckNow": "Wymuś sprawdzenie aktualizacji w tle", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index 1271fc5..d30faea 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -263,6 +263,7 @@ "debugMenu": "Menu Debug", "bgTaskStarted": "Tarefa em segundo plano iniciada - verifique os logs.", "runBgCheckNow": "Execute a verificação de atualização em segundo plano agora", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 8ea5c0f..c725b05 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -263,6 +263,7 @@ "debugMenu": "Меню Отладки", "bgTaskStarted": "Фоновая задача начата - проверьте журналы.", "runBgCheckNow": "Запустить проверку фонового обновления сейчас", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 69954f9..615eb90 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -263,6 +263,7 @@ "debugMenu": "调试选项", "bgTaskStarted": "后台任务已启动 - 详见日志", "runBgCheckNow": "立即进行后台更新检查", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index ee1593a..91911e7 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -117,6 +117,8 @@ class HTML extends AppSource { label: tr('versionExtractionRegEx'), required: false, additionalValidators: [(value) => regExValidator(value)]), + ], + [ GeneratedFormTextField('matchGroupToUse', label: tr('matchGroupToUse'), required: false, @@ -131,6 +133,10 @@ class HTML extends AppSource { return intValidator(value); } ]) + ], + [ + GeneratedFormSwitch('versionExtractWholePage', + label: tr('versionExtractWholePage')) ] ]; overrideVersionDetectionFormDefault('noVersionDetection', @@ -212,7 +218,8 @@ class HTML extends AppSource { var versionExtractionRegEx = additionalSettings['versionExtractionRegEx'] as String?; if (versionExtractionRegEx?.isNotEmpty == true) { - var match = RegExp(versionExtractionRegEx!).allMatches(rel); + var match = RegExp(versionExtractionRegEx!).allMatches( + res.body.split('\r\n').join('\n').split('\n').join('\\n')); if (match.isEmpty) { throw NoVersionError(); } From 503a01675ecc3420945f40c0b540a9234a666908 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 12 Oct 2023 19:10:02 -0400 Subject: [PATCH 546/600] Clearer wording (#991) --- assets/translations/bs.json | 1 + assets/translations/cs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/pt.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/pages/apps.dart | 2 +- 15 files changed, 15 insertions(+), 1 deletion(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 56191e8..7aa21c2 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index b8c9e9a..d20bdfb 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 124e759..4e27572 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Hintergrundaufgabe gestartet – Logs prüfen.", "runBgCheckNow": "Hintergrundaktualisierungsprüfung jetzt durchführen", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index d790e89..7f9316b 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index df72937..74bab70 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 2f78a02..8787732 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 43bf149..dce0ea8 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 5402c95..f942af4 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -264,6 +264,7 @@ "enableBackgroundUpdates": "Frissítések a háttérben", "runBgCheckNow": "Futtassa a Háttérben frissítés ellenőrzését most", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "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 62a5911..9c97af4 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 55d9a4d..eaa6a40 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index ef4d950..6d09cb6 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Uruchomiono zadanie w tle - sprawdź logi.", "runBgCheckNow": "Wymuś sprawdzenie aktualizacji w tle", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index d30faea..fd00a8f 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Tarefa em segundo plano iniciada - verifique os logs.", "runBgCheckNow": "Execute a verificação de atualização em segundo plano agora", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index c725b05..c67269b 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -264,6 +264,7 @@ "bgTaskStarted": "Фоновая задача начата - проверьте журналы.", "runBgCheckNow": "Запустить проверку фонового обновления сейчас", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 615eb90..55fcb0b 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -264,6 +264,7 @@ "bgTaskStarted": "后台任务已启动 - 详见日志", "runBgCheckNow": "立即进行后台更新检查", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index fe98aa9..49feff6 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -566,7 +566,7 @@ class AppsPageState extends State { .toInt() .toString() ]) - : tr('pleaseWait'), + : tr('installing'), textAlign: (listedApps[index].downloadProgress! >= 0) ? TextAlign.start : TextAlign.end, From e613a494ffc52d46aac1532669efa3326d05e0d2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 12 Oct 2023 19:24:23 -0400 Subject: [PATCH 547/600] Better error for some incompatible APK cases (#981) --- lib/providers/apps_provider.dart | 36 ++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index a46a175..588ca1b 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -263,25 +263,29 @@ class AppsProvider with ChangeNotifier { return downloadedFile; } - Future handleAPKIDChange(App app, PackageInfo newInfo, + Future handleAPKIDChange(App app, PackageInfo? newInfo, File downloadedFile, String downloadUrl) async { // If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed // The former case should be handled (give the App its real ID), the latter is a security issue - if (app.id != newInfo.packageName) { - var isTempId = SourceProvider().isTempId(app); - if (apps[app.id] != null && !isTempId && !app.allowIdChange) { - throw IDChangedError(newInfo.packageName!); - } - var idChangeWasAllowed = app.allowIdChange; - app.allowIdChange = false; - var originalAppId = app.id; - app.id = newInfo.packageName!; - downloadedFile = downloadedFile.renameSync( - '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.${downloadedFile.path.split('.').last}'); - if (apps[originalAppId] != null) { - await removeApps([originalAppId]); - await saveApps([app], onlyIfExists: !isTempId && !idChangeWasAllowed); + var isTempId = SourceProvider().isTempId(app); + if (newInfo != null) { + if (app.id != newInfo.packageName) { + if (apps[app.id] != null && !isTempId && !app.allowIdChange) { + throw IDChangedError(newInfo.packageName!); + } + var idChangeWasAllowed = app.allowIdChange; + app.allowIdChange = false; + var originalAppId = app.id; + app.id = newInfo.packageName!; + downloadedFile = downloadedFile.renameSync( + '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.${downloadedFile.path.split('.').last}'); + if (apps[originalAppId] != null) { + await removeApps([originalAppId]); + await saveApps([app], onlyIfExists: !isTempId && !idChangeWasAllowed); + } } + } else if (isTempId) { + throw ObtainiumError('Could not get ID from APK'); } return downloadedFile; } @@ -344,7 +348,7 @@ class AppsProvider with ChangeNotifier { await pm.getPackageArchiveInfo(archiveFilePath: apks.first.path); } downloadedFile = - await handleAPKIDChange(app, newInfo!, downloadedFile, downloadUrl); + await handleAPKIDChange(app, newInfo, downloadedFile, downloadUrl); // Delete older versions of the file if any for (var file in downloadedFile.parent.listSync()) { var fn = file.path.split('/').last; From d06f20690dae3aa50f8121d146218400bd9fef2d Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 12 Oct 2023 19:33:38 -0400 Subject: [PATCH 548/600] Add 'skip update notification' per-app toggle (#980) --- assets/translations/bs.json | 1 + assets/translations/cs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/pt.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/providers/apps_provider.dart | 5 ++++- lib/providers/source_provider.dart | 4 ++++ 16 files changed, 22 insertions(+), 1 deletion(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 7aa21c2..2749d95 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index d20bdfb..2f6ea78 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 4e27572..fe2a44d 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Hintergrundaktualisierungsprüfung jetzt durchführen", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 7f9316b..3d68d57 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 74bab70..3003f67 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 8787732..7c24b96 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index dce0ea8..2eb17dc 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index f942af4..b94b173 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Futtassa a Háttérben frissítés ellenőrzését most", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "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 9c97af4..10ce3f3 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index eaa6a40..c1edaf5 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Run Background Update Check Now", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 6d09cb6..72278c3 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Wymuś sprawdzenie aktualizacji w tle", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index fd00a8f..31ff890 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Execute a verificação de atualização em segundo plano agora", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index c67269b..9628df3 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -265,6 +265,7 @@ "runBgCheckNow": "Запустить проверку фонового обновления сейчас", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 55fcb0b..609aff5 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -265,6 +265,7 @@ "runBgCheckNow": "立即进行后台更新检查", "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 588ca1b..db1087b 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1439,7 +1439,10 @@ Future bgUpdateCheck(int taskId, Map? params) async { if (newApp != null) { if (networkRestricted || !(await appsProvider.canInstallSilently(app!.app))) { - toNotify.add(newApp); + if (newApp.additionalSettings['skipUpdateNotifications'] != + true) { + toNotify.add(newApp); + } } } if (i == (toCheck.length - 1)) { diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 958f8e9..0ac9b91 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -442,6 +442,10 @@ abstract class AppSource { [ GeneratedFormSwitch('exemptFromBackgroundUpdates', label: tr('exemptFromBackgroundUpdates')) + ], + [ + GeneratedFormSwitch('skipUpdateNotifications', + label: tr('skipUpdateNotifications')) ] ]; From 2d7465cca62011d963c147b64e3212556a0b76c2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 12 Oct 2023 19:51:04 -0400 Subject: [PATCH 549/600] Separate notif channel title translations (#979) --- assets/translations/bs.json | 640 ++++++++++----------- assets/translations/cs.json | 47 +- assets/translations/de.json | 10 +- assets/translations/en.json | 10 +- assets/translations/es.json | 10 +- assets/translations/fa.json | 10 +- assets/translations/fr.json | 10 +- assets/translations/hu.json | 650 +++++++++++----------- assets/translations/it.json | 10 +- assets/translations/ja.json | 10 +- assets/translations/pl.json | 22 +- assets/translations/pt.json | 10 +- assets/translations/ru.json | 10 +- assets/translations/zh.json | 10 +- lib/providers/notifications_provider.dart | 32 +- 15 files changed, 807 insertions(+), 684 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 2749d95..acca651 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -1,321 +1,329 @@ { - "invalidURLForSource": "Nije važeći URL aplikacije {}", - "noReleaseFound": "Nije moguće pronaći odgovarajuće izdanje", - "noVersionFound": "Nije moguće odrediti verziju izdanja", - "urlMatchesNoSource": "URL se ne podudara s poznatim izvorom", - "cantInstallOlderVersion": "Nije moguće instalirati stariju verziju aplikacije", - "appIdMismatch": "ID preuzetog paketa se ne podudara s postojećim ID-om aplikacije", - "functionNotImplemented": "Ova klasa nije implementirala ovu funkciju", - "placeholder": "Rezervirano mjesto", - "someErrors": "Došlo je do nekih grešaka", - "unexpectedError": "Neočekivana greška", - "ok": "Dobro", - "and": "i", - "githubPATLabel": "GitHub token za lični pristup (eng. PAT, povećava ograničenje stope)", - "includePrereleases": "Uključi preliminarna izdanja", - "fallbackToOlderReleases": "Povratak na starija izdanja", - "filterReleaseTitlesByRegEx": "Filtrirajte naslove izdanja prema regularnom izrazu", - "invalidRegEx": "Nevažeći regularni izraz", - "noDescription": "Bez opisa", - "cancel": "Otkaži", - "continue": "Nastavite", - "requiredInBrackets": "(obavezno)", - "dropdownNoOptsError": "GREŠKA: PADAJUĆI MENI MORA IMATI NAJMANJE JEDNU OPCIJU", - "colour": "Boja", - "githubStarredRepos": "GitHub repo-i sa zvjezdicom", - "uname": "Korisničko ime", - "wrongArgNum": "Naveden je pogrešan broj argumenata", - "xIsTrackOnly": "{} je samo za praćenje", - "source": "Izvor", - "app": "Aplikacija. ", - "appsFromSourceAreTrackOnly": "Aplikacije iz ovog izvora su 'Samo za praćenje'.", - "youPickedTrackOnly": "Odabrali ste opciju „Samo za praćenje”.", - "trackOnlyAppDescription": "Aplikacija će se pratiti radi ažuriranja, ali Obtainium neće moći da je preuzme ili instalira.", - "cancelled": "Otkazano", - "appAlreadyAdded": "Aplikacija je već dodana", - "alreadyUpToDateQuestion": "Aplikacija je već ažurirana?", - "addApp": "Dodaj aplikaciju", - "appSourceURL": "Izvorni URL aplikacije", - "error": "Greška", - "add": "Dodaj", - "searchSomeSourcesLabel": "Pretraživanje (samo neki izvori)", - "search": "Pretraživanje", - "additionalOptsFor": "Dodatne opcije za {}", - "supportedSources": "Podržani izvori", - "trackOnlyInBrackets": "(Samo za praćenje)", - "searchableInBrackets": "(Može se pretraživati)", - "appsString": "Aplikacije", - "noApps": "Nema aplikacija", - "noAppsForFilter": "Nema aplikacija za filter", - "byX": "Autor {}", - "percentProgress": "Napredak: {}%", - "pleaseWait": "Molimo sačekajte", - "updateAvailable": "Ažuriranje dostupno", - "estimateInBracketsShort": "(Procjena)", - "notInstalled": "Nije instalirano", - "estimateInBrackets": "(Procjena)", - "selectAll": "Označi sve", - "deselectN": "Poništi odabir {}", - "xWillBeRemovedButRemainInstalled": "{} će biti uklonjen iz Obtainiuma, ali će ostati instaliran na uređaju.", - "removeSelectedAppsQuestion": "Želite li ukloniti odabrane aplikacije?", - "removeSelectedApps": "Ukloni odabrane aplikacije", - "updateX": "Nadogradi {}", - "installX": "Instaliraj {}", - "markXTrackOnlyAsUpdated": "Označi {}\n(samo za praćenje)\nkao ažurirano", - "changeX": "Promjena {}", - "installUpdateApps": "Instalirajte/ažurirajte aplikacije", - "installUpdateSelectedApps": "Instalirajte/ažurirajte odabrane aplikacije", - "markXSelectedAppsAsUpdated": "Označite {} odabrane aplikacije kao ažurirane?", - "no": "Ne", - "yes": "Da", - "markSelectedAppsUpdated": "Označi odabrane aplikacije kao ažurirane", - "pinToTop": "Prikvači na vrh", - "unpinFromTop": "Otkvači sa vrha", - "resetInstallStatusForSelectedAppsQuestion": "Resetujte status instalacije za odabrane aplikacije?", - "installStatusOfXWillBeResetExplanation": "Status instalacije bilo koje odabrane aplikacije će se resetovati.\n\nTo može pomoći kada je verzija aplikacije prikazana u Obtainiumu netačna zbog neuspjelih ažuriranja ili drugih problema.", - "shareSelectedAppURLs": "Podijeli odabrane URL-ove aplikacija", - "resetInstallStatus": "Resetujte status instalacije", - "more": "Više", - "removeOutdatedFilter": "Uklonite zastarjeli filter aplikacija", - "showOutdatedOnly": "Prikaži samo zastarjele aplikacije", - "filter": "Filtriranje", - "filterActive": "Filtriranje", - "filterApps": "Filtriraj aplikacije", - "appName": "Naziv aplikacije", - "author": "Autor", - "upToDateApps": "Ažurirane aplikacije", - "nonInstalledApps": "Neinstalirane aplikacije", - "importExport": "Uvoz/izvoz", - "settings": "Postavke", - "exportedTo": "Izvezeno u {}", - "obtainiumExport": "Obtainium Export", - "invalidInput": "Neispravan unos.", - "importedX": "Uvezeno {}", - "obtainiumImport": "Obtainium uvoz", - "importFromURLList": "Uvoz iz URL liste", - "searchQuery": "Pretraga za: ", - "appURLList": "Lista URL adresa aplikacija", - "line": "Linija", - "searchX": "Pretraživanje {}", - "noResults": "Nema rezultata", - "importX": "Uvoz {}", - "importedAppsIdDisclaimer": "Uvezene aplikacije mogu se pogrešno prikazati kao „Nije instalirano”.\nDa biste to riješili, ponovo ih instalirajte putem aplikacije Obtainium.\nTo ne bi trebalo uticati na podatke aplikacije.\n\nUtječe samo na URL i metode uvoza treće strane.", - "importErrors": "Uvezi greške", - "importedXOfYApps": "{} od {} aplikacija uvezeno.", - "followingURLsHadErrors": "Sljedeći URL-ovi su imali greške:", - "okay": "Dobro", - "selectURL": "Odaberite URL", - "selectURLs": "Odaberite URL-ove", - "pick": "Odaberi", - "theme": "Tema", - "dark": "Tamna", - "light": "Svijetla", - "followSystem": "Pratite sistem", + "invalidURLForSource": "Nije važeći URL aplikacije {}", + "noReleaseFound": "Nije moguće pronaći odgovarajuće izdanje", + "noVersionFound": "Nije moguće odrediti verziju izdanja", + "urlMatchesNoSource": "URL se ne podudara s poznatim izvorom", + "cantInstallOlderVersion": "Nije moguće instalirati stariju verziju aplikacije", + "appIdMismatch": "ID preuzetog paketa se ne podudara s postojećim ID-om aplikacije", + "functionNotImplemented": "Ova klasa nije implementirala ovu funkciju", + "placeholder": "Rezervirano mjesto", + "someErrors": "Došlo je do nekih grešaka", + "unexpectedError": "Neočekivana greška", + "ok": "Dobro", + "and": "i", + "githubPATLabel": "GitHub token za lični pristup (eng. PAT, povećava ograničenje stope)", + "includePrereleases": "Uključi preliminarna izdanja", + "fallbackToOlderReleases": "Povratak na starija izdanja", + "filterReleaseTitlesByRegEx": "Filtrirajte naslove izdanja prema regularnom izrazu", + "invalidRegEx": "Nevažeći regularni izraz", + "noDescription": "Bez opisa", + "cancel": "Otkaži", + "continue": "Nastavite", + "requiredInBrackets": "(obavezno)", + "dropdownNoOptsError": "GREŠKA: PADAJUĆI MENI MORA IMATI NAJMANJE JEDNU OPCIJU", + "colour": "Boja", + "githubStarredRepos": "GitHub repo-i sa zvjezdicom", + "uname": "Korisničko ime", + "wrongArgNum": "Naveden je pogrešan broj argumenata", + "xIsTrackOnly": "{} je samo za praćenje", + "source": "Izvor", + "app": "Aplikacija. ", + "appsFromSourceAreTrackOnly": "Aplikacije iz ovog izvora su 'Samo za praćenje'.", + "youPickedTrackOnly": "Odabrali ste opciju „Samo za praćenje”.", + "trackOnlyAppDescription": "Aplikacija će se pratiti radi ažuriranja, ali Obtainium neće moći da je preuzme ili instalira.", + "cancelled": "Otkazano", + "appAlreadyAdded": "Aplikacija je već dodana", + "alreadyUpToDateQuestion": "Aplikacija je već ažurirana?", + "addApp": "Dodaj aplikaciju", + "appSourceURL": "Izvorni URL aplikacije", + "error": "Greška", + "add": "Dodaj", + "searchSomeSourcesLabel": "Pretraživanje (samo neki izvori)", + "search": "Pretraživanje", + "additionalOptsFor": "Dodatne opcije za {}", + "supportedSources": "Podržani izvori", + "trackOnlyInBrackets": "(Samo za praćenje)", + "searchableInBrackets": "(Može se pretraživati)", + "appsString": "Aplikacije", + "noApps": "Nema aplikacija", + "noAppsForFilter": "Nema aplikacija za filter", + "byX": "Autor {}", + "percentProgress": "Napredak: {}%", + "pleaseWait": "Molimo sačekajte", + "updateAvailable": "Ažuriranje dostupno", + "estimateInBracketsShort": "(Procjena)", + "notInstalled": "Nije instalirano", + "estimateInBrackets": "(Procjena)", + "selectAll": "Označi sve", + "deselectN": "Poništi odabir {}", + "xWillBeRemovedButRemainInstalled": "{} će biti uklonjen iz Obtainiuma, ali će ostati instaliran na uređaju.", + "removeSelectedAppsQuestion": "Želite li ukloniti odabrane aplikacije?", + "removeSelectedApps": "Ukloni odabrane aplikacije", + "updateX": "Nadogradi {}", + "installX": "Instaliraj {}", + "markXTrackOnlyAsUpdated": "Označi {}\n(samo za praćenje)\nkao ažurirano", + "changeX": "Promjena {}", + "installUpdateApps": "Instalirajte/ažurirajte aplikacije", + "installUpdateSelectedApps": "Instalirajte/ažurirajte odabrane aplikacije", + "markXSelectedAppsAsUpdated": "Označite {} odabrane aplikacije kao ažurirane?", + "no": "Ne", + "yes": "Da", + "markSelectedAppsUpdated": "Označi odabrane aplikacije kao ažurirane", + "pinToTop": "Prikvači na vrh", + "unpinFromTop": "Otkvači sa vrha", + "resetInstallStatusForSelectedAppsQuestion": "Resetujte status instalacije za odabrane aplikacije?", + "installStatusOfXWillBeResetExplanation": "Status instalacije bilo koje odabrane aplikacije će se resetovati.\n\nTo može pomoći kada je verzija aplikacije prikazana u Obtainiumu netačna zbog neuspjelih ažuriranja ili drugih problema.", + "shareSelectedAppURLs": "Podijeli odabrane URL-ove aplikacija", + "resetInstallStatus": "Resetujte status instalacije", + "more": "Više", + "removeOutdatedFilter": "Uklonite zastarjeli filter aplikacija", + "showOutdatedOnly": "Prikaži samo zastarjele aplikacije", + "filter": "Filtriranje", + "filterActive": "Filtriranje", + "filterApps": "Filtriraj aplikacije", + "appName": "Naziv aplikacije", + "author": "Autor", + "upToDateApps": "Ažurirane aplikacije", + "nonInstalledApps": "Neinstalirane aplikacije", + "importExport": "Uvoz/izvoz", + "settings": "Postavke", + "exportedTo": "Izvezeno u {}", + "obtainiumExport": "Obtainium Export", + "invalidInput": "Neispravan unos.", + "importedX": "Uvezeno {}", + "obtainiumImport": "Obtainium uvoz", + "importFromURLList": "Uvoz iz URL liste", + "searchQuery": "Pretraga za: ", + "appURLList": "Lista URL adresa aplikacija", + "line": "Linija", + "searchX": "Pretraživanje {}", + "noResults": "Nema rezultata", + "importX": "Uvoz {}", + "importedAppsIdDisclaimer": "Uvezene aplikacije mogu se pogrešno prikazati kao „Nije instalirano”.\nDa biste to riješili, ponovo ih instalirajte putem aplikacije Obtainium.\nTo ne bi trebalo uticati na podatke aplikacije.\n\nUtječe samo na URL i metode uvoza treće strane.", + "importErrors": "Uvezi greške", + "importedXOfYApps": "{} od {} aplikacija uvezeno.", + "followingURLsHadErrors": "Sljedeći URL-ovi su imali greške:", + "okay": "Dobro", + "selectURL": "Odaberite URL", + "selectURLs": "Odaberite URL-ove", + "pick": "Odaberi", + "theme": "Tema", + "dark": "Tamna", + "light": "Svijetla", + "followSystem": "Pratite sistem", "obtainium": "Obtainium", - "materialYou": "Material You", - "useBlackTheme": "Koristite čisto crnu tamnu temu", - "appSortBy": "Aplikacije sortirane po", - "authorName": "Autor/Ime", - "nameAuthor": "Ime/Autor", - "asAdded": "Kao što je dodano", - "appSortOrder": "Redoslijed sortiranja aplikacija", - "ascending": "Uzlazno", - "descending": "Silazno", - "bgUpdateCheckInterval": "Interval provjere ažuriranja u pozadini", - "neverManualOnly": "Nikada - samo ručno", - "appearance": "Izgled", - "showWebInAppView": "Prikaži izvornu web stranicu u prikazu aplikacije", - "pinUpdates": "Prikvačite ažuriranja na vrh prikaza aplikacija", - "updates": "Nadogradnje", - "sourceSpecific": "Specifično za izvor", - "appSource": "Izvor aplikacije", - "noLogs": "Nema evidencije", - "appLogs": "Evidencije aplikacija", - "close": "Zatvori", - "share": "Podijeli", - "appNotFound": "Aplikacija nije pronađena", - "obtainiumExportHyphenatedLowercase": "obtainium-export", - "pickAnAPK": "Odaberite APK", - "appHasMoreThanOnePackage": "{} ima više od jednog paketa:", - "deviceSupportsXArch": "Vaš uređaj podržava {} arhitekturu procesora.", - "deviceSupportsFollowingArchs": "Vaš uređaj podržava sljedeće arhitekture procesora:", - "warning": "Upozorenje", - "sourceIsXButPackageFromYPrompt": "Izvor aplikacije je '{}', ali paket za izdavanje dolazi iz '{}'. Želite li nastaviti?", - "updatesAvailable": "Dostupna ažuriranja", - "updatesAvailableNotifDescription": "Obavještava korisnika da su ažuriranja dostupna za jednu ili više aplikacija koje prati Obtainium", - "noNewUpdates": "Nema novih ažuriranja.", - "xHasAnUpdate": "{} ima ažuriranje.", - "appsUpdated": "Aplikacije su ažurirane", - "appsUpdatedNotifDescription": "Obavještava korisnika da su u pozadini primijenjena ažuriranja na jednu ili više aplikacija", - "xWasUpdatedToY": "{} je ažuriran na {}.", - "errorCheckingUpdates": "Greška pri provjeri ažuriranja", - "errorCheckingUpdatesNotifDescription": "Obavijest koja se prikazuje kada provjera sigurnosnog ažuriranja ne uspije", - "appsRemoved": "Aplikacije su uklonjene", - "appsRemovedNotifDescription": "Obavještava korisnika da je jedna ili više aplikacija uklonjeno zbog grešaka prilikom učitavanja", - "xWasRemovedDueToErrorY": "{} je uklonjen zbog ove greške: {}", - "completeAppInstallation": "Dovršite instalaciju aplikacije", - "obtainiumMustBeOpenToInstallApps": "Obtainium mora biti otvoren za instalaciju aplikacija", - "completeAppInstallationNotifDescription": "Traži od korisnika da se vrati u Obtainium kako bi dovršio instalaciju aplikacije", - "checkingForUpdates": "Tražim moguće nadogradnje", - "checkingForUpdatesNotifDescription": "Privremeno obavještenje koje se pojavljuje prilikom provjere ažuriranja", - "pleaseAllowInstallPerm": "Dozvolite Obtainiumu da instalira aplikacije", - "trackOnly": "Samo za praćenje", - "errorWithHttpStatusCode": "Greška {}", - "versionCorrectionDisabled": "Ispravka verzije je onemogućena (izgleda da plugin ne radi)", - "unknown": "Nepoznato", - "none": "Ništa", - "never": "Nikad", - "latestVersionX": "Najnovija verzija: {}", - "installedVersionX": "Instalirana verzija: {}", - "lastUpdateCheckX": "Posljednja provjera ažuriranja: {}", - "remove": "Izbriši", - "yesMarkUpdated": "Da, označi kao ažurirano", - "fdroid": "F-Droid Official", - "appIdOrName": "ID ili ime aplikacije", - "appId": "Apl ID", - "appWithIdOrNameNotFound": "Nije pronađena aplikacija s tim ID-om ili imenom", - "reposHaveMultipleApps": "Repo-i mogu sadržavati više aplikacija", - "fdroidThirdPartyRepo": "F-Droid Repo treće strane", - "steam": "Steam", - "steamMobile": "Steam Mobile", - "steamChat": "Razgovor na Steamu (chat)", - "install": "Instaliraj", - "markInstalled": "Označi kao instalirano", - "update": "Nadogradi", - "markUpdated": "Označi kao ažurirano", - "additionalOptions": "Dodatne opcije", - "disableVersionDetection": "Onemogući detekciju verzije", - "noVersionDetectionExplanation": "Ova opcija bi se trebala koristiti samo za aplikacije gdje detekcija verzije ne radi ispravno.", - "downloadingX": "Preuzimanje {}", - "downloadNotifDescription": "Obavještava korisnika o napretku u preuzimanju aplikacije", - "noAPKFound": "APK nije pronađen", - "noVersionDetection": "Nema detekcije verzije", - "categorize": "Kategoriziraj", - "categories": "Kategorije", - "category": "Kategorija", - "noCategory": "Nema kategorije", - "noCategories": "Nema kategorija", - "deleteCategoriesQuestion": "Želite li izbrisati kategorije?", - "categoryDeleteWarning": "Sve aplikacije u izbrisanim kategorijama će biti postavljene kao nekategorisane.", - "addCategory": "Dodaj kategoriju", - "label": "Oznaka", - "language": "Jezik", - "copiedToClipboard": "Podaci kopirani u međuspremnik", - "storagePermissionDenied": "Dozvola za pohranu je odbijena", - "selectedCategorizeWarning": "Ovo će zamijeniti sve postojeće postavke kategorije za odabrane aplikacije.", - "filterAPKsByRegEx": "Filtrirajte APK-ove prema regularnom izrazu", - "removeFromObtainium": "Ukloni iz Obtainiuma", - "uninstallFromDevice": "Deinstaliraj s uređaja", - "onlyWorksWithNonVersionDetectApps": "Radi samo za aplikacije s onemogućenom detekcijom verzije.", - "releaseDateAsVersion": "Koristi datum izdanja kao verziju", - "releaseDateAsVersionExplanation": "Ova opcija bi se trebala koristiti samo za aplikacije gdje detekcija verzije ne radi ispravno, ali je datum izdavanja dostupan.", - "changes": "Promjene", - "releaseDate": "Datum izdavanja", - "importFromURLsInFile": "Uvoz iz URL-ova u datoteci (kao što je OPML)", - "versionDetection": "Otkrivanje verzije", - "standardVersionDetection": "Detekcija standardne verzije", - "groupByCategory": "Grupiši po kategoriji", - "autoApkFilterByArch": "Pokušajte filtrirati APK-ove po arhitekturi procesora ako je moguće", - "overrideSource": "Premosti izvor", - "dontShowAgain": "Ne prikazuj ovo ponovo", - "dontShowTrackOnlyWarnings": "Ne prikazuj upozorenja „Samo za praćenje”", - "dontShowAPKOriginWarnings": "Ne prikazuj upozorenja o porijeklu APK-a", - "moveNonInstalledAppsToBottom": "Premjesti neinstalirane aplikacije na dno prikaza aplikacija", - "gitlabPATLabel": "GitLab token za lični pristup\n(Omogućava pretraživanje i bolje otkrivanje APK-a)", - "about": "O nama", - "requiresCredentialsInSettings": "Za ovo su potrebni dodatni akreditivi (u Postavkama)", - "checkOnStart": "Provjerite ima li novosti pri pokretanju", - "tryInferAppIdFromCode": "Pokušati otkriti ID aplikacije iz izvornog koda", - "removeOnExternalUninstall": "Automatski ukloni eksterno deinstalirane aplikacije", - "pickHighestVersionCode": "Automatski odaberite najviši kôd verzije APK-a", - "checkUpdateOnDetailPage": "Provjerite ima li novosti pri otvaranju stranice s detaljima aplikacije", - "disablePageTransitions": "Ugasite animaciju prijelaza stranice", - "reversePageTransitions": "Reverzne animacije prijelaza stranice", - "minStarCount": "Minimum Star Count", - "addInfoBelow": "Add this info below.", - "addInfoInSettings": "Add this info in the Settings.", - "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", - "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", - "sortByFileNamesNotLinks": "Sort by file names instead of full links", - "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", - "appsPossiblyUpdated": "App Updates Attempted", - "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", - "enableBackgroundUpdates": "Enable background updates", - "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", - "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", - "verifyLatestTag": "Verify the 'latest' tag", - "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", - "intermediateLinkNotFound": "Intermediate link not found", - "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", - "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", - "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", - "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", - "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", - "autoExportOnChanges": "Auto-export on changes", - "filterVersionsByRegEx": "Filter Versions by Regular Expression", - "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", - "dontSortReleasesList": "Retain release order from API", - "reverseSort": "Reverse sorting", - "debugMenu": "Debug Menu", - "bgTaskStarted": "Background task started - check logs.", - "runBgCheckNow": "Run Background Update Check Now", - "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "materialYou": "Material You", + "useBlackTheme": "Koristite čisto crnu tamnu temu", + "appSortBy": "Aplikacije sortirane po", + "authorName": "Autor/Ime", + "nameAuthor": "Ime/Autor", + "asAdded": "Kao što je dodano", + "appSortOrder": "Redoslijed sortiranja aplikacija", + "ascending": "Uzlazno", + "descending": "Silazno", + "bgUpdateCheckInterval": "Interval provjere ažuriranja u pozadini", + "neverManualOnly": "Nikada - samo ručno", + "appearance": "Izgled", + "showWebInAppView": "Prikaži izvornu web stranicu u prikazu aplikacije", + "pinUpdates": "Prikvačite ažuriranja na vrh prikaza aplikacija", + "updates": "Nadogradnje", + "sourceSpecific": "Specifično za izvor", + "appSource": "Izvor aplikacije", + "noLogs": "Nema evidencije", + "appLogs": "Evidencije aplikacija", + "close": "Zatvori", + "share": "Podijeli", + "appNotFound": "Aplikacija nije pronađena", + "obtainiumExportHyphenatedLowercase": "obtainium-export", + "pickAnAPK": "Odaberite APK", + "appHasMoreThanOnePackage": "{} ima više od jednog paketa:", + "deviceSupportsXArch": "Vaš uređaj podržava {} arhitekturu procesora.", + "deviceSupportsFollowingArchs": "Vaš uređaj podržava sljedeće arhitekture procesora:", + "warning": "Upozorenje", + "sourceIsXButPackageFromYPrompt": "Izvor aplikacije je '{}', ali paket za izdavanje dolazi iz '{}'. Želite li nastaviti?", + "updatesAvailable": "Dostupna ažuriranja", + "updatesAvailableNotifDescription": "Obavještava korisnika da su ažuriranja dostupna za jednu ili više aplikacija koje prati Obtainium", + "noNewUpdates": "Nema novih ažuriranja.", + "xHasAnUpdate": "{} ima ažuriranje.", + "appsUpdated": "Aplikacije su ažurirane", + "appsUpdatedNotifDescription": "Obavještava korisnika da su u pozadini primijenjena ažuriranja na jednu ili više aplikacija", + "xWasUpdatedToY": "{} je ažuriran na {}.", + "errorCheckingUpdates": "Greška pri provjeri ažuriranja", + "errorCheckingUpdatesNotifDescription": "Obavijest koja se prikazuje kada provjera sigurnosnog ažuriranja ne uspije", + "appsRemoved": "Aplikacije su uklonjene", + "appsRemovedNotifDescription": "Obavještava korisnika da je jedna ili više aplikacija uklonjeno zbog grešaka prilikom učitavanja", + "xWasRemovedDueToErrorY": "{} je uklonjen zbog ove greške: {}", + "completeAppInstallation": "Dovršite instalaciju aplikacije", + "obtainiumMustBeOpenToInstallApps": "Obtainium mora biti otvoren za instalaciju aplikacija", + "completeAppInstallationNotifDescription": "Traži od korisnika da se vrati u Obtainium kako bi dovršio instalaciju aplikacije", + "checkingForUpdates": "Tražim moguće nadogradnje", + "checkingForUpdatesNotifDescription": "Privremeno obavještenje koje se pojavljuje prilikom provjere ažuriranja", + "pleaseAllowInstallPerm": "Dozvolite Obtainiumu da instalira aplikacije", + "trackOnly": "Samo za praćenje", + "errorWithHttpStatusCode": "Greška {}", + "versionCorrectionDisabled": "Ispravka verzije je onemogućena (izgleda da plugin ne radi)", + "unknown": "Nepoznato", + "none": "Ništa", + "never": "Nikad", + "latestVersionX": "Najnovija verzija: {}", + "installedVersionX": "Instalirana verzija: {}", + "lastUpdateCheckX": "Posljednja provjera ažuriranja: {}", + "remove": "Izbriši", + "yesMarkUpdated": "Da, označi kao ažurirano", + "fdroid": "F-Droid Official", + "appIdOrName": "ID ili ime aplikacije", + "appId": "Apl ID", + "appWithIdOrNameNotFound": "Nije pronađena aplikacija s tim ID-om ili imenom", + "reposHaveMultipleApps": "Repo-i mogu sadržavati više aplikacija", + "fdroidThirdPartyRepo": "F-Droid Repo treće strane", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Razgovor na Steamu (chat)", + "install": "Instaliraj", + "markInstalled": "Označi kao instalirano", + "update": "Nadogradi", + "markUpdated": "Označi kao ažurirano", + "additionalOptions": "Dodatne opcije", + "disableVersionDetection": "Onemogući detekciju verzije", + "noVersionDetectionExplanation": "Ova opcija bi se trebala koristiti samo za aplikacije gdje detekcija verzije ne radi ispravno.", + "downloadingX": "Preuzimanje {}", + "downloadNotifDescription": "Obavještava korisnika o napretku u preuzimanju aplikacije", + "noAPKFound": "APK nije pronađen", + "noVersionDetection": "Nema detekcije verzije", + "categorize": "Kategoriziraj", + "categories": "Kategorije", + "category": "Kategorija", + "noCategory": "Nema kategorije", + "noCategories": "Nema kategorija", + "deleteCategoriesQuestion": "Želite li izbrisati kategorije?", + "categoryDeleteWarning": "Sve aplikacije u izbrisanim kategorijama će biti postavljene kao nekategorisane.", + "addCategory": "Dodaj kategoriju", + "label": "Oznaka", + "language": "Jezik", + "copiedToClipboard": "Podaci kopirani u međuspremnik", + "storagePermissionDenied": "Dozvola za pohranu je odbijena", + "selectedCategorizeWarning": "Ovo će zamijeniti sve postojeće postavke kategorije za odabrane aplikacije.", + "filterAPKsByRegEx": "Filtrirajte APK-ove prema regularnom izrazu", + "removeFromObtainium": "Ukloni iz Obtainiuma", + "uninstallFromDevice": "Deinstaliraj s uređaja", + "onlyWorksWithNonVersionDetectApps": "Radi samo za aplikacije s onemogućenom detekcijom verzije.", + "releaseDateAsVersion": "Koristi datum izdanja kao verziju", + "releaseDateAsVersionExplanation": "Ova opcija bi se trebala koristiti samo za aplikacije gdje detekcija verzije ne radi ispravno, ali je datum izdavanja dostupan.", + "changes": "Promjene", + "releaseDate": "Datum izdavanja", + "importFromURLsInFile": "Uvoz iz URL-ova u datoteci (kao što je OPML)", + "versionDetection": "Otkrivanje verzije", + "standardVersionDetection": "Detekcija standardne verzije", + "groupByCategory": "Grupiši po kategoriji", + "autoApkFilterByArch": "Pokušajte filtrirati APK-ove po arhitekturi procesora ako je moguće", + "overrideSource": "Premosti izvor", + "dontShowAgain": "Ne prikazuj ovo ponovo", + "dontShowTrackOnlyWarnings": "Ne prikazuj upozorenja „Samo za praćenje”", + "dontShowAPKOriginWarnings": "Ne prikazuj upozorenja o porijeklu APK-a", + "moveNonInstalledAppsToBottom": "Premjesti neinstalirane aplikacije na dno prikaza aplikacija", + "gitlabPATLabel": "GitLab token za lični pristup\n(Omogućava pretraživanje i bolje otkrivanje APK-a)", + "about": "O nama", + "requiresCredentialsInSettings": "Za ovo su potrebni dodatni akreditivi (u Postavkama)", + "checkOnStart": "Provjerite ima li novosti pri pokretanju", + "tryInferAppIdFromCode": "Pokušati otkriti ID aplikacije iz izvornog koda", + "removeOnExternalUninstall": "Automatski ukloni eksterno deinstalirane aplikacije", + "pickHighestVersionCode": "Automatski odaberite najviši kôd verzije APK-a", + "checkUpdateOnDetailPage": "Provjerite ima li novosti pri otvaranju stranice s detaljima aplikacije", + "disablePageTransitions": "Ugasite animaciju prijelaza stranice", + "reversePageTransitions": "Reverzne animacije prijelaza stranice", + "minStarCount": "Minimum Star Count", + "addInfoBelow": "Add this info below.", + "addInfoInSettings": "Add this info in the Settings.", + "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", + "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", + "sortByFileNamesNotLinks": "Sort by file names instead of full links", + "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", + "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", + "appsPossiblyUpdated": "App Updates Attempted", + "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", + "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", + "enableBackgroundUpdates": "Enable background updates", + "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", + "verifyLatestTag": "Verify the 'latest' tag", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", + "intermediateLinkNotFound": "Intermediate link not found", + "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", + "versionExtractionRegEx": "Version Extraction RegEx", + "matchGroupToUse": "Match Group to Use", + "highlightTouchTargets": "Highlight less obvious touch targets", + "pickExportDir": "Pick Export Directory", + "autoExportOnChanges": "Auto-export on changes", + "filterVersionsByRegEx": "Filter Versions by Regular Expression", + "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", + "dontSortReleasesList": "Retain release order from API", + "reverseSort": "Reverse sorting", + "debugMenu": "Debug Menu", + "bgTaskStarted": "Background task started - check logs.", + "runBgCheckNow": "Run Background Update Check Now", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", - "removeAppQuestion": { - "one": "Želite li ukloniti aplikaciju?", - "other": "Želite li ukloniti aplikacije?" - }, - "tooManyRequestsTryAgainInMinutes": { - "one": "Previše zahtjeva (ograničena broj zahteva) - pokušajte ponovo za {} minutu", - "other": "Previše zahtjeva (ograničena cijena) - pokušajte ponovo za {} min." - }, - "bgUpdateGotErrorRetryInMinutes": { - "one": "Provjera ažuriranja u pozadini naišla je na {}, zakazuje se ponovni pokušaj za {} minutu", - "other": "Provjera ažuriranja u pozadini naišla je na {}, zakazuje se ponovni pokušaj za {} min." - }, - "bgCheckFoundUpdatesWillNotifyIfNeeded": { - "one": "Provjera ažuriranja u pozadini je pronašla {} ažuriranje - korisnik će biti obavješten ako je to potrebno", - "other": "Provjera ažuriranja u pozadini je pronašla {} ažuriranja - korisnik će biti obavješten ako je to potrebno" - }, - "apps": { - "one": "{} aplikacija", - "other": "{} aplikacije" - }, - "url": { - "one": "{} URL", - "other": "{} URL-ovi" - }, - "minute": { - "one": "{} minuta", - "other": "min." - }, - "hour": { - "one": "{} sat", - "other": "{} sat/i" - }, - "day": { - "one": "{} dan", - "other": "{} dana" - }, - "clearedNLogsBeforeXAfterY": { - "one": "Izbrisan {n} log (prije = {before}, nakon = {after})", - "other": "Izbrisano {n} log-ova (prije = {before}, nakon = {after})" - }, - "xAndNMoreUpdatesAvailable": { - "one": "{} i još 1 aplikacija ima ažuriranja.", - "other": "{} i još {} aplikacija imaju ažuriranja." - }, - "xAndNMoreUpdatesInstalled": { - "one": "{} i još 1 aplikacija je ažurirana.", - "other": "{} i još {} aplikacija je ažurirano." - }, - "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} and 1 more app may have been updated.", - "other": "{} and {} more apps may have been updated." - } + "updatesAvailableNotifChannel": "Dostupna ažuriranja", + "appsUpdatedNotifChannel": "Aplikacije su ažurirane", + "appsPossiblyUpdatedNotifChannel": "App Updates Attempted", + "errorCheckingUpdatesNotifChannel": "Greška pri provjeri ažuriranja", + "appsRemovedNotifChannel": "Aplikacije su uklonjene", + "downloadingXNotifChannel": "Preuzimanje {}", + "completeAppInstallationNotifChannel": "Dovršite instalaciju aplikacije", + "checkingForUpdatesNotifChannel": "Tražim moguće nadogradnje", + "removeAppQuestion": { + "one": "Želite li ukloniti aplikaciju?", + "other": "Želite li ukloniti aplikacije?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Previše zahtjeva (ograničena broj zahteva) - pokušajte ponovo za {} minutu", + "other": "Previše zahtjeva (ograničena cijena) - pokušajte ponovo za {} min." + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "Provjera ažuriranja u pozadini naišla je na {}, zakazuje se ponovni pokušaj za {} minutu", + "other": "Provjera ažuriranja u pozadini naišla je na {}, zakazuje se ponovni pokušaj za {} min." + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "Provjera ažuriranja u pozadini je pronašla {} ažuriranje - korisnik će biti obavješten ako je to potrebno", + "other": "Provjera ažuriranja u pozadini je pronašla {} ažuriranja - korisnik će biti obavješten ako je to potrebno" + }, + "apps": { + "one": "{} aplikacija", + "other": "{} aplikacije" + }, + "url": { + "one": "{} URL", + "other": "{} URL-ovi" + }, + "minute": { + "one": "{} minuta", + "other": "min." + }, + "hour": { + "one": "{} sat", + "other": "{} sat/i" + }, + "day": { + "one": "{} dan", + "other": "{} dana" + }, + "clearedNLogsBeforeXAfterY": { + "one": "Izbrisan {n} log (prije = {before}, nakon = {after})", + "other": "Izbrisano {n} log-ova (prije = {before}, nakon = {after})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "{} i još 1 aplikacija ima ažuriranja.", + "other": "{} i još {} aplikacija imaju ažuriranja." + }, + "xAndNMoreUpdatesInstalled": { + "one": "{} i još 1 aplikacija je ažurirana.", + "other": "{} i još {} aplikacija je ažurirano." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "{} and 1 more app may have been updated.", + "other": "{} and {} more apps may have been updated." + } } diff --git a/assets/translations/cs.json b/assets/translations/cs.json index 2f6ea78..df3be45 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -25,7 +25,7 @@ "githubStarredRepos": "GitHub Starred Repos", "uname": "username", "wrongArgNum": "Špatný počet předložených argumentů", - "xIsTrackOnly":"{} je určeno pouze pro sledování", + "xIsTrackOnly": "{} je určeno pouze pro sledování", "source": "zdroj", "app": "App", "appsFromSourceAreTrackOnly": "Aplikace z tohoto zdroje jsou 'Jen sledovány'.", @@ -56,7 +56,7 @@ "estimateInBrackets": "(přibližně)", "selectAll": "Vybrat Vše", "deselectN": "{} deselected", - "xWillBeRemovedButRemainInstalled":"{} bude odstraněn z Obtainium, ale zůstane nainstalován v zařízení.", + "xWillBeRemovedButRemainInstalled": "{} bude odstraněn z Obtainium, ale zůstane nainstalován v zařízení.", "removeSelectedAppsQuestion": "Odebrat vybrané aplikace?", "removeSelectedApps": "Odebrat vybrané aplikace", "updateX": "Aktualizovat {}", @@ -101,7 +101,7 @@ "importX": "Import {}", "importedAppsIdDisclaimer": "Importované aplikace mohou být nesprávně zobrazeny jako \"Neinstalované\". Chcete-li to opravit, nainstalujte je znovu prostřednictvím Obtainium. To nemá vliv na data aplikací. Ovlivňuje pouze metody importu URL a třetích stran.", "importErrors": "Import Errors", - "importedXOfYApps":"{}importováno {}aplikací.", + "importedXOfYApps": "{}importováno {}aplikací.", "followingURLsHadErrors": "U následujících adres URL došlo k chybám:", "okay": "Okay", "selectURL": "Select URL", @@ -136,7 +136,7 @@ "appNotFound": "App not found", "obtainiumExportHyphenatedLowercase": "obtainium-export", "pickAnAPK": "Vybrat APK", - "appHasMoreThanOnePackage":"{} má více než jeden balíček:", + "appHasMoreThanOnePackage": "{} má více než jeden balíček:", "deviceSupportsXArch": "Vaše zařízení podporuje architekturu CPU {}.", "deviceSupportsFollowingArchs": "Vaše zařízení podporuje následující architektury CPU:", "warning": "Varování", @@ -144,15 +144,15 @@ "updatesAvailable": "dostupné aktualizace", "updatesAvailableNotifDescription": "Upozorňuje uživatele, že jsou k dispozici aktualizace pro jednu nebo více aplikací sledovaných Obtainium", "noNewUpdates": "Žádné nové aktualizace.", - "xHasAnUpdate":"{} má aktualizaci.", + "xHasAnUpdate": "{} má aktualizaci.", "appsUpdated": "Aplikace aktualizovány", "appsUpdatedNotifDescription": "Upozorňuje uživatele, že byly provedeny aktualizace jedné nebo více aplikací na pozadí", - "xWasUpdatedToY":"{} byl aktualizován na {}", + "xWasUpdatedToY": "{} byl aktualizován na {}", "errorCheckingUpdates": "Chybová kontrola aktualizací", "errorCheckingUpdatesNotifDescription": "Oznámení zobrazené při neúspěšné kontrole aktualizací na pozadí", "appsRemoved": "Odstraněné aplikace", "appsRemovedNotifDescription": "Oznámení uživateli, že jedna nebo více aplikací byly odstraněny z důvodu chyb při načítání", - "xWasRemovedDueToErrorY":"{} byla odstraněna z důvodu následující chyby: {}", + "xWasRemovedDueToErrorY": "{} byla odstraněna z důvodu následující chyby: {}", "completeAppInstallation": "Dokončit instalaci aplikace", "obtainiumMustBeOpenToInstallApps": "Obtainium musí být otevřeno, aby bylo možné instalovat aplikace", "completeAppInstallationNotifDescription": "Vyzvat uživatele k návratu do Obtainium pro dokončení instalace aplikací", @@ -241,7 +241,7 @@ "customLinkFilterRegex": "Vlastní filtr odkazů APK podle regulárního výrazu (výchozí '.apk$')", "appsPossiblyUpdated": "Byly provedeny pokusy o aktualizaci aplikací", "appsPossiblyUpdatedNotifDescription": "Upozorňuje uživatele, že na pozadí mohly být provedeny aktualizace jedné nebo více aplikací", - "xWasPossiblyUpdatedToY":"{} mohlo být aktualizováno na {}.", + "xWasPossiblyUpdatedToY": "{} mohlo být aktualizováno na {}.", "enableBackgroundUpdates": "Povolit aktualizace na pozadí", "backgroundUpdateReqsExplanation": "Aktualizace na pozadí nemusí být možné pro všechny aplikace.", "backgroundUpdateLimitsExplanation": "Úspěšnost instalace na pozadí lze určit pouze v případě, že je otevřen Obtainium.", @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "dostupné aktualizace", + "appsUpdatedNotifChannel": "Aplikace aktualizovány", + "appsPossiblyUpdatedNotifChannel": "Byly provedeny pokusy o aktualizaci aplikací", + "errorCheckingUpdatesNotifChannel": "Chybová kontrola aktualizací", + "appsRemovedNotifChannel": "Odstraněné aplikace", + "downloadingXNotifChannel": "download {}", + "completeAppInstallationNotifChannel": "Dokončit instalaci aplikace", + "checkingForUpdatesNotifChannel": "Zkontrolovat aktualizace", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" @@ -283,15 +291,15 @@ "other": "Kontrola aktualizací na pozadí našla {} aktualizací - v případě potřeby upozorní uživatele" }, "apps": { - "one":"{} App", - "other":"{} apps" + "one": "{} App", + "other": "{} apps" }, "url": { "jedna": "{} URL", "other": "{} URLs" }, "minute": { - "one":"{} minute", + "one": "{} minute", "other": "{} minutes" }, "hour": { @@ -303,20 +311,19 @@ "other": "{} dny" }, "clearedNLogsBeforeXAfterY": { - "one":"{n} log vymazán (před = {před}, po = {po})", + "one": "{n} log vymazán (před = {před}, po = {po})", "other": "{n} logů vymazáno (před = {před}, po = {po})" }, "xAndNMoreUpdatesAvailable": { - "one":"{} a 1 další aplikace mají aktualizace.", - "other":"{} a {} další aplikace mají aktualizace." + "one": "{} a 1 další aplikace mají aktualizace.", + "other": "{} a {} další aplikace mají aktualizace." }, "xAndNMoreUpdatesInstalled": { - "one":"{} a {} další aplikace mají aktualizace.", - "další":"{} a {} další aplikace byly aktualizovány." + "one": "{} a {} další aplikace mají aktualizace.", + "další": "{} a {} další aplikace byly aktualizovány." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one":"{} a {} další aplikace byly možná aktualizovány", - "other":"{} a {} další aplikace mohly být aktualizovány." + "one": "{} a {} další aplikace byly možná aktualizovány", + "other": "{} a {} další aplikace mohly být aktualizovány." } -} - +} \ No newline at end of file diff --git a/assets/translations/de.json b/assets/translations/de.json index fe2a44d..90fbdc6 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "Aktualisierungen verfügbar", + "appsUpdatedNotifChannel": "Apps aktualisiert", + "appsPossiblyUpdatedNotifChannel": "App Aktualisierungen wurden versucht", + "errorCheckingUpdatesNotifChannel": "Fehler beim Prüfen auf Aktualisierungen", + "appsRemovedNotifChannel": "Apps entfernt", + "downloadingXNotifChannel": "Lade {} herunter", + "completeAppInstallationNotifChannel": "App Installation abschließen", + "checkingForUpdatesNotifChannel": "Nach Aktualisierungen suchen", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" @@ -318,4 +326,4 @@ "one": "{} und 1 weitere Anwendung wurden möglicherweise aktualisiert.", "other": "{} und {} weitere Anwendungen wurden möglicherweise aktualisiert." } -} +} \ No newline at end of file diff --git a/assets/translations/en.json b/assets/translations/en.json index 3d68d57..6d8311c 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "Updates Available", + "appsUpdatedNotifChannel": "Apps Updated", + "appsPossiblyUpdatedNotifChannel": "App Updates Attempted", + "errorCheckingUpdatesNotifChannel": "Error Checking for Updates", + "appsRemovedNotifChannel": "Apps Removed", + "downloadingXNotifChannel": "Downloading {}", + "completeAppInstallationNotifChannel": "Complete App Installation", + "checkingForUpdatesNotifChannel": "Checking for Updates", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" @@ -318,4 +326,4 @@ "one": "{} and 1 more app may have been updated.", "other": "{} and {} more apps may have been updated." } -} +} \ No newline at end of file diff --git a/assets/translations/es.json b/assets/translations/es.json index 3003f67..a73970b 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "Actualizaciones Disponibles", + "appsUpdatedNotifChannel": "Aplicaciones Actualizadas", + "appsPossiblyUpdatedNotifChannel": "App Updates Attempted", + "errorCheckingUpdatesNotifChannel": "Error Buscando Actualizaciones", + "appsRemovedNotifChannel": "Aplicaciones Eliminadas", + "downloadingXNotifChannel": "Descargando {}", + "completeAppInstallationNotifChannel": "Instalación Completa de la Aplicación", + "checkingForUpdatesNotifChannel": "Buscando Actualizaciones", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" @@ -318,4 +326,4 @@ "one": "{} and 1 more app may have been updated.", "other": "{} and {} more apps may have been updated." } -} +} \ No newline at end of file diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 7c24b96..f051b48 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "بروزرسانی در دسترس ", + "appsUpdatedNotifChannel": "برنامه ها به روز شدند", + "appsPossiblyUpdatedNotifChannel": "App Updates Attempted", + "errorCheckingUpdatesNotifChannel": "خطا در بررسی به‌روزرسانی‌ها", + "appsRemovedNotifChannel": "برنامه ها حذف شدند", + "downloadingXNotifChannel": "در حال دانلود {}", + "completeAppInstallationNotifChannel": "نصب کامل برنامه", + "checkingForUpdatesNotifChannel": "بررسی به‌روزرسانی‌ها", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" @@ -318,4 +326,4 @@ "one": "{} and 1 more app may have been updated.", "other": "{} and {} more apps may have been updated." } -} +} \ No newline at end of file diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 2eb17dc..649b0ff 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "Mises à jour disponibles", + "appsUpdatedNotifChannel": "Applications mises à jour", + "appsPossiblyUpdatedNotifChannel": "App Updates Attempted", + "errorCheckingUpdatesNotifChannel": "Erreur lors de la vérification des mises à jour", + "appsRemovedNotifChannel": "Applications supprimées", + "downloadingXNotifChannel": "Téléchargement {}", + "completeAppInstallationNotifChannel": "Installation complète de l'application", + "checkingForUpdatesNotifChannel": "Vérification des mises à jour", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" @@ -318,4 +326,4 @@ "one": "{} and 1 more app may have been updated.", "other": "{} and {} more apps may have been updated." } -} +} \ No newline at end of file diff --git a/assets/translations/hu.json b/assets/translations/hu.json index b94b173..b41dfb4 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -1,321 +1,329 @@ -{ - "invalidURLForSource": "Érvénytelen a(z) {} app URL-je", - "noReleaseFound": "Nem található megfelelő kiadás", - "noVersionFound": "Nem sikerült meghatározni a kiadás verzióját", - "urlMatchesNoSource": "Az URL nem egyezik ismert forrással", - "cantInstallOlderVersion": "Nem telepíthető egy app régebbi verziója", - "appIdMismatch": "A letöltött csomagazonosító nem egyezik a meglévő app azonosítóval", - "functionNotImplemented": "Ez az osztály nem valósította meg ezt a függvényt", - "placeholder": "Helykitöltő", - "someErrors": "Néhány hiba történt", - "unexpectedError": "Váratlan hiba", - "ok": "Oké", - "and": "és", - "githubPATLabel": "GitHub Personal Access Token (megnöveli a díjkorlátot)", - "includePrereleases": "Tartalmazza az előzetes kiadásokat", - "fallbackToOlderReleases": "Visszatérés a régebbi kiadásokhoz", - "filterReleaseTitlesByRegEx": "A kiadás címeinek szűrése reguláris kifejezéssel", - "invalidRegEx": "Érvénytelen reguláris kifejezés", - "noDescription": "Nincs leírás", - "cancel": "Mégse", - "continue": "Tovább", - "requiredInBrackets": "(Kötelező)", - "dropdownNoOptsError": "HIBA: A LEDOBÁST LEGALÁBB EGY OPCIÓHOZ KELL RENDELNI", - "colour": "Szín", - "githubStarredRepos": "GitHub Csillagos Repo-k", - "uname": "Felh.név", - "wrongArgNum": "Rossz számú argumentumot adott meg", - "xIsTrackOnly": "A(z) {} csak nyomonkövethető", - "source": "Forrás", - "app": "App", - "appsFromSourceAreTrackOnly": "Az ebből a forrásból származó alkalmazások 'Csak nyomon követhetőek'.", - "youPickedTrackOnly": "A 'Csak követés' opciót választotta.", - "trackOnlyAppDescription": "Az alkalmazás frissítéseit nyomon követi, de az Obtainium nem tudja letölteni vagy telepíteni.", - "cancelled": "Törölve", - "appAlreadyAdded": "Az app már hozzáadva", - "alreadyUpToDateQuestion": "Az app már naprakész?", - "addApp": "App hozzáadás", - "appSourceURL": "App forrás URL", - "error": "Hiba", - "add": "Hozzáadás", - "searchSomeSourcesLabel": "Keresés (csak egyes források)", - "search": "Keresés", - "additionalOptsFor": "További lehetőségek a következőhöz: {}", - "supportedSources": "Támogatott források", - "trackOnlyInBrackets": "(Csak nyomonkövetés)", - "searchableInBrackets": "(Kereshető)", - "appsString": "Appok", - "noApps": "Nincs App", - "noAppsForFilter": "Nincsenek appok a szűrőhöz", - "byX": "Fejlesztő: {}", - "percentProgress": "Folyamat: {}%", - "pleaseWait": "Kis türelmet", - "updateAvailable": "Frissítés érhető el", - "estimateInBracketsShort": "(Becsült)", - "notInstalled": "Nem telepített", - "estimateInBrackets": "(Becslés)", - "selectAll": "Mindet kiválaszt", - "deselectN": "Törölje {} kijelölését", - "xWillBeRemovedButRemainInstalled": "A(z) {} el lesz távolítva az Obtainiumból, de továbbra is telepítve marad az eszközön.", - "removeSelectedAppsQuestion": "Eltávolítja a kiválasztott appokat?", - "removeSelectedApps": "Távolítsa el a kiválasztott appokat", - "updateX": "Frissítés: {}", - "installX": "Telepítés: {}", - "markXTrackOnlyAsUpdated": "Jelölje meg: {}\n(Csak nyomon követhető)\nmint Frissített", - "changeX": "Változás {}", - "installUpdateApps": "Appok telepítése/frissítése", - "installUpdateSelectedApps": "Telepítse/frissítse a kiválasztott appokat", - "markXSelectedAppsAsUpdated": "Megjelöl {} kiválasztott alkalmazást frissítettként?", - "no": "Nem", - "yes": "Igen", - "markSelectedAppsUpdated": "Jelölje meg a kiválasztott appokat frissítettként", - "pinToTop": "Rögzítés felülre", - "unpinFromTop": "Eltávolít felülről", - "resetInstallStatusForSelectedAppsQuestion": "Visszaállítja a kiválasztott appok telepítési állapotát?", - "installStatusOfXWillBeResetExplanation": "A kiválasztott appok telepítési állapota visszaáll.\n\nEz akkor segíthet, ha az Obtainiumban megjelenített app verzió hibás, frissítések vagy egyéb problémák miatt.", - "shareSelectedAppURLs": "Ossza meg a kiválasztott app URL címeit", - "resetInstallStatus": "Telepítési állapot visszaállítása", - "more": "További", - "removeOutdatedFilter": "Távolítsa el az elavult app szűrőt", - "showOutdatedOnly": "Csak az elavult appok megjelenítése", - "filter": "Szűrő", - "filterActive": "Szűrő *", - "filterApps": "Appok szűrése", - "appName": "App név", - "author": "Szerző", - "upToDateApps": "Naprakész appok", - "nonInstalledApps": "Nem telepített appok", - "importExport": "Import/Export", - "settings": "Beállítások", - "exportedTo": "Exportálva ide {}", - "obtainiumExport": "Obtainium Adat Exportálás", - "invalidInput": "Hibás bemenet", - "importedX": "Importálva innen {}", - "obtainiumImport": "Obtainium Adat Importálás", - "importFromURLList": "Importálás URL listából", - "searchQuery": "Keresési lekérdezés", - "appURLList": "App URL lista", - "line": "Sor", - "searchX": "Keresés {}", - "noResults": "Nincs találat", - "importX": "Import {}", - "importedAppsIdDisclaimer": "Előfordulhat, hogy az importált appok helytelenül \"Nincs telepítve\" jelzéssel jelennek meg.\nA probléma megoldásához telepítse újra őket az Obtainiumon keresztül.\nEz nem érinti az alkalmazásadatokat.\n\nCsak az URL-ekre és a harmadik féltől származó importálási módszerekre vonatkozik..", - "importErrors": "Importálási hibák", - "importedXOfYApps": "{}/{} app importálva.", - "followingURLsHadErrors": "A következő URL-ek hibákat tartalmaztak:", - "okay": "Oké", - "selectURL": "Válassza ki az URL-t", - "selectURLs": "Kiválasztott URL-ek", - "pick": "Válasszon", - "theme": "Téma", - "dark": "Sötét", - "light": "Világos", - "followSystem": "Rendszer szerint", - "obtainium": "Obtainium", - "materialYou": "Material You", - "useBlackTheme": "Használjon tiszta fekete sötét témát", - "appSortBy": "App rendezés...", - "authorName": "Szerző/Név", - "nameAuthor": "Név/Szerző", - "asAdded": "Mint Hozzáadott", - "appSortOrder": "Appok rendezése", - "ascending": "Emelkedő", - "descending": "Csökkenő", - "bgUpdateCheckInterval": "Háttérfrissítés ellenőrzés időköze", - "neverManualOnly": "Soha – csak manuális", - "appearance": "Megjelenés", - "showWebInAppView": "Forrás megjelenítése az Appok nézetben", - "pinUpdates": "Frissítések kitűzése az App nézet tetejére", - "updates": "Frissítések", - "sourceSpecific": "Forrás-specifikus", - "appSource": "App forrás", - "noLogs": "Nincsenek naplók", - "appLogs": "App naplók", - "close": "Bezárás", - "share": "Megosztás", - "appNotFound": "App nem található", - "obtainiumExportHyphenatedLowercase": "obtainium-export", - "pickAnAPK": "Válasszon egy APK-t", - "appHasMoreThanOnePackage": "A(z) {} egynél több csomaggal rendelkezik:", - "deviceSupportsXArch": "Eszköze támogatja a {} CPU architektúrát.", - "deviceSupportsFollowingArchs": "Az eszköze a következő CPU architektúrákat támogatja:", - "warning": "Figyelem", - "sourceIsXButPackageFromYPrompt": "Az alkalmazás forrása „{}”, de a kiadási csomag innen származik: „{}”. Folytatja?", - "updatesAvailable": "Frissítések érhetők el", - "updatesAvailableNotifDescription": "Értesíti a felhasználót, hogy frissítések állnak rendelkezésre egy vagy több, az Obtainium által nyomon követett alkalmazáshoz", - "noNewUpdates": "Nincsenek új frissítések.", - "xHasAnUpdate": "A(z) {} frissítést kapott.", - "appsUpdated": "Alkalmazások frissítve", - "appsUpdatedNotifDescription": "Értesíti a felhasználót, hogy egy/több app frissítése megtörtént a háttérben", - "xWasUpdatedToY": "{} frissítve a következőre: {}.", - "errorCheckingUpdates": "Hiba a frissítések keresésekor", - "errorCheckingUpdatesNotifDescription": "Értesítés, amely akkor jelenik meg, ha a háttérbeli frissítések ellenőrzése sikertelen", - "appsRemoved": "Alkalmazások eltávolítva", - "appsRemovedNotifDescription": "Értesíti a felhasználót egy vagy több alkalmazás eltávolításáról a betöltésük során fellépő hibák miatt", - "xWasRemovedDueToErrorY": "A(z) {} a következő hiba miatt lett eltávolítva: {}", - "completeAppInstallation": "Teljes app telepítés", - "obtainiumMustBeOpenToInstallApps": "Az Obtainiumnak megnyitva kell lennie az alkalmazások telepítéséhez", - "completeAppInstallationNotifDescription": "Megkéri a felhasználót, hogy térjen vissza az Obtainiumhoz, hogy befejezze az alkalmazás telepítését", - "checkingForUpdates": "Frissítések keresése", - "checkingForUpdatesNotifDescription": "Átmeneti értesítés, amely a frissítések keresésekor jelenik meg", - "pleaseAllowInstallPerm": "Kérjük, engedélyezze az Obtainiumnak az alkalmazások telepítését", - "trackOnly": "Csak követés", - "errorWithHttpStatusCode": "Hiba {}", - "versionCorrectionDisabled": "Verzió korrekció letiltva (úgy tűnik, a beépülő modul nem működik)", - "unknown": "Ismeretlen", - "none": "Egyik sem", - "never": "Soha", - "latestVersionX": "Legújabb verzió: {}", - "installedVersionX": "Telepített verzió: {}", - "lastUpdateCheckX": "Frissítés ellenőrizve: {}", - "remove": "Eltávolítás", - "yesMarkUpdated": "Igen, megjelölés frissítettként", - "fdroid": "F-Droid Official", - "appIdOrName": "App ID vagy név", - "appId": "App ID", - "appWithIdOrNameNotFound": "Nem található app ezzel az azonosítóval vagy névvel", - "reposHaveMultipleApps": "A repók több alkalmazást is tartalmazhatnak", - "fdroidThirdPartyRepo": "F-Droid Harmadik-fél Repo", - "steam": "Steam", - "steamMobile": "Steam Mobile", - "steamChat": "Steam Chat", - "install": "Telepít", - "markInstalled": "Telepítettnek jelöl", - "update": "Frissít", - "markUpdated": "Frissítettnek jelöl", - "additionalOptions": "További lehetőségek", - "disableVersionDetection": "Verzió érzékelés letiltása", - "noVersionDetectionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzióérzékelés nem működik megfelelően.", - "downloadingX": "{} letöltés", - "downloadNotifDescription": "Értesíti a felhasználót az app letöltésének előrehaladásáról", - "noAPKFound": "Nem található APK", - "noVersionDetection": "Nincs verzió érzékelés", - "categorize": "Kategorizálás", - "categories": "Kategóriák", - "category": "Kategória", - "noCategory": "Nincs kategória", - "noCategories": "No Categories", - "deleteCategoryQuestion": "Törli a kategóriát?", - "categoryDeleteWarning": "A(z) {} összes app kategorizálatlan állapotba kerül.", - "addCategory": "Új kategória", - "label": "Címke", - "language": "Nyelv", - "copiedToClipboard": "Másolva a vágólapra", - "storagePermissionDenied": "Tárhely engedély megtagadva", - "selectedCategorizeWarning": "Ez felváltja a kiválasztott alkalmazások meglévő kategória-beállításait.", - "filterAPKsByRegEx": "Az APK-k szűrése reguláris kifejezéssel", - "removeFromObtainium": "Eltávolítás az Obtainiumból", - "uninstallFromDevice": "Eltávolítás a készülékről", - "onlyWorksWithNonVersionDetectApps": "Csak azoknál az alkalmazásoknál működik, amelyeknél a verzióérzékelés le van tiltva.", - "releaseDateAsVersion": "Használja a Kiadás dátumát, mint verziót", - "releaseDateAsVersionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzió érzékelése nem működik megfelelően, de elérhető a kiadás dátuma.", - "changes": "Változtatások", - "releaseDate": "Kiadás dátuma", - "importFromURLsInFile": "Importálás fájlban található URL-ből (mint pl. OPML)", - "versionDetection": "Verzió érzékelés", - "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-okat", - "overrideSource": "Forrás felülbírálása", - "dontShowAgain": "Ne mutassa ezt újra", - "dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést", - "dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket", - "moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára", - "gitlabPATLabel": "GitLab Personal Access Token\n(Engedélyezi a Keresést és jobb APK felfedezés)", - "about": "Rólunk", - "requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)", - "checkOnStart": "Egyszer az alkalmazás indításakor is", - "tryInferAppIdFromCode": "Próbálja kikövetkeztetni az app azonosítót a forráskódból", - "removeOnExternalUninstall": "A külsőleg eltávolított appok auto. eltávolítása", - "pickHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", - "checkUpdateOnDetailPage": "Frissítések keresése az app részleteit tartalmazó oldal megnyitásakor", - "disablePageTransitions": "Lap áttűnési animációk letiltása", - "reversePageTransitions": "Fordított lap áttűnési animációk", - "minStarCount": "Minimális csillag szám", - "addInfoBelow": "Adja hozzá ezt az infót alább.", - "addInfoInSettings": "Adja hozzá ezt az infót a Beállításokban.", - "githubSourceNote": "A GitHub sebességkorlátozás elkerülhető API-kulcs használatával.", - "gitlabSourceNote": "Előfordulhat, hogy a GitLab APK kibontása nem működik API-kulcs nélkül.", - "sortByFileNamesNotLinks": "Fájlnevek szerinti elrendezés teljes linkek helyett", - "filterReleaseNotesByRegEx": "Kiadási megjegyzések szűrése reguláris kifejezéssel", - "customLinkFilterRegex": "Egyéni APK hivatkozásszűrő reguláris kifejezéssel (Alapérték '.apk$')", - "appsPossiblyUpdated": "App frissítési kísérlet", - "appsPossiblyUpdatedNotifDescription": "Értesíti a felhasználót, hogy egy vagy több alkalmazás frissítése lehetséges a háttérben", - "xWasPossiblyUpdatedToY": "{} frissítve lehet erre {}.", - "backgroundUpdateReqsExplanation": "Előfordulhat, hogy nem minden appnál lehetséges a háttérbeli frissítés.", - "backgroundUpdateLimitsExplanation": "A háttérben történő telepítés sikeressége csak az Obtainium megnyitásakor állapítható meg.", - "verifyLatestTag": "Ellenőrizze a „legújabb” címkét", - "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", - "intermediateLinkNotFound": "Intermediate link not found", - "exemptFromBackgroundUpdates": "Mentes a háttérben történő frissítések alól (ha engedélyezett)", - "bgUpdatesOnWiFiOnly": "Tiltsa le a háttérben frissítéseket, ha nincs Wi-Fi-n", - "autoSelectHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", - "versionExtractionRegEx": "Verzió kibontása reguláris kifejezéssel", - "matchGroupToUse": "Párosítsa a csoportot a használathoz", - "highlightTouchTargets": "Emelje ki a kevésbé nyilvánvaló érintési célokat", - "pickExportDir": "Válassza az Exportálási könyvtárat", - "autoExportOnChanges": "Auto-exportálás a változások után", - "filterVersionsByRegEx": "Verziók szűrése reguláris kifejezéssel", - "trySelectingSuggestedVersionCode": "Próbálja ki a javasolt verziókódú APK-t", - "dontSortReleasesList": "Az API-ból származó kiadási sorrend megőrzése", - "reverseSort": "Fordított rendezés", - "debugMenu": "Hibakereső menü", - "bgTaskStarted": "A háttérfeladat elindult – ellenőrizze a naplókat.", - "enableBackgroundUpdates": "Frissítések a háttérben", - "runBgCheckNow": "Futtassa a Háttérben frissítés ellenőrzését most", - "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", - "installing": "Installing", - "skipUpdateNotifications": "Skip update notifications", - "removeAppQuestion": { - "one": "Eltávolítja az alkalmazást?", - "other": "Eltávolítja az alkalmazást?" - }, - "tooManyRequestsTryAgainInMinutes": { - "one": "Túl sok kérés (korlátozott arány) – próbálja újra {} perc múlva", - "other": "Túl sok kérés (korlátozott arány) – próbálja újra {} perc múlva" - }, - "bgUpdateGotErrorRetryInMinutes": { - "one": "A háttérfrissítések ellenőrzése {}-t észlelt, {} perc múlva ütemezi az újrapróbálkozást", - "other": "A háttérfrissítések ellenőrzése {}-t észlelt, {} perc múlva ütemezi az újrapróbálkozást" - }, - "bgCheckFoundUpdatesWillNotifyIfNeeded": { - "one": "A háttérfrissítés ellenőrzése {} frissítést talált – szükség esetén értesíti a felhasználót", - "other": "A háttérfrissítés ellenőrzése {} frissítést talált – szükség esetén értesíti a felhasználót" - }, - "apps": { - "one": "{} app", - "other": "{} app" - }, - "url": { - "one": "{} URL", - "other": "{} URL" - }, - "minute": { - "one": "{} perc", - "other": "{} perc" - }, - "hour": { - "one": "{} óra", - "other": "{} óra" - }, - "day": { - "one": "{} nap", - "other": "{} nap" - }, - "clearedNLogsBeforeXAfterY": { - "one": "{n} napló törölve (előtte = {előtte}, utána = {utána})", - "other": "{n} napló törölve (előtte = {előtte}, utána = {utána})" - }, - "xAndNMoreUpdatesAvailable": { - "one": "A(z) {} és 1 további alkalmazás frissítéseket kapott.", - "other": "{} és {} további alkalmazás frissítéseket kapott." - }, - "xAndNMoreUpdatesInstalled": { - "one": "A(z) {} és 1 további alkalmazás frissítve.", - "other": "{} és {} további alkalmazás frissítve." - }, - "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} és 1 további alkalmazás is frissült.", - "other": "{} és {} további alkalmazás is frissült." - } -} +{ + "invalidURLForSource": "Érvénytelen a(z) {} app URL-je", + "noReleaseFound": "Nem található megfelelő kiadás", + "noVersionFound": "Nem sikerült meghatározni a kiadás verzióját", + "urlMatchesNoSource": "Az URL nem egyezik ismert forrással", + "cantInstallOlderVersion": "Nem telepíthető egy app régebbi verziója", + "appIdMismatch": "A letöltött csomagazonosító nem egyezik a meglévő app azonosítóval", + "functionNotImplemented": "Ez az osztály nem valósította meg ezt a függvényt", + "placeholder": "Helykitöltő", + "someErrors": "Néhány hiba történt", + "unexpectedError": "Váratlan hiba", + "ok": "Oké", + "and": "és", + "githubPATLabel": "GitHub Personal Access Token (megnöveli a díjkorlátot)", + "includePrereleases": "Tartalmazza az előzetes kiadásokat", + "fallbackToOlderReleases": "Visszatérés a régebbi kiadásokhoz", + "filterReleaseTitlesByRegEx": "A kiadás címeinek szűrése reguláris kifejezéssel", + "invalidRegEx": "Érvénytelen reguláris kifejezés", + "noDescription": "Nincs leírás", + "cancel": "Mégse", + "continue": "Tovább", + "requiredInBrackets": "(Kötelező)", + "dropdownNoOptsError": "HIBA: A LEDOBÁST LEGALÁBB EGY OPCIÓHOZ KELL RENDELNI", + "colour": "Szín", + "githubStarredRepos": "GitHub Csillagos Repo-k", + "uname": "Felh.név", + "wrongArgNum": "Rossz számú argumentumot adott meg", + "xIsTrackOnly": "A(z) {} csak nyomonkövethető", + "source": "Forrás", + "app": "App", + "appsFromSourceAreTrackOnly": "Az ebből a forrásból származó alkalmazások 'Csak nyomon követhetőek'.", + "youPickedTrackOnly": "A 'Csak követés' opciót választotta.", + "trackOnlyAppDescription": "Az alkalmazás frissítéseit nyomon követi, de az Obtainium nem tudja letölteni vagy telepíteni.", + "cancelled": "Törölve", + "appAlreadyAdded": "Az app már hozzáadva", + "alreadyUpToDateQuestion": "Az app már naprakész?", + "addApp": "App hozzáadás", + "appSourceURL": "App forrás URL", + "error": "Hiba", + "add": "Hozzáadás", + "searchSomeSourcesLabel": "Keresés (csak egyes források)", + "search": "Keresés", + "additionalOptsFor": "További lehetőségek a következőhöz: {}", + "supportedSources": "Támogatott források", + "trackOnlyInBrackets": "(Csak nyomonkövetés)", + "searchableInBrackets": "(Kereshető)", + "appsString": "Appok", + "noApps": "Nincs App", + "noAppsForFilter": "Nincsenek appok a szűrőhöz", + "byX": "Fejlesztő: {}", + "percentProgress": "Folyamat: {}%", + "pleaseWait": "Kis türelmet", + "updateAvailable": "Frissítés érhető el", + "estimateInBracketsShort": "(Becsült)", + "notInstalled": "Nem telepített", + "estimateInBrackets": "(Becslés)", + "selectAll": "Mindet kiválaszt", + "deselectN": "Törölje {} kijelölését", + "xWillBeRemovedButRemainInstalled": "A(z) {} el lesz távolítva az Obtainiumból, de továbbra is telepítve marad az eszközön.", + "removeSelectedAppsQuestion": "Eltávolítja a kiválasztott appokat?", + "removeSelectedApps": "Távolítsa el a kiválasztott appokat", + "updateX": "Frissítés: {}", + "installX": "Telepítés: {}", + "markXTrackOnlyAsUpdated": "Jelölje meg: {}\n(Csak nyomon követhető)\nmint Frissített", + "changeX": "Változás {}", + "installUpdateApps": "Appok telepítése/frissítése", + "installUpdateSelectedApps": "Telepítse/frissítse a kiválasztott appokat", + "markXSelectedAppsAsUpdated": "Megjelöl {} kiválasztott alkalmazást frissítettként?", + "no": "Nem", + "yes": "Igen", + "markSelectedAppsUpdated": "Jelölje meg a kiválasztott appokat frissítettként", + "pinToTop": "Rögzítés felülre", + "unpinFromTop": "Eltávolít felülről", + "resetInstallStatusForSelectedAppsQuestion": "Visszaállítja a kiválasztott appok telepítési állapotát?", + "installStatusOfXWillBeResetExplanation": "A kiválasztott appok telepítési állapota visszaáll.\n\nEz akkor segíthet, ha az Obtainiumban megjelenített app verzió hibás, frissítések vagy egyéb problémák miatt.", + "shareSelectedAppURLs": "Ossza meg a kiválasztott app URL címeit", + "resetInstallStatus": "Telepítési állapot visszaállítása", + "more": "További", + "removeOutdatedFilter": "Távolítsa el az elavult app szűrőt", + "showOutdatedOnly": "Csak az elavult appok megjelenítése", + "filter": "Szűrő", + "filterActive": "Szűrő *", + "filterApps": "Appok szűrése", + "appName": "App név", + "author": "Szerző", + "upToDateApps": "Naprakész appok", + "nonInstalledApps": "Nem telepített appok", + "importExport": "Import/Export", + "settings": "Beállítások", + "exportedTo": "Exportálva ide {}", + "obtainiumExport": "Obtainium Adat Exportálás", + "invalidInput": "Hibás bemenet", + "importedX": "Importálva innen {}", + "obtainiumImport": "Obtainium Adat Importálás", + "importFromURLList": "Importálás URL listából", + "searchQuery": "Keresési lekérdezés", + "appURLList": "App URL lista", + "line": "Sor", + "searchX": "Keresés {}", + "noResults": "Nincs találat", + "importX": "Import {}", + "importedAppsIdDisclaimer": "Előfordulhat, hogy az importált appok helytelenül \"Nincs telepítve\" jelzéssel jelennek meg.\nA probléma megoldásához telepítse újra őket az Obtainiumon keresztül.\nEz nem érinti az alkalmazásadatokat.\n\nCsak az URL-ekre és a harmadik féltől származó importálási módszerekre vonatkozik..", + "importErrors": "Importálási hibák", + "importedXOfYApps": "{}/{} app importálva.", + "followingURLsHadErrors": "A következő URL-ek hibákat tartalmaztak:", + "okay": "Oké", + "selectURL": "Válassza ki az URL-t", + "selectURLs": "Kiválasztott URL-ek", + "pick": "Válasszon", + "theme": "Téma", + "dark": "Sötét", + "light": "Világos", + "followSystem": "Rendszer szerint", + "obtainium": "Obtainium", + "materialYou": "Material You", + "useBlackTheme": "Használjon tiszta fekete sötét témát", + "appSortBy": "App rendezés...", + "authorName": "Szerző/Név", + "nameAuthor": "Név/Szerző", + "asAdded": "Mint Hozzáadott", + "appSortOrder": "Appok rendezése", + "ascending": "Emelkedő", + "descending": "Csökkenő", + "bgUpdateCheckInterval": "Háttérfrissítés ellenőrzés időköze", + "neverManualOnly": "Soha – csak manuális", + "appearance": "Megjelenés", + "showWebInAppView": "Forrás megjelenítése az Appok nézetben", + "pinUpdates": "Frissítések kitűzése az App nézet tetejére", + "updates": "Frissítések", + "sourceSpecific": "Forrás-specifikus", + "appSource": "App forrás", + "noLogs": "Nincsenek naplók", + "appLogs": "App naplók", + "close": "Bezárás", + "share": "Megosztás", + "appNotFound": "App nem található", + "obtainiumExportHyphenatedLowercase": "obtainium-export", + "pickAnAPK": "Válasszon egy APK-t", + "appHasMoreThanOnePackage": "A(z) {} egynél több csomaggal rendelkezik:", + "deviceSupportsXArch": "Eszköze támogatja a {} CPU architektúrát.", + "deviceSupportsFollowingArchs": "Az eszköze a következő CPU architektúrákat támogatja:", + "warning": "Figyelem", + "sourceIsXButPackageFromYPrompt": "Az alkalmazás forrása „{}”, de a kiadási csomag innen származik: „{}”. Folytatja?", + "updatesAvailable": "Frissítések érhetők el", + "updatesAvailableNotifDescription": "Értesíti a felhasználót, hogy frissítések állnak rendelkezésre egy vagy több, az Obtainium által nyomon követett alkalmazáshoz", + "noNewUpdates": "Nincsenek új frissítések.", + "xHasAnUpdate": "A(z) {} frissítést kapott.", + "appsUpdated": "Alkalmazások frissítve", + "appsUpdatedNotifDescription": "Értesíti a felhasználót, hogy egy/több app frissítése megtörtént a háttérben", + "xWasUpdatedToY": "{} frissítve a következőre: {}.", + "errorCheckingUpdates": "Hiba a frissítések keresésekor", + "errorCheckingUpdatesNotifDescription": "Értesítés, amely akkor jelenik meg, ha a háttérbeli frissítések ellenőrzése sikertelen", + "appsRemoved": "Alkalmazások eltávolítva", + "appsRemovedNotifDescription": "Értesíti a felhasználót egy vagy több alkalmazás eltávolításáról a betöltésük során fellépő hibák miatt", + "xWasRemovedDueToErrorY": "A(z) {} a következő hiba miatt lett eltávolítva: {}", + "completeAppInstallation": "Teljes app telepítés", + "obtainiumMustBeOpenToInstallApps": "Az Obtainiumnak megnyitva kell lennie az alkalmazások telepítéséhez", + "completeAppInstallationNotifDescription": "Megkéri a felhasználót, hogy térjen vissza az Obtainiumhoz, hogy befejezze az alkalmazás telepítését", + "checkingForUpdates": "Frissítések keresése", + "checkingForUpdatesNotifDescription": "Átmeneti értesítés, amely a frissítések keresésekor jelenik meg", + "pleaseAllowInstallPerm": "Kérjük, engedélyezze az Obtainiumnak az alkalmazások telepítését", + "trackOnly": "Csak követés", + "errorWithHttpStatusCode": "Hiba {}", + "versionCorrectionDisabled": "Verzió korrekció letiltva (úgy tűnik, a beépülő modul nem működik)", + "unknown": "Ismeretlen", + "none": "Egyik sem", + "never": "Soha", + "latestVersionX": "Legújabb verzió: {}", + "installedVersionX": "Telepített verzió: {}", + "lastUpdateCheckX": "Frissítés ellenőrizve: {}", + "remove": "Eltávolítás", + "yesMarkUpdated": "Igen, megjelölés frissítettként", + "fdroid": "F-Droid Official", + "appIdOrName": "App ID vagy név", + "appId": "App ID", + "appWithIdOrNameNotFound": "Nem található app ezzel az azonosítóval vagy névvel", + "reposHaveMultipleApps": "A repók több alkalmazást is tartalmazhatnak", + "fdroidThirdPartyRepo": "F-Droid Harmadik-fél Repo", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Chat", + "install": "Telepít", + "markInstalled": "Telepítettnek jelöl", + "update": "Frissít", + "markUpdated": "Frissítettnek jelöl", + "additionalOptions": "További lehetőségek", + "disableVersionDetection": "Verzió érzékelés letiltása", + "noVersionDetectionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzióérzékelés nem működik megfelelően.", + "downloadingX": "{} letöltés", + "downloadNotifDescription": "Értesíti a felhasználót az app letöltésének előrehaladásáról", + "noAPKFound": "Nem található APK", + "noVersionDetection": "Nincs verzió érzékelés", + "categorize": "Kategorizálás", + "categories": "Kategóriák", + "category": "Kategória", + "noCategory": "Nincs kategória", + "noCategories": "No Categories", + "deleteCategoryQuestion": "Törli a kategóriát?", + "categoryDeleteWarning": "A(z) {} összes app kategorizálatlan állapotba kerül.", + "addCategory": "Új kategória", + "label": "Címke", + "language": "Nyelv", + "copiedToClipboard": "Másolva a vágólapra", + "storagePermissionDenied": "Tárhely engedély megtagadva", + "selectedCategorizeWarning": "Ez felváltja a kiválasztott alkalmazások meglévő kategória-beállításait.", + "filterAPKsByRegEx": "Az APK-k szűrése reguláris kifejezéssel", + "removeFromObtainium": "Eltávolítás az Obtainiumból", + "uninstallFromDevice": "Eltávolítás a készülékről", + "onlyWorksWithNonVersionDetectApps": "Csak azoknál az alkalmazásoknál működik, amelyeknél a verzióérzékelés le van tiltva.", + "releaseDateAsVersion": "Használja a Kiadás dátumát, mint verziót", + "releaseDateAsVersionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzió érzékelése nem működik megfelelően, de elérhető a kiadás dátuma.", + "changes": "Változtatások", + "releaseDate": "Kiadás dátuma", + "importFromURLsInFile": "Importálás fájlban található URL-ből (mint pl. OPML)", + "versionDetection": "Verzió érzékelés", + "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-okat", + "overrideSource": "Forrás felülbírálása", + "dontShowAgain": "Ne mutassa ezt újra", + "dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést", + "dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket", + "moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára", + "gitlabPATLabel": "GitLab Personal Access Token\n(Engedélyezi a Keresést és jobb APK felfedezés)", + "about": "Rólunk", + "requiresCredentialsInSettings": "Ehhez további hitelesítő adatokra van szükség (a Beállításokban)", + "checkOnStart": "Egyszer az alkalmazás indításakor is", + "tryInferAppIdFromCode": "Próbálja kikövetkeztetni az app azonosítót a forráskódból", + "removeOnExternalUninstall": "A külsőleg eltávolított appok auto. eltávolítása", + "pickHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", + "checkUpdateOnDetailPage": "Frissítések keresése az app részleteit tartalmazó oldal megnyitásakor", + "disablePageTransitions": "Lap áttűnési animációk letiltása", + "reversePageTransitions": "Fordított lap áttűnési animációk", + "minStarCount": "Minimális csillag szám", + "addInfoBelow": "Adja hozzá ezt az infót alább.", + "addInfoInSettings": "Adja hozzá ezt az infót a Beállításokban.", + "githubSourceNote": "A GitHub sebességkorlátozás elkerülhető API-kulcs használatával.", + "gitlabSourceNote": "Előfordulhat, hogy a GitLab APK kibontása nem működik API-kulcs nélkül.", + "sortByFileNamesNotLinks": "Fájlnevek szerinti elrendezés teljes linkek helyett", + "filterReleaseNotesByRegEx": "Kiadási megjegyzések szűrése reguláris kifejezéssel", + "customLinkFilterRegex": "Egyéni APK hivatkozásszűrő reguláris kifejezéssel (Alapérték '.apk$')", + "appsPossiblyUpdated": "App frissítési kísérlet", + "appsPossiblyUpdatedNotifDescription": "Értesíti a felhasználót, hogy egy vagy több alkalmazás frissítése lehetséges a háttérben", + "xWasPossiblyUpdatedToY": "{} frissítve lehet erre {}.", + "backgroundUpdateReqsExplanation": "Előfordulhat, hogy nem minden appnál lehetséges a háttérbeli frissítés.", + "backgroundUpdateLimitsExplanation": "A háttérben történő telepítés sikeressége csak az Obtainium megnyitásakor állapítható meg.", + "verifyLatestTag": "Ellenőrizze a „legújabb” címkét", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", + "intermediateLinkNotFound": "Intermediate link not found", + "exemptFromBackgroundUpdates": "Mentes a háttérben történő frissítések alól (ha engedélyezett)", + "bgUpdatesOnWiFiOnly": "Tiltsa le a háttérben frissítéseket, ha nincs Wi-Fi-n", + "autoSelectHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", + "versionExtractionRegEx": "Verzió kibontása reguláris kifejezéssel", + "matchGroupToUse": "Párosítsa a csoportot a használathoz", + "highlightTouchTargets": "Emelje ki a kevésbé nyilvánvaló érintési célokat", + "pickExportDir": "Válassza az Exportálási könyvtárat", + "autoExportOnChanges": "Auto-exportálás a változások után", + "filterVersionsByRegEx": "Verziók szűrése reguláris kifejezéssel", + "trySelectingSuggestedVersionCode": "Próbálja ki a javasolt verziókódú APK-t", + "dontSortReleasesList": "Az API-ból származó kiadási sorrend megőrzése", + "reverseSort": "Fordított rendezés", + "debugMenu": "Hibakereső menü", + "bgTaskStarted": "A háttérfeladat elindult – ellenőrizze a naplókat.", + "enableBackgroundUpdates": "Frissítések a háttérben", + "runBgCheckNow": "Futtassa a Háttérben frissítés ellenőrzését most", + "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "installing": "Installing", + "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "Frissítések érhetők el", + "appsUpdatedNotifChannel": "Alkalmazások frissítve", + "appsPossiblyUpdatedNotifChannel": "App frissítési kísérlet", + "errorCheckingUpdatesNotifChannel": "Hiba a frissítések keresésekor", + "appsRemovedNotifChannel": "Alkalmazások eltávolítva", + "downloadingXNotifChannel": "{} letöltés", + "completeAppInstallationNotifChannel": "Teljes app telepítés", + "checkingForUpdatesNotifChannel": "Frissítések keresése", + "removeAppQuestion": { + "one": "Eltávolítja az alkalmazást?", + "other": "Eltávolítja az alkalmazást?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Túl sok kérés (korlátozott arány) – próbálja újra {} perc múlva", + "other": "Túl sok kérés (korlátozott arány) – próbálja újra {} perc múlva" + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "A háttérfrissítések ellenőrzése {}-t észlelt, {} perc múlva ütemezi az újrapróbálkozást", + "other": "A háttérfrissítések ellenőrzése {}-t észlelt, {} perc múlva ütemezi az újrapróbálkozást" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "A háttérfrissítés ellenőrzése {} frissítést talált – szükség esetén értesíti a felhasználót", + "other": "A háttérfrissítés ellenőrzése {} frissítést talált – szükség esetén értesíti a felhasználót" + }, + "apps": { + "one": "{} app", + "other": "{} app" + }, + "url": { + "one": "{} URL", + "other": "{} URL" + }, + "minute": { + "one": "{} perc", + "other": "{} perc" + }, + "hour": { + "one": "{} óra", + "other": "{} óra" + }, + "day": { + "one": "{} nap", + "other": "{} nap" + }, + "clearedNLogsBeforeXAfterY": { + "one": "{n} napló törölve (előtte = {előtte}, utána = {utána})", + "other": "{n} napló törölve (előtte = {előtte}, utána = {utána})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "A(z) {} és 1 további alkalmazás frissítéseket kapott.", + "other": "{} és {} további alkalmazás frissítéseket kapott." + }, + "xAndNMoreUpdatesInstalled": { + "one": "A(z) {} és 1 további alkalmazás frissítve.", + "other": "{} és {} további alkalmazás frissítve." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "{} és 1 további alkalmazás is frissült.", + "other": "{} és {} további alkalmazás is frissült." + } +} \ No newline at end of file diff --git a/assets/translations/it.json b/assets/translations/it.json index 10ce3f3..8ec4682 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "Aggiornamenti disponibili", + "appsUpdatedNotifChannel": "App aggiornate", + "appsPossiblyUpdatedNotifChannel": "App Updates Attempted", + "errorCheckingUpdatesNotifChannel": "Controllo degli errori per gli aggiornamenti", + "appsRemovedNotifChannel": "App rimosse", + "downloadingXNotifChannel": "Scaricamento di {} in corso", + "completeAppInstallationNotifChannel": "Completa l'installazione dell'app", + "checkingForUpdatesNotifChannel": "Controllo degli aggiornamenti in corso", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" @@ -318,4 +326,4 @@ "one": "{} and 1 more app may have been updated.", "other": "{} and {} more apps may have been updated." } -} +} \ No newline at end of file diff --git a/assets/translations/ja.json b/assets/translations/ja.json index c1edaf5..596669d 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "アップデートが利用可能", + "appsUpdatedNotifChannel": "アプリをアップデートしました", + "appsPossiblyUpdatedNotifChannel": "アプリのアップデートを試行", + "errorCheckingUpdatesNotifChannel": "アップデート確認中のエラー", + "appsRemovedNotifChannel": "削除されたアプリ", + "downloadingXNotifChannel": "{} をダウンロード中", + "completeAppInstallationNotifChannel": "アプリのインストールを完了する", + "checkingForUpdatesNotifChannel": "アップデートを確認中", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" @@ -318,4 +326,4 @@ "one": "{} とさらに 1 個のアプリがアップデートされた可能性があります。", "other": "{} とさらに {} 個のアプリがアップデートされた可能性があります。" } -} +} \ No newline at end of file diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 72278c3..184255a 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -16,7 +16,7 @@ "fallbackToOlderReleases": "Powracaj do starszych wersji", "filterReleaseTitlesByRegEx": "Filtruj tytuły wydań wg. wyrażeń regularnych", "invalidRegEx": "Nieprawidłowe wyrażenie regularne", - "noDescription": "Brak opisu", + "noDescription": "Brak opisu", "cancel": "Anuluj", "continue": "Kontynuuj", "requiredInBrackets": "(Wymagane)", @@ -66,7 +66,7 @@ "installUpdateApps": "Instaluj/aktualizuj aplikacje", "installUpdateSelectedApps": "Zainstaluj/zaktualizuj wybrane aplikacje", "markXSelectedAppsAsUpdated": "Oznaczyć {} wybranych aplikacji jako zaktualizowane?", - "no": "Nie", + "no": "Nie", "yes": "Tak", "markSelectedAppsUpdated": "Oznacz wybrane aplikacje jako zaktualizowane", "pinToTop": "Przypnij", @@ -172,7 +172,7 @@ "yesMarkUpdated": "Tak, oznacz jako zaktualizowane", "fdroid": "Oficjalny F-Droid", "appIdOrName": "ID aplikacji lub nazwa", - "appId": "ID aplikacji", + "appId": "ID aplikacji", "appWithIdOrNameNotFound": "Nie znaleziono aplikacji o tym identyfikatorze lub nazwie", "reposHaveMultipleApps": "Repozytoria mogą zawierać wiele aplikacji", "fdroidThirdPartyRepo": "Zewnętrzne repo F-Droid", @@ -243,14 +243,14 @@ "appsPossiblyUpdatedNotifDescription": "Powiadamiaj o potencjalnym zastosowaniu w tle aktualizacji jednej lub większej ilości aplikacji", "xWasPossiblyUpdatedToY": "{} być może zaktualizowano do {}.", "enableBackgroundUpdates": "Włącz aktualizacje w tle", - "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", + "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", "backgroundUpdateLimitsExplanation": "Powodzenie instalacji w tle można określić dopiero po otwarciu Obtainium.", "verifyLatestTag": "Zweryfikuj najnowszy tag", "intermediateLinkRegex": "Filtr linków \"pośrednich\" do odwiedzenia w pierwszej kolejności", "intermediateLinkNotFound": "Nie znaleziono linku pośredniego", "exemptFromBackgroundUpdates": "Wyklucz z uaktualnień w tle (jeśli są włączone)", "bgUpdatesOnWiFiOnly": "Wyłącz aktualizacje w tle, gdy nie ma połączenia z Wi-Fi", - "autoSelectHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", + "autoSelectHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", "versionExtractionRegEx": "Wyrażenie regularne wyodrębniające wersję", "matchGroupToUse": "Dopasuj grupę do użycia", "highlightTouchTargets": "Wyróżnij mniej oczywiste elementy dotykowe", @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "Dostępne aktualizacje", + "appsUpdatedNotifChannel": "Zaktualizowane aplikacje", + "appsPossiblyUpdatedNotifChannel": "Informuj o próbach aktualizacji", + "errorCheckingUpdatesNotifChannel": "Sprawdzanie błędów aktualizacji", + "appsRemovedNotifChannel": "Usunięte aplikacje", + "downloadingXNotifChannel": "Pobieranie {}", + "completeAppInstallationNotifChannel": "Ukończenie instalacji aplikacji", + "checkingForUpdatesNotifChannel": "Sprawdzanie aktualizacji", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", @@ -276,9 +284,9 @@ "one": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minutę", "few": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minuty", "many": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minut", - "other": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minuty" + "other": "Zbyt wiele żądań (ograniczona częstotliwość) - spróbuj ponownie za {} minuty" }, - "bgUpdateGotErrorRetryInMinutes": { + "bgUpdateGotErrorRetryInMinutes": { "one": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minutę", "few": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minuty", "many": "Sprawdzanie aktualizacji w tle napotkało {}, zaplanuje ponowne sprawdzenie za {} minut", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index 31ff890..1eaaec3 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "Atualizações Disponíveis", + "appsUpdatedNotifChannel": "Apps Atualizados", + "appsPossiblyUpdatedNotifChannel": "Tentativas de atualização de Apps", + "errorCheckingUpdatesNotifChannel": "Erro ao Procurar por Atualizações", + "appsRemovedNotifChannel": "Apps Removidos", + "downloadingXNotifChannel": "Baixando {}", + "completeAppInstallationNotifChannel": "Instalação completa do App", + "checkingForUpdatesNotifChannel": "Checando por Atualizações", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" @@ -318,4 +326,4 @@ "one": "{} e 1 outro app pode ter sido atualizado.", "other": "{} e {} outros apps podem ter sido atualizados." } -} +} \ No newline at end of file diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 9628df3..f4cf61a 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "Доступны обновления", + "appsUpdatedNotifChannel": "Приложения обновлены", + "appsPossiblyUpdatedNotifChannel": "Попытки обновления приложений", + "errorCheckingUpdatesNotifChannel": "Ошибка при проверке обновлений", + "appsRemovedNotifChannel": "Приложение удалено", + "downloadingXNotifChannel": "Загрузка {}", + "completeAppInstallationNotifChannel": "Завершение установки приложения", + "checkingForUpdatesNotifChannel": "Проверка обновлений", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" @@ -318,4 +326,4 @@ "one": "{} и ещё 1 приложение могли быть обновлены.", "other": "{} и ещё {} приложений могли быть обновлены." } -} +} \ No newline at end of file diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 609aff5..b6580ce 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -266,6 +266,14 @@ "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", + "updatesAvailableNotifChannel": "更新可用", + "appsUpdatedNotifChannel": "应用已更新", + "appsPossiblyUpdatedNotifChannel": "已尝试更新应用", + "errorCheckingUpdatesNotifChannel": "检查更新出错", + "appsRemovedNotifChannel": "应用已删除", + "downloadingXNotifChannel": "正在下载{}", + "completeAppInstallationNotifChannel": "完成应用安装", + "checkingForUpdatesNotifChannel": "正在检查更新", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" @@ -318,4 +326,4 @@ "one": "{} 和另外 1 个应用已尝试更新。", "other": "{} 和另外 {} 个应用已尝试更新。" } -} +} \ No newline at end of file diff --git a/lib/providers/notifications_provider.dart b/lib/providers/notifications_provider.dart index 452512a..851fb18 100644 --- a/lib/providers/notifications_provider.dart +++ b/lib/providers/notifications_provider.dart @@ -28,7 +28,7 @@ class UpdateNotification extends ObtainiumNotification { tr('updatesAvailable'), '', 'UPDATES_AVAILABLE', - tr('updatesAvailable'), + tr('updatesAvailableNotifChannel'), tr('updatesAvailableNotifDescription'), Importance.max) { message = updates.isEmpty @@ -42,8 +42,14 @@ class UpdateNotification extends ObtainiumNotification { class SilentUpdateNotification extends ObtainiumNotification { SilentUpdateNotification(List updates, {int? id}) - : super(id ?? 3, tr('appsUpdated'), '', 'APPS_UPDATED', tr('appsUpdated'), - tr('appsUpdatedNotifDescription'), Importance.defaultImportance) { + : super( + id ?? 3, + tr('appsUpdated'), + '', + 'APPS_UPDATED', + tr('appsUpdatedNotifChannel'), + tr('appsUpdatedNotifDescription'), + Importance.defaultImportance) { message = updates.length == 1 ? tr('xWasUpdatedToY', args: [updates[0].finalName, updates[0].latestVersion]) @@ -59,7 +65,7 @@ class SilentUpdateAttemptNotification extends ObtainiumNotification { tr('appsPossiblyUpdated'), '', 'APPS_POSSIBLY_UPDATED', - tr('appsPossiblyUpdated'), + tr('appsPossiblyUpdatedNotifChannel'), tr('appsPossiblyUpdatedNotifDescription'), Importance.defaultImportance) { message = updates.length == 1 @@ -77,15 +83,21 @@ class ErrorCheckingUpdatesNotification extends ObtainiumNotification { tr('errorCheckingUpdates'), error, 'BG_UPDATE_CHECK_ERROR', - tr('errorCheckingUpdates'), + tr('errorCheckingUpdatesNotifChannel'), tr('errorCheckingUpdatesNotifDescription'), Importance.high); } class AppsRemovedNotification extends ObtainiumNotification { AppsRemovedNotification(List> namedReasons) - : super(6, tr('appsRemoved'), '', 'APPS_REMOVED', tr('appsRemoved'), - tr('appsRemovedNotifDescription'), Importance.max) { + : super( + 6, + tr('appsRemoved'), + '', + 'APPS_REMOVED', + tr('appsRemovedNotifChannel'), + tr('appsRemovedNotifDescription'), + Importance.max) { message = ''; for (var r in namedReasons) { message += '${tr('xWasRemovedDueToErrorY', args: [r[0], r[1]])} \n'; @@ -101,7 +113,7 @@ class DownloadNotification extends ObtainiumNotification { tr('downloadingX', args: [appName]), '', 'APP_DOWNLOADING', - tr('downloadingX', args: [tr('app')]), + tr('downloadingXNotifChannel', args: [tr('app')]), tr('downloadNotifDescription'), Importance.low, onlyAlertOnce: true, @@ -113,7 +125,7 @@ final completeInstallationNotification = ObtainiumNotification( tr('completeAppInstallation'), tr('obtainiumMustBeOpenToInstallApps'), 'COMPLETE_INSTALL', - tr('completeAppInstallation'), + tr('completeAppInstallationNotifChannel'), tr('completeAppInstallationNotifDescription'), Importance.max); @@ -124,7 +136,7 @@ class CheckingUpdatesNotification extends ObtainiumNotification { tr('checkingForUpdates'), appName, 'BG_UPDATE_CHECK', - tr('checkingForUpdates'), + tr('checkingForUpdatesNotifChannel'), tr('checkingForUpdatesNotifDescription'), Importance.min); } From 67b56cee50bdcd7fe31675315d242b5ca479e724 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Thu, 12 Oct 2023 19:51:55 -0400 Subject: [PATCH 550/600] Upgrade packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 16 ++++++++-------- pubspec.yaml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index bb0ac3a..4088f9b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.26'; +const String currentVersion = '0.14.27'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index a51aef1..3ea4961 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -142,10 +142,10 @@ packages: dependency: transitive description: name: cross_file - sha256: fd832b5384d0d6da4f6df60b854d33accaaeb63aa9e10e736a87381f08dee2cb + sha256: "445db18de832dba8d851e287aff8ccf169bed30d2e94243cb54c7d2f1ed2142c" url: "https://pub.dev" source: hosted - version: "0.3.3+5" + version: "0.3.3+6" crypto: dependency: transitive description: @@ -238,10 +238,10 @@ packages: dependency: transitive description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "7.0.0" file_picker: dependency: "direct main" description: @@ -658,10 +658,10 @@ packages: dependency: transitive description: name: shared_preferences_linux - sha256: c2eb5bf57a2fe9ad6988121609e47d3e07bb3bdca5b6f8444e4cf302428a128a + sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" shared_preferences_platform_interface: dependency: transitive description: @@ -682,10 +682,10 @@ packages: dependency: transitive description: name: shared_preferences_windows - sha256: f763a101313bd3be87edffe0560037500967de9c394a714cd598d945517f694f + sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" shared_storage: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index a860b55..be36743 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.14.26+218 # When changing this, update the tag in main() accordingly +version: 0.14.27+219 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 03447c33be0a3cdaafcc61c65903242fd589cdcc Mon Sep 17 00:00:00 2001 From: DwainZwerg <97027379+DwainZwerg@users.noreply.github.com> Date: Fri, 13 Oct 2023 07:30:23 +0000 Subject: [PATCH 551/600] Update de.json --- assets/translations/de.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 90fbdc6..bc0a558 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -170,7 +170,7 @@ "lastUpdateCheckX": "Letzte Aktualisierungsprüfung: {}", "remove": "Entfernen", "yesMarkUpdated": "Ja, als aktualisiert markieren", - "fdroid": "F-Droid Official", + "fdroid": "offizielles F-Droid-Repo", "appIdOrName": "App ID oder Name", "appId": "App ID", "appWithIdOrNameNotFound": "Es wurde keine App mit dieser ID oder diesem Namen gefunden", @@ -246,26 +246,26 @@ "backgroundUpdateReqsExplanation": "Die Hintergrundaktualisierung ist möglicherweise nicht für alle Apps möglich.", "backgroundUpdateLimitsExplanation": "Der Erfolg einer Hintergrundinstallation kann nur festgestellt werden, wenn Obtainium geöffnet wird.", "verifyLatestTag": "Überprüfe das „latest“ Tag", - "intermediateLinkRegex": "Filter für einen \"Zwischen\"-Link, der zuerst besucht werden soll", - "intermediateLinkNotFound": "Zwischenlink nicht gefunden", + "intermediateLinkRegex": "Filter für einen \„Zwischen\“-Link, der zuerst besucht werden soll", + "intermediateLinkNotFound": "\„Zwischen\“link nicht gefunden", "exemptFromBackgroundUpdates": "Ausschluss von Hintergrundaktualisierungen (falls aktiviert)", "bgUpdatesOnWiFiOnly": "Hintergrundaktualisierungen deaktivieren, wenn kein WLAN vorhanden ist", "autoSelectHighestVersionCode": "Automatisch höchste APK-Code-Version auswählen", - "versionExtractionRegEx": "Versions-Extraktion RegEx", + "versionExtractionRegEx": "Versions-Extraktion per RegEx", "matchGroupToUse": "Zu verwendende Gruppe abgleichen", "highlightTouchTargets": "Weniger offensichtliche Ziele hervorheben", "pickExportDir": "Export-Verzeichnis wählen", "autoExportOnChanges": "Automatischer Export bei Änderung", "filterVersionsByRegEx": "Versionen nach regulären Ausdrücken filtern", "trySelectingSuggestedVersionCode": "Versuchen, die vorgeschlagene APK-Code-Version auszuwählen", - "dontSortReleasesList": "Retain release order from API", + "dontSortReleasesList": "Freigaberelease von der API ordern", "reverseSort": "Umgekehrtes Sortieren", - "debugMenu": "Debug Menü", + "debugMenu": "Debug-Menü", "bgTaskStarted": "Hintergrundaufgabe gestartet – Logs prüfen.", "runBgCheckNow": "Hintergrundaktualisierungsprüfung jetzt durchführen", - "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", - "installing": "Installing", - "skipUpdateNotifications": "Skip update notifications", + "versionExtractWholePage": "Versions-Extraktion per RegEx auf die gesamte Seite anwenden", + "installing": "Installiere", + "skipUpdateNotifications": "Keine Benachrichtigung zu App-Updates geben", "updatesAvailableNotifChannel": "Aktualisierungen verfügbar", "appsUpdatedNotifChannel": "Apps aktualisiert", "appsPossiblyUpdatedNotifChannel": "App Aktualisierungen wurden versucht", @@ -326,4 +326,4 @@ "one": "{} und 1 weitere Anwendung wurden möglicherweise aktualisiert.", "other": "{} und {} weitere Anwendungen wurden möglicherweise aktualisiert." } -} \ No newline at end of file +} From 1eefeae060a423db53ce352bf982f0422414bfea Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Fri, 13 Oct 2023 13:00:16 +0200 Subject: [PATCH 552/600] locale(pl): Update Polish translations --- assets/translations/pl.json | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 184255a..9aa9f31 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -142,20 +142,20 @@ "warning": "Uwaga", "sourceIsXButPackageFromYPrompt": "Źródłem aplikacji jest '{}', ale pakiet wydania pochodzi z '{}'. Kontynuować?", "updatesAvailable": "Dostępne aktualizacje", - "updatesAvailableNotifDescription": "Powiadamia użytkownika o dostępności aktualizacji dla jednej lub więcej aplikacji obserwowanych przez Obtainium", + "updatesAvailableNotifDescription": "Informuje o dostępności aktualizacji dla jednej lub więcej aplikacji obserwowanych przez Obtainium", "noNewUpdates": "Brak nowych aktualizacji.", "xHasAnUpdate": "{} ma aktualizację.", - "appsUpdated": "Zaktualizowane aplikacje", - "appsUpdatedNotifDescription": "Powiadamia użytkownika, gdy jedna lub więcej aplikacji zostało zaktualizowanych w tle", + "appsUpdated": "Zaktualizowano aplikacje", + "appsUpdatedNotifDescription": "Informuje, gdy co najmniej jedna aplikacja została zaktualizowana w tle", "xWasUpdatedToY": "{} zaktualizowano do {}.", - "errorCheckingUpdates": "Sprawdzanie błędów aktualizacji", - "errorCheckingUpdatesNotifDescription": "Powiadomienie wyświetlane, gdy sprawdzanie aktualizacji w tle nie powiedzie się", + "errorCheckingUpdates": "Błąd sprawdzania aktualizacji", + "errorCheckingUpdatesNotifDescription": "Jest wyświetlane, gdy sprawdzanie aktualizacji w tle nie powiedzie się", "appsRemoved": "Usunięte aplikacje", - "appsRemovedNotifDescription": "Powiadamia użytkownika, gdy jedna lub więcej aplikacji zostało usuniętych z powodu błędów wczytywania", + "appsRemovedNotifDescription": "Informuje, gdy co najmniej jedna aplikacja została usunięta z powodu błędów podczas wczytywania", "xWasRemovedDueToErrorY": "Usunięto {} z powodu błędu: {}", "completeAppInstallation": "Ukończenie instalacji aplikacji", "obtainiumMustBeOpenToInstallApps": "Aby zainstalować aplikacje, Obtainium musi być otwarte", - "completeAppInstallationNotifDescription": "Prosi użytkownika o powrót do Obtainium w celu dokończenia instalacji aplikacji", + "completeAppInstallationNotifDescription": "Informuje o możliwości powrotu do Obtainium w celu dokończenia instalacji aplikacji", "checkingForUpdates": "Sprawdzanie aktualizacji", "checkingForUpdatesNotifDescription": "Tymczasowe powiadomienie pojawiające się podczas sprawdzania aktualizacji", "pleaseAllowInstallPerm": "Pozwól Obtainium instalować aplikacje", @@ -187,7 +187,7 @@ "disableVersionDetection": "Wyłącz wykrywanie wersji", "noVersionDetectionExplanation": "Opcja ta powinna być używana tylko w przypadku aplikacji, w których wykrywanie wersji nie działa poprawnie.", "downloadingX": "Pobieranie {}", - "downloadNotifDescription": "Powiadamia użytkownika o postępach w pobieraniu aplikacji", + "downloadNotifDescription": "Informuje o postępach w pobieraniu aplikacji", "noAPKFound": "Nie znaleziono pakietu APK", "noVersionDetection": "Bez wykrywania wersji", "categorize": "Kategoryzuj", @@ -240,7 +240,7 @@ "filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego", "customLinkFilterRegex": "Filtruj linki APK według wyrażenia regularnego (domyślnie \".apk$\")", "appsPossiblyUpdated": "Próbowano zaktualizować aplikację", - "appsPossiblyUpdatedNotifDescription": "Powiadamiaj o potencjalnym zastosowaniu w tle aktualizacji jednej lub większej ilości aplikacji", + "appsPossiblyUpdatedNotifDescription": "Powiadamia, gdy co najmniej jedna aktualizacja aplikacji została potencjalnie zastosowana w tle", "xWasPossiblyUpdatedToY": "{} być może zaktualizowano do {}.", "enableBackgroundUpdates": "Włącz aktualizacje w tle", "backgroundUpdateReqsExplanation": "Aktualizacje w tle mogą nie być możliwe dla wszystkich aplikacji.", @@ -252,7 +252,7 @@ "bgUpdatesOnWiFiOnly": "Wyłącz aktualizacje w tle, gdy nie ma połączenia z Wi-Fi", "autoSelectHighestVersionCode": "Automatycznie wybierz najwyższy kod wersji APK", "versionExtractionRegEx": "Wyrażenie regularne wyodrębniające wersję", - "matchGroupToUse": "Dopasuj grupę do użycia", + "matchGroupToUse": "Dopasuj grupę do użycia dla wyrażenia regularnego wyodrębniania wersji", "highlightTouchTargets": "Wyróżnij mniej oczywiste elementy dotykowe", "pickExportDir": "Wybierz katalog eksportu", "autoExportOnChanges": "Automatyczny eksport po wprowadzeniu zmian", @@ -263,17 +263,17 @@ "debugMenu": "Menu debugowania", "bgTaskStarted": "Uruchomiono zadanie w tle - sprawdź logi.", "runBgCheckNow": "Wymuś sprawdzenie aktualizacji w tle", - "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", - "installing": "Installing", - "skipUpdateNotifications": "Skip update notifications", - "updatesAvailableNotifChannel": "Dostępne aktualizacje", + "versionExtractWholePage": "Zastosuj wyrażenie regularne wyodrębniania wersji dla całej strony", + "installing": "Instalacja", + "skipUpdateNotifications": "Pomiń powiadomienia o aktualizacjach", + "updatesAvailableNotifChannel": "Dostępne aktualizacje aplikacji", "appsUpdatedNotifChannel": "Zaktualizowane aplikacje", "appsPossiblyUpdatedNotifChannel": "Informuj o próbach aktualizacji", - "errorCheckingUpdatesNotifChannel": "Sprawdzanie błędów aktualizacji", + "errorCheckingUpdatesNotifChannel": "Błędy sprawdzania aktualizacji", "appsRemovedNotifChannel": "Usunięte aplikacje", - "downloadingXNotifChannel": "Pobieranie {}", + "downloadingXNotifChannel": "Pobieranie aplikacji", "completeAppInstallationNotifChannel": "Ukończenie instalacji aplikacji", - "checkingForUpdatesNotifChannel": "Sprawdzanie aktualizacji", + "checkingForUpdatesNotifChannel": "Sprawdzanie dostępności aktualizacji", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", From 7f3e87767c25457d61dccc9c84129d1f7c2db955 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 13 Oct 2023 23:39:24 -0400 Subject: [PATCH 553/600] Switch back to parallelized BG task (#963) + better logging --- lib/custom_errors.dart | 12 +- lib/pages/app.dart | 4 +- lib/pages/apps.dart | 2 +- lib/pages/import_export.dart | 10 +- lib/pages/settings.dart | 4 +- lib/providers/apps_provider.dart | 218 ++++++++++++++++++------------- 6 files changed, 143 insertions(+), 107 deletions(-) diff --git a/lib/custom_errors.dart b/lib/custom_errors.dart index 657a82a..eed8484 100644 --- a/lib/custom_errors.dart +++ b/lib/custom_errors.dart @@ -101,9 +101,9 @@ class MultiAppMultiError extends ObtainiumError { .join('\n\n'); } -showError(dynamic e, BuildContext context) { +showMessage(dynamic e, BuildContext context, {bool isError = false}) { Provider.of(context, listen: false) - .add(e.toString(), level: LogLevels.error); + .add(e.toString(), level: isError ? LogLevels.error : LogLevels.info); if (e is String || (e is ObtainiumError && !e.unexpected)) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(e.toString())), @@ -115,8 +115,8 @@ showError(dynamic e, BuildContext context) { return AlertDialog( scrollable: true, title: Text(e is MultiAppMultiError - ? tr('someErrors') - : tr('unexpectedError')), + ? tr(isError ? 'someErrors' : 'updates') + : tr(isError ? 'unexpectedError' : 'unknown')), content: GestureDetector( onLongPress: () { Clipboard.setData(ClipboardData(text: e.toString())); @@ -137,6 +137,10 @@ showError(dynamic e, BuildContext context) { } } +showError(dynamic e, BuildContext context) { + showMessage(e, context, isError: true); +} + String list2FriendlyString(List list) { return list.length == 2 ? '${list[0]} ${tr('and')} ${list[1]}' diff --git a/lib/pages/app.dart b/lib/pages/app.dart index b49deb4..7622a96 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -292,7 +292,7 @@ class _AppPageState extends State { if (source?.enforceTrackOnly == true) { app.app.additionalSettings['trackOnly'] = true; // ignore: use_build_context_synchronously - showError(tr('appsFromSourceAreTrackOnly'), context); + showMessage(tr('appsFromSourceAreTrackOnly'), context); } if (app.app.additionalSettings['versionDetection'] == 'releaseDateAsVersion') { @@ -343,7 +343,7 @@ class _AppPageState extends State { ); if (app?.app.installedVersion != null && !trackOnly) { // ignore: use_build_context_synchronously - showError(tr('appsUpdated'), context); + showMessage(tr('appsUpdated'), context); } if (res.isNotEmpty && mounted) { Navigator.of(context).pop(); diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 49feff6..0d3c2c8 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -705,7 +705,7 @@ class AppsPageState extends State { return []; }).then((value) { if (shouldInstallUpdates) { - showError(tr('appsUpdated'), context); + showMessage(tr('appsUpdated'), context); } }); } diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index 68de7f5..200ff7a 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -81,7 +81,7 @@ class _ImportExportPageState extends State { }); appsProvider.addAppsByURL(urls).then((errors) { if (errors.isEmpty) { - showError(tr('importedX', args: [plural('apps', urls.length)]), + showMessage(tr('importedX', args: [plural('apps', urls.length)]), context); } else { showDialog( @@ -111,7 +111,7 @@ class _ImportExportPageState extends State { sp: settingsProvider) .then((String? result) { if (result != null) { - showError(tr('exportedTo', args: [result]), context); + showMessage(tr('exportedTo', args: [result]), context); } }).catchError((e) { showError(e, context); @@ -141,7 +141,7 @@ class _ImportExportPageState extends State { } }); appsProvider.addMissingCategories(settingsProvider); - showError(tr('importedX', args: [plural('apps', value)]), context); + showMessage(tr('importedX', args: [plural('apps', value)]), context); }); } else { // User canceled the picker @@ -216,7 +216,7 @@ class _ImportExportPageState extends State { var errors = await appsProvider.addAppsByURL(selectedUrls); if (errors.isEmpty) { // ignore: use_build_context_synchronously - showError( + showMessage( tr('importedX', args: [plural('apps', selectedUrls.length)]), context); @@ -274,7 +274,7 @@ class _ImportExportPageState extends State { var errors = await appsProvider.addAppsByURL(selectedUrls); if (errors.isEmpty) { // ignore: use_build_context_synchronously - showError( + showMessage( tr('importedX', args: [plural('apps', selectedUrls.length)]), context); } else { diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 02237de..265be4e 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -535,7 +535,7 @@ class _SettingsPageState extends State { onPressed: () { context.read().get().then((logs) { if (logs.isEmpty) { - showError(ObtainiumError(tr('noLogs')), context); + showMessage(ObtainiumError(tr('noLogs')), context); } else { showDialog( context: context, @@ -577,7 +577,7 @@ class _SettingsPageState extends State { const Duration(seconds: 0), bgUpdateCheckAlarmId + 200, bgUpdateCheck); - showError(tr('bgTaskStarted'), context); + showMessage(tr('bgTaskStarted'), context); }, child: Text(tr('runBgCheckNow'))) ], diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index db1087b..b84306d 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1325,18 +1325,19 @@ class _APKOriginWarningDialogState extends State { /// /// @param List>? toCheck: The appIds to check for updates (with the number of previous attempts made per appid) (defaults to all apps) /// -/// @param List? toInstall: The appIds to attempt to update (defaults to an empty array) +/// @param List? toInstall: The appIds to attempt to update (if empty - which is the default - all pending updates are taken) /// /// When toCheck is empty, the function is in "install mode" (else it is in "update mode"). -/// In update mode, all apps in toCheck are checked for updates. -/// If an update is available, the appId is either added to toInstall (if a background update is possible) or the user is notified. -/// If there are errors, the task is run again for the remaining apps after a few minutes (duration depends on the errors), up to a maximum of 5 tries for any app. +/// In update mode, all apps in toCheck are checked for updates (in parallel). +/// If an update is available and it cannot be installed silently, the user is notified of the available update. +/// If there are any errors, the task is run again for the remaining apps after a few minutes (based on the error with the longest retry interval). +/// Any app that has reached it's retry limit, the user is notified that it could not be checked. /// /// Once all update checks are complete, the task is run again in install mode. -/// In this mode, all apps in toInstall are downloaded and installed in the background (install result is unknown). -/// If there is an error, the function tries to continue after a few minutes (duration depends on the error), up to a maximum of 5 tries. +/// In this mode, all pending silent updates are downloaded and installed in the background (serially - one at a time). +/// If there is an error, the offending app is moved to the back of the line of remaining apps, and the task is retried. +/// If an app repeatedly fails to install up to its retry limit, the user is notified. /// -/// In either mode, if the function fails after the maximum number of tries, the user is notified. @pragma('vm:entry-point') Future bgUpdateCheck(int taskId, Map? params) async { WidgetsFlutterBinding.ensureInitialized(); @@ -1405,97 +1406,120 @@ Future bgUpdateCheck(int taskId, Map? params) async { bool installMode = toCheck.isEmpty; // Task is either in update mode or install mode - // In install mode, grab all available silent updates unless explicitly told otherwise - if (installMode && toInstall.isEmpty && !networkRestricted) { - var temp = appsProvider.findExistingUpdates(installedOnly: true); - for (var i = 0; i < temp.length; i++) { - if (await appsProvider - .canInstallSilently(appsProvider.apps[temp[i]]!.app)) { - toInstall.add(MapEntry(temp[i], 0)); - } - } - } - logs.add( 'BG ${installMode ? 'install' : 'update'} task $taskId: Started (${installMode ? toInstall.length : toCheck.length}).'); if (!installMode) { - // If in update mode... - var didCompleteChecking = false; - CheckingUpdatesNotification? notif; - // Loop through all updates and check each - List toNotify = []; + // If in update mode, we check for updates. + // We divide the results into 4 groups: + // - toNotify - Apps with updates that the user will be notified about (can't be silently installed) + // - toRetry - Apps with update check errors that will be retried in a while + // - toThrow - Apps with update check errors that the user will be notified about (no retry) + // After grouping the updates, we take care of toNotify and toThrow first + // Then if toRetry is not empty, we schedule another update task to run in a while + // If toRetry is empty, we take care of schedule another task that will run in install mode (toCheck is empty) + + // Init. vars. + List updates = []; // All updates found (silent and non-silent) + List toNotify = + []; // All non-silent updates that the user will be notified about + List> toRetry = + []; // All apps that got errors while checking + var retryAfterXSeconds = + 0; // How long to wait until the next attempt (if there are errors) + MultiAppMultiError? + errors; // All errors including those that will lead to a retry + MultiAppMultiError toThrow = + MultiAppMultiError(); // All errors that will not lead to a retry, just a notification + CheckingUpdatesNotification notif = CheckingUpdatesNotification( + plural('apps', toCheck.length)); // The notif. to show while checking + + // Set a bool for when we're no on wifi/wired and the user doesn't want to download apps in that state + var networkRestricted = false; + if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { + var netResult = await (Connectivity().checkConnectivity()); + networkRestricted = (netResult != ConnectivityResult.wifi) && + (netResult != ConnectivityResult.ethernet); + } + try { - for (int i = 0; i < toCheck.length; i++) { - var appId = toCheck[i].key; - var attemptCount = toCheck[i].value + 1; - AppInMemory? app = appsProvider.apps[appId]; - if (app?.app.installedVersion != null) { - try { - notificationsProvider.notify( - notif = CheckingUpdatesNotification(app?.name ?? appId), - cancelExisting: true); - App? newApp = await appsProvider.checkUpdate(appId); - if (newApp != null) { - if (networkRestricted || - !(await appsProvider.canInstallSilently(app!.app))) { - if (newApp.additionalSettings['skipUpdateNotifications'] != - true) { - toNotify.add(newApp); - } - } - } - if (i == (toCheck.length - 1)) { - didCompleteChecking = true; - } - } catch (e) { - // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue checking shortly - logs.add( - 'BG update task $taskId: Got error on checking for $appId \'${e.toString()}\'.'); - if (attemptCount < maxAttempts) { - var remainingSeconds = e is RateLimitError - ? (i == 0 ? (e.remainingMinutes * 60) : (5 * 60)) - : e is ClientException - ? (15 * 60) - : pow(attemptCount, 2).toInt(); - logs.add( - 'BG update task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); - var remainingToCheck = moveStrToEndMapEntryWithCount( - toCheck.sublist(i), MapEntry(appId, attemptCount)); - AndroidAlarmManager.oneShot(Duration(seconds: remainingSeconds), - taskId + 1, bgUpdateCheck, - params: { - 'toCheck': remainingToCheck - .map( - (entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - 'toInstall': toInstall - .map( - (entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - }); - break; - } else { - // If the offender has reached its fail limit, notify the user and remove it from the list (task can continue) - toCheck.removeAt(i); - i--; - notificationsProvider - .notify(ErrorCheckingUpdatesNotification(e.toString())); - } - } finally { - if (notif != null) { - notificationsProvider.cancel(notif.id); + // Check for updates + notificationsProvider.notify(notif, cancelExisting: true); + updates = await appsProvider.checkUpdates( + specificIds: toCheck.map((e) => e.key).toList()); + } catch (e) { + // If there were errors, group them into toRetry and toThrow based on max retry count per app + if (e is Map) { + updates = e['updates']; + errors = e['errors']; + errors!.rawErrors.forEach((key, err) { + logs.add( + 'BG update task $taskId: Got error on checking for $key \'${err.toString()}\'.'); + var toCheckApp = toCheck.where((element) => element.key == key).first; + if (toCheckApp.value < maxAttempts) { + toRetry.add(MapEntry(toCheckApp.key, toCheckApp.value + 1)); + // Next task interval is based on the error with the longest retry time + var minRetryIntervalForThisApp = err is RateLimitError + ? (err.remainingMinutes * 60) + : e is ClientException + ? (15 * 60) + : pow(toCheckApp.value + 1, 2).toInt(); + if (minRetryIntervalForThisApp > retryAfterXSeconds) { + retryAfterXSeconds = minRetryIntervalForThisApp; } + } else { + toThrow.add(key, err, appName: errors?.appIdNames[key]); } - } + }); + } else { + // We don't expect to ever get here in any situation so no need to catch (but log it in case) + logs.add('Fatal error in BG update task: ${e.toString()}'); + rethrow; } } finally { - if (toNotify.isNotEmpty) { - notificationsProvider.notify(UpdateNotification(toNotify)); + notificationsProvider.cancel(notif.id); + } + + // Filter out updates that will be installed silently (the rest go into toNotify) + for (var i = 0; i < updates.length; i++) { + if (networkRestricted || + !(await appsProvider.canInstallSilently(updates[i]))) { + if (updates[i].additionalSettings['skipUpdateNotifications'] != true) { + toNotify.add(updates[i]); + } } } - // If you're done checking and found some silently installable updates, schedule another task which will run in install mode - if (didCompleteChecking) { + + // Send the update notification + if (toNotify.isNotEmpty) { + notificationsProvider.notify(UpdateNotification(toNotify)); + } + + // Send the error notifications (grouped by error string) + if (toThrow.rawErrors.isNotEmpty) { + for (var element in toThrow.idsByErrorString.entries) { + notificationsProvider.notify(ErrorCheckingUpdatesNotification( + errors!.errorsAppsString(element.key, element.value), + id: Random().nextInt(10000))); + } + } + + // if there are update checks to retry, schedule a retry task + if (toRetry.isNotEmpty) { + logs.add( + 'BG update task $taskId: Will retry in $retryAfterXSeconds seconds.'); + AndroidAlarmManager.oneShot( + Duration(seconds: retryAfterXSeconds), taskId + 1, bgUpdateCheck, + params: { + 'toCheck': toRetry + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + 'toInstall': toInstall + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + }); + } else { + // If there are no more update checks, schedule an install task logs.add( 'BG update task $taskId: Done. Scheduling install task to run immediately.'); AndroidAlarmManager.oneShot( @@ -1506,11 +1530,19 @@ Future bgUpdateCheck(int taskId, Map? params) async { .map((entry) => {'key': entry.key, 'value': entry.value}) .toList() }); - } else if (didCompleteChecking) { - logs.add('BG update task $taskId: Done.'); } } else { - // If in install mode... + // In install mode... + // If you haven't explicitly been given updates to install (which is the case for new tasks), grab all available silent updates + if (toInstall.isEmpty && !networkRestricted) { + var temp = appsProvider.findExistingUpdates(installedOnly: true); + for (var i = 0; i < temp.length; i++) { + if (await appsProvider + .canInstallSilently(appsProvider.apps[temp[i]]!.app)) { + toInstall.add(MapEntry(temp[i], 0)); + } + } + } var didCompleteInstalling = false; var tempObtArr = toInstall.where((element) => element.key == obtainiumId); if (tempObtArr.isNotEmpty) { @@ -1562,9 +1594,9 @@ Future bgUpdateCheck(int taskId, Map? params) async { .notify(ErrorCheckingUpdatesNotification(e.toString())); } } - if (didCompleteInstalling) { - logs.add('BG install task $taskId: Done.'); - } + } + if (didCompleteInstalling || toInstall.isEmpty) { + logs.add('BG install task $taskId: Done.'); } } } From aa8d45e63659a380ea70e36e9d63a82c7d7bc4a7 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 14 Oct 2023 01:29:02 -0400 Subject: [PATCH 554/600] Make Third Party F-Droid Repos Searchable (#995) --- lib/app_sources/fdroidrepo.dart | 83 ++++++++++++++++++++++++++++-- lib/pages/add_app.dart | 2 +- lib/providers/apps_provider.dart | 8 +-- lib/providers/source_provider.dart | 17 +++--- 4 files changed, 95 insertions(+), 15 deletions(-) diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index 31f8435..22b8e49 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -7,6 +7,7 @@ import 'package:obtainium/providers/source_provider.dart'; class FDroidRepo extends AppSource { FDroidRepo() { name = tr('fdroidThirdPartyRepo'); + canSearch = true; additionalSourceAppSpecificSettingFormItems = [ [ @@ -22,12 +23,85 @@ class FDroidRepo extends AppSource { ]; } + String removeQueryParamsFromUrl(String url, {List keep = const []}) { + var uri = Uri.parse(url); + Map resultParams = {}; + uri.queryParameters.forEach((key, value) { + if (keep.contains(key)) { + resultParams[key] = value; + } + }); + url = uri.replace(queryParameters: resultParams).toString(); + if (url.endsWith('?')) { + url = url.substring(0, url.length - 1); + } + return url; + } + + @override + String sourceSpecificStandardizeURL(String url) { + var standardUri = Uri.parse(url); + var pathSegments = standardUri.pathSegments; + if (pathSegments.last == 'index.xml') { + pathSegments.removeLast(); + standardUri = standardUri.replace(path: pathSegments.join('/')); + } + return removeQueryParamsFromUrl(standardUri.toString(), keep: ['appId']); + } + + @override + Future>> search(String query, + {Map querySettings = const {}}) async { + query = removeQueryParamsFromUrl(standardizeUrl(query)); + var res = await sourceRequest('$query/index.xml'); + if (res.statusCode == 200) { + var body = parse(res.body); + Map> results = {}; + body.querySelectorAll('application').toList().forEach((app) { + String appId = app.attributes['id']!; + results['$query?appId=$appId'] = [ + app.querySelector('name')?.innerHtml ?? appId, + app.querySelector('desc')?.innerHtml ?? '' + ]; + }); + return results; + } else { + throw getObtainiumHttpError(res); + } + } + + @override + App endOfGetAppChanges(App app) { + var uri = Uri.parse(app.url); + String? appId; + if (!isTempId(app)) { + appId = app.id; + } else if (uri.queryParameters['appId'] != null) { + appId = uri.queryParameters['appId']; + } + if (appId != null) { + app.url = uri + .replace( + queryParameters: Map.fromEntries( + [...uri.queryParameters.entries, MapEntry('appId', appId)])) + .toString(); + app.additionalSettings['appIdOrName'] = appId; + app.id = appId; + } + return app; + } + @override Future getLatestAPKDetails( String standardUrl, Map additionalSettings, ) async { String? appIdOrName = additionalSettings['appIdOrName']; + var standardUri = Uri.parse(standardUrl); + if (standardUri.queryParameters['appId'] != null) { + appIdOrName = standardUri.queryParameters['appId']; + } + standardUrl = removeQueryParamsFromUrl(standardUrl); bool pickHighestVersionCode = additionalSettings['pickHighestVersionCode']; if (appIdOrName == null) { throw NoReleasesError(); @@ -41,7 +115,7 @@ class FDroidRepo extends AppSource { if (foundApps.isEmpty) { foundApps = body.querySelectorAll('application').where((element) { return element.querySelector('name')?.innerHtml.toLowerCase() == - appIdOrName.toLowerCase(); + appIdOrName!.toLowerCase(); }).toList(); } if (foundApps.isEmpty) { @@ -50,7 +124,7 @@ class FDroidRepo extends AppSource { .querySelector('name') ?.innerHtml .toLowerCase() - .contains(appIdOrName.toLowerCase()) ?? + .contains(appIdOrName!.toLowerCase()) ?? false; }).toList(); } @@ -58,8 +132,9 @@ class FDroidRepo extends AppSource { throw ObtainiumError(tr('appWithIdOrNameNotFound')); } var authorName = body.querySelector('repo')?.attributes['name'] ?? name; - var appName = - foundApps[0].querySelector('name')?.innerHtml ?? appIdOrName; + String appId = foundApps[0].attributes['id']!; + foundApps[0].querySelector('name')?.innerHtml ?? appId; + var appName = foundApps[0].querySelector('name')?.innerHtml ?? appId; var releases = foundApps[0].querySelectorAll('package'); String? latestVersion = releases[0].querySelector('version')?.innerHtml; String? added = releases[0].querySelector('added')?.innerHtml; diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index c792a2a..bbe82ad 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -153,7 +153,7 @@ class _AddAppPageState extends State { overrideSource: pickedSourceOverride, inferAppIdIfOptional: inferAppIdIfOptional); // Only download the APK here if you need to for the package ID - if (sourceProvider.isTempId(app) && + if (isTempId(app) && app.additionalSettings['trackOnly'] != true) { // ignore: use_build_context_synchronously var apkUrl = await appsProvider.confirmApkUrl(app, context); diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index b84306d..3ef8e73 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -267,10 +267,10 @@ class AppsProvider with ChangeNotifier { File downloadedFile, String downloadUrl) async { // If the APK package ID is different from the App ID, it is either new (using a placeholder ID) or the ID has changed // The former case should be handled (give the App its real ID), the latter is a security issue - var isTempId = SourceProvider().isTempId(app); + var isTempIdBool = isTempId(app); if (newInfo != null) { if (app.id != newInfo.packageName) { - if (apps[app.id] != null && !isTempId && !app.allowIdChange) { + if (apps[app.id] != null && !isTempIdBool && !app.allowIdChange) { throw IDChangedError(newInfo.packageName!); } var idChangeWasAllowed = app.allowIdChange; @@ -281,10 +281,10 @@ class AppsProvider with ChangeNotifier { '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.${downloadedFile.path.split('.').last}'); if (apps[originalAppId] != null) { await removeApps([originalAppId]); - await saveApps([app], onlyIfExists: !isTempId && !idChangeWasAllowed); + await saveApps([app], onlyIfExists: !isTempIdBool && !idChangeWasAllowed); } } - } else if (isTempId) { + } else if (isTempIdBool) { throw ObtainiumError('Could not get ID from APK'); } return downloadedFile; diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 0ac9b91..e3e1c3a 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -372,6 +372,10 @@ abstract class AppSource { return null; } + App endOfGetAppChanges(App app) { + return app; + } + Future sourceRequest(String url, {bool followRedirects = true, Map additionalSettings = @@ -541,6 +545,11 @@ intValidator(String? value, {bool positive = false}) { return null; } +bool isTempId(App app) { + // return app.id == generateTempID(app.url, app.additionalSettings); + return RegExp('^[0-9]+\$').hasMatch(app.id); +} + class SourceProvider { // Add more source classes here so they are available via the service List get sources => [ @@ -626,11 +635,6 @@ class SourceProvider { String standardUrl, Map additionalSettings) => (standardUrl + additionalSettings.toString()).hashCode.toString(); - bool isTempId(App app) { - // return app.id == generateTempID(app.url, app.additionalSettings); - return RegExp('^[0-9]+\$').hasMatch(app.id); - } - Future getApp( AppSource source, String url, Map additionalSettings, {App? currentApp, @@ -672,7 +676,7 @@ class SourceProvider { String apkVersion = apk.version.replaceAll('/', '-'); var name = currentApp != null ? currentApp.name.trim() : ''; name = name.isNotEmpty ? name : apk.names.name; - return App( + App finalApp = App( currentApp?.id ?? ((!source.appIdInferIsOptional || (source.appIdInferIsOptional && inferAppIdIfOptional)) @@ -698,6 +702,7 @@ class SourceProvider { source.appIdInferIsOptional && inferAppIdIfOptional // Optional ID inferring may be incorrect - allow correction on first install ); + return source.endOfGetAppChanges(finalApp); } // Returns errors in [results, errors] instead of throwing them From 7d7803247dfe6e8eb84bb28e642fe1b9f5d84334 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 14 Oct 2023 01:30:37 -0400 Subject: [PATCH 555/600] Update packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 8 ++++---- pubspec.yaml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 4088f9b..c202d40 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.27'; +const String currentVersion = '0.14.28'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 3ea4961..39e4c03 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -246,10 +246,10 @@ packages: dependency: "direct main" description: name: file_picker - sha256: be325344c1f3070354a1d84a231a1ba75ea85d413774ec4bdf444c023342e030 + sha256: "903dd4ba13eae7cef64acc480e91bf54c3ddd23b5b90b639c170f3911e489620" url: "https://pub.dev" source: hosted - version: "5.5.0" + version: "6.0.0" flutter: dependency: "direct main" description: flutter @@ -546,10 +546,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: ace7d15a3d1a4a0b91c041d01e5405df221edb9de9116525efc773c74e6fc790 + sha256: f9fddd3b46109bd69ff3f9efa5006d2d309b7aec0f3c1c5637a60a2d5659e76e url: "https://pub.dev" source: hosted - version: "11.0.5" + version: "11.1.0" permission_handler_apple: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index be36743..02990a4 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.14.27+219 # When changing this, update the tag in main() accordingly +version: 0.14.28+220 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' @@ -49,7 +49,7 @@ dependencies: permission_handler: ^11.0.0 fluttertoast: ^8.0.9 device_info_plus: ^9.0.0 - file_picker: ^5.2.10 + file_picker: ^6.0.0 animations: ^2.0.4 android_package_installer: git: From 8b4709c1323301b812635cd4440a5b6d74825ea9 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 14 Oct 2023 01:36:26 -0400 Subject: [PATCH 556/600] Fixed syntax errors in de.json --- assets/translations/de.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index bc0a558..9f9efbe 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -246,8 +246,8 @@ "backgroundUpdateReqsExplanation": "Die Hintergrundaktualisierung ist möglicherweise nicht für alle Apps möglich.", "backgroundUpdateLimitsExplanation": "Der Erfolg einer Hintergrundinstallation kann nur festgestellt werden, wenn Obtainium geöffnet wird.", "verifyLatestTag": "Überprüfe das „latest“ Tag", - "intermediateLinkRegex": "Filter für einen \„Zwischen\“-Link, der zuerst besucht werden soll", - "intermediateLinkNotFound": "\„Zwischen\“link nicht gefunden", + "intermediateLinkRegex": "Filter für einen „Zwischen“-Link, der zuerst besucht werden soll", + "intermediateLinkNotFound": "„Zwischen“link nicht gefunden", "exemptFromBackgroundUpdates": "Ausschluss von Hintergrundaktualisierungen (falls aktiviert)", "bgUpdatesOnWiFiOnly": "Hintergrundaktualisierungen deaktivieren, wenn kein WLAN vorhanden ist", "autoSelectHighestVersionCode": "Automatisch höchste APK-Code-Version auswählen", From a726b09f266fe22ac61bae51c1a52aeaa10f7ec7 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 14 Oct 2023 05:24:08 -0400 Subject: [PATCH 557/600] Fix Source selection (HTML) which broke in the last release --- lib/app_sources/fdroidrepo.dart | 1 + lib/main.dart | 2 +- lib/providers/source_provider.dart | 3 ++- pubspec.yaml | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index 22b8e49..6152c2b 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -8,6 +8,7 @@ class FDroidRepo extends AppSource { FDroidRepo() { name = tr('fdroidThirdPartyRepo'); canSearch = true; + neverAutoSelect = true; additionalSourceAppSpecificSettingFormItems = [ [ diff --git a/lib/main.dart b/lib/main.dart index c202d40..0a6ada9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.28'; +const String currentVersion = '0.14.29'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index e3e1c3a..ce07727 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -330,6 +330,7 @@ abstract class AppSource { bool appIdInferIsOptional = false; bool allowSubDomains = false; bool naiveStandardVersionDetection = false; + bool neverAutoSelect = false; AppSource() { name = runtimeType.toString(); @@ -604,7 +605,7 @@ class SourceProvider { } } if (source == null) { - for (var s in sources.where((element) => element.host == null)) { + for (var s in sources.where((element) => element.host == null && !element.neverAutoSelect)) { try { s.sourceSpecificStandardizeURL(url); source = s; diff --git a/pubspec.yaml b/pubspec.yaml index 02990a4..e90cf53 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.14.28+220 # When changing this, update the tag in main() accordingly +version: 0.14.29+221 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 43d5a3da2797b5b173ec5a508b069c860eac3904 Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Sat, 14 Oct 2023 12:30:55 +0000 Subject: [PATCH 558/600] Update sv.json updated --- assets/translations/sv.json | 112 ++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index dc2666c..f730494 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -13,7 +13,7 @@ "and": "och", "githubPATLabel": "GitHub Personal Access Token (Increases Rate Limit)", "includePrereleases": "Inkludera förreleaser", - "fallbackToOlderReleases": "Fallback to older releases", + "fallbackToOlderReleases": "Fall tillbaka till äldre releaser", "filterReleaseTitlesByRegEx": "Filter Release Titles by Regular Expression", "invalidRegEx": "Invalid regular expression", "noDescription": "Ingen beskrivning", @@ -32,10 +32,10 @@ "youPickedTrackOnly": "You have selected the 'Track-Only' option.", "trackOnlyAppDescription": "The App will be tracked for updates, but Obtainium will not be able to download or install it.", "cancelled": "Avbruten", - "appAlreadyAdded": "App already added", + "appAlreadyAdded": "App redan tillagd", "alreadyUpToDateQuestion": "App Already up to Date?", - "addApp": "Add App", - "appSourceURL": "App Source URL", + "addApp": "Lägg till App", + "appSourceURL": "uRL till Appkälla", "error": "Fel", "add": "Lägg till", "searchSomeSourcesLabel": "Sök (Bara några källor)", @@ -43,62 +43,62 @@ "additionalOptsFor": "Additional Options for {}", "supportedSources": "Supported Sources", "trackOnlyInBrackets": "(Track-Only)", - "searchableInBrackets": "(Searchable)", + "searchableInBrackets": "(Sökbar)", "appsString": "Appar", "noApps": "Inga Appar", - "noAppsForFilter": "No Apps for Filter", + "noAppsForFilter": "Inga Appar för Filter", "byX": "Av {}", "percentProgress": "Progress: {}%", "pleaseWait": "Vänta", - "updateAvailable": "Update Available", + "updateAvailable": "Uppdatering Tillgänglig", "estimateInBracketsShort": "(Est.)", - "notInstalled": "Not Installed", + "notInstalled": "Inte Installerad", "estimateInBrackets": "(Estimate)", "selectAll": "Välj Alla", - "deselectN": "Deselect {}", + "deselectN": "Avmarkera {}", "xWillBeRemovedButRemainInstalled": "{} will be removed from Obtainium but remain installed on device.", - "removeSelectedAppsQuestion": "Remove Selected Apps?", - "removeSelectedApps": "Remove Selected Apps", + "removeSelectedAppsQuestion": "Ta bort markerade Appar?", + "removeSelectedApps": "Ta bort markerade Appar", "updateX": "Uppdatera {}", "installX": "Installera {}", "markXTrackOnlyAsUpdated": "Mark {}\n(Track-Only)\nas Updated", "changeX": "Byt {}", - "installUpdateApps": "Install/Update Apps", - "installUpdateSelectedApps": "Install/Update Selected Apps", + "installUpdateApps": "Installera/Uppdatera Appar", + "installUpdateSelectedApps": "Installera/Uppdatera Markerade Appar", "markXSelectedAppsAsUpdated": "Mark {} Selected Apps as Updated?", "no": "Nej", "yes": "Ja", - "markSelectedAppsUpdated": "Mark Selected Apps as Updated", - "pinToTop": "Pin to top", - "unpinFromTop": "Unpin from top", + "markSelectedAppsUpdated": "Märk Valda Appar som Uppdaterade", + "pinToTop": "Nåla fast högst upp", + "unpinFromTop": "Avnåla", "resetInstallStatusForSelectedAppsQuestion": "Reset Install Status for Selected Apps?", "installStatusOfXWillBeResetExplanation": "The install status of any selected Apps will be reset.\n\nThis can help when the App version shown in Obtainium is incorrect due to failed updates or other issues.", "shareSelectedAppURLs": "Share Selected App URLs", "resetInstallStatus": "Reset Install Status", - "more": "More", + "more": "Mer", "removeOutdatedFilter": "Remove Out-of-Date App Filter", "showOutdatedOnly": "Show Out-of-Date Apps Only", "filter": "Filter", "filterActive": "Filter *", - "filterApps": "Filter Apps", - "appName": "App Name", + "filterApps": "Filtrera Appar", + "appName": "Appnamn", "author": "Author", "upToDateApps": "Up to Date Apps", "nonInstalledApps": "Non-Installed Apps", - "importExport": "Import/Export", - "settings": "Settings", - "exportedTo": "Exported to {}", + "importExport": "Importera/Exportera", + "settings": "Inställningar", + "exportedTo": "Exporterad till {}", "obtainiumExport": "Obtainium Export", "invalidInput": "Invalid input", - "importedX": "Imported {}", + "importedX": "Importerad {}", "obtainiumImport": "Obtainium Import", - "importFromURLList": "Import from URL List", + "importFromURLList": "Importera från URL-lista", "searchQuery": "Search Query", "appURLList": "App URL List", - "line": "Line", - "searchX": "Search {}", - "noResults": "No results found", - "importX": "Import {}", + "line": "Linje", + "searchX": "Sök {}", + "noResults": "Inga resultat", + "importX": "Importera {}", "importedAppsIdDisclaimer": "Imported Apps may incorrectly show as \"Not Installed\".\nTo fix this, re-install them through Obtainium.\nThis should not affect App data.\n\nOnly affects URL and third-party import methods.", "importErrors": "Import Errors", "importedXOfYApps": "{} of {} Apps imported.", @@ -128,14 +128,14 @@ "pinUpdates": "Pin updates to top of Apps view", "updates": "Updates", "sourceSpecific": "Source-Specific", - "appSource": "App Source", - "noLogs": "No Logs", - "appLogs": "App Logs", + "appSource": "Appkälla", + "noLogs": "Inga Loggar", + "appLogs": "Apploggar", "close": "Stäng", "share": "Dela", "appNotFound": "App ej funnen", "obtainiumExportHyphenatedLowercase": "obtainium-export", - "pickAnAPK": "Pick an APK", + "pickAnAPK": "Välj en APK", "appHasMoreThanOnePackage": "{} has more than one package:", "deviceSupportsXArch": "Your device supports the {} CPU architecture.", "deviceSupportsFollowingArchs": "Your device supports the following CPU architectures:", @@ -150,7 +150,7 @@ "xWasUpdatedToY": "{} was updated to {}.", "errorCheckingUpdates": "Error Checking for Updates", "errorCheckingUpdatesNotifDescription": "A notification that shows when background update checking fails", - "appsRemoved": "Apps Removed", + "appsRemoved": "Appar borttagna", "appsRemovedNotifDescription": "Notifies the user that one or more Apps were removed due to errors while loading them", "xWasRemovedDueToErrorY": "{} was removed due to this error: {}", "completeAppInstallation": "Complete App Installation", @@ -160,16 +160,16 @@ "checkingForUpdatesNotifDescription": "Transient notification that appears when checking for updates", "pleaseAllowInstallPerm": "Please allow Obtainium to install Apps", "trackOnly": "Track-Only", - "errorWithHttpStatusCode": "Error {}", + "errorWithHttpStatusCode": "Fel {}", "versionCorrectionDisabled": "Version correction disabled (plugin doesn't seem to work)", - "unknown": "Unknown", + "unknown": "Okänd", "none": "None", "never": "Aldrig", - "latestVersionX": "Latest Version: {}", - "installedVersionX": "Installed Version: {}", - "lastUpdateCheckX": "Last Update Check: {}", - "remove": "Remove", - "yesMarkUpdated": "Yes, Mark as Updated", + "latestVersionX": "Senaste Version: {}", + "installedVersionX": "Installerad Version: {}", + "lastUpdateCheckX": "Senaste uppdateringskoll: {}", + "remove": "Ta bort", + "yesMarkUpdated": "Ja, Märk som Uppdaterad", "fdroid": "F-Droid Official", "appIdOrName": "App-ID eller Namn", "appId": "App-ID", @@ -180,24 +180,24 @@ "steamMobile": "Steam Mobile", "steamChat": "Steam Chat", "install": "Installera", - "markInstalled": "Mark Installed", - "update": "Update", - "markUpdated": "Mark Updated", - "additionalOptions": "Additional Options", + "markInstalled": "Märk Installerad", + "update": "Uppdatera", + "markUpdated": "Märk Uppdaterad", + "additionalOptions": "Ytterligare Alternativ", "disableVersionDetection": "Disable Version Detection", "noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.", "downloadingX": "Downloading {}", "downloadNotifDescription": "Notifies the user of the progress in downloading an App", - "noAPKFound": "No APK found", + "noAPKFound": "Ingen APK funnen", "noVersionDetection": "No version detection", - "categorize": "Categorize", - "categories": "Categories", - "category": "Category", - "noCategory": "No Category", - "noCategories": "No Categories", - "deleteCategoriesQuestion": "Delete Categories?", + "categorize": "Kategorisera", + "categories": "Kategorier", + "category": "Kategori", + "noCategory": "Ingen Kategori", + "noCategories": "Inga Kategorier", + "deleteCategoriesQuestion": "Ta Bort Kategorier?", "categoryDeleteWarning": "All Apps in deleted categories will be set to uncategorized.", - "addCategory": "Add Category", + "addCategory": "Lägg till Kategori", "label": "Label", "language": "Språk", "copiedToClipboard": "Kopierat till Urklipp", @@ -209,15 +209,15 @@ "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", "releaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", - "changes": "Changes", - "releaseDate": "Release Date", + "changes": "Ändringar", + "releaseDate": "Releasedatum", "importFromURLsInFile": "Import from URLs in File (like OPML)", "versionDetection": "Version Detection", "standardVersionDetection": "Standard version detection", - "groupByCategory": "Group by Category", + "groupByCategory": "Gruppera via Katergori", "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", "overrideSource": "Override Source", - "dontShowAgain": "Don't show this again", + "dontShowAgain": "Visa inte detta igen", "dontShowTrackOnlyWarnings": "Don't show 'Track-Only' warnings", "dontShowAPKOriginWarnings": "Don't show APK origin warnings", "moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view", From 99ef6ca86130ff4300946bc35bafc156b2c2605a Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Sat, 14 Oct 2023 12:32:28 +0000 Subject: [PATCH 559/600] Update sv.json --- assets/translations/sv.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index f730494..bc53eb9 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -281,23 +281,23 @@ }, "apps": { "one": "{} App", - "other": "{} Apps" + "other": "{} Appar" }, "url": { "one": "{} URL", - "other": "{} URLs" + "other": "{} URL:er" }, "minute": { - "one": "{} Minute", - "other": "{} Minutes" + "one": "{} Minut", + "other": "{} Minuter" }, "hour": { - "one": "{} Hour", - "other": "{} Hours" + "one": "{} Timme", + "other": "{} Timmar" }, "day": { - "one": "{} Day", - "other": "{} Days" + "one": "{} Dag", + "other": "{} Dagar" }, "clearedNLogsBeforeXAfterY": { "one": "Cleared {n} log (before = {before}, after = {after})", From ce5639bb983192b846d19eb3e64d02b6dd21d87e Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Sat, 14 Oct 2023 12:48:03 +0000 Subject: [PATCH 560/600] Update sv.json --- assets/translations/sv.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index bc53eb9..32e95d0 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -262,10 +262,10 @@ "reverseSort": "Reverse sorting", "debugMenu": "Debug Menu", "bgTaskStarted": "Background task started - check logs.", - "runBgCheckNow": "Run Background Update Check Now", + "runBgCheckNow": "Kör Bakgrundsuppdateringskoll Nu", "removeAppQuestion": { - "one": "Remove App?", - "other": "Remove Apps?" + "one": "Ta Bort App?", + "other": "Ta Bort Appar?" }, "tooManyRequestsTryAgainInMinutes": { "one": "Too many requests (rate limited) - try again in {} minute", @@ -300,19 +300,19 @@ "other": "{} Dagar" }, "clearedNLogsBeforeXAfterY": { - "one": "Cleared {n} log (before = {before}, after = {after})", - "other": "Cleared {n} logs (before = {before}, after = {after})" + "one": "Rensade {n} logg (före = {before}, efter = {after})", + "other": "Rensade {n} loggar (före = {before}, efter = {after})" }, "xAndNMoreUpdatesAvailable": { - "one": "{} and 1 more app have updates.", - "other": "{} and {} more apps have updates." + "one": "{} och 1 app till har tillgängliga uppdateringar.", + "other": "{} och {} appar till har tillgängliga uppdateringar." }, "xAndNMoreUpdatesInstalled": { - "one": "{} and 1 more app was updated.", - "other": "{} and {} more apps were updated." + "one": "{} och 1 till app uppdaterades.", + "other": "{} och {} appar till uppdaterades." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} and 1 more app may have been updated.", - "other": "{} and {} more apps may have been updated." + "one": "{} och 1 till app kan ha uppdaterats.", + "other": "{} och {} appar till kan ha uppdaterats." } } From 9506c11951b684073d0468b4e76f315067efe9fa Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 14 Oct 2023 13:25:26 -0400 Subject: [PATCH 561/600] Fix broken search (#1006) --- lib/app_sources/fdroidrepo.dart | 1 + lib/pages/add_app.dart | 8 ++++---- lib/pages/import_export.dart | 3 ++- lib/providers/source_provider.dart | 4 +++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index 6152c2b..e61d544 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -8,6 +8,7 @@ class FDroidRepo extends AppSource { FDroidRepo() { name = tr('fdroidThirdPartyRepo'); canSearch = true; + excludeFromMassSearch = true; neverAutoSelect = true; additionalSourceAppSpecificSettingFormItems = [ diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index bbe82ad..41d047c 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -153,8 +153,7 @@ class _AddAppPageState extends State { overrideSource: pickedSourceOverride, inferAppIdIfOptional: inferAppIdIfOptional); // Only download the APK here if you need to for the package ID - if (isTempId(app) && - app.additionalSettings['trackOnly'] != true) { + if (isTempId(app) && app.additionalSettings['trackOnly'] != true) { // ignore: use_build_context_synchronously var apkUrl = await appsProvider.confirmApkUrl(app, context); if (apkUrl == null) { @@ -260,8 +259,9 @@ class _AddAppPageState extends State { searching = true; }); try { - var results = await Future.wait( - sourceProvider.sources.where((e) => e.canSearch).map((e) async { + var results = await Future.wait(sourceProvider.sources + .where((e) => e.canSearch && !e.excludeFromMassSearch) + .map((e) async { try { return await e.search(searchQuery); } catch (err) { diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index 200ff7a..f99efb5 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -141,7 +141,8 @@ class _ImportExportPageState extends State { } }); appsProvider.addMissingCategories(settingsProvider); - showMessage(tr('importedX', args: [plural('apps', value)]), context); + showMessage( + tr('importedX', args: [plural('apps', value)]), context); }); } else { // User canceled the picker diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index ce07727..0285aa7 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -494,6 +494,7 @@ abstract class AppSource { } bool canSearch = false; + bool excludeFromMassSearch = false; List searchQuerySettingFormItems = []; Future>> search(String query, {Map querySettings = const {}}) { @@ -605,7 +606,8 @@ class SourceProvider { } } if (source == null) { - for (var s in sources.where((element) => element.host == null && !element.neverAutoSelect)) { + for (var s in sources.where( + (element) => element.host == null && !element.neverAutoSelect)) { try { s.sourceSpecificStandardizeURL(url); source = s; From 63fa6d466026d6e79c86a6bf24044fb7a83be8e8 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sat, 14 Oct 2023 13:25:49 -0400 Subject: [PATCH 562/600] Increment version --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 0a6ada9..b353775 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.29'; +const String currentVersion = '0.14.30'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.yaml b/pubspec.yaml index e90cf53..2d61b0a 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.14.29+221 # When changing this, update the tag in main() accordingly +version: 0.14.30+222 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 623804ae68af5bfa748b3b1e0f3ec41656b3ac68 Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Sat, 14 Oct 2023 18:35:37 +0000 Subject: [PATCH 563/600] Update sv.json --- assets/translations/sv.json | 84 ++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index 32e95d0..a8bc341 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -6,7 +6,7 @@ "cantInstallOlderVersion": "Kan inte installera en äldre version av en app", "appIdMismatch": "Nerladdat paket-ID matchar inte nuvarande App-ID", "functionNotImplemented": "This class has not implemented this function", - "placeholder": "Placeholder", + "placeholder": "Platshållare", "someErrors": "Några fel uppstod", "unexpectedError": "Oväntat fel", "ok": "Okej", @@ -22,27 +22,27 @@ "requiredInBrackets": "(Kräver)", "dropdownNoOptsError": "ERROR: DROPDOWN MUST HAVE AT LEAST ONE OPT", "colour": "Färg", - "githubStarredRepos": "GitHub Starred Repos", + "githubStarredRepos": "GitHub Stjärnmärkta Förråd", "uname": "Användarnamn", "wrongArgNum": "Wrong number of arguments provided", - "xIsTrackOnly": "{} is Track-Only", + "xIsTrackOnly": "{} är 'Följ-Endast'", "source": "Källa", "app": "App", - "appsFromSourceAreTrackOnly": "Apps from this source are 'Track-Only'.", - "youPickedTrackOnly": "You have selected the 'Track-Only' option.", - "trackOnlyAppDescription": "The App will be tracked for updates, but Obtainium will not be able to download or install it.", + "appsFromSourceAreTrackOnly": "Apparna från denna källa är 'Följ-Endast'.", + "youPickedTrackOnly": "Du har markerat 'Följ-Endast'-alternativet", + "trackOnlyAppDescription": "Appen kommer följas för uppdateringar medn Obtainium kommer inte ladda ner eller installera den.", "cancelled": "Avbruten", "appAlreadyAdded": "App redan tillagd", "alreadyUpToDateQuestion": "App Already up to Date?", "addApp": "Lägg till App", - "appSourceURL": "uRL till Appkälla", + "appSourceURL": "URL till Appkälla", "error": "Fel", "add": "Lägg till", "searchSomeSourcesLabel": "Sök (Bara några källor)", "search": "Sök", - "additionalOptsFor": "Additional Options for {}", - "supportedSources": "Supported Sources", - "trackOnlyInBrackets": "(Track-Only)", + "additionalOptsFor": "Ytterligare Alternativ för {}", + "supportedSources": "Stödda Källor", + "trackOnlyInBrackets": "(Följ-Endast)", "searchableInBrackets": "(Sökbar)", "appsString": "Appar", "noApps": "Inga Appar", @@ -53,7 +53,7 @@ "updateAvailable": "Uppdatering Tillgänglig", "estimateInBracketsShort": "(Est.)", "notInstalled": "Inte Installerad", - "estimateInBrackets": "(Estimate)", + "estimateInBrackets": "(Uppskattning)", "selectAll": "Välj Alla", "deselectN": "Avmarkera {}", "xWillBeRemovedButRemainInstalled": "{} will be removed from Obtainium but remain installed on device.", @@ -65,7 +65,7 @@ "changeX": "Byt {}", "installUpdateApps": "Installera/Uppdatera Appar", "installUpdateSelectedApps": "Installera/Uppdatera Markerade Appar", - "markXSelectedAppsAsUpdated": "Mark {} Selected Apps as Updated?", + "markXSelectedAppsAsUpdated": "Märk {} markerade Appar som Uppdaterade?", "no": "Nej", "yes": "Ja", "markSelectedAppsUpdated": "Märk Valda Appar som Uppdaterade", @@ -73,27 +73,27 @@ "unpinFromTop": "Avnåla", "resetInstallStatusForSelectedAppsQuestion": "Reset Install Status for Selected Apps?", "installStatusOfXWillBeResetExplanation": "The install status of any selected Apps will be reset.\n\nThis can help when the App version shown in Obtainium is incorrect due to failed updates or other issues.", - "shareSelectedAppURLs": "Share Selected App URLs", - "resetInstallStatus": "Reset Install Status", + "shareSelectedAppURLs": "Dela Valda Appars URL:er", + "resetInstallStatus": "Återställ Installationstatus", "more": "Mer", "removeOutdatedFilter": "Remove Out-of-Date App Filter", - "showOutdatedOnly": "Show Out-of-Date Apps Only", + "showOutdatedOnly": "Visa Endast Utgånga Appar", "filter": "Filter", "filterActive": "Filter *", "filterApps": "Filtrera Appar", "appName": "Appnamn", - "author": "Author", - "upToDateApps": "Up to Date Apps", - "nonInstalledApps": "Non-Installed Apps", + "author": "Utvecklare", + "upToDateApps": "Uppdaterade Appar", + "nonInstalledApps": "Icke-Installerade Appar", "importExport": "Importera/Exportera", "settings": "Inställningar", "exportedTo": "Exporterad till {}", "obtainiumExport": "Obtainium Export", - "invalidInput": "Invalid input", + "invalidInput": "Ogiltig input", "importedX": "Importerad {}", "obtainiumImport": "Obtainium Import", "importFromURLList": "Importera från URL-lista", - "searchQuery": "Search Query", + "searchQuery": "Sökförfrågan", "appURLList": "App URL List", "line": "Linje", "searchX": "Sök {}", @@ -102,11 +102,11 @@ "importedAppsIdDisclaimer": "Imported Apps may incorrectly show as \"Not Installed\".\nTo fix this, re-install them through Obtainium.\nThis should not affect App data.\n\nOnly affects URL and third-party import methods.", "importErrors": "Import Errors", "importedXOfYApps": "{} of {} Apps imported.", - "followingURLsHadErrors": "The following URLs had errors:", - "okay": "Okay", + "followingURLsHadErrors": "Följande URL:er hade fel:", + "okay": "Okej", "selectURL": "Välj URL", "selectURLs": "Välj URL:er", - "pick": "Pick", + "pick": "Välj", "theme": "Tema", "dark": "Mörkt", "light": "Ljust", @@ -115,19 +115,19 @@ "materialYou": "Material You", "useBlackTheme": "Use pure black dark theme", "appSortBy": "App Sort By", - "authorName": "Author/Name", - "nameAuthor": "Name/Author", + "authorName": "Utvecklare/Namn", + "nameAuthor": "Namn/Utvecklare", "asAdded": "As Added", "appSortOrder": "App Sort Order", - "ascending": "Ascending", - "descending": "Descending", + "ascending": "Stigande", + "descending": "Fallande", "bgUpdateCheckInterval": "Background Update Checking Interval", "neverManualOnly": "Never - Manual Only", - "appearance": "Appearance", + "appearance": "Utseende", "showWebInAppView": "Show Source webpage in App view", "pinUpdates": "Pin updates to top of Apps view", - "updates": "Updates", - "sourceSpecific": "Source-Specific", + "updates": "Uppdateringar", + "sourceSpecific": "Källspecifik", "appSource": "Appkälla", "noLogs": "Inga Loggar", "appLogs": "Apploggar", @@ -137,11 +137,11 @@ "obtainiumExportHyphenatedLowercase": "obtainium-export", "pickAnAPK": "Välj en APK", "appHasMoreThanOnePackage": "{} has more than one package:", - "deviceSupportsXArch": "Your device supports the {} CPU architecture.", - "deviceSupportsFollowingArchs": "Your device supports the following CPU architectures:", - "warning": "Warning", + "deviceSupportsXArch": "Din enhet stödjer {} CPU-arkiktektur.", + "deviceSupportsFollowingArchs": "YDin enhet stödjer följande CPU-arkitekturer:", + "warning": "Varning", "sourceIsXButPackageFromYPrompt": "The App source is '{}' but the release package comes from '{}'. Continue?", - "updatesAvailable": "Updates Available", + "updatesAvailable": "Uppdateringar Tillgängliga", "updatesAvailableNotifDescription": "Notifies the user that updates are available for one or more Apps tracked by Obtainium", "noNewUpdates": "Inga nya uppdateringar.", "xHasAnUpdate": "{} har en uppdatering.", @@ -156,10 +156,10 @@ "completeAppInstallation": "Complete App Installation", "obtainiumMustBeOpenToInstallApps": "Obtainium must be open to install Apps", "completeAppInstallationNotifDescription": "Asks the user to return to Obtainium to finish installing an App", - "checkingForUpdates": "Checking for Updates", + "checkingForUpdates": "Kollar efter Uppdateringar", "checkingForUpdatesNotifDescription": "Transient notification that appears when checking for updates", - "pleaseAllowInstallPerm": "Please allow Obtainium to install Apps", - "trackOnly": "Track-Only", + "pleaseAllowInstallPerm": "Tillåt Obtanium att installera Appar", + "trackOnly": "Följ-Endast", "errorWithHttpStatusCode": "Fel {}", "versionCorrectionDisabled": "Version correction disabled (plugin doesn't seem to work)", "unknown": "Okänd", @@ -204,17 +204,17 @@ "storagePermissionDenied": "Storage permission denied", "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", "filterAPKsByRegEx": "Filter APKs by Regular Expression", - "removeFromObtainium": "Remove from Obtainium", - "uninstallFromDevice": "Uninstall from Device", + "removeFromObtainium": "Ta bort från Obtainium", + "uninstallFromDevice": "Avinstallera från Enheten", "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", "releaseDateAsVersion": "Use Release Date as Version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Ändringar", "releaseDate": "Releasedatum", "importFromURLsInFile": "Import from URLs in File (like OPML)", - "versionDetection": "Version Detection", - "standardVersionDetection": "Standard version detection", - "groupByCategory": "Gruppera via Katergori", + "versionDetection": "Versionsdetektering", + "standardVersionDetection": "Standardversionsdetektering", + "groupByCategory": "Gruppera via Kategori", "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", "overrideSource": "Override Source", "dontShowAgain": "Visa inte detta igen", From f44424d37ab57f99bb34447719811670afb9a07f Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Sat, 14 Oct 2023 19:11:25 +0000 Subject: [PATCH 564/600] Update sv.json --- assets/translations/sv.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index a8bc341..990673f 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -61,7 +61,7 @@ "removeSelectedApps": "Ta bort markerade Appar", "updateX": "Uppdatera {}", "installX": "Installera {}", - "markXTrackOnlyAsUpdated": "Mark {}\n(Track-Only)\nas Updated", + "markXTrackOnlyAsUpdated": "Märk {}\n(Följ-Endast)\nsom Uppdaterad", "changeX": "Byt {}", "installUpdateApps": "Installera/Uppdatera Appar", "installUpdateSelectedApps": "Installera/Uppdatera Markerade Appar", @@ -71,12 +71,12 @@ "markSelectedAppsUpdated": "Märk Valda Appar som Uppdaterade", "pinToTop": "Nåla fast högst upp", "unpinFromTop": "Avnåla", - "resetInstallStatusForSelectedAppsQuestion": "Reset Install Status for Selected Apps?", + "resetInstallStatusForSelectedAppsQuestion": "Återställ Installationsstatus för valda Appar?", "installStatusOfXWillBeResetExplanation": "The install status of any selected Apps will be reset.\n\nThis can help when the App version shown in Obtainium is incorrect due to failed updates or other issues.", "shareSelectedAppURLs": "Dela Valda Appars URL:er", "resetInstallStatus": "Återställ Installationstatus", "more": "Mer", - "removeOutdatedFilter": "Remove Out-of-Date App Filter", + "removeOutdatedFilter": "Ta bort Utgånga App-filtret", "showOutdatedOnly": "Visa Endast Utgånga Appar", "filter": "Filter", "filterActive": "Filter *", @@ -89,7 +89,7 @@ "settings": "Inställningar", "exportedTo": "Exporterad till {}", "obtainiumExport": "Obtainium Export", - "invalidInput": "Ogiltig input", + "invalidInput": "Ogiltig inmatning", "importedX": "Importerad {}", "obtainiumImport": "Obtainium Import", "importFromURLList": "Importera från URL-lista", @@ -100,8 +100,8 @@ "noResults": "Inga resultat", "importX": "Importera {}", "importedAppsIdDisclaimer": "Imported Apps may incorrectly show as \"Not Installed\".\nTo fix this, re-install them through Obtainium.\nThis should not affect App data.\n\nOnly affects URL and third-party import methods.", - "importErrors": "Import Errors", - "importedXOfYApps": "{} of {} Apps imported.", + "importErrors": "Importfel", + "importedXOfYApps": "{} av {} Appar importerade.", "followingURLsHadErrors": "Följande URL:er hade fel:", "okay": "Okej", "selectURL": "Välj URL", @@ -242,14 +242,14 @@ "appsPossiblyUpdated": "App Updates Attempted", "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", - "enableBackgroundUpdates": "Enable background updates", - "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", + "enableBackgroundUpdates": "Aktivera Bakgrundsuppdateringar", + "backgroundUpdateReqsExplanation": "Bakgrundsuppdateringar är inte möjligt för alla appar.", "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", - "verifyLatestTag": "Verify the 'latest' tag", + "verifyLatestTag": "Verifiera 'senaste'-taggen", "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", "intermediateLinkNotFound": "Intermediate link not found", "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", - "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", + "bgUpdatesOnWiFiOnly": "Inaktivera Bakgrundsuppdateringar utan WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", @@ -260,7 +260,7 @@ "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", "reverseSort": "Reverse sorting", - "debugMenu": "Debug Menu", + "debugMenu": "Felsökningsmeny", "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Kör Bakgrundsuppdateringskoll Nu", "removeAppQuestion": { From e6da2b73ed5e8cdffa6b47ffb82db6e84d0aa43a Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Sat, 14 Oct 2023 19:16:26 +0000 Subject: [PATCH 565/600] Update sv.json --- assets/translations/sv.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index 990673f..ab989c6 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -88,7 +88,7 @@ "importExport": "Importera/Exportera", "settings": "Inställningar", "exportedTo": "Exporterad till {}", - "obtainiumExport": "Obtainium Export", + "obtainiumExport": "Obtainiumexport", "invalidInput": "Ogiltig inmatning", "importedX": "Importerad {}", "obtainiumImport": "Obtainium Import", @@ -113,7 +113,7 @@ "followSystem": "Följ System", "obtainium": "Obtainium", "materialYou": "Material You", - "useBlackTheme": "Use pure black dark theme", + "useBlackTheme": "Använd svart tema", "appSortBy": "App Sort By", "authorName": "Utvecklare/Namn", "nameAuthor": "Namn/Utvecklare", @@ -173,9 +173,9 @@ "fdroid": "F-Droid Official", "appIdOrName": "App-ID eller Namn", "appId": "App-ID", - "appWithIdOrNameNotFound": "No App was found with that ID or Name", - "reposHaveMultipleApps": "Repos may contain multiple Apps", - "fdroidThirdPartyRepo": "F-Droid Third-Party Repo", + "appWithIdOrNameNotFound": "Ingen App funnen med det namnet eller ID", + "reposHaveMultipleApps": "Förråd kan innehålla flera ApparR", + "fdroidThirdPartyRepo": "F-Droid Tredjeparts Förråd", "steam": "Steam", "steamMobile": "Steam Mobile", "steamChat": "Steam Chat", @@ -184,12 +184,12 @@ "update": "Uppdatera", "markUpdated": "Märk Uppdaterad", "additionalOptions": "Ytterligare Alternativ", - "disableVersionDetection": "Disable Version Detection", + "disableVersionDetection": "Inaktivera versiondetektering", "noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.", "downloadingX": "Downloading {}", "downloadNotifDescription": "Notifies the user of the progress in downloading an App", "noAPKFound": "Ingen APK funnen", - "noVersionDetection": "No version detection", + "noVersionDetection": "Ingen versiondetektering", "categorize": "Kategorisera", "categories": "Kategorier", "category": "Kategori", @@ -222,9 +222,9 @@ "dontShowAPKOriginWarnings": "Don't show APK origin warnings", "moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view", "gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)", - "about": "About", + "about": "Om", "requiresCredentialsInSettings": "This needs additional credentials (in Settings)", - "checkOnStart": "Check for updates on startup", + "checkOnStart": "Kolla efter uppdateringar vid start", "tryInferAppIdFromCode": "Try inferring App ID from source code", "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", "pickHighestVersionCode": "Auto-select highest version code APK", From 598df624df3bd6da3575ac397d5848b1eb961054 Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Sat, 14 Oct 2023 19:31:08 +0000 Subject: [PATCH 566/600] Update sv.json --- assets/translations/sv.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index ab989c6..b9b0902 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -30,10 +30,10 @@ "app": "App", "appsFromSourceAreTrackOnly": "Apparna från denna källa är 'Följ-Endast'.", "youPickedTrackOnly": "Du har markerat 'Följ-Endast'-alternativet", - "trackOnlyAppDescription": "Appen kommer följas för uppdateringar medn Obtainium kommer inte ladda ner eller installera den.", + "trackOnlyAppDescription": "Appen kommer följas för uppdateringar men Obtainium kommer inte ladda ner eller installera den.", "cancelled": "Avbruten", "appAlreadyAdded": "App redan tillagd", - "alreadyUpToDateQuestion": "App Already up to Date?", + "alreadyUpToDateQuestion": "App redan uppdaterad?", "addApp": "Lägg till App", "appSourceURL": "URL till Appkälla", "error": "Fel", @@ -56,7 +56,7 @@ "estimateInBrackets": "(Uppskattning)", "selectAll": "Välj Alla", "deselectN": "Avmarkera {}", - "xWillBeRemovedButRemainInstalled": "{} will be removed from Obtainium but remain installed on device.", + "xWillBeRemovedButRemainInstalled": "{} kommer tas bort från Obtainium men kommer vara fortsatt installerad på enheten.", "removeSelectedAppsQuestion": "Ta bort markerade Appar?", "removeSelectedApps": "Ta bort markerade Appar", "updateX": "Uppdatera {}", @@ -114,7 +114,7 @@ "obtainium": "Obtainium", "materialYou": "Material You", "useBlackTheme": "Använd svart tema", - "appSortBy": "App Sort By", + "appSortBy": "Sortera Appar via", "authorName": "Utvecklare/Namn", "nameAuthor": "Namn/Utvecklare", "asAdded": "As Added", @@ -170,7 +170,7 @@ "lastUpdateCheckX": "Senaste uppdateringskoll: {}", "remove": "Ta bort", "yesMarkUpdated": "Ja, Märk som Uppdaterad", - "fdroid": "F-Droid Official", + "fdroid": "F-Droid Officiell", "appIdOrName": "App-ID eller Namn", "appId": "App-ID", "appWithIdOrNameNotFound": "Ingen App funnen med det namnet eller ID", @@ -254,12 +254,12 @@ "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", + "pickExportDir": "Välj Exportsökväg", "autoExportOnChanges": "Auto-export on changes", "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", - "reverseSort": "Reverse sorting", + "reverseSort": "Omvänd sortering", "debugMenu": "Felsökningsmeny", "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Kör Bakgrundsuppdateringskoll Nu", From 858a50a4143d9403e73d131078636e6c9be49619 Mon Sep 17 00:00:00 2001 From: LucasTavaresA Date: Sun, 15 Oct 2023 20:13:45 -0300 Subject: [PATCH 567/600] Update pt.json --- assets/translations/pt.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/pt.json b/assets/translations/pt.json index 1eaaec3..047b9f8 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -263,9 +263,9 @@ "debugMenu": "Menu Debug", "bgTaskStarted": "Tarefa em segundo plano iniciada - verifique os logs.", "runBgCheckNow": "Execute a verificação de atualização em segundo plano agora", - "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", - "installing": "Installing", - "skipUpdateNotifications": "Skip update notifications", + "versionExtractWholePage": "Aplicar Regex de Extração de Versão à Página Inteira", + "installing": "Instalando", + "skipUpdateNotifications": "Pular notificações de update", "updatesAvailableNotifChannel": "Atualizações Disponíveis", "appsUpdatedNotifChannel": "Apps Atualizados", "appsPossiblyUpdatedNotifChannel": "Tentativas de atualização de Apps", From b68cf3c67177183dc27438574fb800688ab4b711 Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Mon, 16 Oct 2023 14:12:09 +0000 Subject: [PATCH 568/600] Update sv.json --- assets/translations/sv.json | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index b9b0902..c999c8f 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -72,7 +72,7 @@ "pinToTop": "Nåla fast högst upp", "unpinFromTop": "Avnåla", "resetInstallStatusForSelectedAppsQuestion": "Återställ Installationsstatus för valda Appar?", - "installStatusOfXWillBeResetExplanation": "The install status of any selected Apps will be reset.\n\nThis can help when the App version shown in Obtainium is incorrect due to failed updates or other issues.", + "installStatusOfXWillBeResetExplanation": "Installationsstatusen för de markerade apparna kommer återställas.\n\n Detta kan hjälpa när appversionen visad i Obtanium är fel på grund av misslyckade uppdateringar eller andra orsaker.", "shareSelectedAppURLs": "Dela Valda Appars URL:er", "resetInstallStatus": "Återställ Installationstatus", "more": "Mer", @@ -99,7 +99,7 @@ "searchX": "Sök {}", "noResults": "Inga resultat", "importX": "Importera {}", - "importedAppsIdDisclaimer": "Imported Apps may incorrectly show as \"Not Installed\".\nTo fix this, re-install them through Obtainium.\nThis should not affect App data.\n\nOnly affects URL and third-party import methods.", + "importedAppsIdDisclaimer": "Importerade Appar kan felaktigt visas som \"Inte Installerad\".\nFör att fixa detta återinstallera dem genom Obtainium.\nDetta skall inte påverka appdata.\n\n Påverkar endast URL:en och tredjepartsimportermetoder.", "importErrors": "Importfel", "importedXOfYApps": "{} av {} Appar importerade.", "followingURLsHadErrors": "Följande URL:er hade fel:", @@ -121,11 +121,11 @@ "appSortOrder": "App Sort Order", "ascending": "Stigande", "descending": "Fallande", - "bgUpdateCheckInterval": "Background Update Checking Interval", + "bgUpdateCheckInterval": "Bakgrundsuppdateringskollfrekvens", "neverManualOnly": "Never - Manual Only", "appearance": "Utseende", - "showWebInAppView": "Show Source webpage in App view", - "pinUpdates": "Pin updates to top of Apps view", + "showWebInAppView": "Visa källans hemsida i appvyn", + "pinUpdates": "Fäst uppdateringar högst upp i appvyn", "updates": "Uppdateringar", "sourceSpecific": "Källspecifik", "appSource": "Appkälla", @@ -136,32 +136,32 @@ "appNotFound": "App ej funnen", "obtainiumExportHyphenatedLowercase": "obtainium-export", "pickAnAPK": "Välj en APK", - "appHasMoreThanOnePackage": "{} has more than one package:", + "appHasMoreThanOnePackage": "{} har fler än ett paket:", "deviceSupportsXArch": "Din enhet stödjer {} CPU-arkiktektur.", "deviceSupportsFollowingArchs": "YDin enhet stödjer följande CPU-arkitekturer:", "warning": "Varning", - "sourceIsXButPackageFromYPrompt": "The App source is '{}' but the release package comes from '{}'. Continue?", + "sourceIsXButPackageFromYPrompt": "Appens källa är '{}' men releasepaketet kommer från '{}'. Vill du fortsätta?", "updatesAvailable": "Uppdateringar Tillgängliga", - "updatesAvailableNotifDescription": "Notifies the user that updates are available for one or more Apps tracked by Obtainium", + "updatesAvailableNotifDescription": "Aviserar användaren att det finns uppdateringar tillgängaliga för en eller fler Appar som spåras av Obtainium", "noNewUpdates": "Inga nya uppdateringar.", "xHasAnUpdate": "{} har en uppdatering.", "appsUpdated": "Appar Uppdaterade", "appsUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were applied in the background", - "xWasUpdatedToY": "{} was updated to {}.", - "errorCheckingUpdates": "Error Checking for Updates", - "errorCheckingUpdatesNotifDescription": "A notification that shows when background update checking fails", + "xWasUpdatedToY": "{} uppdaterades till {}.", + "errorCheckingUpdates": "Fel vid uppdateringskoll", + "errorCheckingUpdatesNotifDescription": "En aviserings som visar när bakgrundsuppdateringarkollar misslyckas", "appsRemoved": "Appar borttagna", - "appsRemovedNotifDescription": "Notifies the user that one or more Apps were removed due to errors while loading them", - "xWasRemovedDueToErrorY": "{} was removed due to this error: {}", - "completeAppInstallation": "Complete App Installation", - "obtainiumMustBeOpenToInstallApps": "Obtainium must be open to install Apps", - "completeAppInstallationNotifDescription": "Asks the user to return to Obtainium to finish installing an App", + "appsRemovedNotifDescription": "Aviserar användaren när en eller fler Appar togs bort på grund av fel när de laddades", + "xWasRemovedDueToErrorY": "{} togs bort på grund av detta felet: {}", + "completeAppInstallation": "Gör klar appinstallation", + "obtainiumMustBeOpenToInstallApps": "Obtainium måste vara öppet för att installera Appar", + "completeAppInstallationNotifDescription": "Frågar användaren att återvända till Obtaiunium när appinstallation är klar", "checkingForUpdates": "Kollar efter Uppdateringar", "checkingForUpdatesNotifDescription": "Transient notification that appears when checking for updates", "pleaseAllowInstallPerm": "Tillåt Obtanium att installera Appar", "trackOnly": "Följ-Endast", "errorWithHttpStatusCode": "Fel {}", - "versionCorrectionDisabled": "Version correction disabled (plugin doesn't seem to work)", + "versionCorrectionDisabled": "Versionskorrigering inaktiverat (plugin verkar inte fungera)", "unknown": "Okänd", "none": "None", "never": "Aldrig", @@ -184,7 +184,7 @@ "update": "Uppdatera", "markUpdated": "Märk Uppdaterad", "additionalOptions": "Ytterligare Alternativ", - "disableVersionDetection": "Inaktivera versiondetektering", + "disableVersionDetection": "Inaktivera versionsdetektering", "noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.", "downloadingX": "Downloading {}", "downloadNotifDescription": "Notifies the user of the progress in downloading an App", From 8b29158d8bd0231e5fb1ea7b6c65ce794b4317d4 Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Mon, 16 Oct 2023 14:17:13 +0000 Subject: [PATCH 569/600] Update sv.json --- assets/translations/sv.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index c999c8f..796f575 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -186,7 +186,7 @@ "additionalOptions": "Ytterligare Alternativ", "disableVersionDetection": "Inaktivera versionsdetektering", "noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.", - "downloadingX": "Downloading {}", + "downloadingX": "Laddar ner {}", "downloadNotifDescription": "Notifies the user of the progress in downloading an App", "noAPKFound": "Ingen APK funnen", "noVersionDetection": "Ingen versiondetektering", @@ -201,17 +201,17 @@ "label": "Label", "language": "Språk", "copiedToClipboard": "Kopierat till Urklipp", - "storagePermissionDenied": "Storage permission denied", + "storagePermissionDenied": "Lagringsbehörighet nekad", "selectedCategorizeWarning": "This will replace any existing category settings for the selected Apps.", "filterAPKsByRegEx": "Filter APKs by Regular Expression", "removeFromObtainium": "Ta bort från Obtainium", "uninstallFromDevice": "Avinstallera från Enheten", - "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", - "releaseDateAsVersion": "Use Release Date as Version", + "onlyWorksWithNonVersionDetectApps": "Fungerar bara för Appar med versionsdetektering inaktiverat..", + "releaseDateAsVersion": "Använd releasedatum som version", "releaseDateAsVersionExplanation": "This option should only be used for Apps where version detection does not work correctly, but a release date is available.", "changes": "Ändringar", "releaseDate": "Releasedatum", - "importFromURLsInFile": "Import from URLs in File (like OPML)", + "importFromURLsInFile": "Importera från URL:er i fil (som OPML)", "versionDetection": "Versionsdetektering", "standardVersionDetection": "Standardversionsdetektering", "groupByCategory": "Gruppera via Kategori", @@ -233,7 +233,7 @@ "reversePageTransitions": "Reverse page transition animations", "minStarCount": "Minimum Star Count", "addInfoBelow": "Add this info below.", - "addInfoInSettings": "Add this info in the Settings.", + "addInfoInSettings": "Lägg till denna informationen i Inställningar.", "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", @@ -248,14 +248,14 @@ "verifyLatestTag": "Verifiera 'senaste'-taggen", "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", "intermediateLinkNotFound": "Intermediate link not found", - "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", + "exemptFromBackgroundUpdates": "Unta från bakgrundsuppdaterings (om aktiverar)", "bgUpdatesOnWiFiOnly": "Inaktivera Bakgrundsuppdateringar utan WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", "matchGroupToUse": "Match Group to Use", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Välj Exportsökväg", - "autoExportOnChanges": "Auto-export on changes", + "autoExportOnChanges": "Automatisk export vid ändringar", "filterVersionsByRegEx": "Filter Versions by Regular Expression", "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", "dontSortReleasesList": "Retain release order from API", From 5d9f31b99ef5cd9c7b283466a320a55432fa8f73 Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Mon, 16 Oct 2023 14:21:50 +0000 Subject: [PATCH 570/600] Update sv.json --- assets/translations/sv.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index 796f575..18aacd4 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -142,7 +142,7 @@ "warning": "Varning", "sourceIsXButPackageFromYPrompt": "Appens källa är '{}' men releasepaketet kommer från '{}'. Vill du fortsätta?", "updatesAvailable": "Uppdateringar Tillgängliga", - "updatesAvailableNotifDescription": "Aviserar användaren att det finns uppdateringar tillgängaliga för en eller fler Appar som spåras av Obtainium", + "updatesAvailableNotifDescription": "Aviserar användaren att det finns uppdateringar tillgängaliga för en eller fler Appar som följs av Obtainium", "noNewUpdates": "Inga nya uppdateringar.", "xHasAnUpdate": "{} har en uppdatering.", "appsUpdated": "Appar Uppdaterade", @@ -196,7 +196,7 @@ "noCategory": "Ingen Kategori", "noCategories": "Inga Kategorier", "deleteCategoriesQuestion": "Ta Bort Kategorier?", - "categoryDeleteWarning": "All Apps in deleted categories will be set to uncategorized.", + "categoryDeleteWarning": "Alla Appar i de borttagna kategorierna kommer att märkas som okategoriserade.", "addCategory": "Lägg till Kategori", "label": "Label", "language": "Språk", @@ -216,10 +216,10 @@ "standardVersionDetection": "Standardversionsdetektering", "groupByCategory": "Gruppera via Kategori", "autoApkFilterByArch": "Attempt to filter APKs by CPU architecture if possible", - "overrideSource": "Override Source", + "overrideSource": "Överskrid Källa", "dontShowAgain": "Visa inte detta igen", - "dontShowTrackOnlyWarnings": "Don't show 'Track-Only' warnings", - "dontShowAPKOriginWarnings": "Don't show APK origin warnings", + "dontShowTrackOnlyWarnings": "Visa inte 'Följ-Endast' varningar", + "dontShowAPKOriginWarnings": "Visa inte APK-ursprung varningar", "moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view", "gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)", "about": "Om", @@ -231,9 +231,9 @@ "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", "disablePageTransitions": "Disable page transition animations", "reversePageTransitions": "Reverse page transition animations", - "minStarCount": "Minimum Star Count", - "addInfoBelow": "Add this info below.", - "addInfoInSettings": "Lägg till denna informationen i Inställningar.", + "minStarCount": "Minsta antal stjärnmarkeringar", + "addInfoBelow": "Lägg till denna information nedanför.", + "addInfoInSettings": "Lägg till denna information i Inställningar.", "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", "sortByFileNamesNotLinks": "Sort by file names instead of full links", From 8601e2af7a05b1a14ed943f3d3c65b600c1c115b Mon Sep 17 00:00:00 2001 From: Mr-Bajs <93934125+Mr-Bajs@users.noreply.github.com> Date: Mon, 16 Oct 2023 14:22:38 +0000 Subject: [PATCH 571/600] Update sv.json --- assets/translations/sv.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/sv.json b/assets/translations/sv.json index 18aacd4..06aeabb 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -248,7 +248,7 @@ "verifyLatestTag": "Verifiera 'senaste'-taggen", "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", "intermediateLinkNotFound": "Intermediate link not found", - "exemptFromBackgroundUpdates": "Unta från bakgrundsuppdaterings (om aktiverar)", + "exemptFromBackgroundUpdates": "Undta från bakgrundsuppdateringar (om aktiverad)", "bgUpdatesOnWiFiOnly": "Inaktivera Bakgrundsuppdateringar utan WiFi", "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", "versionExtractionRegEx": "Version Extraction RegEx", From 92f5da306d0488180a99d2ff85e1bebc93c1f97d Mon Sep 17 00:00:00 2001 From: DwainZwerg <97027379+DwainZwerg@users.noreply.github.com> Date: Tue, 17 Oct 2023 09:10:18 +0000 Subject: [PATCH 572/600] Update de.json (small improvements --- assets/translations/de.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index 9f9efbe..b8a39ad 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -250,14 +250,14 @@ "intermediateLinkNotFound": "„Zwischen“link nicht gefunden", "exemptFromBackgroundUpdates": "Ausschluss von Hintergrundaktualisierungen (falls aktiviert)", "bgUpdatesOnWiFiOnly": "Hintergrundaktualisierungen deaktivieren, wenn kein WLAN vorhanden ist", - "autoSelectHighestVersionCode": "Automatisch höchste APK-Code-Version auswählen", + "autoSelectHighestVersionCode": "Automatisch höchste APK-Version auswählen", "versionExtractionRegEx": "Versions-Extraktion per RegEx", - "matchGroupToUse": "Zu verwendende Gruppe abgleichen", - "highlightTouchTargets": "Weniger offensichtliche Ziele hervorheben", + "matchGroupToUse": "zu verwendende Gruppe abgleichen", + "highlightTouchTargets": "Weniger offensichtliche Touch-Ziele hervorheben", "pickExportDir": "Export-Verzeichnis wählen", - "autoExportOnChanges": "Automatischer Export bei Änderung", + "autoExportOnChanges": "Automatischer Export bei Änderung(en)", "filterVersionsByRegEx": "Versionen nach regulären Ausdrücken filtern", - "trySelectingSuggestedVersionCode": "Versuchen, die vorgeschlagene APK-Code-Version auszuwählen", + "trySelectingSuggestedVersionCode": "Versuchen, den vorgeschlagenen APK-Versionscode auszuwählen", "dontSortReleasesList": "Freigaberelease von der API ordern", "reverseSort": "Umgekehrtes Sortieren", "debugMenu": "Debug-Menü", From aa23267d70fd5627ca7fa302672b8d52f43255ba Mon Sep 17 00:00:00 2001 From: unbranched <39440265+unbranched@users.noreply.github.com> Date: Tue, 17 Oct 2023 09:58:12 +0000 Subject: [PATCH 573/600] Update it.json --- assets/translations/it.json | 106 ++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/assets/translations/it.json b/assets/translations/it.json index 8ec4682..3a0f8a8 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -11,7 +11,7 @@ "unexpectedError": "Errore imprevisto", "ok": "Va bene", "and": "e", - "githubPATLabel": "GitHub Personal Access Token (diminuisce limite di traffico)", + "githubPATLabel": "GitHub Personal Access Token (riduce limite di traffico)", "includePrereleases": "Includi prerelease", "fallbackToOlderReleases": "Ripiega su release precedenti", "filterReleaseTitlesByRegEx": "Filtra release con espressioni regolari", @@ -51,9 +51,9 @@ "percentProgress": "Avanzamento: {}%", "pleaseWait": "In attesa", "updateAvailable": "Aggiornamento disponibile", - "estimateInBracketsShort": "(prev.)", + "estimateInBracketsShort": "(stim.)", "notInstalled": "Non installato", - "estimateInBrackets": "(previsto)", + "estimateInBrackets": "(stimato)", "selectAll": "Seleziona tutto", "deselectN": "Deseleziona {}", "xWillBeRemovedButRemainInstalled": "Verà effettuata la rimozione di {}, ma non la disinstallazione.", @@ -61,7 +61,7 @@ "removeSelectedApps": "Rimuovi le app selezionate", "updateX": "Aggiorna {}", "installX": "Installa {}", - "markXTrackOnlyAsUpdated": "Contrassegna {}\n(Solo-Monitoraggio)\ncome aggiornato", + "markXTrackOnlyAsUpdated": "Contrassegna {}\n(Solo-Monitoraggio)\ncome aggiornata", "changeX": "Modifica {}", "installUpdateApps": "Installa/Aggiorna app", "installUpdateSelectedApps": "Installa/Aggiorna le app selezionate", @@ -128,7 +128,7 @@ "pinUpdates": "Fissa aggiornamenti disponibili in alto", "updates": "Aggiornamenti", "sourceSpecific": "Specifiche per la fonte", - "appSource": "Sorgente dell'app", + "appSource": "Codice dell'app", "noLogs": "Nessun log", "appLogs": "Log dell'app", "close": "Chiudi", @@ -169,7 +169,7 @@ "installedVersionX": "Versione installata: {}", "lastUpdateCheckX": "Ultimo controllo degli aggiornamenti: {}", "remove": "Rimuovi", - "yesMarkUpdated": "Sì, contrassegna come aggiornato", + "yesMarkUpdated": "Sì, contrassegna come aggiornata", "fdroid": "F-Droid ufficiale", "appIdOrName": "ID o nome dell'app", "appId": "ID dell'app", @@ -180,9 +180,9 @@ "steamMobile": "Steam Mobile", "steamChat": "Steam Chat", "install": "Installa", - "markInstalled": "Contrassegna come installato", + "markInstalled": "Contrassegna come installata", "update": "Aggiorna", - "markUpdated": "Contrassegna come aggiornato", + "markUpdated": "Contrassegna come aggiornata", "additionalOptions": "Opzioni aggiuntive", "disableVersionDetection": "Disattiva il rilevamento della versione", "noVersionDetectionExplanation": "Questa opzione dovrebbe essere usata solo per le app la cui versione non viene rilevata correttamente.", @@ -221,54 +221,54 @@ "dontShowTrackOnlyWarnings": "Non mostrare gli avvisi 'Solo-Monitoraggio'", "dontShowAPKOriginWarnings": "Non mostrare gli avvisi di origine dell'APK", "moveNonInstalledAppsToBottom": "Sposta le app non installate in fondo alla lista", - "gitlabPATLabel": "GitLab Personal Access Token\n(attiva la ricerca and Better APK Discovery)", + "gitlabPATLabel": "GitLab Personal Access Token\n(attiva la ricerca e migliora la rilevazione di apk)", "about": "Informazioni", "requiresCredentialsInSettings": "Servono credenziali aggiuntive (in Impostazioni)", "checkOnStart": "Controlla una volta all'avvio", "tryInferAppIdFromCode": "Prova a dedurre l'ID dell'app dal codice sorgente", - "removeOnExternalUninstall": "Automatically remove externally uninstalled Apps", - "pickHighestVersionCode": "Auto-select highest version code APK", - "checkUpdateOnDetailPage": "Check for updates on opening an App detail page", - "disablePageTransitions": "Disable page transition animations", - "reversePageTransitions": "Reverse page transition animations", - "minStarCount": "Minimum Star Count", - "addInfoBelow": "Add this info below.", - "addInfoInSettings": "Add this info in the Settings.", - "githubSourceNote": "GitHub rate limiting can be avoided using an API key.", - "gitlabSourceNote": "GitLab APK extraction may not work without an API key.", - "sortByFileNamesNotLinks": "Sort by file names instead of full links", - "filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression", - "customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')", - "appsPossiblyUpdated": "App Updates Attempted", - "appsPossiblyUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were potentially applied in the background", - "xWasPossiblyUpdatedToY": "{} may have been updated to {}.", - "enableBackgroundUpdates": "Enable background updates", - "backgroundUpdateReqsExplanation": "Background updates may not be possible for all apps.", - "backgroundUpdateLimitsExplanation": "The success of a background install can only be determined when Obtainium is opened.", - "verifyLatestTag": "Verify the 'latest' tag", - "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", - "intermediateLinkNotFound": "Intermediate link not found", - "exemptFromBackgroundUpdates": "Exempt from background updates (if enabled)", - "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi", - "autoSelectHighestVersionCode": "Auto-select highest versionCode APK", - "versionExtractionRegEx": "Version Extraction RegEx", - "matchGroupToUse": "Match Group to Use", - "highlightTouchTargets": "Highlight less obvious touch targets", - "pickExportDir": "Pick Export Directory", - "autoExportOnChanges": "Auto-export on changes", - "filterVersionsByRegEx": "Filter Versions by Regular Expression", - "trySelectingSuggestedVersionCode": "Try selecting suggested versionCode APK", - "dontSortReleasesList": "Retain release order from API", - "reverseSort": "Reverse sorting", - "debugMenu": "Debug Menu", - "bgTaskStarted": "Background task started - check logs.", - "runBgCheckNow": "Run Background Update Check Now", - "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", - "installing": "Installing", - "skipUpdateNotifications": "Skip update notifications", + "removeOnExternalUninstall": "Rimuovi automaticamente app disinstallate esternamente", + "pickHighestVersionCode": "Auto-seleziona APK con version code più alto", + "checkUpdateOnDetailPage": "Controlla aggiornamenti all'apertura dei dettagli dell'app", + "disablePageTransitions": "Disattiva animazioni di transizione pagina", + "reversePageTransitions": "Inverti animazioni di transizione pagina", + "minStarCount": "Numero minimo di stelle", + "addInfoBelow": "Aggiungi questa info sotto.", + "addInfoInSettings": "Aggiungi questa info nelle impostazioni.", + "githubSourceNote": "Il limite di ricerca GitHub può essere evitato usando una chiave API.", + "gitlabSourceNote": "L'estrazione di APK da GitLab potrebbe non funzionare senza chiave API.", + "sortByFileNamesNotLinks": "Ordina per nome del file invece dei link completi", + "filterReleaseNotesByRegEx": "Filtra le note di rilascio con espressione regolare", + "customLinkFilterRegex": "Filtra link APK personalizzato con espressione regolare (predefinito '.apk$')", + "appsPossiblyUpdated": "Aggiornamenti app tentati", + "appsPossiblyUpdatedNotifDescription": "Notifica all'utente che sono stati potenzialmente applicati in secondo piano aggiornamenti a una o più app", + "xWasPossiblyUpdatedToY": "{} potrebbe essere stata aggiornata alla {}.", + "enableBackgroundUpdates": "Attiva aggiornamenti in secondo piano", + "backgroundUpdateReqsExplanation": "Gli aggiornamenti in secondo piano potrebbero non essere possibili per tutte le app.", + "backgroundUpdateLimitsExplanation": "La riuscita di un'installazione in secondo piano può essere determinata solo quando viene aperto Obtainium.", + "verifyLatestTag": "Verifica l'etichetta 'Latest'", + "intermediateLinkRegex": "Filtra un link 'Intermedio' da visitare prima", + "intermediateLinkNotFound": "Link intermedio non trovato", + "exemptFromBackgroundUpdates": "Esente da aggiornamenti in secondo piano (se attivo)", + "bgUpdatesOnWiFiOnly": "Disattiva aggiornamenti in secondo piano quando non si usa il WiFi", + "autoSelectHighestVersionCode": "Auto-seleziona APK con versionCode più alto", + "versionExtractionRegEx": "RegEx di estrazione versione", + "matchGroupToUse": "Gruppo da usare", + "highlightTouchTargets": "Evidenzia elementi toccabili meno ovvi", + "pickExportDir": "Scegli cartella esp.", + "autoExportOnChanges": "Auto-esporta dopo modifiche", + "filterVersionsByRegEx": "Filtra versioni con espressione regolare", + "trySelectingSuggestedVersionCode": "Prova a selezionare APK con versionCode suggerito", + "dontSortReleasesList": "Conserva l'ordine di release da API", + "reverseSort": "Ordine inverso", + "debugMenu": "Menu di debug", + "bgTaskStarted": "Attività in secondo piano iniziata - controllo log.", + "runBgCheckNow": "Inizia aggiornamento in secondo piano ora", + "versionExtractWholePage": "Applica regex di estrazione versione a tutta la pagina", + "installing": "Installazione", + "skipUpdateNotifications": "Salta notifiche di aggiornamento", "updatesAvailableNotifChannel": "Aggiornamenti disponibili", "appsUpdatedNotifChannel": "App aggiornate", - "appsPossiblyUpdatedNotifChannel": "App Updates Attempted", + "appsPossiblyUpdatedNotifChannel": "Aggiornamenti app tentati", "errorCheckingUpdatesNotifChannel": "Controllo degli errori per gli aggiornamenti", "appsRemovedNotifChannel": "App rimosse", "downloadingXNotifChannel": "Scaricamento di {} in corso", @@ -323,7 +323,7 @@ "other": "{} e altre {} app sono state aggiornate." }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} and 1 more app may have been updated.", - "other": "{} and {} more apps may have been updated." + "one": "{} e un'altra app potrebbero essere state aggiornate.", + "other": "{} e altre {} app potrebbero essere state aggiornate." } -} \ No newline at end of file +} From d0174479d7d8c7e2786d123e50aadaf5a23f3138 Mon Sep 17 00:00:00 2001 From: k03mad Date: Tue, 17 Oct 2023 17:50:10 +0300 Subject: [PATCH 574/600] update ru translation --- assets/translations/ru.json | 216 ++++++++++++++++++------------------ 1 file changed, 108 insertions(+), 108 deletions(-) diff --git a/assets/translations/ru.json b/assets/translations/ru.json index f4cf61a..1f9d373 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -1,5 +1,5 @@ { - "invalidURLForSource": "Неверный URL-адрес {} приложения", + "invalidURLForSource": "Неверный URL-адрес приложения: {}", "noReleaseFound": "Не удалось найти подходящий релиз", "noVersionFound": "Не удалось определить версию релиза", "urlMatchesNoSource": "URL-адрес не соответствует известному источнику", @@ -9,41 +9,41 @@ "placeholder": "Заполнитель", "someErrors": "Возникли некоторые ошибки", "unexpectedError": "Неожиданная ошибка", - "ok": "Окей", + "ok": "Ok", "and": "и", - "githubPATLabel": "Персональный токен доступа GitHub (увеличивает лимит запросов)", + "githubPATLabel": "Персональный токен доступа GitHub\n(увеличивает лимит запросов)", "includePrereleases": "Включить предварительные релизы", - "fallbackToOlderReleases": "Откатиться к более старым версиям", - "filterReleaseTitlesByRegEx": "Фильтровать заголовки релизов\nс помощью регулярного выражения", + "fallbackToOlderReleases": "Откатываться к предыдущей версии", + "filterReleaseTitlesByRegEx": "Фильтровать заголовки релизов\n(регулярное выражение)", "invalidRegEx": "Неверное регулярное выражение", "noDescription": "Нет описания", "cancel": "Отмена", "continue": "Продолжить", - "requiredInBrackets": "(Обязательно)", - "dropdownNoOptsError": "Ошибка: Выпадающий список должен содержать хотя бы одну опцию", + "requiredInBrackets": "(обязательно)", + "dropdownNoOptsError": "Ошибка: в выпадающем списке должна быть выбрана хотя бы одна настройка", "colour": "Цвет", - "githubStarredRepos": "Помеченные звездочкой репозитории на GitHub", + "githubStarredRepos": "Избранные репозитории GitHub", "uname": "Имя пользователя", "wrongArgNum": "Неправильное количество предоставленных аргументов", "xIsTrackOnly": "{} только для отслеживания", "source": "Источник", "app": "Приложение", - "appsFromSourceAreTrackOnly": "Приложения из этого источника являются 'только для отслеживания'.", - "youPickedTrackOnly": "Вы выбрали опцию 'Только для отслеживания'.", - "trackOnlyAppDescription": "Приложение будет отслеживаться на предмет обновлений, но Obtainium не сможет загрузить или установить его.", + "appsFromSourceAreTrackOnly": "Приложения из этого источника настроены только для отслеживания", + "youPickedTrackOnly": "Вы выбрали опцию 'Только для отслеживания'", + "trackOnlyAppDescription": "Приложение будет отслеживаться на предмет обновлений, но Obtainium не сможет загрузить или установить его", "cancelled": "Отменено", "appAlreadyAdded": "Приложение уже добавлено", "alreadyUpToDateQuestion": "Приложение уже обновлено?", - "addApp": "Добавить приложение", + "addApp": "Добавить", "appSourceURL": "URL-источник приложения", "error": "Ошибка", "add": "Добавить", - "searchSomeSourcesLabel": "Поиск (только в некоторых источниках)", + "searchSomeSourcesLabel": "Поиск (в некоторых источниках)", "search": "Поиск", - "additionalOptsFor": "Дополнительные опции для {}", + "additionalOptsFor": "Дополнительные настройки для {}", "supportedSources": "Поддерживаемые источники", - "trackOnlyInBrackets": "(Только для отслеживания)", - "searchableInBrackets": "(Поиск)", + "trackOnlyInBrackets": "(только отслеживание)", + "searchableInBrackets": "(поиск)", "appsString": "Приложения", "noApps": "Нет приложений", "noAppsForFilter": "Нет приложений для фильтра", @@ -54,9 +54,9 @@ "estimateInBracketsShort": "(Оценка)", "notInstalled": "Не установлено", "estimateInBrackets": "(Оценка)", - "selectAll": "Выбрать все", + "selectAll": "Выбрать всё", "deselectN": "Отменить выбор {}", - "xWillBeRemovedButRemainInstalled": "{} будет удалено из Obtainium, но останется установленным на устройстве.", + "xWillBeRemovedButRemainInstalled": "{} будет удалено из Obtainium, но останется на устройстве", "removeSelectedAppsQuestion": "Удалить выбранные приложения?", "removeSelectedApps": "Удалить выбранные приложения", "updateX": "Обновить {}", @@ -65,17 +65,17 @@ "changeX": "Изменить {}", "installUpdateApps": "Установить/Обновить приложения", "installUpdateSelectedApps": "Установить/Обновить выбранные приложения", - "markXSelectedAppsAsUpdated": "Отметить {} выбранные приложения как обновленные?", + "markXSelectedAppsAsUpdated": "Выбрано приложений: {}. Отметить как обновлённые?", "no": "Нет", "yes": "Да", - "markSelectedAppsUpdated": "Отметить выбранные приложения как обновленные", + "markSelectedAppsUpdated": "Отметить выбранные приложения как обновлённые", "pinToTop": "Закрепить сверху", "unpinFromTop": "Открепить", "resetInstallStatusForSelectedAppsQuestion": "Сбросить статус установки для выбранных приложений?", - "installStatusOfXWillBeResetExplanation": "Статус установки для выбранных приложений будет сброшен.\n\nЭто может помочь, если версия приложения, отображаемая в Obtainium, неправильная из-за неудачных обновлений или других проблем.", + "installStatusOfXWillBeResetExplanation": "Статус установки для выбранных приложений будет сброшен.\n\nЭто может помочь, если версия приложения, отображаемая в Obtainium, некорректная — из-за неудачных обновлений или других проблем", "shareSelectedAppURLs": "Поделиться выбранными URL-адресами приложений", "resetInstallStatus": "Сбросить статус установки", - "more": "Еще", + "more": "Ещё", "removeOutdatedFilter": "Удалить фильтр для устаревших приложений", "showOutdatedOnly": "Показывать только устаревшие приложения", "filter": "Фильтр", @@ -85,7 +85,7 @@ "author": "Автор", "upToDateApps": "Приложения со свежими обновлениями", "nonInstalledApps": "Неустановленные приложения", - "importExport": "Импорт/экспорт", + "importExport": "Данные", "settings": "Настройки", "exportedTo": "Экспортировано в {}", "obtainiumExport": "Экспорт из Obtainium", @@ -99,63 +99,63 @@ "searchX": "Поиск {}", "noResults": "Результатов не найдено", "importX": "Импорт {}", - "importedAppsIdDisclaimer": "Импортированные приложения могут неверно отображаться как 'Не установлены'.\nДля исправления этой проблемы повторно установите их через Obtainium.\nЭто не должно повлиять на данные приложения.\n\nПроблемы возникают только при импорте из URL-адреса и сторонних источников.", + "importedAppsIdDisclaimer": "Импортированные приложения могут неверно отображаться как неустановленные.\nДля исправления этой проблемы повторно установите их через Obtainium.\nЭто не должно повлиять на данные приложения.\n\nПроблемы возникают только при импорте из URL-адреса и сторонних источников", "importErrors": "Ошибка импорта", - "importedXOfYApps": "Импортировано {} из {} приложений.", + "importedXOfYApps": "Импортировано приложений: {} из {}", "followingURLsHadErrors": "При импорте следующие URL-адреса содержали ошибки:", - "okay": "Окей", + "okay": "Ok", "selectURL": "Выбрать URL-адрес", "selectURLs": "Выбрать URL-адреса", "pick": "Выбрать", "theme": "Тема", - "dark": "Темная", + "dark": "Тёмная", "light": "Светлая", - "followSystem": "Как в системе", + "followSystem": "Системная", "obtainium": "Obtainium", "materialYou": "Material You", "useBlackTheme": "Использовать чёрную тему", - "appSortBy": "Сортировка приложений по", + "appSortBy": "Сортировка приложений", "authorName": "Автор/Название", "nameAuthor": "Название/Автор", "asAdded": "В порядке добавления", - "appSortOrder": "Порядок сортировки приложений", + "appSortOrder": "Порядок", "ascending": "По возрастанию", "descending": "По убыванию", "bgUpdateCheckInterval": "Интервал проверки обновлений в фоновом режиме", - "neverManualOnly": "Никогда - Только вручную", + "neverManualOnly": "Никогда — только вручную", "appearance": "Внешний вид", - "showWebInAppView": "Показывать исходную веб-страницу в представлении приложения", - "pinUpdates": "Закрепить обновления сверху списка приложений", + "showWebInAppView": "Показывать исходную веб-страницу на странице приложения", + "pinUpdates": "Отображать обновления приложений сверху списка", "updates": "Обновления", - "sourceSpecific": "Специфика источника", - "appSource": "Источник приложения", + "sourceSpecific": "Настройки источников", + "appSource": "Исходный код", "noLogs": "Нет журналов", - "appLogs": "Журналы приложений", + "appLogs": "Логи", "close": "Закрыть", "share": "Поделиться", "appNotFound": "Приложение не найдено", "obtainiumExportHyphenatedLowercase": "obtainium-export", "pickAnAPK": "Выберите APK-файл", "appHasMoreThanOnePackage": "{} имеет более одного пакета:", - "deviceSupportsXArch": "Ваше устройство поддерживает архитектуру процессора {}.", + "deviceSupportsXArch": "Ваше устройство поддерживает архитектуру процессора {}", "deviceSupportsFollowingArchs": "Ваше устройство поддерживает следующие архитектуры процессора:", "warning": "Предупреждение", - "sourceIsXButPackageFromYPrompt": "Источник приложения - '{}', но пакет для установки получен из '{}'. Продолжить?", + "sourceIsXButPackageFromYPrompt": "Источник приложения — '{}', но пакет для установки получен из '{}'. Продолжить?", "updatesAvailable": "Доступны обновления", - "updatesAvailableNotifDescription": "Уведомляет пользователя о наличии обновлений для одного или нескольких приложений, отслеживаемых Obtainium", - "noNewUpdates": "Нет новых обновлений.", - "xHasAnUpdate": "{} есть обновление.", + "updatesAvailableNotifDescription": "Уведомляет о наличии обновлений для одного или нескольких приложений в Obtainium", + "noNewUpdates": "Нет новых обновлений", + "xHasAnUpdate": "{} есть обновление", "appsUpdated": "Приложения обновлены", - "appsUpdatedNotifDescription": "Уведомляет пользователя о том, что обновления для одного или нескольких приложений были применены в фоновом режиме", - "xWasUpdatedToY": "{} была обновлена до версии {}.", + "appsUpdatedNotifDescription": "Уведомляет об обновлении одного или нескольких приложений в фоновом режиме", + "xWasUpdatedToY": "{} была обновлена до версии {}", "errorCheckingUpdates": "Ошибка при проверке обновлений", - "errorCheckingUpdatesNotifDescription": "Уведомление, которое появляется, когда проверка обновлений в фоновом режиме завершилась с ошибкой", + "errorCheckingUpdatesNotifDescription": "Уведомление о завершении проверки обновлений в фоновом режиме с ошибкой", "appsRemoved": "Приложение удалено", - "appsRemovedNotifDescription": "Уведомляет пользователя о том, что одно или несколько приложений было удалено из-за ошибок при их загрузке", + "appsRemovedNotifDescription": "Уведомление об удалении одного или несколько приложений из-за ошибок при их загрузке", "xWasRemovedDueToErrorY": "{} был удален из-за ошибки: {}", "completeAppInstallation": "Завершение установки приложения", - "obtainiumMustBeOpenToInstallApps": "Для установки приложений Obtainium должен быть открыт", - "completeAppInstallationNotifDescription": "Просит пользователя вернуться в Obtainium, чтобы завершить установку приложения", + "obtainiumMustBeOpenToInstallApps": "Obtainium должен быть открыт для установки приложений", + "completeAppInstallationNotifDescription": "Уведомление о необходимости открыть Obtainium для завершения установки приложения", "checkingForUpdates": "Проверка обновлений", "checkingForUpdatesNotifDescription": "Временное уведомление, которое появляется при проверке обновлений", "pleaseAllowInstallPerm": "Пожалуйста, разрешите Obtainium устанавливать приложения", @@ -167,14 +167,14 @@ "never": "Никогда", "latestVersionX": "Последняя версия: {}", "installedVersionX": "Установленная версия: {}", - "lastUpdateCheckX": "Последняя проверка обновлений: {}", + "lastUpdateCheckX": "Последняя проверка: {}", "remove": "Удалить", "yesMarkUpdated": "Да, отметить как обновленное", - "fdroid": "Официальный F-Droid", + "fdroid": "Официальные репозитории F-Droid", "appIdOrName": "ID или название приложения", "appId": "ID приложения", "appWithIdOrNameNotFound": "Приложение с таким ID или названием не было найдено", - "reposHaveMultipleApps": "В хранилище может быть несколько приложений", + "reposHaveMultipleApps": "В хранилище несколько приложений", "fdroidThirdPartyRepo": "Сторонние репозитории F-Droid", "steam": "Steam", "steamMobile": "Steam Mobile", @@ -182,75 +182,75 @@ "install": "Установить", "markInstalled": "Пометить как установленное", "update": "Обновить", - "markUpdated": "Отметить обновленным", - "additionalOptions": "Дополнительные опции", + "markUpdated": "Отметить обновлённым", + "additionalOptions": "Дополнительные настройки", "disableVersionDetection": "Отключить обнаружение версии", - "noVersionDetectionExplanation": "Эта опция должна использоваться только для приложений, где обнаружение версии не работает корректно.", + "noVersionDetectionExplanation": "Эта настройка должна использоваться только для приложений, где обнаружение версии не работает корректно", "downloadingX": "Загрузка {}", "downloadNotifDescription": "Уведомляет пользователя о прогрессе загрузки приложения", "noAPKFound": "APK не найден", - "noVersionDetection": "Версий не обнаружено", + "noVersionDetection": "Обнаружение версий отключено", "categorize": "Категоризировать", "categories": "Категории", "category": "Категория", "noCategory": "Без категории", "noCategories": "Без категорий", "deleteCategoriesQuestion": "Удалить категории?", - "categoryDeleteWarning": "Все приложения в удаленных категориях будут помечены как без категории.", + "categoryDeleteWarning": "Все приложения в удаленных категориях будут помечены как без категории", "addCategory": "Добавить категорию", "label": "Метка", "language": "Язык", "copiedToClipboard": "Скопировано в буфер обмена", "storagePermissionDenied": "Отказано в доступе к хранилищу", - "selectedCategorizeWarning": "Это заменит все текущие настройки категорий для выбранных приложений.", - "filterAPKsByRegEx": "Фильтровать APK-файлы с помощью\nрегулярного выражения", + "selectedCategorizeWarning": "Это заменит все текущие настройки категорий для выбранных приложений", + "filterAPKsByRegEx": "Отфильтровать APK-файлы\n(регулярное выражение)", "removeFromObtainium": "Удалить из Obtainium", "uninstallFromDevice": "Удалить с устройства", - "onlyWorksWithNonVersionDetectApps": "Работает только для приложений с отключенным определением версии.", - "releaseDateAsVersion": "Использовать дату выпуска в качестве версии", - "releaseDateAsVersionExplanation": "Этот параметр следует использовать только для приложений, в которых определение версии не работает правильно, но имеется дата выпуска.", + "onlyWorksWithNonVersionDetectApps": "Работает только для приложений с отключенным определением версии", + "releaseDateAsVersion": "Дата выпуска вместо версии", + "releaseDateAsVersionExplanation": "Этот параметр следует использовать только для приложений, в которых определение версии не работает правильно, но имеется дата выпуска", "changes": "Изменения", "releaseDate": "Дата выпуска", - "importFromURLsInFile": "Импорт URL-адресов из файла (например, OPML)", + "importFromURLsInFile": "Импорт из файла URL-адресов (например: OPML)", "versionDetection": "Определение версии", - "standardVersionDetection": "Стандартное определение версии", + "standardVersionDetection": "Стандартное", "groupByCategory": "Группировать по категориям", - "autoApkFilterByArch": "Попытка фильтрации APK-файлов по архитектуре процессора, если это возможно", + "autoApkFilterByArch": "Попытаться отфильтровать APK-файлы по архитектуре процессора", "overrideSource": "Переопределить источник", "dontShowAgain": "Не показывать снова", "dontShowTrackOnlyWarnings": "Не показывать предупреждения о только отслеживаемых приложениях", - "dontShowAPKOriginWarnings": "Не показывать предупреждения об источнике APK-файлов", - "moveNonInstalledAppsToBottom": "Переместить неустановленные приложения вниз списка", - "gitlabPATLabel": "Персональный токен доступа GitLab\n(Включает поиск и улучшает обнаружение APK)", - "about": "О приложении", + "dontShowAPKOriginWarnings": "Не показывать предупреждения об отличающемся источнике APK-файлов", + "moveNonInstalledAppsToBottom": "Отображать неустановленные приложения внизу списка", + "gitlabPATLabel": "Персональный токен доступа GitLab\n(включает поиск и улучшает обнаружение APK)", + "about": "Описание", "requiresCredentialsInSettings": "Для этого требуются дополнительные учетные данные (в настройках)", "checkOnStart": "Проверять наличие обновлений при запуске", "tryInferAppIdFromCode": "Попытаться определить ID приложения из исходного кода", "removeOnExternalUninstall": "Автоматически убирать из списка удаленные извне приложения", - "pickHighestVersionCode": "Автовыбор кода наивысшей версии APK", - "checkUpdateOnDetailPage": "Проверять наличие обновлений при открытии страницы представления приложения", + "pickHighestVersionCode": "Автовыбор актуальной версии кода APK", + "checkUpdateOnDetailPage": "Проверять наличие обновлений при открытии страницы приложения", "disablePageTransitions": "Отключить анимацию перехода между страницами", "reversePageTransitions": "Реверс анимации перехода между страницами", "minStarCount": "Минимальное количество звёзд", - "addInfoBelow": "Добавьте эту информацию ниже.", - "addInfoInSettings": "Добавьте эту информацию в Настройки.", - "githubSourceNote": "Лимит запросов GitHub можно обойти, используя ключ API.", - "gitlabSourceNote": "Извлечение APK из GitLab может не работать без ключа API.", - "sortByFileNamesNotLinks": "Сортировать по именам файлов, а не по полным ссылкам", - "filterReleaseNotesByRegEx": "Фильтровать примечания к выпуску по регулярному выражению", - "customLinkFilterRegex": "Пользовательский фильтр ссылок APK по регулярному выражению (по умолчанию '.apk$')", + "addInfoBelow": "Добавьте эту информацию ниже", + "addInfoInSettings": "Добавьте эту информацию в Настройки", + "githubSourceNote": "Используя ключ API можно обойти лимит запросов GitHub", + "gitlabSourceNote": "Без ключа API может не работать извлечение APK с GitLab", + "sortByFileNamesNotLinks": "Сортировать по именам файлов, а не ссылкам целиком", + "filterReleaseNotesByRegEx": "Фильтровать примечания к выпуску\n(регулярное выражение)", + "customLinkFilterRegex": "Пользовательский фильтр ссылок APK\n(регулярное выражение, по умолчанию: '.apk$')", "appsPossiblyUpdated": "Попытки обновления приложений", - "appsPossiblyUpdatedNotifDescription": "Уведомляет пользователя о возможных обновлениях одного или нескольких приложений в фоновом режиме", - "xWasPossiblyUpdatedToY": "{} возможно был обновлен до {}.", + "appsPossiblyUpdatedNotifDescription": "Уведомление о возможных обновлениях одного или нескольких приложений в фоновом режиме", + "xWasPossiblyUpdatedToY": "{} возможно был обновлен до {}", "enableBackgroundUpdates": "Включить обновления в фоне", - "backgroundUpdateReqsExplanation": "Фоновые обновления могут быть невозможны для всех приложений.", - "backgroundUpdateLimitsExplanation": "Успех фоновой установки можно определить только после открытия Obtainium.", - "verifyLatestTag": "Проверьте тег 'последний'", - "intermediateLinkRegex": "Фильтр ссылок 'промежуточного' типа для приоритетного посещения", + "backgroundUpdateReqsExplanation": "Фоновые обновления могут быть возможны не для всех приложений", + "backgroundUpdateLimitsExplanation": "Успешность фоновой установки можно определить только после открытия Obtainium", + "verifyLatestTag": "Проверять тег 'latest'", + "intermediateLinkRegex": "Фильтр промежуточных ссылок для первоочередного посещения\n(регулярное выражение)", "intermediateLinkNotFound": "Промежуточная ссылка не найдена", "exemptFromBackgroundUpdates": "Исключить из фоновых обновлений (если включено)", "bgUpdatesOnWiFiOnly": "Отключить фоновые обновления, если нет соединения с Wi-Fi", - "autoSelectHighestVersionCode": "Автоматически выбирать APK с наивысшим кодом версии", + "autoSelectHighestVersionCode": "Автоматически выбирать APK с актуальной версией кода", "versionExtractionRegEx": "Регулярное выражение для извлечения версии", "matchGroupToUse": "Выберите группу для использования", "highlightTouchTargets": "Выделить менее очевидные элементы управления касанием", @@ -258,14 +258,14 @@ "autoExportOnChanges": "Автоэкспорт при изменениях", "filterVersionsByRegEx": "Фильтровать версии по регулярному выражению", "trySelectingSuggestedVersionCode": "Попробуйте выбрать предложенный код версии APK", - "dontSortReleasesList": "Сохранить порядок выпусков от API", + "dontSortReleasesList": "Сохранить порядок релизов от API", "reverseSort": "Обратная сортировка", - "debugMenu": "Меню Отладки", - "bgTaskStarted": "Фоновая задача начата - проверьте журналы.", + "debugMenu": "Меню отладки", + "bgTaskStarted": "Фоновая задача начата — проверьте журналы", "runBgCheckNow": "Запустить проверку фонового обновления сейчас", - "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", - "installing": "Installing", - "skipUpdateNotifications": "Skip update notifications", + "versionExtractWholePage": "Применить регулярное выражение версии ко всей странице", + "installing": "Устанавливается", + "skipUpdateNotifications": "Не оповещать об обновлениях", "updatesAvailableNotifChannel": "Доступны обновления", "appsUpdatedNotifChannel": "Приложения обновлены", "appsPossiblyUpdatedNotifChannel": "Попытки обновления приложений", @@ -279,51 +279,51 @@ "other": "Удалить приложения?" }, "tooManyRequestsTryAgainInMinutes": { - "one": "Слишком много запросов (ограничение скорости) - попробуйте снова через {} минуту", - "other": "Слишком много запросов (ограничение скорости) - попробуйте снова через {} минуты" + "one": "Слишком много запросов (ограничение скорости) — попробуйте снова через {} минуту", + "other": "Слишком много запросов (ограничение скорости) — попробуйте снова через {} минуты" }, "bgUpdateGotErrorRetryInMinutes": { "one": "При проверке обновлений в фоновом режиме возникла ошибка {}, повторная проверка будет запланирована через {} минуту", "other": "При проверке обновлений в фоновом режиме возникла ошибка {}, повторная проверка будет запланирована через {} минуты" }, "bgCheckFoundUpdatesWillNotifyIfNeeded": { - "one": "В ходе проверки обновления в фоновом режиме было обнаружено {} обновление - Пользователю будет отправлено уведомление, если это необходимо", - "other": "В ходе проверки обновления в фоновом режиме было обнаружено {} обновлений - Пользователю будет отправлено уведомление, если это необходимо" + "one": "В ходе проверки обновления в фоновом режиме было обнаружено {} обновление — Пользователю будет отправлено уведомление, если это необходимо", + "other": "В ходе проверки обновления в фоновом режиме было обнаружено {} обновлений — Пользователю будет отправлено уведомление, если это необходимо" }, "apps": { - "one": "{} Приложение", - "other": "{} Приложений" + "one": "{} приложение", + "other": "{} приложений" }, "url": { "one": "{} URL-адрес", "other": "{} URL-адреса" }, "minute": { - "one": "{} Минута", - "other": "{} Минуты" + "one": "{} минута", + "other": "{} минуты" }, "hour": { - "one": "{} Час", - "other": "{} Часов" + "one": "{} час", + "other": "{} часов" }, "day": { - "one": "{} День", - "other": "{} Дней" + "one": "{} день", + "other": "{} дней" }, "clearedNLogsBeforeXAfterY": { "one": "Очищен {n} журнал (до = {before}, после = {after})", "other": "Очищено {n} журналов (до = {before}, после = {after})" }, "xAndNMoreUpdatesAvailable": { - "one": "У {} и еще 1 приложения есть обновление.", - "other": "У {} и ещё {} приложений есть обновления." + "one": "У {} и еще 1 приложения есть обновление", + "other": "У {} и ещё {} приложений есть обновления" }, "xAndNMoreUpdatesInstalled": { - "one": "{} и ещё 1 приложение были обновлены.", - "other": "{} и ещё {} приложений были обновлены." + "one": "{} и ещё 1 приложение были обновлены", + "other": "{} и ещё {} приложений были обновлены" }, "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} и ещё 1 приложение могли быть обновлены.", - "other": "{} и ещё {} приложений могли быть обновлены." + "one": "{} и ещё 1 приложение могли быть обновлены", + "other": "{} и ещё {} приложений могли быть обновлены" } -} \ No newline at end of file +} From 2518c70ec890f952ef99083f615b18997294f753 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 18 Oct 2023 19:42:15 -0400 Subject: [PATCH 575/600] Bugfixes Don't replace / in versions (#1023) Fix HTML version extraction (#1021) Update check only for installed apps (#1012) --- assets/translations/bs.json | 1 + assets/translations/cs.json | 1 + assets/translations/de.json | 1 + assets/translations/en.json | 1 + assets/translations/es.json | 1 + assets/translations/fa.json | 1 + assets/translations/fr.json | 1 + assets/translations/hu.json | 1 + assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/pl.json | 1 + assets/translations/pt.json | 1 + assets/translations/ru.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/html.dart | 4 ++- lib/pages/settings.dart | 20 ++++++++++++- lib/providers/apps_provider.dart | 45 ++++++++++++++++++++-------- lib/providers/settings_provider.dart | 9 ++++++ lib/providers/source_provider.dart | 3 +- 19 files changed, 79 insertions(+), 16 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index acca651..d3bf65a 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "Preuzimanje {}", "completeAppInstallationNotifChannel": "Dovršite instalaciju aplikacije", "checkingForUpdatesNotifChannel": "Tražim moguće nadogradnje", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index df3be45..b4b052e 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "download {}", "completeAppInstallationNotifChannel": "Dokončit instalaci aplikace", "checkingForUpdatesNotifChannel": "Zkontrolovat aktualizace", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/de.json b/assets/translations/de.json index b8a39ad..f25949f 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "Lade {} herunter", "completeAppInstallationNotifChannel": "App Installation abschließen", "checkingForUpdatesNotifChannel": "Nach Aktualisierungen suchen", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 6d8311c..4e4626a 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "Downloading {}", "completeAppInstallationNotifChannel": "Complete App Installation", "checkingForUpdatesNotifChannel": "Checking for Updates", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index a73970b..481838a 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "Descargando {}", "completeAppInstallationNotifChannel": "Instalación Completa de la Aplicación", "checkingForUpdatesNotifChannel": "Buscando Actualizaciones", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index f051b48..013ee34 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "در حال دانلود {}", "completeAppInstallationNotifChannel": "نصب کامل برنامه", "checkingForUpdatesNotifChannel": "بررسی به‌روزرسانی‌ها", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 649b0ff..e5d3bba 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "Téléchargement {}", "completeAppInstallationNotifChannel": "Installation complète de l'application", "checkingForUpdatesNotifChannel": "Vérification des mises à jour", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index b41dfb4..12a288f 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "{} letöltés", "completeAppInstallationNotifChannel": "Teljes app telepítés", "checkingForUpdatesNotifChannel": "Frissítések keresése", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "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 3a0f8a8..e00c0b8 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "Scaricamento di {} in corso", "completeAppInstallationNotifChannel": "Completa l'installazione dell'app", "checkingForUpdatesNotifChannel": "Controllo degli aggiornamenti in corso", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 596669d..385de2d 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "{} をダウンロード中", "completeAppInstallationNotifChannel": "アプリのインストールを完了する", "checkingForUpdatesNotifChannel": "アップデートを確認中", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 9aa9f31..bb55a51 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "Pobieranie aplikacji", "completeAppInstallationNotifChannel": "Ukończenie instalacji aplikacji", "checkingForUpdatesNotifChannel": "Sprawdzanie dostępności aktualizacji", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index 047b9f8..9611468 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "Baixando {}", "completeAppInstallationNotifChannel": "Instalação completa do App", "checkingForUpdatesNotifChannel": "Checando por Atualizações", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "Remover App?", "other": "Remover Apps?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 1f9d373..f02a7da 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "Загрузка {}", "completeAppInstallationNotifChannel": "Завершение установки приложения", "checkingForUpdatesNotifChannel": "Проверка обновлений", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index b6580ce..d1e64e8 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -274,6 +274,7 @@ "downloadingXNotifChannel": "正在下载{}", "completeAppInstallationNotifChannel": "完成应用安装", "checkingForUpdatesNotifChannel": "正在检查更新", + "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 91911e7..a2dacdb 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -219,7 +219,9 @@ class HTML extends AppSource { additionalSettings['versionExtractionRegEx'] as String?; if (versionExtractionRegEx?.isNotEmpty == true) { var match = RegExp(versionExtractionRegEx!).allMatches( - res.body.split('\r\n').join('\n').split('\n').join('\\n')); + additionalSettings['versionExtractWholePage'] == true + ? res.body.split('\r\n').join('\n').split('\n').join('\\n') + : rel); if (match.isEmpty) { throw NoVersionError(); } diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 265be4e..c36c958 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -310,6 +310,23 @@ class _SettingsPageState extends State { }) ], ), + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text(tr( + 'onlyCheckInstalledOrTrackOnlyApps'))), + Switch( + value: settingsProvider + .onlyCheckInstalledOrTrackOnlyApps, + onChanged: (value) { + settingsProvider + .onlyCheckInstalledOrTrackOnlyApps = + value; + }) + ], + ), height32, Text( tr('sourceSpecific'), @@ -535,7 +552,8 @@ class _SettingsPageState extends State { onPressed: () { context.read().get().then((logs) { if (logs.isEmpty) { - showMessage(ObtainiumError(tr('noLogs')), context); + showMessage( + ObtainiumError(tr('noLogs')), context); } else { showDialog( context: context, diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 3ef8e73..d4085d6 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -281,7 +281,8 @@ class AppsProvider with ChangeNotifier { '${downloadedFile.parent.path}/${app.id}-${downloadUrl.hashCode}.${downloadedFile.path.split('.').last}'); if (apps[originalAppId] != null) { await removeApps([originalAppId]); - await saveApps([app], onlyIfExists: !isTempIdBool && !idChangeWasAllowed); + await saveApps([app], + onlyIfExists: !isTempIdBool && !idChangeWasAllowed); } } } else if (isTempIdBool) { @@ -716,9 +717,11 @@ class AppsProvider with ChangeNotifier { if (app?.app == null) { return false; } - var naiveStandardVersionDetection = SourceProvider() - .getSource(app!.app.url, overrideSource: app.app.overrideSource) - .naiveStandardVersionDetection; + var naiveStandardVersionDetection = + app!.app.additionalSettings['naiveStandardVersionDetection'] == true || + SourceProvider() + .getSource(app.app.url, overrideSource: app.app.overrideSource) + .naiveStandardVersionDetection; return app.app.additionalSettings['trackOnly'] != true && app.app.additionalSettings['versionDetection'] != 'releaseDateAsVersion' && @@ -739,9 +742,11 @@ class AppsProvider with ChangeNotifier { var versionDetectionIsStandard = app.additionalSettings['versionDetection'] == 'standardVersionDetection'; - var naiveStandardVersionDetection = SourceProvider() - .getSource(app.url, overrideSource: app.overrideSource) - .naiveStandardVersionDetection; + var naiveStandardVersionDetection = + app.additionalSettings['naiveStandardVersionDetection'] == true || + SourceProvider() + .getSource(app.url, overrideSource: app.overrideSource) + .naiveStandardVersionDetection; // FIRST, COMPARE THE APP'S REPORTED AND REAL INSTALLED VERSIONS, WHERE ONE IS NULL if (installedInfo == null && app.installedVersion != null && !trackOnly) { // App says it's installed but isn't really (and isn't track only) - set to not installed @@ -1055,12 +1060,21 @@ class AppsProvider with ChangeNotifier { } List getAppsSortedByUpdateCheckTime( - {DateTime? ignoreAppsCheckedAfter}) { + {DateTime? ignoreAppsCheckedAfter, + bool onlyCheckInstalledOrTrackOnlyApps = false}) { List appIds = apps.values .where((app) => app.app.lastUpdateCheck == null || ignoreAppsCheckedAfter == null || app.app.lastUpdateCheck!.isBefore(ignoreAppsCheckedAfter)) + .where((app) { + if (!onlyCheckInstalledOrTrackOnlyApps) { + return true; + } else { + return app.app.installedVersion != null || + app.app.additionalSettings['trackOnly'] == true; + } + }) .map((e) => e.app.id) .toList(); appIds.sort((a, b) => @@ -1073,14 +1087,18 @@ class AppsProvider with ChangeNotifier { Future> checkUpdates( {DateTime? ignoreAppsCheckedAfter, bool throwErrorsForRetry = false, - List? specificIds}) async { + List? specificIds, + SettingsProvider? sp}) async { + SettingsProvider settingsProvider = sp ?? this.settingsProvider; List updates = []; MultiAppMultiError errors = MultiAppMultiError(); if (!gettingUpdates) { gettingUpdates = true; try { List appIds = getAppsSortedByUpdateCheckTime( - ignoreAppsCheckedAfter: ignoreAppsCheckedAfter); + ignoreAppsCheckedAfter: ignoreAppsCheckedAfter, + onlyCheckInstalledOrTrackOnlyApps: + settingsProvider.onlyCheckInstalledOrTrackOnlyApps); if (specificIds != null) { appIds = appIds.where((aId) => specificIds.contains(aId)).toList(); } @@ -1362,7 +1380,9 @@ Future bgUpdateCheck(int taskId, Map? params) async { entry['key'] as String, entry['value'] as int)) .toList() ?? appsProvider - .getAppsSortedByUpdateCheckTime() + .getAppsSortedByUpdateCheckTime( + onlyCheckInstalledOrTrackOnlyApps: appsProvider + .settingsProvider.onlyCheckInstalledOrTrackOnlyApps) .map((e) => MapEntry(e, 0))) ]; List> toInstall = >[ @@ -1446,7 +1466,8 @@ Future bgUpdateCheck(int taskId, Map? params) async { // Check for updates notificationsProvider.notify(notif, cancelExisting: true); updates = await appsProvider.checkUpdates( - specificIds: toCheck.map((e) => e.key).toList()); + specificIds: toCheck.map((e) => e.key).toList(), + sp: appsProvider.settingsProvider); } catch (e) { // If there were errors, group them into toRetry and toThrow based on max retry count per app if (e is Map) { diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 2085168..d72fd8d 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -406,4 +406,13 @@ class SettingsProvider with ChangeNotifier { prefs?.setBool('autoExportOnChanges', val); notifyListeners(); } + + bool get onlyCheckInstalledOrTrackOnlyApps { + return prefs?.getBool('onlyCheckInstalledOrTrackOnlyApps') ?? false; + } + + set onlyCheckInstalledOrTrackOnlyApps(bool val) { + prefs?.setBool('onlyCheckInstalledOrTrackOnlyApps', val); + notifyListeners(); + } } diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 0285aa7..e5ea114 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -676,7 +676,6 @@ class SourceProvider { } } } - String apkVersion = apk.version.replaceAll('/', '-'); var name = currentApp != null ? currentApp.name.trim() : ''; name = name.isNotEmpty ? name : apk.names.name; App finalApp = App( @@ -691,7 +690,7 @@ class SourceProvider { apk.names.author, name, currentApp?.installedVersion, - apkVersion, + apk.version, apk.apkUrls, apk.apkUrls.length - 1 >= 0 ? apk.apkUrls.length - 1 : 0, additionalSettings, From a083da1546faad55a23d06eba5cdc6f0c05a0600 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 18 Oct 2023 19:46:11 -0400 Subject: [PATCH 576/600] Upgrade packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 40 ++++++++++++++++++++++++---------------- pubspec.yaml | 4 ++-- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index b353775..1ca5444 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.30'; +const String currentVersion = '0.14.31'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 39e4c03..52d0c32 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -118,10 +118,10 @@ packages: dependency: "direct main" description: name: connectivity_plus - sha256: "94d51c6f1299133a2baa4c5c3d2c11ec7d7fb4768dee5c52a56f7d7522fcf70e" + sha256: b502a681ba415272ecc41400bd04fe543ed1a62632137dc84d25a91e7746f55f url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.0.1" connectivity_plus_platform_interface: dependency: transitive description: @@ -182,10 +182,10 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: "86add5ef97215562d2e090535b0a16f197902b10c369c558a100e74ea06e8659" + sha256: "7035152271ff67b072a211152846e9f1259cf1be41e34cd3e0b5463d2d6b8419" url: "https://pub.dev" source: hosted - version: "9.0.3" + version: "9.1.0" device_info_plus_platform_interface: dependency: transitive description: @@ -198,10 +198,10 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: "96bff3df72e3d428bda2b874c7a521e8c86f592cae626ea594922fcc8d166e0c" + sha256: "8b8bd1d798bd393e11eddeaa8ae95b12ff028bf7d5998fc5d003488cd5f4ce2f" url: "https://pub.dev" source: hosted - version: "1.6.7" + version: "1.6.8" easy_localization: dependency: "direct main" description: @@ -283,10 +283,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + sha256: ad76540d21c066228ee3f9d1dad64a9f7e46530e8bb7c85011a88bc1fd874bc5 url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "3.0.0" flutter_local_notifications: dependency: "direct main" description: @@ -418,10 +418,10 @@ packages: dependency: transitive description: name: lints - sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "3.0.0" markdown: dependency: transitive description: @@ -618,18 +618,18 @@ packages: dependency: "direct main" description: name: share_plus - sha256: "6cec740fa0943a826951223e76218df002804adb588235a8910dc3d6b0654e11" + sha256: f74fc3f1cbd99f39760182e176802f693fa0ec9625c045561cfad54681ea93dd url: "https://pub.dev" source: hosted - version: "7.1.0" + version: "7.2.1" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface - sha256: "357412af4178d8e11d14f41723f80f12caea54cf0d5cd29af9dcdab85d58aea7" + sha256: df08bc3a07d01f5ea47b45d03ffcba1fa9cd5370fb44b3f38c70e42cced0f956 url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "3.3.1" shared_preferences: dependency: "direct main" description: @@ -707,6 +707,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" sqflite: dependency: "direct main" description: @@ -855,10 +863,10 @@ packages: dependency: transitive description: name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + sha256: b715b8d3858b6fa9f68f87d20d98830283628014750c2b09b6f516c1da4af2a7 url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "4.1.0" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2d61b0a..9f61728 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.14.30+222 # When changing this, update the tag in main() accordingly +version: 0.14.31+223 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' @@ -77,7 +77,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^2.0.1 + flutter_lints: ^3.0.0 flutter_launcher_icons: android: "ic_launcher" From deae96e191a987772d3779f6f195fcdb0de157b5 Mon Sep 17 00:00:00 2001 From: unbranched <39440265+unbranched@users.noreply.github.com> Date: Thu, 19 Oct 2023 08:56:18 +0000 Subject: [PATCH 577/600] Update it.json Missed one string & fixed one --- assets/translations/it.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/translations/it.json b/assets/translations/it.json index e00c0b8..945dfc0 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -11,7 +11,7 @@ "unexpectedError": "Errore imprevisto", "ok": "Va bene", "and": "e", - "githubPATLabel": "GitHub Personal Access Token (riduce limite di traffico)", + "githubPATLabel": "GitHub Personal Access Token (aumenta limite di traffico)", "includePrereleases": "Includi prerelease", "fallbackToOlderReleases": "Ripiega su release precedenti", "filterReleaseTitlesByRegEx": "Filtra release con espressioni regolari", @@ -274,7 +274,7 @@ "downloadingXNotifChannel": "Scaricamento di {} in corso", "completeAppInstallationNotifChannel": "Completa l'installazione dell'app", "checkingForUpdatesNotifChannel": "Controllo degli aggiornamenti in corso", - "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", + "onlyCheckInstalledOrTrackOnlyApps": "Cerca aggiornamenti solo per app installate e app in Solo-Monitoraggio", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" From dfb5a2b97fb7bcb4508b2d353134846ffaec691a Mon Sep 17 00:00:00 2001 From: iDazai <50296346+iDazai@users.noreply.github.com> Date: Sat, 21 Oct 2023 17:19:20 +0200 Subject: [PATCH 578/600] Update de.json translated latest addition --- assets/translations/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/de.json b/assets/translations/de.json index f25949f..5b22bfd 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -274,7 +274,7 @@ "downloadingXNotifChannel": "Lade {} herunter", "completeAppInstallationNotifChannel": "App Installation abschließen", "checkingForUpdatesNotifChannel": "Nach Aktualisierungen suchen", - "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", + "onlyCheckInstalledOrTrackOnlyApps": "Überprüfe nur installierte und mit „nur Nachverfolgen“ markierte Apps nach Aktualisierungen", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" From d3247a9ec16e127004bb296e5b663a2978f3c2f0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 22 Oct 2023 00:59:51 -0400 Subject: [PATCH 579/600] Switched to WorkManager for reliability (#608) --- lib/main.dart | 29 +- lib/pages/settings.dart | 10 +- lib/providers/apps_provider.dart | 482 ++++++++++++++++--------------- pubspec.lock | 18 +- pubspec.yaml | 4 +- 5 files changed, 280 insertions(+), 263 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 1ca5444..69fd16b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,7 +12,7 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; +import 'package:workmanager/workmanager.dart'; import 'package:easy_localization/easy_localization.dart'; // ignore: implementation_imports import 'package:easy_localization/src/easy_localization_controller.dart'; @@ -23,7 +23,7 @@ const String currentVersion = '0.14.31'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES -const int bgUpdateCheckAlarmId = 666; +const String bgUpdateTaskId = 'bgUpdate'; List> supportedLocales = const [ MapEntry(Locale('en'), 'English'), @@ -71,6 +71,17 @@ Future loadTranslations() async { fallbackTranslations: controller.fallbackTranslations); } +@pragma('vm:entry-point') +void bgTaskDispatcher() { + Workmanager().executeTask((taskId, params) { + if (taskId == bgUpdateTaskId) { + return bgUpdateTask(taskId, params); + } else { + return Future.value(true); + } + }); +} + void main() async { WidgetsFlutterBinding.ensureInitialized(); try { @@ -88,7 +99,7 @@ void main() async { ); SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); } - await AndroidAlarmManager.initialize(); + await Workmanager().initialize(bgTaskDispatcher); runApp(MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => AppsProvider()), @@ -158,7 +169,7 @@ class _ObtainiumState extends State { var actualUpdateInterval = settingsProvider.updateInterval; if (existingUpdateInterval != actualUpdateInterval) { if (actualUpdateInterval == 0) { - AndroidAlarmManager.cancel(bgUpdateCheckAlarmId); + Workmanager().cancelByUniqueName(bgUpdateTaskId); } else { var settingChanged = existingUpdateInterval != -1; var lastCheckWasTooLongAgo = actualUpdateInterval != 0 && @@ -168,12 +179,10 @@ class _ObtainiumState extends State { if (settingChanged || lastCheckWasTooLongAgo) { logs.add( 'Update interval was set to ${actualUpdateInterval.toString()} (reason: ${settingChanged ? 'setting changed' : 'last check was ${settingsProvider.lastBGCheckTime.toLocal().toString()}'}).'); - AndroidAlarmManager.periodic( - Duration(minutes: actualUpdateInterval), - bgUpdateCheckAlarmId, - bgUpdateCheck, - rescheduleOnReboot: true, - wakeup: true); + Workmanager().registerPeriodicTask( + bgUpdateTaskId, "BG Update Main Loop", + initialDelay: Duration(minutes: actualUpdateInterval), + existingWorkPolicy: ExistingWorkPolicy.replace); } } existingUpdateInterval = actualUpdateInterval; diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index c36c958..38f7db7 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -1,4 +1,4 @@ -import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; +import 'package:workmanager/workmanager.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -591,10 +591,10 @@ class _SettingsPageState extends State { height16, TextButton( onPressed: () { - AndroidAlarmManager.oneShot( - const Duration(seconds: 0), - bgUpdateCheckAlarmId + 200, - bgUpdateCheck); + Workmanager().registerOneOffTask( + '$bgUpdateTaskId+Manual', bgUpdateTaskId, + existingWorkPolicy: + ExistingWorkPolicy.replace); showMessage(tr('bgTaskStarted'), context); }, child: Text(tr('runBgCheckNow'))) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index d4085d6..e299190 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -7,7 +7,7 @@ import 'dart:io'; import 'dart:math'; import 'package:http/http.dart' as http; -import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; +import 'package:workmanager/workmanager.dart'; import 'package:android_intent_plus/flag.dart'; import 'package:android_package_installer/android_package_installer.dart'; import 'package:android_package_manager/android_package_manager.dart'; @@ -1356,268 +1356,276 @@ class _APKOriginWarningDialogState extends State { /// If there is an error, the offending app is moved to the back of the line of remaining apps, and the task is retried. /// If an app repeatedly fails to install up to its retry limit, the user is notified. /// -@pragma('vm:entry-point') -Future bgUpdateCheck(int taskId, Map? params) async { +Future bgUpdateTask(String taskId, Map? params) async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); - await AndroidAlarmManager.initialize(); + await Workmanager().initialize(bgTaskDispatcher); await loadTranslations(); LogsProvider logs = LogsProvider(); - NotificationsProvider notificationsProvider = NotificationsProvider(); - AppsProvider appsProvider = AppsProvider(isBg: true); - await appsProvider.loadApps(); + try { + NotificationsProvider notificationsProvider = NotificationsProvider(); + AppsProvider appsProvider = AppsProvider(isBg: true); + await appsProvider.loadApps(); - int maxAttempts = 4; + int maxAttempts = 4; - params ??= {}; - if (params['toCheck'] == null) { - appsProvider.settingsProvider.lastBGCheckTime = DateTime.now(); - } - List> toCheck = >[ - ...(params['toCheck'] - ?.map((entry) => MapEntry( - entry['key'] as String, entry['value'] as int)) - .toList() ?? - appsProvider - .getAppsSortedByUpdateCheckTime( - onlyCheckInstalledOrTrackOnlyApps: appsProvider - .settingsProvider.onlyCheckInstalledOrTrackOnlyApps) - .map((e) => MapEntry(e, 0))) - ]; - List> toInstall = >[ - ...(params['toInstall'] - ?.map((entry) => MapEntry( - entry['key'] as String, entry['value'] as int)) - .toList() ?? - (>>[])) - ]; + params ??= {}; + if (params['toCheck'] == null) { + appsProvider.settingsProvider.lastBGCheckTime = DateTime.now(); + } + List> toCheck = >[ + ...(params['toCheck']?.map((str) { + var temp = str.split(','); + return MapEntry(temp[0], int.parse(temp[1])); + }).toList() ?? + appsProvider + .getAppsSortedByUpdateCheckTime( + onlyCheckInstalledOrTrackOnlyApps: appsProvider + .settingsProvider.onlyCheckInstalledOrTrackOnlyApps) + .map((e) => MapEntry(e, 0))) + ]; + List> toInstall = >[ + ...(params['toInstall']?.map((str) { + var temp = str.split(','); + return MapEntry(temp[0], int.parse(temp[1])); + }).toList() ?? + (>>[])) + ]; - var netResult = await (Connectivity().checkConnectivity()); + var netResult = await (Connectivity().checkConnectivity()); - if (netResult == ConnectivityResult.none) { - var networkBasedRetryInterval = 15; - var nextRegularCheck = appsProvider.settingsProvider.lastBGCheckTime - .add(Duration(minutes: appsProvider.settingsProvider.updateInterval)); - var potentialNetworkRetryCheck = - DateTime.now().add(Duration(minutes: networkBasedRetryInterval)); - var shouldRetry = potentialNetworkRetryCheck.isBefore(nextRegularCheck); - logs.add( - 'BG update task $taskId: No network. Will ${shouldRetry ? 'retry in $networkBasedRetryInterval minutes' : 'not retry'}.'); - AndroidAlarmManager.oneShot( - const Duration(minutes: 15), taskId + 1, bgUpdateCheck, - params: { - 'toCheck': toCheck - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - 'toInstall': toInstall - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - }); - return; - } + if (netResult == ConnectivityResult.none) { + var networkBasedRetryInterval = 15; + var nextRegularCheck = appsProvider.settingsProvider.lastBGCheckTime + .add(Duration(minutes: appsProvider.settingsProvider.updateInterval)); + var potentialNetworkRetryCheck = + DateTime.now().add(Duration(minutes: networkBasedRetryInterval)); + var shouldRetry = potentialNetworkRetryCheck.isBefore(nextRegularCheck); + logs.add( + 'BG task $taskId: No network. Will ${shouldRetry ? 'retry in $networkBasedRetryInterval minutes' : 'not retry'}.'); + await Workmanager().registerOneOffTask("$taskId+Retry", taskId, + initialDelay: const Duration(minutes: 15), + existingWorkPolicy: ExistingWorkPolicy.replace, + inputData: { + 'toCheck': + toCheck.map((entry) => '${entry.key},${entry.value}').toList(), + 'toInstall': toInstall + .map((entry) => '${entry.key},${entry.value}') + .toList(), + }); + } - var networkRestricted = false; - if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { - networkRestricted = (netResult != ConnectivityResult.wifi) && - (netResult != ConnectivityResult.ethernet); - } - - bool installMode = - toCheck.isEmpty; // Task is either in update mode or install mode - - logs.add( - 'BG ${installMode ? 'install' : 'update'} task $taskId: Started (${installMode ? toInstall.length : toCheck.length}).'); - - if (!installMode) { - // If in update mode, we check for updates. - // We divide the results into 4 groups: - // - toNotify - Apps with updates that the user will be notified about (can't be silently installed) - // - toRetry - Apps with update check errors that will be retried in a while - // - toThrow - Apps with update check errors that the user will be notified about (no retry) - // After grouping the updates, we take care of toNotify and toThrow first - // Then if toRetry is not empty, we schedule another update task to run in a while - // If toRetry is empty, we take care of schedule another task that will run in install mode (toCheck is empty) - - // Init. vars. - List updates = []; // All updates found (silent and non-silent) - List toNotify = - []; // All non-silent updates that the user will be notified about - List> toRetry = - []; // All apps that got errors while checking - var retryAfterXSeconds = - 0; // How long to wait until the next attempt (if there are errors) - MultiAppMultiError? - errors; // All errors including those that will lead to a retry - MultiAppMultiError toThrow = - MultiAppMultiError(); // All errors that will not lead to a retry, just a notification - CheckingUpdatesNotification notif = CheckingUpdatesNotification( - plural('apps', toCheck.length)); // The notif. to show while checking - - // Set a bool for when we're no on wifi/wired and the user doesn't want to download apps in that state var networkRestricted = false; if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { - var netResult = await (Connectivity().checkConnectivity()); networkRestricted = (netResult != ConnectivityResult.wifi) && (netResult != ConnectivityResult.ethernet); } - try { - // Check for updates - notificationsProvider.notify(notif, cancelExisting: true); - updates = await appsProvider.checkUpdates( - specificIds: toCheck.map((e) => e.key).toList(), - sp: appsProvider.settingsProvider); - } catch (e) { - // If there were errors, group them into toRetry and toThrow based on max retry count per app - if (e is Map) { - updates = e['updates']; - errors = e['errors']; - errors!.rawErrors.forEach((key, err) { - logs.add( - 'BG update task $taskId: Got error on checking for $key \'${err.toString()}\'.'); - var toCheckApp = toCheck.where((element) => element.key == key).first; - if (toCheckApp.value < maxAttempts) { - toRetry.add(MapEntry(toCheckApp.key, toCheckApp.value + 1)); - // Next task interval is based on the error with the longest retry time - var minRetryIntervalForThisApp = err is RateLimitError - ? (err.remainingMinutes * 60) - : e is ClientException - ? (15 * 60) - : pow(toCheckApp.value + 1, 2).toInt(); - if (minRetryIntervalForThisApp > retryAfterXSeconds) { - retryAfterXSeconds = minRetryIntervalForThisApp; - } - } else { - toThrow.add(key, err, appName: errors?.appIdNames[key]); - } - }); - } else { - // We don't expect to ever get here in any situation so no need to catch (but log it in case) - logs.add('Fatal error in BG update task: ${e.toString()}'); - rethrow; - } - } finally { - notificationsProvider.cancel(notif.id); - } + bool installMode = + toCheck.isEmpty; // Task is either in update mode or install mode - // Filter out updates that will be installed silently (the rest go into toNotify) - for (var i = 0; i < updates.length; i++) { - if (networkRestricted || - !(await appsProvider.canInstallSilently(updates[i]))) { - if (updates[i].additionalSettings['skipUpdateNotifications'] != true) { - toNotify.add(updates[i]); - } - } - } + logs.add( + 'BG ${installMode ? 'install' : 'update'} task $taskId: Started (${installMode ? toInstall.length : toCheck.length}).'); - // Send the update notification - if (toNotify.isNotEmpty) { - notificationsProvider.notify(UpdateNotification(toNotify)); - } + if (!installMode) { + // If in update mode, we check for updates. + // We divide the results into 4 groups: + // - toNotify - Apps with updates that the user will be notified about (can't be silently installed) + // - toRetry - Apps with update check errors that will be retried in a while + // - toThrow - Apps with update check errors that the user will be notified about (no retry) + // After grouping the updates, we take care of toNotify and toThrow first + // Then if toRetry is not empty, we schedule another update task to run in a while + // If toRetry is empty, we take care of schedule another task that will run in install mode (toCheck is empty) - // Send the error notifications (grouped by error string) - if (toThrow.rawErrors.isNotEmpty) { - for (var element in toThrow.idsByErrorString.entries) { - notificationsProvider.notify(ErrorCheckingUpdatesNotification( - errors!.errorsAppsString(element.key, element.value), - id: Random().nextInt(10000))); - } - } + // Init. vars. + List updates = []; // All updates found (silent and non-silent) + List toNotify = + []; // All non-silent updates that the user will be notified about + List> toRetry = + []; // All apps that got errors while checking + var retryAfterXSeconds = + 0; // How long to wait until the next attempt (if there are errors) + MultiAppMultiError? + errors; // All errors including those that will lead to a retry + MultiAppMultiError toThrow = + MultiAppMultiError(); // All errors that will not lead to a retry, just a notification + CheckingUpdatesNotification notif = CheckingUpdatesNotification( + plural('apps', toCheck.length)); // The notif. to show while checking - // if there are update checks to retry, schedule a retry task - if (toRetry.isNotEmpty) { - logs.add( - 'BG update task $taskId: Will retry in $retryAfterXSeconds seconds.'); - AndroidAlarmManager.oneShot( - Duration(seconds: retryAfterXSeconds), taskId + 1, bgUpdateCheck, - params: { - 'toCheck': toRetry - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - 'toInstall': toInstall - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - }); - } else { - // If there are no more update checks, schedule an install task - logs.add( - 'BG update task $taskId: Done. Scheduling install task to run immediately.'); - AndroidAlarmManager.oneShot( - const Duration(minutes: 0), taskId + 1, bgUpdateCheck, - params: { - 'toCheck': [], - 'toInstall': toInstall - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList() - }); - } - } else { - // In install mode... - // If you haven't explicitly been given updates to install (which is the case for new tasks), grab all available silent updates - if (toInstall.isEmpty && !networkRestricted) { - var temp = appsProvider.findExistingUpdates(installedOnly: true); - for (var i = 0; i < temp.length; i++) { - if (await appsProvider - .canInstallSilently(appsProvider.apps[temp[i]]!.app)) { - toInstall.add(MapEntry(temp[i], 0)); - } + // Set a bool for when we're no on wifi/wired and the user doesn't want to download apps in that state + var networkRestricted = false; + if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { + var netResult = await (Connectivity().checkConnectivity()); + networkRestricted = (netResult != ConnectivityResult.wifi) && + (netResult != ConnectivityResult.ethernet); } - } - var didCompleteInstalling = false; - var tempObtArr = toInstall.where((element) => element.key == obtainiumId); - if (tempObtArr.isNotEmpty) { - // Move obtainium to the end of the list as it must always install last - var obt = tempObtArr.first; - toInstall = moveStrToEndMapEntryWithCount(toInstall, obt); - } - // Loop through all updates and install each - for (var i = 0; i < toInstall.length; i++) { - var appId = toInstall[i].key; - var retryCount = toInstall[i].value; + try { - logs.add( - 'BG install task $taskId: Attempting to update $appId in the background.'); - await appsProvider.downloadAndInstallLatestApps([appId], null, - notificationsProvider: notificationsProvider); - await Future.delayed(const Duration( - seconds: - 5)); // Just in case task ending causes install fail (not clear) - if (i == (toCheck.length - 1)) { - didCompleteInstalling = true; - } + // Check for updates + notificationsProvider.notify(notif, cancelExisting: true); + updates = await appsProvider.checkUpdates( + specificIds: toCheck.map((e) => e.key).toList(), + sp: appsProvider.settingsProvider); } catch (e) { - // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue installing shortly - logs.add( - 'BG install task $taskId: Got error on updating $appId \'${e.toString()}\'.'); - if (retryCount < maxAttempts) { - var remainingSeconds = retryCount; - logs.add( - 'BG install task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); - var remainingToInstall = moveStrToEndMapEntryWithCount( - toInstall.sublist(i), MapEntry(appId, retryCount + 1)); - AndroidAlarmManager.oneShot( - Duration(seconds: remainingSeconds), taskId + 1, bgUpdateCheck, - params: { - 'toCheck': toCheck - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - 'toInstall': remainingToInstall - .map((entry) => {'key': entry.key, 'value': entry.value}) - .toList(), - }); - break; + // If there were errors, group them into toRetry and toThrow based on max retry count per app + if (e is Map) { + updates = e['updates']; + errors = e['errors']; + errors!.rawErrors.forEach((key, err) { + logs.add( + 'BG task $taskId: Got error on checking for $key \'${err.toString()}\'.'); + var toCheckApp = + toCheck.where((element) => element.key == key).first; + if (toCheckApp.value < maxAttempts) { + toRetry.add(MapEntry(toCheckApp.key, toCheckApp.value + 1)); + // Next task interval is based on the error with the longest retry time + var minRetryIntervalForThisApp = err is RateLimitError + ? (err.remainingMinutes * 60) + : e is ClientException + ? (15 * 60) + : pow(toCheckApp.value + 1, 2).toInt(); + if (minRetryIntervalForThisApp > retryAfterXSeconds) { + retryAfterXSeconds = minRetryIntervalForThisApp; + } + } else { + toThrow.add(key, err, appName: errors?.appIdNames[key]); + } + }); } else { - // If the offender has reached its fail limit, notify the user and remove it from the list (task can continue) - toInstall.removeAt(i); - i--; - notificationsProvider - .notify(ErrorCheckingUpdatesNotification(e.toString())); + // We don't expect to ever get here in any situation so no need to catch (but log it in case) + logs.add('Fatal error in BG task: ${e.toString()}'); + rethrow; + } + } finally { + notificationsProvider.cancel(notif.id); + } + + // Filter out updates that will be installed silently (the rest go into toNotify) + for (var i = 0; i < updates.length; i++) { + if (networkRestricted || + !(await appsProvider.canInstallSilently(updates[i]))) { + if (updates[i].additionalSettings['skipUpdateNotifications'] != + true) { + toNotify.add(updates[i]); + } } } + + // Send the update notification + if (toNotify.isNotEmpty) { + notificationsProvider.notify(UpdateNotification(toNotify)); + } + + // Send the error notifications (grouped by error string) + if (toThrow.rawErrors.isNotEmpty) { + for (var element in toThrow.idsByErrorString.entries) { + notificationsProvider.notify(ErrorCheckingUpdatesNotification( + errors!.errorsAppsString(element.key, element.value), + id: Random().nextInt(10000))); + } + } + + // if there are update checks to retry, schedule a retry task + if (toRetry.isNotEmpty) { + logs.add('BG task $taskId: Will retry in $retryAfterXSeconds seconds.'); + await Workmanager().registerOneOffTask("$taskId+Retry", taskId, + initialDelay: Duration(seconds: retryAfterXSeconds), + existingWorkPolicy: ExistingWorkPolicy.replace, + inputData: { + 'toCheck': toRetry + .map((entry) => '${entry.key},${entry.value}') + .toList(), + 'toInstall': toInstall + .map((entry) => '${entry.key},${entry.value}') + .toList(), + }); + } else { + // If there are no more update checks, schedule an install task + logs.add( + 'BG task $taskId: Done. Scheduling install task to run immediately.'); + await Workmanager().registerOneOffTask( + "$bgUpdateTaskId+Install", taskId, + existingWorkPolicy: ExistingWorkPolicy.replace, + inputData: { + 'toCheck': [], + 'toInstall': toInstall + .map((entry) => '${entry.key},${entry.value}') + .toList() + }); + } + } else { + // In install mode... + // If you haven't explicitly been given updates to install (which is the case for new tasks), grab all available silent updates + if (toInstall.isEmpty && !networkRestricted) { + var temp = appsProvider.findExistingUpdates(installedOnly: true); + for (var i = 0; i < temp.length; i++) { + if (await appsProvider + .canInstallSilently(appsProvider.apps[temp[i]]!.app)) { + toInstall.add(MapEntry(temp[i], 0)); + } + } + } + var didCompleteInstalling = false; + var tempObtArr = toInstall.where((element) => element.key == obtainiumId); + if (tempObtArr.isNotEmpty) { + // Move obtainium to the end of the list as it must always install last + var obt = tempObtArr.first; + toInstall = moveStrToEndMapEntryWithCount(toInstall, obt); + } + // Loop through all updates and install each + for (var i = 0; i < toInstall.length; i++) { + var appId = toInstall[i].key; + var retryCount = toInstall[i].value; + try { + logs.add( + 'BG task $taskId: Attempting to update $appId in the background.'); + await appsProvider.downloadAndInstallLatestApps([appId], null, + notificationsProvider: notificationsProvider); + await Future.delayed(const Duration( + seconds: + 5)); // Just in case task ending causes install fail (not clear) + if (i == (toCheck.length - 1)) { + didCompleteInstalling = true; + } + } catch (e) { + // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue installing shortly + logs.add( + 'BG task $taskId: Got error on updating $appId \'${e.toString()}\'.'); + if (retryCount < maxAttempts) { + var remainingSeconds = retryCount; + logs.add( + 'BG task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); + var remainingToInstall = moveStrToEndMapEntryWithCount( + toInstall.sublist(i), MapEntry(appId, retryCount + 1)); + await Workmanager().registerOneOffTask("$taskId+Retry", taskId, + initialDelay: Duration(seconds: remainingSeconds), + existingWorkPolicy: ExistingWorkPolicy.replace, + inputData: { + 'toCheck': toCheck + .map((entry) => '${entry.key},${entry.value}') + .toList(), + 'toInstall': remainingToInstall + .map((entry) => '${entry.key},${entry.value}') + .toList(), + }); + break; + } else { + // If the offender has reached its fail limit, notify the user and remove it from the list (task can continue) + toInstall.removeAt(i); + i--; + notificationsProvider + .notify(ErrorCheckingUpdatesNotification(e.toString())); + } + } + } + if (didCompleteInstalling || toInstall.isEmpty) { + logs.add('BG task $taskId: Done.'); + } } - if (didCompleteInstalling || toInstall.isEmpty) { - logs.add('BG install task $taskId: Done.'); - } + return true; + } catch (e) { + logs.add(e.toString()); + return false; } } diff --git a/pubspec.lock b/pubspec.lock index 52d0c32..4cda985 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,14 +1,6 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - android_alarm_manager_plus: - dependency: "direct main" - description: - name: android_alarm_manager_plus - sha256: "82fb28c867c4b3dd7e9157728e46426b8916362f977dbba46b949210f00099f4" - url: "https://pub.dev" - source: hosted - version: "3.0.3" android_intent_plus: dependency: "direct main" description: @@ -931,6 +923,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" + workmanager: + dependency: "direct main" + description: + name: workmanager + sha256: ed13530cccd28c5c9959ad42d657cd0666274ca74c56dea0ca183ddd527d3a00 + url: "https://pub.dev" + source: hosted + version: "0.5.2" xdg_directories: dependency: transitive description: @@ -956,5 +956,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0 <4.0.0" + dart: ">=3.1.2 <4.0.0" flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index 9f61728..a3bcc91 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.14.31+223 # When changing this, update the tag in main() accordingly +version: 0.14.31+224 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' @@ -57,7 +57,6 @@ dependencies: ref: main android_package_manager: ^0.6.0 share_plus: ^7.0.0 - android_alarm_manager_plus: ^3.0.0 sqflite: ^2.2.0+3 easy_localization: ^3.0.1 android_intent_plus: ^4.0.0 @@ -66,6 +65,7 @@ dependencies: hsluv: ^1.1.3 connectivity_plus: ^5.0.0 shared_storage: ^0.8.0 + workmanager: ^0.5.2 dev_dependencies: flutter_test: From a34a447164ba09cce69535fa91edc1568567c9b0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 22 Oct 2023 12:50:54 -0400 Subject: [PATCH 580/600] Revert "Switched to WorkManager for reliability (#608)" This reverts commit d3247a9ec16e127004bb296e5b663a2978f3c2f0. --- lib/main.dart | 29 +- lib/pages/settings.dart | 10 +- lib/providers/apps_provider.dart | 492 +++++++++++++++---------------- pubspec.lock | 18 +- pubspec.yaml | 4 +- 5 files changed, 268 insertions(+), 285 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 69fd16b..1ca5444 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,7 +12,7 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:workmanager/workmanager.dart'; +import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; import 'package:easy_localization/easy_localization.dart'; // ignore: implementation_imports import 'package:easy_localization/src/easy_localization_controller.dart'; @@ -23,7 +23,7 @@ const String currentVersion = '0.14.31'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES -const String bgUpdateTaskId = 'bgUpdate'; +const int bgUpdateCheckAlarmId = 666; List> supportedLocales = const [ MapEntry(Locale('en'), 'English'), @@ -71,17 +71,6 @@ Future loadTranslations() async { fallbackTranslations: controller.fallbackTranslations); } -@pragma('vm:entry-point') -void bgTaskDispatcher() { - Workmanager().executeTask((taskId, params) { - if (taskId == bgUpdateTaskId) { - return bgUpdateTask(taskId, params); - } else { - return Future.value(true); - } - }); -} - void main() async { WidgetsFlutterBinding.ensureInitialized(); try { @@ -99,7 +88,7 @@ void main() async { ); SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); } - await Workmanager().initialize(bgTaskDispatcher); + await AndroidAlarmManager.initialize(); runApp(MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => AppsProvider()), @@ -169,7 +158,7 @@ class _ObtainiumState extends State { var actualUpdateInterval = settingsProvider.updateInterval; if (existingUpdateInterval != actualUpdateInterval) { if (actualUpdateInterval == 0) { - Workmanager().cancelByUniqueName(bgUpdateTaskId); + AndroidAlarmManager.cancel(bgUpdateCheckAlarmId); } else { var settingChanged = existingUpdateInterval != -1; var lastCheckWasTooLongAgo = actualUpdateInterval != 0 && @@ -179,10 +168,12 @@ class _ObtainiumState extends State { if (settingChanged || lastCheckWasTooLongAgo) { logs.add( 'Update interval was set to ${actualUpdateInterval.toString()} (reason: ${settingChanged ? 'setting changed' : 'last check was ${settingsProvider.lastBGCheckTime.toLocal().toString()}'}).'); - Workmanager().registerPeriodicTask( - bgUpdateTaskId, "BG Update Main Loop", - initialDelay: Duration(minutes: actualUpdateInterval), - existingWorkPolicy: ExistingWorkPolicy.replace); + AndroidAlarmManager.periodic( + Duration(minutes: actualUpdateInterval), + bgUpdateCheckAlarmId, + bgUpdateCheck, + rescheduleOnReboot: true, + wakeup: true); } } existingUpdateInterval = actualUpdateInterval; diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 38f7db7..c36c958 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -1,4 +1,4 @@ -import 'package:workmanager/workmanager.dart'; +import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; @@ -591,10 +591,10 @@ class _SettingsPageState extends State { height16, TextButton( onPressed: () { - Workmanager().registerOneOffTask( - '$bgUpdateTaskId+Manual', bgUpdateTaskId, - existingWorkPolicy: - ExistingWorkPolicy.replace); + AndroidAlarmManager.oneShot( + const Duration(seconds: 0), + bgUpdateCheckAlarmId + 200, + bgUpdateCheck); showMessage(tr('bgTaskStarted'), context); }, child: Text(tr('runBgCheckNow'))) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index e299190..d4085d6 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -7,7 +7,7 @@ import 'dart:io'; import 'dart:math'; import 'package:http/http.dart' as http; -import 'package:workmanager/workmanager.dart'; +import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart'; import 'package:android_intent_plus/flag.dart'; import 'package:android_package_installer/android_package_installer.dart'; import 'package:android_package_manager/android_package_manager.dart'; @@ -1356,276 +1356,268 @@ class _APKOriginWarningDialogState extends State { /// If there is an error, the offending app is moved to the back of the line of remaining apps, and the task is retried. /// If an app repeatedly fails to install up to its retry limit, the user is notified. /// -Future bgUpdateTask(String taskId, Map? params) async { +@pragma('vm:entry-point') +Future bgUpdateCheck(int taskId, Map? params) async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); - await Workmanager().initialize(bgTaskDispatcher); + await AndroidAlarmManager.initialize(); await loadTranslations(); LogsProvider logs = LogsProvider(); - try { - NotificationsProvider notificationsProvider = NotificationsProvider(); - AppsProvider appsProvider = AppsProvider(isBg: true); - await appsProvider.loadApps(); + NotificationsProvider notificationsProvider = NotificationsProvider(); + AppsProvider appsProvider = AppsProvider(isBg: true); + await appsProvider.loadApps(); - int maxAttempts = 4; + int maxAttempts = 4; - params ??= {}; - if (params['toCheck'] == null) { - appsProvider.settingsProvider.lastBGCheckTime = DateTime.now(); - } - List> toCheck = >[ - ...(params['toCheck']?.map((str) { - var temp = str.split(','); - return MapEntry(temp[0], int.parse(temp[1])); - }).toList() ?? - appsProvider - .getAppsSortedByUpdateCheckTime( - onlyCheckInstalledOrTrackOnlyApps: appsProvider - .settingsProvider.onlyCheckInstalledOrTrackOnlyApps) - .map((e) => MapEntry(e, 0))) - ]; - List> toInstall = >[ - ...(params['toInstall']?.map((str) { - var temp = str.split(','); - return MapEntry(temp[0], int.parse(temp[1])); - }).toList() ?? - (>>[])) - ]; + params ??= {}; + if (params['toCheck'] == null) { + appsProvider.settingsProvider.lastBGCheckTime = DateTime.now(); + } + List> toCheck = >[ + ...(params['toCheck'] + ?.map((entry) => MapEntry( + entry['key'] as String, entry['value'] as int)) + .toList() ?? + appsProvider + .getAppsSortedByUpdateCheckTime( + onlyCheckInstalledOrTrackOnlyApps: appsProvider + .settingsProvider.onlyCheckInstalledOrTrackOnlyApps) + .map((e) => MapEntry(e, 0))) + ]; + List> toInstall = >[ + ...(params['toInstall'] + ?.map((entry) => MapEntry( + entry['key'] as String, entry['value'] as int)) + .toList() ?? + (>>[])) + ]; - var netResult = await (Connectivity().checkConnectivity()); + var netResult = await (Connectivity().checkConnectivity()); - if (netResult == ConnectivityResult.none) { - var networkBasedRetryInterval = 15; - var nextRegularCheck = appsProvider.settingsProvider.lastBGCheckTime - .add(Duration(minutes: appsProvider.settingsProvider.updateInterval)); - var potentialNetworkRetryCheck = - DateTime.now().add(Duration(minutes: networkBasedRetryInterval)); - var shouldRetry = potentialNetworkRetryCheck.isBefore(nextRegularCheck); - logs.add( - 'BG task $taskId: No network. Will ${shouldRetry ? 'retry in $networkBasedRetryInterval minutes' : 'not retry'}.'); - await Workmanager().registerOneOffTask("$taskId+Retry", taskId, - initialDelay: const Duration(minutes: 15), - existingWorkPolicy: ExistingWorkPolicy.replace, - inputData: { - 'toCheck': - toCheck.map((entry) => '${entry.key},${entry.value}').toList(), - 'toInstall': toInstall - .map((entry) => '${entry.key},${entry.value}') - .toList(), - }); - } + if (netResult == ConnectivityResult.none) { + var networkBasedRetryInterval = 15; + var nextRegularCheck = appsProvider.settingsProvider.lastBGCheckTime + .add(Duration(minutes: appsProvider.settingsProvider.updateInterval)); + var potentialNetworkRetryCheck = + DateTime.now().add(Duration(minutes: networkBasedRetryInterval)); + var shouldRetry = potentialNetworkRetryCheck.isBefore(nextRegularCheck); + logs.add( + 'BG update task $taskId: No network. Will ${shouldRetry ? 'retry in $networkBasedRetryInterval minutes' : 'not retry'}.'); + AndroidAlarmManager.oneShot( + const Duration(minutes: 15), taskId + 1, bgUpdateCheck, + params: { + 'toCheck': toCheck + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + 'toInstall': toInstall + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + }); + return; + } + var networkRestricted = false; + if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { + networkRestricted = (netResult != ConnectivityResult.wifi) && + (netResult != ConnectivityResult.ethernet); + } + + bool installMode = + toCheck.isEmpty; // Task is either in update mode or install mode + + logs.add( + 'BG ${installMode ? 'install' : 'update'} task $taskId: Started (${installMode ? toInstall.length : toCheck.length}).'); + + if (!installMode) { + // If in update mode, we check for updates. + // We divide the results into 4 groups: + // - toNotify - Apps with updates that the user will be notified about (can't be silently installed) + // - toRetry - Apps with update check errors that will be retried in a while + // - toThrow - Apps with update check errors that the user will be notified about (no retry) + // After grouping the updates, we take care of toNotify and toThrow first + // Then if toRetry is not empty, we schedule another update task to run in a while + // If toRetry is empty, we take care of schedule another task that will run in install mode (toCheck is empty) + + // Init. vars. + List updates = []; // All updates found (silent and non-silent) + List toNotify = + []; // All non-silent updates that the user will be notified about + List> toRetry = + []; // All apps that got errors while checking + var retryAfterXSeconds = + 0; // How long to wait until the next attempt (if there are errors) + MultiAppMultiError? + errors; // All errors including those that will lead to a retry + MultiAppMultiError toThrow = + MultiAppMultiError(); // All errors that will not lead to a retry, just a notification + CheckingUpdatesNotification notif = CheckingUpdatesNotification( + plural('apps', toCheck.length)); // The notif. to show while checking + + // Set a bool for when we're no on wifi/wired and the user doesn't want to download apps in that state var networkRestricted = false; if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { + var netResult = await (Connectivity().checkConnectivity()); networkRestricted = (netResult != ConnectivityResult.wifi) && (netResult != ConnectivityResult.ethernet); } - bool installMode = - toCheck.isEmpty; // Task is either in update mode or install mode - - logs.add( - 'BG ${installMode ? 'install' : 'update'} task $taskId: Started (${installMode ? toInstall.length : toCheck.length}).'); - - if (!installMode) { - // If in update mode, we check for updates. - // We divide the results into 4 groups: - // - toNotify - Apps with updates that the user will be notified about (can't be silently installed) - // - toRetry - Apps with update check errors that will be retried in a while - // - toThrow - Apps with update check errors that the user will be notified about (no retry) - // After grouping the updates, we take care of toNotify and toThrow first - // Then if toRetry is not empty, we schedule another update task to run in a while - // If toRetry is empty, we take care of schedule another task that will run in install mode (toCheck is empty) - - // Init. vars. - List updates = []; // All updates found (silent and non-silent) - List toNotify = - []; // All non-silent updates that the user will be notified about - List> toRetry = - []; // All apps that got errors while checking - var retryAfterXSeconds = - 0; // How long to wait until the next attempt (if there are errors) - MultiAppMultiError? - errors; // All errors including those that will lead to a retry - MultiAppMultiError toThrow = - MultiAppMultiError(); // All errors that will not lead to a retry, just a notification - CheckingUpdatesNotification notif = CheckingUpdatesNotification( - plural('apps', toCheck.length)); // The notif. to show while checking - - // Set a bool for when we're no on wifi/wired and the user doesn't want to download apps in that state - var networkRestricted = false; - if (appsProvider.settingsProvider.bgUpdatesOnWiFiOnly) { - var netResult = await (Connectivity().checkConnectivity()); - networkRestricted = (netResult != ConnectivityResult.wifi) && - (netResult != ConnectivityResult.ethernet); - } - - try { - // Check for updates - notificationsProvider.notify(notif, cancelExisting: true); - updates = await appsProvider.checkUpdates( - specificIds: toCheck.map((e) => e.key).toList(), - sp: appsProvider.settingsProvider); - } catch (e) { - // If there were errors, group them into toRetry and toThrow based on max retry count per app - if (e is Map) { - updates = e['updates']; - errors = e['errors']; - errors!.rawErrors.forEach((key, err) { - logs.add( - 'BG task $taskId: Got error on checking for $key \'${err.toString()}\'.'); - var toCheckApp = - toCheck.where((element) => element.key == key).first; - if (toCheckApp.value < maxAttempts) { - toRetry.add(MapEntry(toCheckApp.key, toCheckApp.value + 1)); - // Next task interval is based on the error with the longest retry time - var minRetryIntervalForThisApp = err is RateLimitError - ? (err.remainingMinutes * 60) - : e is ClientException - ? (15 * 60) - : pow(toCheckApp.value + 1, 2).toInt(); - if (minRetryIntervalForThisApp > retryAfterXSeconds) { - retryAfterXSeconds = minRetryIntervalForThisApp; - } - } else { - toThrow.add(key, err, appName: errors?.appIdNames[key]); + try { + // Check for updates + notificationsProvider.notify(notif, cancelExisting: true); + updates = await appsProvider.checkUpdates( + specificIds: toCheck.map((e) => e.key).toList(), + sp: appsProvider.settingsProvider); + } catch (e) { + // If there were errors, group them into toRetry and toThrow based on max retry count per app + if (e is Map) { + updates = e['updates']; + errors = e['errors']; + errors!.rawErrors.forEach((key, err) { + logs.add( + 'BG update task $taskId: Got error on checking for $key \'${err.toString()}\'.'); + var toCheckApp = toCheck.where((element) => element.key == key).first; + if (toCheckApp.value < maxAttempts) { + toRetry.add(MapEntry(toCheckApp.key, toCheckApp.value + 1)); + // Next task interval is based on the error with the longest retry time + var minRetryIntervalForThisApp = err is RateLimitError + ? (err.remainingMinutes * 60) + : e is ClientException + ? (15 * 60) + : pow(toCheckApp.value + 1, 2).toInt(); + if (minRetryIntervalForThisApp > retryAfterXSeconds) { + retryAfterXSeconds = minRetryIntervalForThisApp; } - }); - } else { - // We don't expect to ever get here in any situation so no need to catch (but log it in case) - logs.add('Fatal error in BG task: ${e.toString()}'); - rethrow; - } - } finally { - notificationsProvider.cancel(notif.id); - } - - // Filter out updates that will be installed silently (the rest go into toNotify) - for (var i = 0; i < updates.length; i++) { - if (networkRestricted || - !(await appsProvider.canInstallSilently(updates[i]))) { - if (updates[i].additionalSettings['skipUpdateNotifications'] != - true) { - toNotify.add(updates[i]); - } - } - } - - // Send the update notification - if (toNotify.isNotEmpty) { - notificationsProvider.notify(UpdateNotification(toNotify)); - } - - // Send the error notifications (grouped by error string) - if (toThrow.rawErrors.isNotEmpty) { - for (var element in toThrow.idsByErrorString.entries) { - notificationsProvider.notify(ErrorCheckingUpdatesNotification( - errors!.errorsAppsString(element.key, element.value), - id: Random().nextInt(10000))); - } - } - - // if there are update checks to retry, schedule a retry task - if (toRetry.isNotEmpty) { - logs.add('BG task $taskId: Will retry in $retryAfterXSeconds seconds.'); - await Workmanager().registerOneOffTask("$taskId+Retry", taskId, - initialDelay: Duration(seconds: retryAfterXSeconds), - existingWorkPolicy: ExistingWorkPolicy.replace, - inputData: { - 'toCheck': toRetry - .map((entry) => '${entry.key},${entry.value}') - .toList(), - 'toInstall': toInstall - .map((entry) => '${entry.key},${entry.value}') - .toList(), - }); - } else { - // If there are no more update checks, schedule an install task - logs.add( - 'BG task $taskId: Done. Scheduling install task to run immediately.'); - await Workmanager().registerOneOffTask( - "$bgUpdateTaskId+Install", taskId, - existingWorkPolicy: ExistingWorkPolicy.replace, - inputData: { - 'toCheck': [], - 'toInstall': toInstall - .map((entry) => '${entry.key},${entry.value}') - .toList() - }); - } - } else { - // In install mode... - // If you haven't explicitly been given updates to install (which is the case for new tasks), grab all available silent updates - if (toInstall.isEmpty && !networkRestricted) { - var temp = appsProvider.findExistingUpdates(installedOnly: true); - for (var i = 0; i < temp.length; i++) { - if (await appsProvider - .canInstallSilently(appsProvider.apps[temp[i]]!.app)) { - toInstall.add(MapEntry(temp[i], 0)); - } - } - } - var didCompleteInstalling = false; - var tempObtArr = toInstall.where((element) => element.key == obtainiumId); - if (tempObtArr.isNotEmpty) { - // Move obtainium to the end of the list as it must always install last - var obt = tempObtArr.first; - toInstall = moveStrToEndMapEntryWithCount(toInstall, obt); - } - // Loop through all updates and install each - for (var i = 0; i < toInstall.length; i++) { - var appId = toInstall[i].key; - var retryCount = toInstall[i].value; - try { - logs.add( - 'BG task $taskId: Attempting to update $appId in the background.'); - await appsProvider.downloadAndInstallLatestApps([appId], null, - notificationsProvider: notificationsProvider); - await Future.delayed(const Duration( - seconds: - 5)); // Just in case task ending causes install fail (not clear) - if (i == (toCheck.length - 1)) { - didCompleteInstalling = true; - } - } catch (e) { - // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue installing shortly - logs.add( - 'BG task $taskId: Got error on updating $appId \'${e.toString()}\'.'); - if (retryCount < maxAttempts) { - var remainingSeconds = retryCount; - logs.add( - 'BG task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); - var remainingToInstall = moveStrToEndMapEntryWithCount( - toInstall.sublist(i), MapEntry(appId, retryCount + 1)); - await Workmanager().registerOneOffTask("$taskId+Retry", taskId, - initialDelay: Duration(seconds: remainingSeconds), - existingWorkPolicy: ExistingWorkPolicy.replace, - inputData: { - 'toCheck': toCheck - .map((entry) => '${entry.key},${entry.value}') - .toList(), - 'toInstall': remainingToInstall - .map((entry) => '${entry.key},${entry.value}') - .toList(), - }); - break; } else { - // If the offender has reached its fail limit, notify the user and remove it from the list (task can continue) - toInstall.removeAt(i); - i--; - notificationsProvider - .notify(ErrorCheckingUpdatesNotification(e.toString())); + toThrow.add(key, err, appName: errors?.appIdNames[key]); } - } + }); + } else { + // We don't expect to ever get here in any situation so no need to catch (but log it in case) + logs.add('Fatal error in BG update task: ${e.toString()}'); + rethrow; } - if (didCompleteInstalling || toInstall.isEmpty) { - logs.add('BG task $taskId: Done.'); + } finally { + notificationsProvider.cancel(notif.id); + } + + // Filter out updates that will be installed silently (the rest go into toNotify) + for (var i = 0; i < updates.length; i++) { + if (networkRestricted || + !(await appsProvider.canInstallSilently(updates[i]))) { + if (updates[i].additionalSettings['skipUpdateNotifications'] != true) { + toNotify.add(updates[i]); + } } } - return true; - } catch (e) { - logs.add(e.toString()); - return false; + + // Send the update notification + if (toNotify.isNotEmpty) { + notificationsProvider.notify(UpdateNotification(toNotify)); + } + + // Send the error notifications (grouped by error string) + if (toThrow.rawErrors.isNotEmpty) { + for (var element in toThrow.idsByErrorString.entries) { + notificationsProvider.notify(ErrorCheckingUpdatesNotification( + errors!.errorsAppsString(element.key, element.value), + id: Random().nextInt(10000))); + } + } + + // if there are update checks to retry, schedule a retry task + if (toRetry.isNotEmpty) { + logs.add( + 'BG update task $taskId: Will retry in $retryAfterXSeconds seconds.'); + AndroidAlarmManager.oneShot( + Duration(seconds: retryAfterXSeconds), taskId + 1, bgUpdateCheck, + params: { + 'toCheck': toRetry + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + 'toInstall': toInstall + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + }); + } else { + // If there are no more update checks, schedule an install task + logs.add( + 'BG update task $taskId: Done. Scheduling install task to run immediately.'); + AndroidAlarmManager.oneShot( + const Duration(minutes: 0), taskId + 1, bgUpdateCheck, + params: { + 'toCheck': [], + 'toInstall': toInstall + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList() + }); + } + } else { + // In install mode... + // If you haven't explicitly been given updates to install (which is the case for new tasks), grab all available silent updates + if (toInstall.isEmpty && !networkRestricted) { + var temp = appsProvider.findExistingUpdates(installedOnly: true); + for (var i = 0; i < temp.length; i++) { + if (await appsProvider + .canInstallSilently(appsProvider.apps[temp[i]]!.app)) { + toInstall.add(MapEntry(temp[i], 0)); + } + } + } + var didCompleteInstalling = false; + var tempObtArr = toInstall.where((element) => element.key == obtainiumId); + if (tempObtArr.isNotEmpty) { + // Move obtainium to the end of the list as it must always install last + var obt = tempObtArr.first; + toInstall = moveStrToEndMapEntryWithCount(toInstall, obt); + } + // Loop through all updates and install each + for (var i = 0; i < toInstall.length; i++) { + var appId = toInstall[i].key; + var retryCount = toInstall[i].value; + try { + logs.add( + 'BG install task $taskId: Attempting to update $appId in the background.'); + await appsProvider.downloadAndInstallLatestApps([appId], null, + notificationsProvider: notificationsProvider); + await Future.delayed(const Duration( + seconds: + 5)); // Just in case task ending causes install fail (not clear) + if (i == (toCheck.length - 1)) { + didCompleteInstalling = true; + } + } catch (e) { + // If you got an error, move the offender to the back of the line (increment their fail count) and schedule another task to continue installing shortly + logs.add( + 'BG install task $taskId: Got error on updating $appId \'${e.toString()}\'.'); + if (retryCount < maxAttempts) { + var remainingSeconds = retryCount; + logs.add( + 'BG install task $taskId: Will continue in $remainingSeconds seconds (with $appId moved to the end of the line).'); + var remainingToInstall = moveStrToEndMapEntryWithCount( + toInstall.sublist(i), MapEntry(appId, retryCount + 1)); + AndroidAlarmManager.oneShot( + Duration(seconds: remainingSeconds), taskId + 1, bgUpdateCheck, + params: { + 'toCheck': toCheck + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + 'toInstall': remainingToInstall + .map((entry) => {'key': entry.key, 'value': entry.value}) + .toList(), + }); + break; + } else { + // If the offender has reached its fail limit, notify the user and remove it from the list (task can continue) + toInstall.removeAt(i); + i--; + notificationsProvider + .notify(ErrorCheckingUpdatesNotification(e.toString())); + } + } + } + if (didCompleteInstalling || toInstall.isEmpty) { + logs.add('BG install task $taskId: Done.'); + } } } diff --git a/pubspec.lock b/pubspec.lock index 4cda985..52d0c32 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + android_alarm_manager_plus: + dependency: "direct main" + description: + name: android_alarm_manager_plus + sha256: "82fb28c867c4b3dd7e9157728e46426b8916362f977dbba46b949210f00099f4" + url: "https://pub.dev" + source: hosted + version: "3.0.3" android_intent_plus: dependency: "direct main" description: @@ -923,14 +931,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.2" - workmanager: - dependency: "direct main" - description: - name: workmanager - sha256: ed13530cccd28c5c9959ad42d657cd0666274ca74c56dea0ca183ddd527d3a00 - url: "https://pub.dev" - source: hosted - version: "0.5.2" xdg_directories: dependency: transitive description: @@ -956,5 +956,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.2 <4.0.0" + dart: ">=3.1.0 <4.0.0" flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index a3bcc91..9f61728 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.14.31+224 # When changing this, update the tag in main() accordingly +version: 0.14.31+223 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' @@ -57,6 +57,7 @@ dependencies: ref: main android_package_manager: ^0.6.0 share_plus: ^7.0.0 + android_alarm_manager_plus: ^3.0.0 sqflite: ^2.2.0+3 easy_localization: ^3.0.1 android_intent_plus: ^4.0.0 @@ -65,7 +66,6 @@ dependencies: hsluv: ^1.1.3 connectivity_plus: ^5.0.0 shared_storage: ^0.8.0 - workmanager: ^0.5.2 dev_dependencies: flutter_test: From 6d416f45a96077dac8f00f68730179a5e206e088 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 22 Oct 2023 12:51:30 -0400 Subject: [PATCH 581/600] Higher versionCode after revert --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 9f61728..5635a7d 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.14.31+223 # When changing this, update the tag in main() accordingly +version: 0.14.31+225 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From 53cf253b6774706378804517e180c3a4c49f10bf Mon Sep 17 00:00:00 2001 From: gidano Date: Mon, 23 Oct 2023 10:20:51 +0200 Subject: [PATCH 582/600] Update hu.json --- assets/translations/hu.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 12a288f..23ff3d3 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -245,8 +245,8 @@ "backgroundUpdateReqsExplanation": "Előfordulhat, hogy nem minden appnál lehetséges a háttérbeli frissítés.", "backgroundUpdateLimitsExplanation": "A háttérben történő telepítés sikeressége csak az Obtainium megnyitásakor állapítható meg.", "verifyLatestTag": "Ellenőrizze a „legújabb” címkét", - "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit First", - "intermediateLinkNotFound": "Intermediate link not found", + "intermediateLinkRegex": "Szűrés egy 'közvetítő' linkre, amelyet először meg kell látogatni", + "intermediateLinkNotFound": "Közvetítő link nem található", "exemptFromBackgroundUpdates": "Mentes a háttérben történő frissítések alól (ha engedélyezett)", "bgUpdatesOnWiFiOnly": "Tiltsa le a háttérben frissítéseket, ha nincs Wi-Fi-n", "autoSelectHighestVersionCode": "A legmagasabb verziószámú APK auto. kiválasztása", @@ -263,9 +263,9 @@ "bgTaskStarted": "A háttérfeladat elindult – ellenőrizze a naplókat.", "enableBackgroundUpdates": "Frissítések a háttérben", "runBgCheckNow": "Futtassa a Háttérben frissítés ellenőrzését most", - "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", - "installing": "Installing", - "skipUpdateNotifications": "Skip update notifications", + "versionExtractWholePage": "Alkalmazza a Version Extraction Regex-et az egész oldalra", + "installing": "Telepítés", + "skipUpdateNotifications": "A frissítési értesítések kihagyása", "updatesAvailableNotifChannel": "Frissítések érhetők el", "appsUpdatedNotifChannel": "Alkalmazások frissítve", "appsPossiblyUpdatedNotifChannel": "App frissítési kísérlet", @@ -274,7 +274,7 @@ "downloadingXNotifChannel": "{} letöltés", "completeAppInstallationNotifChannel": "Teljes app telepítés", "checkingForUpdatesNotifChannel": "Frissítések keresése", - "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", + "onlyCheckInstalledOrTrackOnlyApps": "Csak a telepített és a csak követhető appokat ellenőrizze frissítésekért", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazást?" @@ -327,4 +327,4 @@ "one": "{} és 1 további alkalmazás is frissült.", "other": "{} és {} további alkalmazás is frissült." } -} \ No newline at end of file +} From 18f9049bc6b17583e4434a1871d3b683b32654aa Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Thu, 19 Oct 2023 19:33:05 +0200 Subject: [PATCH 583/600] locale(pl): Update Polish translations --- assets/translations/pl.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index bb55a51..73311c8 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -239,7 +239,7 @@ "sortByFileNamesNotLinks": "Sortuj wg nazw plików zamiast pełnych linków", "filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego", "customLinkFilterRegex": "Filtruj linki APK według wyrażenia regularnego (domyślnie \".apk$\")", - "appsPossiblyUpdated": "Próbowano zaktualizować aplikację", + "appsPossiblyUpdated": "Aplikacje mogły zostać zaktualizowane", "appsPossiblyUpdatedNotifDescription": "Powiadamia, gdy co najmniej jedna aktualizacja aplikacji została potencjalnie zastosowana w tle", "xWasPossiblyUpdatedToY": "{} być może zaktualizowano do {}.", "enableBackgroundUpdates": "Włącz aktualizacje w tle", @@ -274,7 +274,7 @@ "downloadingXNotifChannel": "Pobieranie aplikacji", "completeAppInstallationNotifChannel": "Ukończenie instalacji aplikacji", "checkingForUpdatesNotifChannel": "Sprawdzanie dostępności aktualizacji", - "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", + "onlyCheckInstalledOrTrackOnlyApps": "Sprawdzaj tylko zainstalowane i obserwowane aplikacje pod kątem aktualizacji", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", @@ -353,4 +353,4 @@ "many": "{} i {} innych apek mogło zostać zaktualizowanych.", "other": "{} i {} inne apki mogły zostać zaktualizowane." } -} \ No newline at end of file +} From 26971aa109fa93d80d95ba2b3624edda8a43e880 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Wed, 25 Oct 2023 18:22:58 -0400 Subject: [PATCH 584/600] Upgrade packages --- pubspec.lock | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 52d0c32..1ad4fe5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -328,10 +328,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c + sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da url: "https://pub.dev" source: hosted - version: "2.0.16" + version: "2.0.17" flutter_test: dependency: "direct dev" description: flutter @@ -498,10 +498,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1" + sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.2.1" path_provider_foundation: dependency: transitive description: @@ -807,58 +807,58 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330 + sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" url: "https://pub.dev" source: hosted - version: "6.1.0" + version: "6.2.0" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f" + sha256: "4ac97281cf60e2e8c5cc703b2b28528f9b50c8f7cebc71df6bdf0845f647268a" url: "https://pub.dev" source: hosted - version: "6.1.5" + version: "6.2.0" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e + sha256: "9f2d390e096fdbe1e6e6256f97851e51afc2d9c423d3432f1d6a02a8a9a8b9fd" url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.1.0" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88 + sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "3.1.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618" + sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.2.0" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5" + sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" url: "https://pub.dev" source: hosted - version: "2.0.20" + version: "2.2.0" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069" + sha256: "7754a1ad30ee896b265f8d14078b0513a4dba28d358eabb9d5f339886f4a1adc" url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.1.0" uuid: dependency: transitive description: @@ -911,10 +911,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "30b9af6bdd457b44c08748b9190d23208b5165357cc2eb57914fee1366c42974" + sha256: b4b42295b3aa91ed22ba6d3dd7de56efbb8f3ab3d6e41d8b1615d13537c7801d url: "https://pub.dev" source: hosted - version: "3.9.1" + version: "3.9.2" win32: dependency: transitive description: From 9be3d765902156c1b157cd8d79cee9c3a3ab919a Mon Sep 17 00:00:00 2001 From: Bardesss <30936735+Bardesss@users.noreply.github.com> Date: Wed, 1 Nov 2023 10:01:44 +0000 Subject: [PATCH 585/600] Add nl.json Adding Dutch translation to Obtanium --- assets/translations/nl.json | 330 ++++++++++++++++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 assets/translations/nl.json diff --git a/assets/translations/nl.json b/assets/translations/nl.json new file mode 100644 index 0000000..93f7386 --- /dev/null +++ b/assets/translations/nl.json @@ -0,0 +1,330 @@ +{ + "invalidURLForSource": "Geen valide {} app URL", + "noReleaseFound": "Kan geen geschikte release vinden", + "noVersionFound": "Kan de versie niet bepalen", + "urlMatchesNoSource": "URL komt niet overeen met bekende bron", + "cantInstallOlderVersion": "Kan geen oudere versie van de app installeren", + "appIdMismatch": "Gedownloade pakket-ID komt niet overeen met de bestaande app-ID", + "functionNotImplemented": "Deze class heeft deze functie niet geïmplementeerd.", + "placeholder": "Plaatshouder", + "someErrors": "Er zijn enkele fouten opgetreden", + "unexpectedError": "Onverwachte fout", + "ok": "Ok", + "and": "en", + "githubPATLabel": "GitHub Personal Access Token (Verhoogt limiet aantal verzoeken)", + "includePrereleases": "Bevat prereleases", + "fallbackToOlderReleases": "Terugvallen op oudere releases", + "filterReleaseTitlesByRegEx": "Filter release-titels met reguliere expressies.", + "invalidRegEx": "Ongeldige reguliere expressie", + "noDescription": "Geen omschrijving", + "cancel": "Annuleer", + "continue": "Ga verder", + "requiredInBrackets": "(Verplicht)", + "dropdownNoOptsError": "FOUTMELDING: DROPDOWN MOET TENMINSTE ÉÉN OPT HEBBEN", + "colour": "Kleur", + "githubStarredRepos": "GitHub Starred Repos", + "uname": "Gebruikersnaam", + "wrongArgNum": "Onjuist aantal argumenten verstrekt.", + "xIsTrackOnly": "{} is Track-Only", + "source": "Bron", + "app": "App", + "appsFromSourceAreTrackOnly": "Apps van deze bron zijn 'Track-Only'.", + "youPickedTrackOnly": "Je hebt de 'Track-Only' optie geselecteerd.", + "trackOnlyAppDescription": "De app zal worden gevolgd voor updates, maar Obtainium zal niet in staat zijn om deze te downloaden of te installeren.", + "cancelled": "Geannuleerd", + "appAlreadyAdded": "App al toegevoegd", + "alreadyUpToDateQuestion": "Is de app al up-to-date?", + "addApp": "App toevoegen", + "appSourceURL": "App bron URL", + "error": "Foutmelding", + "add": "Toevoegen", + "searchSomeSourcesLabel": "Zoeken (Alleen sommige bronnen)", + "search": "Zoeken", + "additionalOptsFor": "Aanvullende opties voor {}", + "supportedSources": "Ondersteunde bronnen", + "trackOnlyInBrackets": "(Track-Only)", + "searchableInBrackets": "(Doorzoekbaar)", + "appsString": "Apps", + "noApps": "Geen Apps", + "noAppsForFilter": "Geen Apps voor filter", + "byX": "Door {}", + "percentProgress": "Vooruitgang: {}%", + "pleaseWait": "Even geduld", + "updateAvailable": "Update beschikbaar", + "estimateInBracketsShort": "(Ong.)", + "notInstalled": "Niet geinstalleerd", + "estimateInBrackets": "(Ongeveer)", + "selectAll": "Selecteer alles", + "deselectN": "Deselecteer {}", + "xWillBeRemovedButRemainInstalled": "{} zal worden verwijderd uit Obtainium, maar blijft geïnstalleerd op het apparaat.", + "removeSelectedAppsQuestion": "Geselecteerde apps verwijderen??", + "removeSelectedApps": "Geselecteerde apps verwijderen", + "updateX": "Update {}", + "installX": "Installeer {}", + "markXTrackOnlyAsUpdated": "Markeer {}\n(Track-Only)\nals up-to-date", + "changeX": "Verander {}", + "installUpdateApps": "Installeer/Update apps", + "installUpdateSelectedApps": "Installeer/Update geselecteerde apps", + "markXSelectedAppsAsUpdated": "{} geselecteerde apps markeren als up-to-date?", + "no": "Nee", + "yes": "Ja", + "markSelectedAppsUpdated": "Markeer geselecteerde aps als up-to-date", + "pinToTop": "Vastzetten aan de bovenkant", + "unpinFromTop": "Losmaken van de bovenkant", + "resetInstallStatusForSelectedAppsQuestion": "Installatiestatus resetten voor geselecteerde apps?", + "installStatusOfXWillBeResetExplanation": "De installatiestatus van alle geselecteerde apps zal worden gereset.\n\nDit kan helpen wanneer de versie van de app die in Obtainium wordt weergegeven onjuist is vanwege mislukte updates of andere problemen.", + "shareSelectedAppURLs": "Deel geselecteerde app URL's", + "resetInstallStatus": "Reset installatiestatus", + "more": "Meer", + "removeOutdatedFilter": "Verwijder out-of-date app filter", + "showOutdatedOnly": "Toon alleen out-of-date apps", + "filter": "Filter", + "filterActive": "Filter *", + "filterApps": "Filter apps", + "appName": "App naam", + "author": "Auteur", + "upToDateApps": "Up-to-date apps", + "nonInstalledApps": "Niet-geïnstalleerde apps", + "importExport": "Import/Export", + "settings": "Instellingen", + "exportedTo": "Geëxporteerd naar {}", + "obtainiumExport": "Obtainium export", + "invalidInput": "Ongeldige invoer", + "importedX": "Geïmporteerd {}", + "obtainiumImport": "Obtainium import", + "importFromURLList": "Importeer van URL-lijsten", + "searchQuery": "Zoekopdracht", + "appURLList": "App URL-lijst", + "line": "Lijn", + "searchX": "Zoek {}", + "noResults": "Geen resultaten gevonden", + "importX": "Import {}", + "importedAppsIdDisclaimer": "Geïmporteerde apps kunnen mogelijk onjuist worden weergegeven als \"Niet geïnstalleerd\".\nOm dit op te lossen, herinstalleer ze via Obtainium.\nDit zou geen invloed moeten hebben op app-gegevens.\n\nDit heeft alleen invloed op URL- en importmethoden van derden.", + "importErrors": "Import foutmeldingen", + "importedXOfYApps": "{} van {} apps geïmporteerd.", + "followingURLsHadErrors": "De volgende URL's bevatten fouten:", + "okay": "Ok", + "selectURL": "Selecteer URL", + "selectURLs": "Selecteer URL's", + "pick": "Kies", + "theme": "Thema", + "dark": "Donker", + "light": "Licht", + "followSystem": "Volg systeem", + "obtainium": "Obtainium", + "materialYou": "Material You", + "useBlackTheme": "Gebruik zwart thema", + "appSortBy": "App sorteren op", + "authorName": "Auteur/Naam", + "nameAuthor": "Naam/Auteur", + "asAdded": "Zoals toegevoegd", + "appSortOrder": "App sorteervolgorde", + "ascending": "Oplopend", + "descending": "Aflopend", + "bgUpdateCheckInterval": "Frequentie voor achtergrondupdatecontrole", + "neverManualOnly": "Nooit - Alleen handmatig", + "appearance": "Weergave", + "showWebInAppView": "Toon de bronwebpagina in app-weergave", + "pinUpdates": "Updates bovenaan in de apps-weergave vastpinnen", + "updates": "Updates", + "sourceSpecific": "Bron-specifiek", + "appSource": "App bron", + "noLogs": "Geen logs", + "appLogs": "App logs", + "close": "Sluiten", + "share": "Delen", + "appNotFound": "App niet gevonden", + "obtainiumExportHyphenatedLowercase": "obtainium-export", + "pickAnAPK": "Kies een APK", + "appHasMoreThanOnePackage": "{} heeft meer dan één package:", + "deviceSupportsXArch": "Jouw apparaat support de {} CPU-architectuur.", + "deviceSupportsFollowingArchs": "Je apparaat ondersteunt de volgende CPU-architecturen:", + "warning": "Waarschuwing", + "sourceIsXButPackageFromYPrompt": "De appbron is '{}' maar de release package komt van '{}'. Doorgaan?", + "updatesAvailable": "Updates beschikbaar", + "updatesAvailableNotifDescription": "Stelt de gebruiker op de hoogte dat er updates beschikbaar zijn voor één of meer apps die worden bijgehouden door Obtainium.", + "noNewUpdates": "Geen nieuwe updates.", + "xHasAnUpdate": "{} heeft een update.", + "appsUpdated": "Apps bijgewerkt", + "appsUpdatedNotifDescription": "Stelt de gebruiker op de hoogte dat updates voor één of meer apps in de achtergrond zijn toegepast.", + "xWasUpdatedToY": "{} is bijgewerkt naar {}.", + "errorCheckingUpdates": "Fout bij het controleren op updates", + "errorCheckingUpdatesNotifDescription": "Een melding die verschijnt wanneer het controleren op updates in de achtergrond mislukt", + "appsRemoved": "Apps verwijderd", + "appsRemovedNotifDescription": "Stelt de gebruiker op de hoogte dat één of meer apps zijn verwijderd vanwege fouten tijdens het laden ervan", + "xWasRemovedDueToErrorY": "{} is verwijderd vanwege deze foutmelding: {}", + "completeAppInstallation": "Complete app installatie", + "obtainiumMustBeOpenToInstallApps": "Obtainium moet geopend zijn om apps te installeren", + "completeAppInstallationNotifDescription": "Vraagt de gebruiker om terug te keren naar Obtainium om de installatie van een app af te ronden", + "checkingForUpdates": "Controleren op updates", + "checkingForUpdatesNotifDescription": "Tijdelijke melding die verschijnt tijdens het controleren op updates", + "pleaseAllowInstallPerm": "Sta Obtainium toe om apps te installeren", + "trackOnly": "Track-Only", + "errorWithHttpStatusCode": "Foutmelding {}", + "versionCorrectionDisabled": "Versiecorrectie uitgeschakeld (de plug-in lijkt niet te werken)", + "unknown": "Onbekend", + "none": "Geen", + "never": "Nooit", + "latestVersionX": "Laatste versie: {}", + "installedVersionX": "Geïnstalleerde versie: {}", + "lastUpdateCheckX": "Laatste updatecontrole: {}", + "remove": "Verwijderen", + "yesMarkUpdated": "Ja, markeer als bijgewerkt", + "fdroid": "F-Droid Official", + "appIdOrName": "App ID of naam", + "appId": "App ID", + "appWithIdOrNameNotFound": "Er werd geen app gevonden met dat ID of die naam", + "reposHaveMultipleApps": "Repositories kunnen meerdere apps bevatten", + "fdroidThirdPartyRepo": "F-Droid Third-Party Repo", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Chat", + "install": "Installeren", + "markInstalled": "Als geïnstalleerd markere", + "update": "Update", + "markUpdated": "Markeren als bijgewerkt", + "additionalOptions": "Aanvullende opties", + "disableVersionDetection": "Versieherkenning uitschakelen", + "noVersionDetectionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt.", + "downloadingX": "Downloaden {}", + "downloadNotifDescription": "Stelt de gebruiker op de hoogte van de voortgang bij het downloaden van een app", + "noAPKFound": "Geen APK gevonden", + "noVersionDetection": "Geen versieherkenning", + "categorize": "Categoriseren", + "categories": "Categorieën", + "category": "Categorie", + "noCategory": "Geen categorie", + "noCategories": "Geen categorieën", + "deleteCategoriesQuestion": "Categorieën verwijderen?", + "categoryDeleteWarning": "Alle apps in verwijderde categorieën worden teruggezet naar 'ongecategoriseerd'.", + "addCategory": "Categorie toevoegen", + "label": "Label", + "language": "Taal", + "copiedToClipboard": "Gekopieerd naar klembord", + "storagePermissionDenied": "Toegang tot opslag geweigerd", + "selectedCategorizeWarning": "Dit zal eventuele bestaande categorie-instellingen voor de geselecteerde apps vervangen.", + "filterAPKsByRegEx": "Filter APK's op reguliere expressie", + "removeFromObtainium": "Verwijder van Obtainium", + "uninstallFromDevice": "Verwijder van apparaat", + "onlyWorksWithNonVersionDetectApps": "Werkt alleen voor apps waarbij versieherkenning is uitgeschakeld.", + "releaseDateAsVersion": "Gebruik de releasedatum als versie", + "releaseDateAsVersionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt, maar waar wel een releasedatum beschikbaar is.", + "changes": "Veranderingen", + "releaseDate": "Releasedatum", + "importFromURLsInFile": "Importeren vanaf URL's in een bestand (zoals OPML)", + "versionDetection": "Versieherkenning", + "standardVersionDetection": "Standaard versieherkenning", + "groupByCategory": "Groepeer op categorie", + "autoApkFilterByArch": "Poging om APK's te filteren op CPU-architectuur indien mogelijk", + "overrideSource": "Bron overschrijven", + "dontShowAgain": "Don't show this again", + "dontShowTrackOnlyWarnings": "Geen waarschuwingen voor 'Track-Only' weergeven", + "dontShowAPKOriginWarnings": "APK-herkomstwaarschuwingen niet weergeven", + "moveNonInstalledAppsToBottom": "Verplaats niet-geïnstalleerde apps naar de onderkant van de apps-weergave", + "gitlabPATLabel": "GitLab Personal Access Token\n(Maakt het mogelijk beter te zoeken naar APK's)", + "about": "Over", + "requiresCredentialsInSettings": "Dit vereist aanvullende referenties (in Instellingen)", + "checkOnStart": "Controleren op updates bij opstarten", + "tryInferAppIdFromCode": "Probeer de app-ID af te leiden uit de broncode", + "removeOnExternalUninstall": "Automatisch extern verwijderde apps verwijderen", + "pickHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren", + "checkUpdateOnDetailPage": "Controleren op updates bij het openen van een app-detailpagina", + "disablePageTransitions": "Schakel overgangsanimaties tussen pagina's uit", + "reversePageTransitions": "Omgekeerde overgangsanimaties tussen pagina's", + "minStarCount": "Minimale Github Stars", + "addInfoBelow": "Voeg deze informatie hieronder toe.", + "addInfoInSettings": "Voeg deze informatie toe in de instellingen.", + "githubSourceNote": "Beperkingen van GitHub kunnen worden vermeden door het gebruik van een API-sleutel.", + "gitlabSourceNote": "GitLab APK-extractie werkt mogelijk niet zonder een API-sleutel.", + "sortByFileNamesNotLinks": "Sorteren op bestandsnamen in plaats van volledige links.", + "filterReleaseNotesByRegEx": "Filter release-opmerkingen met een reguliere expressie.", + "customLinkFilterRegex": "Aangepaste APK-linkfilter met een reguliere expressie (Standaard '.apk$').", + "appsPossiblyUpdated": "Poging tot app-updates", + "appsPossiblyUpdatedNotifDescription": "Stelt de gebruiker op de hoogte dat updates voor één of meer apps mogelijk in de achtergrond zijn toegepast", + "xWasPossiblyUpdatedToY": "{} mogelijk bijgewerkt naar {}.", + "enableBackgroundUpdates": "Achtergrondupdates inschakelen", + "backgroundUpdateReqsExplanation": "Achtergrondupdates zijn mogelijk niet voor alle apps mogelijk.", + "backgroundUpdateLimitsExplanation": "THet succes van een installatie in de achtergrond kan alleen worden bepaald wanneer Obtainium is geopend.", + "verifyLatestTag": "Verifieer de 'Laatste'-tag", + "intermediateLinkRegex": "Filter voor een 'tussenliggende' link om eerst te bezoeken", + "intermediateLinkNotFound": "Tussenliggende link niet gevonden", + "exemptFromBackgroundUpdates": "Vrijgesteld van achtergrondupdates (indien ingeschakeld)", + "bgUpdatesOnWiFiOnly": "Achtergrondupdates uitschakelen wanneer niet verbonden met WiFi", + "autoSelectHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren", + "versionExtractionRegEx": "Reguliere expressie voor versie-extractie", + "matchGroupToUse": "Overeenkomende groep om te gebruiken voor de reguliere expressie voor versie-extractie", + "highlightTouchTargets": "Markeer minder voor de hand liggende aanraakdoelen.", + "pickExportDir": "Kies de exportmap", + "autoExportOnChanges": "Automatisch exporteren bij wijzigingen", + "filterVersionsByRegEx": "Filter versies met een reguliere expressie", + "trySelectingSuggestedVersionCode": "Probeer de voorgestelde versiecode APK te selecteren", + "dontSortReleasesList": "Volgorde van releases behouden vanuit de API", + "reverseSort": "Sortering omkeren", + "debugMenu": "Debug menu", + "bgTaskStarted": "Achtergrondtaak gestart - controleer de logs.", + "runBgCheckNow": "Voer nu een achtergrondupdatecontrole uit", + "versionExtractWholePage": "De reguliere expressie voor versie-extractie toepassen op de hele pagina", + "installing": "Installeren", + "skipUpdateNotifications": "Updatemeldingen overslaan", + "updatesAvailableNotifChannel": "Updates beschikbaar", + "appsUpdatedNotifChannel": "Apps bijgewerkt", + "appsPossiblyUpdatedNotifChannel": "Poging tot app-updates", + "errorCheckingUpdatesNotifChannel": "Foutcontrole bij het zoeken naar updates", + "appsRemovedNotifChannel": "Apps verwijderd", + "downloadingXNotifChannel": "{} downloaden", + "completeAppInstallationNotifChannel": "Voltooien van de app-installatie", + "checkingForUpdatesNotifChannel": "Controleren op updates", + "onlyCheckInstalledOrTrackOnlyApps": "Alleen geïnstalleerde en Track-Only apps controleren op updates", + "removeAppQuestion": { + "one": "App verwijderen?", + "other": "Apps verwijderen?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuut", + "other": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuten" + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuut", + "other": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuten" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "Achtergrondupdatecontrole heeft {} update gevonden - zal de gebruiker op de hoogte stellen indien nodig", + "other": "Achtergrondupdatecontrole heeft {} updates gevonden - zal de gebruiker op de hoogte stellen indien nodig" + }, + "apps": { + "one": "{} app", + "other": "{} apps" + }, + "url": { + "one": "{} URL", + "other": "{} URLs" + }, + "minute": { + "one": "{} minuut", + "other": "{} minuten" + }, + "hour": { + "one": "{} uur", + "other": "{} uren" + }, + "day": { + "one": "{} dag", + "other": "{} dagen" + }, + "clearedNLogsBeforeXAfterY": { + "one": "{n} logboekitem gewist (voor = {before}, na = {after})", + "other": "{n} logboekitems gewist (voor = {before}, na = {after})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "{} en nog 1 app hebben updates.", + "other": "{} en {} meer apps hebben updates." + }, + "xAndNMoreUpdatesInstalled": { + "one": "{} en nog 1 app is bijgewerkt.", + "other": "{} en {} meer apps zijn bijgewerkt." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "{} en nog 1 app zijn mogelijk bijgewerkt.", + "other": "{} en {} meer apps zijn mogelijk bijgwerkt." + } +} \ No newline at end of file From 5b142b44016fa14f1aa96b41585060889b13a4dd Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 3 Nov 2023 19:35:42 -0400 Subject: [PATCH 586/600] Various fixes and improvements (#454, #1026, #1050, #1051, #1052, #1060) --- lib/app_sources/fdroid.dart | 2 +- lib/app_sources/fdroidrepo.dart | 3 ++- lib/app_sources/html.dart | 8 ++++++++ lib/app_sources/uptodown.dart | 8 ++++---- lib/pages/app.dart | 27 +++++++++++++++------------ lib/providers/source_provider.dart | 5 +---- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index c7b2dda..c071c02 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -181,7 +181,7 @@ APKDetails getAPKUrlsFromFDroidPackagesAPIResponse( List apkUrls = releaseChoices .map((e) => '${apkUrlPrefix}_${e['versionCode']}.apk') .toList(); - return APKDetails(version, getApkUrlsFromUrls(apkUrls), + return APKDetails(version, getApkUrlsFromUrls(apkUrls.toSet().toList()), AppNames(sourceName, Uri.parse(standardUrl).pathSegments.last)); } else { throw getObtainiumHttpError(res); diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index e61d544..b0d74d8 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -108,7 +108,8 @@ class FDroidRepo extends AppSource { if (appIdOrName == null) { throw NoReleasesError(); } - var res = await sourceRequest('$standardUrl/index.xml'); + var res = await sourceRequest( + '$standardUrl${standardUrl.endsWith('/index.xml') ? '' : '/index.xml'}'); if (res.statusCode == 200) { var body = parse(res.body); var foundApps = body.querySelectorAll('application').where((element) { diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index a2dacdb..13dcdd8 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -170,7 +170,15 @@ class HTML extends AppSource { List allLinks = html .querySelectorAll('a') .map((element) => element.attributes['href'] ?? '') + .where((element) => element.isNotEmpty) .toList(); + if (allLinks.isEmpty) { + allLinks = RegExp( + r'(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?') + .allMatches(res.body) + .map((match) => match.group(0)!) + .toList(); + } List links = []; if ((additionalSettings['intermediateLinkRegex'] as String?) ?.isNotEmpty == diff --git a/lib/app_sources/uptodown.dart b/lib/app_sources/uptodown.dart index c764b7c..7a0b41d 100644 --- a/lib/app_sources/uptodown.dart +++ b/lib/app_sources/uptodown.dart @@ -89,11 +89,11 @@ class Uptodown extends AppSource { throw getObtainiumHttpError(res); } var html = parse(res.body); - var finalUrl = - (html.querySelector('.post-download')?.attributes['data-url']); - if (finalUrl == null) { + var finalUrlKey = + html.querySelector('.post-download')?.attributes['data-url']; + if (finalUrlKey == null) { throw NoAPKError(); } - return finalUrl; + return 'https://dw.$host/dwn/$finalUrlKey'; } } diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 7622a96..14e33d4 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -155,10 +155,13 @@ class _AppPageState extends State { const SizedBox(height: 20), app?.icon != null ? Row(mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.memory( - app!.icon!, - height: 150, - gaplessPlayback: true, + GestureDetector( + child: Image.memory( + app!.icon!, + height: 150, + gaplessPlayback: true, + ), + onTap: () => pm.openApp(app.app.id), ) ]) : Container(), @@ -463,15 +466,15 @@ class _AppPageState extends State { : null)) ], )); - + appScreenAppBar() => AppBar( - leading: IconButton( - icon: const Icon(Icons.arrow_back), - onPressed: () { - Navigator.pop(context); - }, - ), - ); + leading: IconButton( + icon: const Icon(Icons.arrow_back), + onPressed: () { + Navigator.pop(context); + }, + ), + ); return Scaffold( appBar: settingsProvider.showAppWebpage ? AppBar() : appScreenAppBar(), diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index e5ea114..5736027 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -283,9 +283,6 @@ preStandardizeUrl(String url) { url.toLowerCase().indexOf('https://') != 0) { url = 'https://$url'; } - if (url.toLowerCase().indexOf('https://www.') == 0) { - url = 'https://${url.substring(12)}'; - } url = url .split('/') .where((e) => e.isNotEmpty) @@ -599,7 +596,7 @@ class SourceProvider { AppSource? source; for (var s in sources.where((element) => element.host != null)) { if (RegExp( - '://${s.allowSubDomains ? '([^\\.]+\\.)*' : ''}${s.host}(/|\\z)?') + '://(${s.allowSubDomains ? '([^\\.]+\\.)*' : ''}|www\\.)${s.host}(/|\\z)?') .hasMatch(url)) { source = s; break; From 168c1cf1ceb8092d6c220d31eeec696182814f3c Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 3 Nov 2023 19:36:39 -0400 Subject: [PATCH 587/600] Upgrade packages, increment version --- lib/main.dart | 2 +- pubspec.lock | 20 ++++++++++---------- pubspec.yaml | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 1ca5444..0e3d6d6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.31'; +const String currentVersion = '0.14.32'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/pubspec.lock b/pubspec.lock index 1ad4fe5..7ab0e9f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -283,10 +283,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: ad76540d21c066228ee3f9d1dad64a9f7e46530e8bb7c85011a88bc1fd874bc5 + sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.1" flutter_local_notifications: dependency: "direct main" description: @@ -799,10 +799,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27" + sha256: b1c9e98774adf8820c96fbc7ae3601231d324a7d5ebd8babe27b6dfac91357ba url: "https://pub.dev" source: hosted - version: "6.1.14" + version: "6.2.1" url_launcher_android: dependency: transitive description: @@ -887,18 +887,18 @@ packages: dependency: "direct main" description: name: webview_flutter - sha256: c1ab9b81090705c6069197d9fdc1625e587b52b8d70cdde2339d177ad0dbb98e + sha256: "42393b4492e629aa3a88618530a4a00de8bb46e50e7b3993fedbfdc5352f0dbf" url: "https://pub.dev" source: hosted - version: "4.4.1" + version: "4.4.2" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: b0cd33dd7d3dd8e5f664e11a19e17ba12c352647269921a3b568406b001f1dff + sha256: "8326ee235f87605a2bfc444a4abc897f4abc78d83f054ba7d3d1074ce82b4fbf" url: "https://pub.dev" source: hosted - version: "3.12.0" + version: "3.12.1" webview_flutter_platform_interface: dependency: transitive description: @@ -911,10 +911,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: b4b42295b3aa91ed22ba6d3dd7de56efbb8f3ab3d6e41d8b1615d13537c7801d + sha256: af6f5ab05918070b33507b0d453ba9fb7d39338a3256c23cf9433dc68100774a url: "https://pub.dev" source: hosted - version: "3.9.2" + version: "3.9.3" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5635a7d..6c7cb05 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.14.31+225 # When changing this, update the tag in main() accordingly +version: 0.14.32+226 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0' From b03675811cb8263d586654f07c3460fee15374b1 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Fri, 3 Nov 2023 19:40:19 -0400 Subject: [PATCH 588/600] Added new language menu entries --- lib/main.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/main.dart b/lib/main.dart index 0e3d6d6..4d973de 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -40,6 +40,8 @@ List> supportedLocales = const [ MapEntry(Locale('bs'), 'Bosanski'), MapEntry(Locale('pt'), 'Brasileiro'), MapEntry(Locale('cs'), 'Česky'), + MapEntry(Locale('sv'), 'Svenska'), + MapEntry(Locale('nl'), 'Nederlands'), ]; const fallbackLocale = Locale('en'); const localeDir = 'assets/translations'; From efd3c461e089ed47fd2027fb87d772679ee1e86b Mon Sep 17 00:00:00 2001 From: Matsuri Date: Sun, 5 Nov 2023 14:56:41 +0800 Subject: [PATCH 589/600] Update zh.json - Translate new strings - Minor improvements Signed-off-by: Matsuri --- assets/translations/zh.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/assets/translations/zh.json b/assets/translations/zh.json index d1e64e8..314d9fe 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -14,7 +14,7 @@ "githubPATLabel": "GitHub 个人访问令牌(提升 API 请求限额)", "includePrereleases": "包含预发行版", "fallbackToOlderReleases": "将旧发行版作为备选", - "filterReleaseTitlesByRegEx": "使用正则表达式筛选发行标题", + "filterReleaseTitlesByRegEx": "筛选发行标题(正则表达式)", "invalidRegEx": "无效的正则表达式", "noDescription": "无描述", "cancel": "取消", @@ -203,7 +203,7 @@ "copiedToClipboard": "已复制至剪贴板", "storagePermissionDenied": "已拒绝授予存储权限", "selectedCategorizeWarning": "这将覆盖选中应用当前的类别设置。", - "filterAPKsByRegEx": "使用正则表达式筛选 APK 文件", + "filterAPKsByRegEx": "筛选 APK 文件(正则表达式)", "removeFromObtainium": "从 Obtainium 中删除", "uninstallFromDevice": "从设备中卸载", "onlyWorksWithNonVersionDetectApps": "仅适用于禁用版本检测的应用。", @@ -221,7 +221,7 @@ "dontShowTrackOnlyWarnings": "不显示“仅追踪”模式警告", "dontShowAPKOriginWarnings": "不显示 APK 文件来源警告", "moveNonInstalledAppsToBottom": "将未安装应用置底", - "gitlabPATLabel": "GitLab 个人访问令牌\n(启用搜索功能并增强 APK 发现)", + "gitlabPATLabel": "GitLab 个人访问令牌(启用搜索功能并增强 APK 发现)", "about": "相关文档", "requiresCredentialsInSettings": "此功能需要额外的凭据(在“设置”中添加)", "checkOnStart": "启动时进行一次检查", @@ -237,8 +237,8 @@ "githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。", "gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。", "sortByFileNamesNotLinks": "使用文件名代替链接进行排序", - "filterReleaseNotesByRegEx": "使用正则表达式筛选发行说明", - "customLinkFilterRegex": "使用正则表达式筛选自定义来源 APK 文件链接\n(未填写时,默认匹配模式为“.apk$”)", + "filterReleaseNotesByRegEx": "筛选发行说明(正则表达式)", + "customLinkFilterRegex": "筛选自定义来源 APK 文件链接\n(正则表达式,默认匹配模式为“.apk$”)", "appsPossiblyUpdated": "已尝试更新应用", "appsPossiblyUpdatedNotifDescription": "当应用已尝试在后台更新时发送通知", "xWasPossiblyUpdatedToY": "已尝试将“{}”更新至 {}。", @@ -246,26 +246,26 @@ "backgroundUpdateReqsExplanation": "后台更新未必适用于所有的应用。", "backgroundUpdateLimitsExplanation": "只有在启动 Obtainium 时才能确认安装是否成功。", "verifyLatestTag": "验证“Latest”标签", - "intermediateLinkRegex": "筛选一个首先访问的“中转”链接(正则表达式)", + "intermediateLinkRegex": "筛选首先访问的“中转”链接(正则表达式)", "intermediateLinkNotFound": "未找到“中转”链接", - "exemptFromBackgroundUpdates": "单独禁用后台更新(若已经全局启用)", + "exemptFromBackgroundUpdates": "禁用后台更新\n(如果已经全局启用)", "bgUpdatesOnWiFiOnly": "未连接 Wi-Fi 时禁用后台更新", "autoSelectHighestVersionCode": "自动选择版本号最高的 APK 文件", - "versionExtractionRegEx": "获取版本号的正则表达式", + "versionExtractionRegEx": "提取版本号(正则表达式)", "matchGroupToUse": "引用的捕获组", "highlightTouchTargets": "突出展示不明显的触摸区域", "pickExportDir": "选择导出文件夹", "autoExportOnChanges": "数据变更时自动导出", - "filterVersionsByRegEx": "使用正则表达式筛选版本号", + "filterVersionsByRegEx": "筛选版本号(正则表达式)", "trySelectingSuggestedVersionCode": "尝试选择推荐版本的 APK 文件", "dontSortReleasesList": "保持来自 API 的发行顺序", "reverseSort": "反转排序", "debugMenu": "调试选项", "bgTaskStarted": "后台任务已启动 - 详见日志", "runBgCheckNow": "立即进行后台更新检查", - "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", - "installing": "Installing", - "skipUpdateNotifications": "Skip update notifications", + "versionExtractWholePage": "将提取版本号的正则表达式应用于整个页面", + "installing": "正在安装", + "skipUpdateNotifications": "忽略更新通知", "updatesAvailableNotifChannel": "更新可用", "appsUpdatedNotifChannel": "应用已更新", "appsPossiblyUpdatedNotifChannel": "已尝试更新应用", @@ -274,7 +274,7 @@ "downloadingXNotifChannel": "正在下载{}", "completeAppInstallationNotifChannel": "完成应用安装", "checkingForUpdatesNotifChannel": "正在检查更新", - "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", + "onlyCheckInstalledOrTrackOnlyApps": "只对已安装和“仅追踪”的应用进行更新检查", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" From 5be7229c4b9cd616af561c59ffb404e17748abea Mon Sep 17 00:00:00 2001 From: Bardesss <30936735+Bardesss@users.noreply.github.com> Date: Tue, 7 Nov 2023 08:49:35 +0000 Subject: [PATCH 590/600] Update nl.json --- assets/translations/nl.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/translations/nl.json b/assets/translations/nl.json index 93f7386..7c953da 100644 --- a/assets/translations/nl.json +++ b/assets/translations/nl.json @@ -11,7 +11,7 @@ "unexpectedError": "Onverwachte fout", "ok": "Ok", "and": "en", - "githubPATLabel": "GitHub Personal Access Token (Verhoogt limiet aantal verzoeken)", + "githubPATLabel": "GitHub Personal Access Token\n(Verhoogt limiet aantal verzoeken)", "includePrereleases": "Bevat prereleases", "fallbackToOlderReleases": "Terugvallen op oudere releases", "filterReleaseTitlesByRegEx": "Filter release-titels met reguliere expressies.", @@ -244,7 +244,7 @@ "xWasPossiblyUpdatedToY": "{} mogelijk bijgewerkt naar {}.", "enableBackgroundUpdates": "Achtergrondupdates inschakelen", "backgroundUpdateReqsExplanation": "Achtergrondupdates zijn mogelijk niet voor alle apps mogelijk.", - "backgroundUpdateLimitsExplanation": "THet succes van een installatie in de achtergrond kan alleen worden bepaald wanneer Obtainium is geopend.", + "backgroundUpdateLimitsExplanation": "Het succes van een installatie in de achtergrond kan alleen worden bepaald wanneer Obtainium is geopend.", "verifyLatestTag": "Verifieer de 'Laatste'-tag", "intermediateLinkRegex": "Filter voor een 'tussenliggende' link om eerst te bezoeken", "intermediateLinkNotFound": "Tussenliggende link niet gevonden", @@ -305,7 +305,7 @@ }, "hour": { "one": "{} uur", - "other": "{} uren" + "other": "{} uur" }, "day": { "one": "{} dag", @@ -327,4 +327,4 @@ "one": "{} en nog 1 app zijn mogelijk bijgewerkt.", "other": "{} en {} meer apps zijn mogelijk bijgwerkt." } -} \ No newline at end of file +} From 509bd2165531445411872167666ba223ee46065f Mon Sep 17 00:00:00 2001 From: Daviteusz Date: Thu, 9 Nov 2023 15:48:57 +0100 Subject: [PATCH 591/600] Update Polish translations --- assets/translations/pl.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 73311c8..e36ef9c 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -28,8 +28,8 @@ "xIsTrackOnly": "{} jest tylko obserwowane", "source": "Źródło", "app": "Aplikacja", - "appsFromSourceAreTrackOnly": "Aplikacje z tego źródła są „tylko obserwowane”.", - "youPickedTrackOnly": "Wybrano opcję „Tylko obserwuj”.", + "appsFromSourceAreTrackOnly": "Aplikacje z tego źródła są tylko obserwowane.", + "youPickedTrackOnly": "Wybrano opcję \"Tylko obserwuj\".", "trackOnlyAppDescription": "Aplikacja będzie obserwowana pod kątem aktualizacji, ale Obtainium nie będzie w stanie jej pobrać ani zainstalować.", "cancelled": "Anulowano", "appAlreadyAdded": "Aplikacja już została dodana", @@ -99,7 +99,7 @@ "searchX": "Przeszukaj {}", "noResults": "Nie znaleziono wyników", "importX": "Importuj {}", - "importedAppsIdDisclaimer": "Zaimportowane aplikacje mogą być wyświetlane jako „Niezainstalowane”.\nAby to naprawić, zainstaluj je ponownie za pomocą Obtainium.\nNie powinno to mieć wpływu na dane aplikacji.\n\nDotyczy tylko adresów URL i metod importu innych aplikacji.", + "importedAppsIdDisclaimer": "Zaimportowane aplikacje mogą być wyświetlane jako niezainstalowane.\nAby to naprawić, przeinstaluj je za pomocą Obtainium.\nNie powinno to mieć wpływu na dane aplikacji.\n\nDotyczy tylko adresu URL i innych metod importu.", "importErrors": "Błędy importowania", "importedXOfYApps": "Zaimportowano {} z {} aplikacji.", "followingURLsHadErrors": "Następujące adresy URL zawierały błędy:", @@ -218,7 +218,7 @@ "autoApkFilterByArch": "Spróbuj filtrować pliki APK według architektury procesora, jeśli to możliwe", "overrideSource": "Nadpisz źródło", "dontShowAgain": "Nie pokazuj tego ponownie", - "dontShowTrackOnlyWarnings": "Nie pokazuj ostrzeżeń „Tylko obserwowana”", + "dontShowTrackOnlyWarnings": "Nie pokazuj ostrzeżeń \"Tylko obserwowana\"", "dontShowAPKOriginWarnings": "Nie pokazuj ostrzeżeń o pochodzeniu APK", "moveNonInstalledAppsToBottom": "Przenieś niezainstalowane aplikacje na dół widoku aplikacji", "gitlabPATLabel": "Osobisty token dostępu GitLab\n(Umożliwia wyszukiwanie i lepsze wykrywanie APK)", @@ -353,4 +353,4 @@ "many": "{} i {} innych apek mogło zostać zaktualizowanych.", "other": "{} i {} inne apki mogły zostać zaktualizowane." } -} +} \ No newline at end of file From e0f9fc233dc77b680b7d20d33917f1108f95cf17 Mon Sep 17 00:00:00 2001 From: John Betaro <114379310+JohnBetaro@users.noreply.github.com> Date: Fri, 10 Nov 2023 21:15:57 -1000 Subject: [PATCH 592/600] Update release.yml --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7ac5e34..00a4cce 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,7 +21,6 @@ jobs: - name: Build APKs run: | - sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle flutter build apk && flutter build apk --split-per-abi rm ./build/app/outputs/flutter-apk/*.sha1 ls -l ./build/app/outputs/flutter-apk/ From 5223e58f838bc0fa13129c8f8aa3fcb348336288 Mon Sep 17 00:00:00 2001 From: John Betaro <114379310+JohnBetaro@users.noreply.github.com> Date: Fri, 10 Nov 2023 21:17:40 -1000 Subject: [PATCH 593/600] Update build.gradle --- android/app/build.gradle | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 764d501..d013381 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -57,18 +57,10 @@ android { versionCode flutterVersionCode.toInteger() versionName flutterVersionName } - - signingConfigs { - release { - keyAlias keystoreProperties['keyAlias'] - keyPassword keystoreProperties['keyPassword'] - storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null - storePassword keystoreProperties['storePassword'] - } - } + buildTypes { release { - signingConfig signingConfigs.release + } } } From 3311c49236207891b5f1e1553531e3c99874921a Mon Sep 17 00:00:00 2001 From: John Betaro <114379310+JohnBetaro@users.noreply.github.com> Date: Fri, 10 Nov 2023 21:18:35 -1000 Subject: [PATCH 594/600] Update release.yml --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 00a4cce..05fd8ff 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,6 +2,7 @@ name: Build and Release on: workflow_dispatch: + push: jobs: build: From 6791b20121bd3f23e182d86b9c05b44965279d34 Mon Sep 17 00:00:00 2001 From: John Betaro <114379310+JohnBetaro@users.noreply.github.com> Date: Fri, 10 Nov 2023 21:20:21 -1000 Subject: [PATCH 595/600] Update release.yml --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 05fd8ff..00a4cce 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,7 +2,6 @@ name: Build and Release on: workflow_dispatch: - push: jobs: build: From c8eef9181300bd67a42f4449502d6d3a5f55868a Mon Sep 17 00:00:00 2001 From: ngocanhtve Date: Sat, 11 Nov 2023 15:44:56 +0700 Subject: [PATCH 596/600] Create vn.json Translation for Vietnamese language! --- assets/translations/vn.json | 330 ++++++++++++++++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 assets/translations/vn.json diff --git a/assets/translations/vn.json b/assets/translations/vn.json new file mode 100644 index 0000000..886879d --- /dev/null +++ b/assets/translations/vn.json @@ -0,0 +1,330 @@ +{ + "invalidURLForSource": "URL ứng dụng {} không hợp lệ", + "noReleaseFound": "Không thể tìm thấy bản phát hành phù hợp", + "noVersionFound": "Không thể xác định phiên bản phát hành", + "urlMatchesNoSource": "URL không khớp với nguồn đã biết", + "cantInstallOlderVersion": "Không thể cài đặt phiên bản cũ hơn của Ứng dụng", + "appIdMismatch": "ID gói đã tải xuống không khớp với ID ứng dụng hiện tại", + "functionNotImplemented": "Lớp này chưa triển khai chức năng này", + "placeholder": "Giữ chỗ", + "someErrors": "Đã xảy ra một số lỗi", + "unexpectedError": "Lỗi không mong đợi", + "ok": "Ôkê", + "and": "và", + "githubPATLabel": "Mã thông báo truy cập cá nhân GitHub (Tăng tốc độ giới hạn)", + "includePrereleases": "Bao gồm các bản phát hành trước", + "fallbackToOlderReleases": "Dự phòng về bản phát hành cũ hơn", + "filterReleaseTitlesByRegEx": "Lọc tiêu đề bản phát hành theo biểu thức chính quy", + "invalidRegEx": "Biểu thức chính quy không hợp lệ", + "noDescription": "Không có mô tả", + "cancel": "Hủy bỏ", + "continue": "Tiếp tục", + "requiredInBrackets": "(Yêu cầu)", + "dropdownNoOptsError": "LỖI: TẢI XUỐNG PHẢI CÓ ÍT NHẤT MỘT LỰA CHỌN", + "colour": "Màu sắc", + "githubStarredRepos": "Kho lưu trữ có gắn dấu sao GitHub", + "uname": "Tên người dùng", + "wrongArgNum": "Số lượng đối số được cung cấp sai", + "xIsTrackOnly": "{}là Chỉ-Theo dõi", + "source": "Nguồn", + "app": "Ứng dụng", + "appsFromSourceAreTrackOnly": "Các ứng dụng từ nguồn này là 'Chỉ-Theo dõi'.", + "youPickedTrackOnly": "Bạn đã chọn tùy chọn 'Chỉ-Theo dõi'.", + "trackOnlyAppDescription": "Ứng dụng sẽ được theo dõi để cập nhật, nhưng Obtainium sẽ không thể tải xuống hoặc cài đặt nó.", + "cancelled": "Đã hủy", + "appAlreadyAdded": "Ứng dụng được thêm rồi", + "alreadyUpToDateQuestion": "Ứng dụng đã được cập nhật?", + "addApp": "Thêm ứng dụng", + "appSourceURL": "URL nguồn ứng dụng", + "error": "Lỗi", + "add": "Thêm", + "searchSomeSourcesLabel": "Tìm kiếm (Chỉ một số nguồn)", + "search": "Tìm kiếm", + "additionalOptsFor": "Tùy chọn bổ sung cho {}", + "supportedSources": "Nguồn được hỗ trợ", + "trackOnlyInBrackets": "(Chỉ-Theo dõi)", + "searchableInBrackets": "(Có thể tìm kiếm)", + "appsString": "Ứng dụng", + "noApps": "Không có ứng dụng", + "noAppsForFilter": "Không có ứng dụng cho bộ lọc", + "byX": "Bởi {}", + "percentProgress": "Tiến triển: {}%", + "pleaseWait": "Vui lòng chờ", + "updateAvailable": "Có sẵn bản cập nhật", + "estimateInBracketsShort": "(Ước lượng.)", + "notInstalled": "Chưa cài đặt", + "estimateInBrackets": "(Ước lượng)", + "selectAll": "Chọn tất cả", + "deselectN": "Bỏ chọn {}", + "xWillBeRemovedButRemainInstalled": "{} sẽ bị xóa khỏi Obtainium nhưng vẫn còn cài đặt trên thiết bị.", + "removeSelectedAppsQuestion": "Xóa ứng dụng đã chọn?", + "removeSelectedApps": "Xóa ứng dụng đã chọn", + "updateX": "Cập nhật {}", + "installX": "Cài đặt {}", + "markXTrackOnlyAsUpdated": "Đánh dấu {}\n(Chỉ-Theo dõi)\nnhư là đã cập nhật", + "changeX": "Thay đổi {}", + "installUpdateApps": "Cài đặt/Cập nhật ứng dụng", + "installUpdateSelectedApps": "Cài đặt/Cập nhật ứng dụng đã chọn", + "markXSelectedAppsAsUpdated": "Đánh dấu {} ứng dụng đã chọn là đã cập nhật?", + "no": "Không", + "yes": "Đúng", + "markSelectedAppsUpdated": "Đánh dấu các ứng dụng đã chọn là đã cập nhật", + "pinToTop": "Ghim đầu trang", + "unpinFromTop": "Bỏ ghim khỏi đầu trang", + "resetInstallStatusForSelectedAppsQuestion": "Đặt lại trạng thái cài đặt cho ứng dụng đã chọn?", + "installStatusOfXWillBeResetExplanation": "Trạng thái cài đặt của mọi Ứng dụng đã chọn sẽ được đặt lại.\n\nĐiều này có thể hữu ích khi phiên bản Ứng dụng hiển thị trong Obtainium không chính xác do cập nhật không thành công hoặc các sự cố khác.", + "shareSelectedAppURLs": "Chia sẻ URL ứng dụng đã chọn", + "resetInstallStatus": "Đặt lại trạng thái cài đặt", + "more": "Nhiều hơn", + "removeOutdatedFilter": "Xóa bộ lọc ứng dụng lỗi thời", + "showOutdatedOnly": "Chỉ hiển thị các ứng dụng lỗi thời", + "filter": "Lọc", + "filterActive": "Lọc *", + "filterApps": "Lọc ứng dụng", + "appName": "Tên ứng dụng", + "author": "Tác giả", + "upToDateApps": "Ứng dụng cập nhật", + "nonInstalledApps": "Ứng dụng chưa được cài đặt", + "importExport": "Nhập/Xuất", + "settings": "Cài đặt", + "exportedTo": "Đã xuất sang {}", + "obtainiumExport": "Xuất Obtainium", + "invalidInput": "Đầu vào không hợp lệ", + "importedX": "Đã nhập {}", + "obtainiumImport": "Nhập Obtainium", + "importFromURLList": "Nhập từ danh sách URL", + "searchQuery": "Truy vấn tìm kiếm", + "appURLList": "Danh sách URL ứng dụng", + "line": "Hàng", + "searchX": "Tìm kiếm {}", + "noResults": "Không có kết quả nào được tìm thấy", + "importX": "Nhập {}", + "importedAppsIdDisclaimer": "Ứng dụng đã nhập có thể hiển thị không chính xác là \"Chưa được cài đặt\".\nĐể khắc phục sự cố này, hãy cài đặt lại chúng thông qua Obtainium.\nĐiều này sẽ không ảnh hưởng đến dữ liệu Ứng dụng.\n\nChỉ ảnh hưởng đến URL và phương thức nhập của bên thứ ba.", + "importErrors": "Lỗi nhập", + "importedXOfYApps": "{} trong số {} Ứng dụng đã được nhập.", + "followingURLsHadErrors": "Các URL sau có lỗi:", + "okay": "Ôkê", + "selectURL": "Chọn URL", + "selectURLs": "Chọn URL", + "pick": "Chọn", + "theme": "Chủ đề", + "dark": "Tối", + "light": "Sáng", + "followSystem": "Theo hệ thống", + "obtainium": "Obtainium", + "materialYou": "Material You", + "useBlackTheme": "Sử dụng chủ đề tối màu đen thuần túy", + "appSortBy": "Sắp xếp ứng dụng theo", + "authorName": "Tác giả/Tên", + "nameAuthor": "Tên/Tác giả", + "asAdded": "Như đã thêm", + "appSortOrder": "Thứ tự sắp xếp ứng dụng", + "ascending": "Tăng dần", + "descending": "Giảm dần", + "bgUpdateCheckInterval": "Khoảng thời gian kiểm tra cập nhật nền", + "neverManualOnly": "Không bao giờ - Chỉ thủ công", + "appearance": "Vẻ ngoài", + "showWebInAppView": "Hiển thị trang web Nguồn trong chế độ xem Ứng dụng", + "pinUpdates": "Ghim nội dung cập nhật lên đầu chế độ xem Ứng dụng", + "updates": "Cập nhật", + "sourceSpecific": "Nguồn cụ thể", + "appSource": "Nguồn ứng dụng", + "noLogs": "Không có nhật ký", + "appLogs": "Nhật ký ứng dụng", + "close": "Đóng", + "share": "Chia sẻ", + "appNotFound": "Không tìm thấy ứng dụng", + "obtainiumExportHyphenatedLowercase": "xuất khẩu-obtainium", + "pickAnAPK": "Chọn một APK", + "appHasMoreThanOnePackage": "{} có nhiều gói:", + "deviceSupportsXArch": "Thiết bị của bạn hỗ trợ kiến trúc CPU {}.", + "deviceSupportsFollowingArchs": "Thiết bị của bạn hỗ trợ các kiến trúc CPU sau:", + "warning": "Cảnh báo", + "sourceIsXButPackageFromYPrompt": "Nguồn ứng dụng là '{}' nhưng gói phát hành đến từ '{}'. Tiếp tục?", + "updatesAvailable": "Cập nhật có sẵn", + "updatesAvailableNotifDescription": "Thông báo cho người dùng rằng có bản cập nhật cho một hoặc nhiều Ứng dụng được theo dõi bởi Obtainium", + "noNewUpdates": "Không có bản cập nhật mới.", + "xHasAnUpdate": "{} có bản cập nhật.", + "appsUpdated": "Ứng dụng đã cập nhật ", + "appsUpdatedNotifDescription": "Thông báo cho người dùng rằng các bản cập nhật cho một hoặc nhiều Ứng dụng đã được áp dụng trong nền", + "xWasUpdatedToY": "{} đã được cập nhật thành {}.", + "errorCheckingUpdates": "Lỗi kiểm tra bản cập nhật", + "errorCheckingUpdatesNotifDescription": "Thông báo hiển thị khi kiểm tra cập nhật nền không thành công", + "appsRemoved": "Ứng dụng đã loại bỏ", + "appsRemovedNotifDescription": "Thông báo cho người dùng rằng một hoặc nhiều Ứng dụng đã bị loại bỏ do lỗi khi tải chúng", + "xWasRemovedDueToErrorY": "{} đã bị loại bỏ do lỗi này: {}", + "completeAppInstallation": "Hoàn tất cài đặt ứng dụng", + "obtainiumMustBeOpenToInstallApps": "Obtainium phải được mở để cài đặt Ứng dụng", + "completeAppInstallationNotifDescription": "Yêu cầu người dùng quay lại Obtainium để hoàn tất cài đặt Ứng dụng", + "checkingForUpdates": "Đang kiểm tra cập nhật", + "checkingForUpdatesNotifDescription": "Thông báo tạm thời xuất hiện khi kiểm tra bản cập nhật", + "pleaseAllowInstallPerm": "Vui lòng cho phép Obtainium cài đặt Ứng dụng", + "trackOnly": "Chỉ-Theo dõi", + "errorWithHttpStatusCode": "Lỗi {}", + "versionCorrectionDisabled": "Tính năng sửa phiên bản bị vô hiệu hóa (plugin dường như không hoạt động)", + "unknown": "Không xác định", + "none": "Không", + "never": "Không bao giờ", + "latestVersionX": "Phiên bản mới nhất: {}", + "installedVersionX": "Phiên bản đã cài đặt: {}", + "lastUpdateCheckX": "Kiểm tra cập nhật lần cuối: {}", + "remove": "Loại bỏ", + "yesMarkUpdated": "Có, Đánh dấu là đã cập nhật", + "fdroid": "Chính thức của F-Droid", + "appIdOrName": "ID hoặc tên ứng dụng", + "appId": "ID ứng dụng", + "appWithIdOrNameNotFound": "Không tìm thấy ứng dụng nào có ID hoặc tên đó", + "reposHaveMultipleApps": "Kho có thể chứa nhiều Ứng dụng", + "fdroidThirdPartyRepo": "Kho lưu trữ bên thứ ba F-Droid", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Chat", + "install": "Cài đặt", + "markInstalled": "Đánh dấu là đã cài đặt", + "update": "Cập nhật", + "markUpdated": "Đánh dấu đã cập nhật", + "additionalOptions": "Tùy chọn bổ sung", + "disableVersionDetection": "Tắt tính năng phát hiện phiên bản", + "noVersionDetectionExplanation": "Chỉ nên sử dụng tùy chọn này cho Ứng dụng mà tính năng phát hiện phiên bản không hoạt động chính xác.", + "downloadingX": "Đang tải xuống {}", + "downloadNotifDescription": "Thông báo cho người dùng về tiến trình tải xuống Ứng dụng", + "noAPKFound": "Không tìm thấy APK", + "noVersionDetection": "Không phát hiện phiên bản", + "categorize": "Phân loại", + "categories": "Thể loại", + "category": "Thể loại", + "noCategory": "Không thể loại", + "noCategories": "Không thể loại", + "deleteCategoriesQuestion": "Xóa thể loại?", + "categoryDeleteWarning": "Tất cả ứng dụng trong thể loại đã xóa sẽ được đặt thành chưa được phân loại.", + "addCategory": "Thêm thể loại", + "label": "Nhãn", + "language": "Ngôn ngữ", + "copiedToClipboard": "Sao chép vào clipboard", + "storagePermissionDenied": "Quyền lưu trữ bị từ chối", + "selectedCategorizeWarning": "Điều này sẽ thay thế mọi cài đặt thể loại hiện có cho Ứng dụng đã chọn.", + "filterAPKsByRegEx": "Lọc APK theo biểu thức chính quy", + "removeFromObtainium": "Loại khỏi Obtainium", + "uninstallFromDevice": "Gỡ cài đặt khỏi thiết bị", + "onlyWorksWithNonVersionDetectApps": "Chỉ hoạt động với Ứng dụng đã tắt tính năng phát hiện phiên bản.", + "releaseDateAsVersion": "Sử dụng ngày phát hành làm phiên bản", + "releaseDateAsVersionExplanation": "Chỉ nên sử dụng tùy chọn này cho Ứng dụng trong đó tính năng phát hiện phiên bản không hoạt động chính xác nhưng đã có ngày phát hành.", + "changes": "Thay đổi", + "releaseDate": "Ngày phát hành", + "importFromURLsInFile": "Nhập từ URL trong Tệp (như OPML)", + "versionDetection": "Phát hiện phiên bản", + "standardVersionDetection": "Phát hiện phiên bản tiêu chuẩn", + "groupByCategory": "Nhóm theo thể loại", + "autoApkFilterByArch": "Cố gắng lọc APK theo kiến trúc CPU nếu có thể", + "overrideSource": "Ghi đè nguồn", + "dontShowAgain": "Đừng hiển thị thông tin này nữa", + "dontShowTrackOnlyWarnings": "Không hiển thị cảnh báo 'Chỉ-Theo dõi'", + "dontShowAPKOriginWarnings": "Không hiển thị cảnh báo nguồn gốc APK", + "moveNonInstalledAppsToBottom": "Di chuyển Ứng dụng chưa được cài đặt xuống cuối chế độ xem Ứng dụng", + "gitlabPATLabel": "Mã thông báo truy cập cá nhân GitLab\n(Cho phép tìm kiếm và khám phá APK tốt hơn)", + "about": "Giới thiệu", + "requiresCredentialsInSettings": "Điều này cần thông tin xác thực bổ sung (trong Cài đặt)", + "checkOnStart": "Kiểm tra các bản cập nhật khi khởi động", + "tryInferAppIdFromCode": "Thử suy ra ID ứng dụng từ mã nguồn", + "removeOnExternalUninstall": "Tự động xóa ứng dụng đã gỡ cài đặt bên ngoài", + "pickHighestVersionCode": "Tự động chọn APK mã phiên bản cao nhất", + "checkUpdateOnDetailPage": "Kiểm tra các bản cập nhật khi mở trang chi tiết Ứng dụng", + "disablePageTransitions": "Tắt hoạt ảnh chuyển trang", + "reversePageTransitions": "Hoạt ảnh chuyển đổi trang đảo ngược", + "minStarCount": "Số lượng sao tối thiểu", + "addInfoBelow": "Thêm thông tin này vào bên dưới.", + "addInfoInSettings": "Thêm thông tin này vào Cài đặt.", + "githubSourceNote": "Có thể tránh được việc giới hạn tốc độ GitHub bằng cách sử dụng khóa API.", + "gitlabSourceNote": "Trích xuất APK GitLab có thể không hoạt động nếu không có khóa API.", + "sortByFileNamesNotLinks": "Sắp xếp theo tên tệp thay vì liên kết đầy đủ", + "filterReleaseNotesByRegEx": "Lọc ghi chú phát hành theo biểu thức chính quy", + "customLinkFilterRegex": "Bộ lọc liên kết APK tùy chỉnh theo biểu thức chính quy (Mặc định '.apk$')", + "appsPossiblyUpdated": "Đã cố gắng cập nhật ứng dụng", + "appsPossiblyUpdatedNotifDescription": "Thông báo cho người dùng rằng các bản cập nhật cho một hoặc nhiều Ứng dụng có khả năng được áp dụng trong nền", + "xWasPossiblyUpdatedToY": "{} có thể đã được cập nhật thành {}.", + "enableBackgroundUpdates": "Bật cập nhật nền", + "backgroundUpdateReqsExplanation": "Có thể không thực hiện được cập nhật nền cho tất cả ứng dụng.", + "backgroundUpdateLimitsExplanation": "Sự thành công của cài đặt nền chỉ có thể được xác định khi mở Obtainium.", + "verifyLatestTag": "Xác minh thẻ 'mới nhất'", + "intermediateLinkRegex": "Lọc tìm liên kết 'Trung gian' để truy cập trước", + "intermediateLinkNotFound": "Không tìm thấy liên kết trung gian", + "exemptFromBackgroundUpdates": "Miễn cập nhật nền (nếu được bật)", + "bgUpdatesOnWiFiOnly": "Tắt cập nhật nền khi không có WiFi", + "autoSelectHighestVersionCode": "Tự động chọn APK mã phiên bản cao nhất", + "versionExtractionRegEx": "Trích xuất phiên bản RegEx", + "matchGroupToUse": "Nhóm đối sánh để sử dụng cho Regex trích xuất phiên bản", + "highlightTouchTargets": "Đánh dấu các mục tiêu cảm ứng ít rõ ràng hơn", + "pickExportDir": "Chọn thư mục xuất", + "autoExportOnChanges": "Tự động xuất khi thay đổi", + "filterVersionsByRegEx": "Lọc phiên bản theo biểu thức chính quy", + "trySelectingSuggestedVersionCode": "Thử chọn APK Mã phiên bản được đề xuất", + "dontSortReleasesList": "Giữ lại thứ tự phát hành từ API", + "reverseSort": "Sắp xếp ngược", + "debugMenu": "Danh sách gỡ lỗi", + "bgTaskStarted": "Tác vụ nền đã bắt đầu - kiểm tra nhật ký.", + "runBgCheckNow": "Chạy kiểm tra cập nhật nền ngay bây giờ", + "versionExtractWholePage": "Áp dụng Regex trích xuất phiên bản cho toàn bộ trang", + "installing": "Đang cài đặt", + "skipUpdateNotifications": "Bỏ qua thông báo cập nhật", + "updatesAvailableNotifChannel": "Cập nhật có sẵn", + "appsUpdatedNotifChannel": "Đã cập nhật ứng dụng", + "appsPossiblyUpdatedNotifChannel": "Đã cố gắng cập nhật ứng dụng", + "errorCheckingUpdatesNotifChannel": "Lỗi kiểm tra bản cập nhật", + "appsRemovedNotifChannel": "Ứng dụng đã bị loại bỏ", + "downloadingXNotifChannel": "Đang tải xuống {}", + "completeAppInstallationNotifChannel": "Hoàn tất cài đặt ứng dụng", + "checkingForUpdatesNotifChannel": "Đang kiểm tra cập nhật", + "onlyCheckInstalledOrTrackOnlyApps": "Chỉ kiểm tra các ứng dụng đã cài đặt và Chỉ-Theo dõi để biết các bản cập nhật", + "removeAppQuestion":{ + "one": "Gỡ ứng dụng?", + "other": "Gỡ ứng dụng?" + }, + "tooManyRequestsTryAgainInMinutes":{ + "one": "Quá nhiều yêu cầu (tốc độ giới hạn) - hãy thử lại sau {} phút", + "other": "Quá nhiều yêu cầu (tốc độ giới hạn) - hãy thử lại sau {} phút" + }, + "bgUpdateGotErrorRetryInMinutes":{ + "one": "Việc kiểm tra bản cập nhật BG gặp phải {}, sẽ lên lịch kiểm tra lại sau {} phút", + "other": "Việc kiểm tra bản cập nhật BG gặp phải {}, sẽ lên lịch kiểm tra lại sau {} phút" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded":{ + "one": "Đang kiểm tra bản cập nhật BG tìm thấy {} bản cập nhật - sẽ thông báo cho người dùng nếu cần", + "other": "Đang kiểm tra bản cập nhật BG tìm thấy {} bản cập nhật - sẽ thông báo cho người dùng nếu cần" + }, + "apps":{ + "one": "{} Ứng dụng", + "other": "{} Ứng dụng" + }, + "url":{ + "one": "{} URL", + "other": "{} URL" + }, + "minute":{ + "one": "{} Phút", + "other": "{} Phút" + }, + "hour":{ + "one": "{} Giờ", + "other": "{} Giờ" + }, + "day":{ + "one": "{} Ngày", + "other": "{} ngày" + }, + "clearedNLogsBeforeXAfterY":{ + "one": "Đã xóa {n} nhật ký (trước = {trước}, sau = {sau})", + "other": "Đã xóa {n} nhật ký (trước = {trước}, sau = {sau})" + }, + "xAndNMoreUpdatesAvailable":{ + "one": "{} và 1 ứng dụng khác có bản cập nhật.", + "other": "{} và {} ứng dụng khác có bản cập nhật." + }, + "xAndNMoreUpdatesInstalled":{ + "one": "{} và 1 ứng dụng khác đã được cập nhật.", + "other": "{} và {} ứng dụng khác đã được cập nhật." + }, + "xAndNMoreUpdatesPossiblyInstalled":{ + "one": "{} và 1 ứng dụng khác có thể đã được cập nhật.", + "other": "{} và {} ứng dụng khác có thể đã được cập nhật." + } +} \ No newline at end of file From 35160ce385daf522d2577fa45aa99c8649a3dba5 Mon Sep 17 00:00:00 2001 From: mamiyaso <124776073+mamiyaso@users.noreply.github.com> Date: Tue, 14 Nov 2023 17:48:59 +0300 Subject: [PATCH 597/600] Create tr.json Added Turkish translation --- assets/translations/tr.json | 330 ++++++++++++++++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 assets/translations/tr.json diff --git a/assets/translations/tr.json b/assets/translations/tr.json new file mode 100644 index 0000000..3071bc9 --- /dev/null +++ b/assets/translations/tr.json @@ -0,0 +1,330 @@ +{ + "invalidURLForSource": "Geçerli bir {} Uygulama URL'si değil", + "noReleaseFound": "Uygun bir sürüm bulunamadı", + "noVersionFound": "Sürüm bulunamadı", + "urlMatchesNoSource": "URL, bilinen bir kaynağa uymuyor", + "cantInstallOlderVersion": "Eski bir sürümü yükleyemem", + "appIdMismatch": "İndirilen paket kimliği mevcut Uygulama kimliği ile eşleşmiyor", + "functionNotImplemented": "Bu sınıf bu işlevi uygulamamıştır", + "placeholder": "Yer Tutucu", + "someErrors": "Bazı Hatalar Oluştu", + "unexpectedError": "Beklenmeyen Hata", + "ok": "Tamam", + "and": "ve", + "githubPATLabel": "GitHub Kişisel Erişim Anahtarı (Sınırlamayı Artırır)", + "includePrereleases": "Ön sürümleri dahil et", + "fallbackToOlderReleases": "Daha eski sürümlere geri dön", + "filterReleaseTitlesByRegEx": "Düzenli İfadelerle Sürüm Başlıklarını Filtrele", + "invalidRegEx": "Geçersiz düzenli ifade", + "noDescription": "Açıklama yok", + "cancel": "İptal", + "continue": "Devam Et", + "requiredInBrackets": "(Gerekli)", + "dropdownNoOptsError": "HATA: DİPLOMADA EN AZ BİR SEÇENEK OLMALI", + "colour": "Renk", + "githubStarredRepos": "GitHub'a Yıldızlı Depolar", + "uname": "Kullanıcı Adı", + "wrongArgNum": "Hatalı argüman sayısı sağlandı", + "xIsTrackOnly": "{} yalnızca Takip Edilen", + "source": "Kaynak", + "app": "Uygulama", + "appsFromSourceAreTrackOnly": "Bu kaynaktan gelen uygulamalar 'Yalnızca Takip Edilen'dir.", + "youPickedTrackOnly": "'Yalnızca Takip Edilen' seçeneğini seçtiniz.", + "trackOnlyAppDescription": "Uygulama güncellemeleri için takip edilecek, ancak Obtainium onu indiremeyecek veya kuramayacaktır.", + "cancelled": "İptal Edildi", + "appAlreadyAdded": "Uygulama zaten eklenmiş", + "alreadyUpToDateQuestion": "Uygulama Zaten Güncel mi?", + "addApp": "Uygulama Ekle", + "appSourceURL": "Uygulama Kaynak URL'si", + "error": "Hata", + "add": "Ekle" + "searchSomeSourcesLabel": "Ara (Bazı Kaynaklar Yalnızca)", + "search": "Ara", + "additionalOptsFor": "{} İçin Ek Seçenekler", + "supportedSources": "Desteklenen Kaynaklar", + "trackOnlyInBrackets": "(Yalnızca Takip)", + "searchableInBrackets": "(Aranabilir)", + "appsString": "Uygulamalar", + "noApps": "Uygulama Yok", + "noAppsForFilter": "Filtre İçin Uygulama Yok", + "byX": "{} Tarafından", + "percentProgress": "İlerleme: {}%", + "pleaseWait": "Lütfen Bekleyin", + "updateAvailable": "Güncelleme Var", + "estimateInBracketsShort": "(Est.)", + "notInstalled": "Yüklenmedi", + "estimateInBrackets": "(Tahmini)", + "selectAll": "Hepsini Seç", + "deselectN": "{}'yi Seçimden Kaldır", + "xWillBeRemovedButRemainInstalled": "{} Obtainium'dan kaldırılacak ancak cihazınızda yüklü kalacaktır.", + "removeSelectedAppsQuestion": "Seçilen Uygulamaları Kaldırmak İstiyor musunuz?", + "removeSelectedApps": "Seçilen Uygulamaları Kaldır", + "updateX": "{}'yi Güncelle", + "installX": "{}'yi Yükle", + "markXTrackOnlyAsUpdated": "{}(Takip Edilen) olarak Güncellendi olarak İşaretle", + "changeX": "{}'yi Değiştir", + "installUpdateApps": "Uygulamaları Yükle/Güncelle", + "installUpdateSelectedApps": "Seçilen Uygulamaları Yükle/Güncelle", + "markXSelectedAppsAsUpdated": "Seçilen Uygulamaları {} olarak Güncellendi olarak İşaretle?", + "no": "Hayır", + "yes": "Evet", + "markSelectedAppsUpdated": "Seçilen Uygulamaları Güncellendi olarak İşaretle", + "pinToTop": "Üstte Tut", + "unpinFromTop": "Üstten Kaldır", + "resetInstallStatusForSelectedAppsQuestion": "Seçilen Uygulamaların Yükleme Durumunu Sıfırlamak İstiyor musunuz?", + "installStatusOfXWillBeResetExplanation": "Seçilen Uygulamaların yükleme durumu sıfırlanacak.\n\nBu, Obtainium'da gösterilen uygulama sürümünün başarısız güncellemeler veya diğer sorunlar nedeniyle yanlış olması durumunda yardımcı olabilir.", + "shareSelectedAppURLs": "Seçilen Uygulama URL'larını Paylaş", + "resetInstallStatus": "Yükleme Durumunu Sıfırla", + "more": "Daha Fazla", + "removeOutdatedFilter": "Güncel Olmayan Uygulama Filtresini Kaldır", + "showOutdatedOnly": "Yalnızca Güncel Olmayan Uygulamaları Göster", + "filter": "Filtre", + "filterActive": "Filtre *", + "filterApps": "Uygulamaları Filtrele", + "appName": "Uygulama Adı", + "author": "Yazar", + "upToDateApps": "Güncel Uygulamalar", + "nonInstalledApps": "Yüklenmemiş Uygulamalar", + "importExport": "İçe/Dışa Aktar", + "settings": "Ayarlar", + "exportedTo": "{}'e Dışa Aktarıldı", + "obtainiumExport": "Obtainium Dışa Aktar", + "invalidInput": "Geçersiz Giriş", + "importedX": "{} İçe Aktarıldı", + "obtainiumImport": "Obtainium İçe Aktar", + "importFromURLList": "URL Listesinden İçe Aktar (Örneğin OPML)", + "searchQuery": "Arama Sorgusu", + "appURLList": "Uygulama URL Listesi", + "line": "Satır", + "searchX": "{}'yi Ara", + "noResults": "Sonuç Bulunamadı", + "importX": "{} İçe Aktar", + "importedAppsIdDisclaimer": "İçe Aktarılan Uygulamalar yanlışlıkla \"Yüklenmedi\" olarak gösterilebilir.\nBunu düzeltmek için bunları Obtainium üzerinden yeniden yükleyin.\nBu, yalnızca URL ve üçüncü taraf içe aktarma yöntemlerini etkiler.\n\nYalnızca URL ve üçüncü taraf içe aktarma yöntemlerini etkiler.", + "importErrors": "İçe Aktarma Hataları", + "importedXOfYApps": "{}'den {} Uygulama İçe Aktarıldı.", + "followingURLsHadErrors": "Aşağıdaki URL'lerde hatalar oluştu:", + "okay": "Tamam", + "selectURL": "URL Seç", + "selectURLs": "URL'leri Seç", + "pick": "Seç", + "theme": "Tema", + "dark": "Koyu", + "light": "Aydınlık", + "followSystem": "Sistemi Takip Et", + "obtainium": "Obtainium", + "materialYou": "Material You", + "useBlackTheme": "Saf siyah koyu temasını kullan", + "appSortBy": "Uygulama Sıralama Ölçütü", + "authorName": "Yazar/Ad", + "nameAuthor": "Ad/Yazar", + "asAdded": "Eklendiği Gibi", + "appSortOrder": "Uygulama Sıralama Sırası", + "ascending": "Artan", + "descending": "Azalan", + "bgUpdateCheckInterval": "Arka Planda Güncelleme Kontrol Aralığı", + "neverManualOnly": "Asla - Yalnızca El ile", + "appearance": "Görünüm", + "showWebInAppView": "Kaynağı Uygulama Görünümünde Göster", + "pinUpdates": "Güncellemeleri Uygulamalar Görünümünün Üstüne Sabitle", + "updates": "Güncellemeler", + "sourceSpecific": "Kaynak Özel", + "appSource": "Uygulama Kaynağı", + "noLogs": "Günlük Yok", + "appLogs": "Uygulama Günlükleri", + "close": "Kapat", + "share": "Paylaş", + "appNotFound": "Uygulama Bulunamadı", + "obtainiumExportHyphenatedLowercase": "obtainium-ihracat", + "pickAnAPK": "APK Seç", + "appHasMoreThanOnePackage": "{}'nin birden fazla paketi var:", + "deviceSupportsXArch": "Cihazınız {} CPU mimarisini destekliyor.", + "deviceSupportsFollowingArchs": "Cihazınız aşağıdaki CPU mimarilerini destekliyor:", + "warning": "Uyarı", + "sourceIsXButPackageFromYPrompt": "Uygulama kaynağı '{}', ancak dağıtım paketi '{}'. Devam etmek istiyor musunuz?", + "updatesAvailable": "Güncellemeler Var", + "updatesAvailableNotifDescription": "Kullanıcıya Obtainium tarafından takip edilen bir veya daha fazla uygulama için güncelleme bulunduğuna dair bilgi verir", + "noNewUpdates": "Yeni güncelleme yok.", + "xHasAnUpdate": "{} güncelleme alıyor.", + "appsUpdated": "Uygulamalar Güncellendi", + "appsUpdatedNotifDescription": "Kullanıcıya bir veya daha fazla uygulamanın arka planda güncellendiğine dair bilgi verir", + "xWasUpdatedToY": "{} şu sürüme güncellendi: {}.", + "errorCheckingUpdates": "Güncellemeler Kontrol Edilirken Hata Oluştu", + "errorCheckingUpdatesNotifDescription": "Arka planda güncelleme kontrolü sırasında hata oluştuğunda görünen bir bildirim", + "appsRemoved": "Uygulamalar Kaldırıldı", + "appsRemovedNotifDescription": "Bir veya daha fazla uygulamanın yüklenirken hata nedeniyle kaldırıldığını bildiren bir bildirim", + "xWasRemovedDueToErrorY": "{} şu hatadan dolayı kaldırıldı: {}", + "completeAppInstallation": "Uygulama Yüklemeyi Tamamla", + "obtainiumMustBeOpenToInstallApps": "Uygulamaları yüklemek için Obtainium'un açık olması gerekiyor", + "completeAppInstallationNotifDescription": "Kullanıcıdan Obtainium'a geri dönüp bir uygulama yüklemeyi tamamlamasını isteyen bir bildirim", + "checkingForUpdates": "Güncellemeler Kontrol Ediliyor", + "checkingForUpdatesNotifDescription": "Güncellemeler kontrol edildiğinde görünen geçici bir bildirim", + "pleaseAllowInstallPerm": "Lütfen Obtainium'un uygulama yüklemesine izin verin", + "trackOnly": "Sadece Takip Et", + "errorWithHttpStatusCode": "Hata {}", + "versionCorrectionDisabled": "Sürüm düzeltme devre dışı bırakıldı (eklenti çalışmıyor gibi görünüyor)", + "unknown": "Bilinmiyor", + "none": "Hiçbiri", + "never": "Asla", + "latestVersionX": "En Son Sürüm: {}", + "installedVersionX": "Yüklenen Sürüm: {}", + "lastUpdateCheckX": "Son Güncelleme Kontrolü: {}", + "remove": "Kaldır", + "yesMarkUpdated": "Evet, Güncellendi olarak İşaretle", + "fdroid": "F-Droid Resmi", + "appIdOrName": "Uygulama Kimliği veya Adı", + "appId": "Uygulama Kimliği", + "appWithIdOrNameNotFound": "Bu kimlik veya ada sahip bir uygulama bulunamadı", + "reposHaveMultipleApps": "Depolar birden fazla uygulama içerebilir", + "fdroidThirdPartyRepo": "F-Droid Üçüncü Taraf Depo", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Sohbet", + "install": "Yükle", + "markInstalled": "Yüklendi olarak İşaretle", + "update": "Güncelle", + "markUpdated": "Güncellendi olarak İşaretle", + "additionalOptions": "Ek Seçenekler", + "disableVersionDetection": "Sürüm Algılama Devre Dışı", + "noVersionDetectionExplanation": "Bu seçenek, sürüm algılamanın doğru çalışmadığı uygulamalar için kullanılmalıdır.", + "downloadingX": "{} İndiriliyor", + "downloadNotifDescription": "Bir uygulamanın indirme sürecinde ilerlemeyi bildiren bir bildirim", + "noAPKFound": "APK bulunamadı", + "noVersionDetection": "Sürüm Algılanamıyor", + "categorize": "Kategorize Et", + "categories": "Kategoriler", + "category": "Kategori", + "noCategory": "Kategori Yok", + "noCategories": "Kategoriler Yok", + "deleteCategoriesQuestion": "Kategorileri Silmek İstiyor musunuz?", + "categoryDeleteWarning": "Silinen kategorilerdeki tüm uygulamalar kategorisiz olarak ayarlanacaktır.", + "addCategory": "Kategori Ekle", + "label": "Etiket", + "language": "Dil", + "copiedToClipboard": "Panoya Kopyalandı", + "storagePermissionDenied": "Depolama izni reddedildi", + "selectedCategorizeWarning": "Bu, seçilen uygulamalar için mevcut kategori ayarlarını değiştirecektir.", + "filterAPKsByRegEx": "APK'leri Düzenli İfade ile Filtrele", + "removeFromObtainium": "Obtainium'dan Kaldır", + "uninstallFromDevice": "Cihazdan Kaldır", + "onlyWorksWithNonVersionDetectApps": "Yalnızca Sürüm Algılaması Devre Dışı Uygulamalar İçin Çalışır.", + "releaseDateAsVersion": "Sürüm Olarak Yayın Tarihi Kullan", + "releaseDateAsVersionExplanation": "Bu seçenek, sürüm algılamanın doğru çalışmadığı ancak bir sürüm tarihinin mevcut olduğu uygulamalar için kullanılmalıdır.", + "changes": "Değişiklikler", + "releaseDate": "Yayın Tarihi", + "importFromURLsInFile": "Dosyadaki URL'lerden İçe Aktar", + "versionDetection": "Sürüm Tespiti", + "standardVersionDetection": "Standart sürüm tespiti", + "groupByCategory": "Kategoriye Göre Grupla", + "autoApkFilterByArch": "Mümkünse APK'leri CPU mimarisi ile filtreleme girişimi", + "overrideSource": "Kaynağı Geçersiz Kıl", + "dontShowAgain": "Bunu tekrar gösterme", + "dontShowTrackOnlyWarnings": "'Yalnızca Takip Edilen' uyarılarını gösterme", + "dontShowAPKOriginWarnings": "APK kaynağı uyarılarını gösterme", + "moveNonInstalledAppsToBottom": "Yüklenmemiş Uygulamaları Uygulamalar Görünümünün Altına Taşı", + "gitlabPATLabel": "GitLab Kişisel Erişim Belirteci\n(Arama ve Daha İyi APK Keşfi İçin)", + "about": "Hakkında", + "requiresCredentialsInSettings": "Bu, ek kimlik bilgilerine ihtiyaç duyar (Ayarlar'da)", + "checkOnStart": "Başlangıçta güncellemeleri kontrol et", + "tryInferAppIdFromCode": "Uygulama kimliğini kaynak kodundan çıkarma girişimi", + "removeOnExternalUninstall": "Harici kaldırmada otomatik olarak kaldırılan uygulamalar" + "pickHighestVersionCode": "Otomatik olarak en yüksek sürüm kodlu APK'yi seç", + "checkUpdateOnDetailPage": "Uygulama detay sayfasını açarken güncellemeleri kontrol et", + "disablePageTransitions": "Sayfa geçiş animasyonlarını devre dışı bırak", + "reversePageTransitions": "Sayfa geçiş animasyonlarını tersine çevir", + "minStarCount": "Minimum Yıldız Sayısı", + "addInfoBelow": "Bu bilgiyi aşağıya ekle.", + "addInfoInSettings": "Bu bilgiyi Ayarlar'da ekleyin.", + "githubSourceNote": "GitHub hız sınırlaması bir API anahtarı kullanılarak atlanabilir.", + "gitlabSourceNote": "GitLab APK çıkarma işlemi bir API anahtarı olmadan çalışmayabilir.", + "sortByFileNamesNotLinks": "Bağlantılar yerine dosya adlarına göre sırala", + "filterReleaseNotesByRegEx": "Sürüm Notlarını Düzenli İfade ile Filtrele", + "customLinkFilterRegex": "Özel APK Bağlantı Filtresi Düzenli İfade ile (Varsayılan '.apk$')", + "appsPossiblyUpdated": "Uygulama Güncellemeleri Denendi", + "appsPossiblyUpdatedNotifDescription": "Kullanıcıya bir veya daha fazla uygulamanın arka planda potansiyel olarak güncellendiğini bildiren bildirim", + "xWasPossiblyUpdatedToY": "{} muhtemelen {} sürümüne güncellendi." + "enableBackgroundUpdates": "Arka plan güncellemelerini etkinleştir", + "backgroundUpdateReqsExplanation": "Arka plan güncellemeleri tüm uygulamalar için mümkün olmayabilir.", + "backgroundUpdateLimitsExplanation": "Arka plan kurulumunun başarısı, Obtainium'un açıldığında ancak belirlenebilir.", + "verifyLatestTag": "'latest' etiketini doğrula", + "intermediateLinkRegex": "İlk Ziyaret Edilecek 'Ara' Bağlantısını Filtrele", + "intermediateLinkNotFound": "Ara bağlantı bulunamadı", + "exemptFromBackgroundUpdates": "Arka plan güncellemelerinden muaf tut (etkinse)", + "bgUpdatesOnWiFiOnly": "WiFi olmadığında arka plan güncellemelerini devre dışı bırak", + "autoSelectHighestVersionCode": "Otomatik olarak en yüksek sürüm kodunu seç", + "versionExtractionRegEx": "Sürüm Çıkarma Düzenli İfade", + "matchGroupToUse": "Sürüm Çıkarma Regex için Kullanılacak Eşleşme Grubu", + "highlightTouchTargets": "Daha az belirgin dokunma hedeflerini vurgula", + "pickExportDir": "Dışa Aktarılacak Klasörü Seç", + "autoExportOnChanges": "Değişikliklerde otomatik olarak dışa aktar", + "filterVersionsByRegEx": "Sürümleri Düzenli İfade ile Filtrele", + "trySelectingSuggestedVersionCode": "Önerilen sürüm kodunu seçmeyi dene", + "dontSortReleasesList": "API'den sıralama düzenini koru" + "reverseSort": "Ters sıralama", + "debugMenu": "Hata Ayıklama Menüsü", + "bgTaskStarted": "Arka plan görevi başladı - günlükleri kontrol et.", + "runBgCheckNow": "Arka Plan Güncelleme Kontrolünü Şimdi Çalıştır", + "versionExtractWholePage": "Tüm Sayfaya Sürüm Çıkarma Regex'i Uygula", + "installing": "Yükleniyor", + "skipUpdateNotifications": "Güncelleme bildirimlerini atla", + "updatesAvailableNotifChannel": "Güncellemeler Mevcut", + "appsUpdatedNotifChannel": "Güncellenen Uygulamalar", + "appsPossiblyUpdatedNotifChannel": "Uygulama Güncellemeleri Denendi", + "errorCheckingUpdatesNotifChannel": "Güncellemeler Kontrol Edilirken Hata", + "appsRemovedNotifChannel": "Kaldırılan Uygulamalar", + "downloadingXNotifChannel": "{} İndiriliyor", + "completeAppInstallationNotifChannel": "Uygulama Kurulumu Tamamlandı", + "checkingForUpdatesNotifChannel": "Güncellemeler Kontrol Ediliyor", + "onlyCheckInstalledOrTrackOnlyApps": "Yalnızca yüklü ve Yalnızca İzleme Uygulamalarını güncelleme" +"removeAppQuestion": { + "one": "Uygulamayı Kaldır?", + "other": "Uygulamaları Kaldır?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Çok fazla istek (hız sınırlı) - {} dakika sonra tekrar deneyin", + "other": "Çok fazla istek (hız sınırlı) - {} dakika sonra tekrar deneyin" + }, + "bgUpdateGotErrorRetryInMinutes": { + "one": "Arka plan güncelleme kontrolü bir hatayla karşılaştı, {} dakika sonra tekrar kontrol edilecek", + "other": "Arka plan güncelleme kontrolü bir hatayla karşılaştı, {} dakika sonra tekrar kontrol edilecek" + }, + "bgCheckFoundUpdatesWillNotifyIfNeeded": { + "one": "Arka plan güncelleme kontrolü {} güncelleme buldu - gerektiğinde kullanıcıyı bilgilendirecek", + "other": "Arka plan güncelleme kontrolü {} güncelleme buldu - gerektiğinde kullanıcıyı bilgilendirecek" + } + "apps": { + "one": "{} Uygulama", + "other": "{} Uygulamalar" + }, + "url": { + "one": "{} URL", + "other": "{} URL'ler" + }, + "minute": { + "one": "{} Dakika", + "other": "{} Dakika" + }, + "hour": { + "one": "{} Saat", + "other": "{} Saat" + }, + "day": { + "one": "{} Gün", + "other": "{} Gün" + }, + "clearedNLogsBeforeXAfterY": { + "one": "{n} log temizlendi (önce = {before}, sonra = {after})", + "other": "{n} log temizlendi (önce = {before}, sonra = {after})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "{} ve 1 diğer uygulama güncellemeye sahip.", + "other": "{} ve {} daha fazla uygulama güncellemeye sahip." + }, + "xAndNMoreUpdatesInstalled": { + "one": "{} ve 1 diğer uygulama güncellendi.", + "other": "{} ve {} daha fazla uygulama güncellendi." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "{} ve 1 diğer uygulama muhtemelen güncellendi.", + "other": "{} ve {} daha fazla uygulama muhtemelen güncellendi." + } +} From ff3c37f1b40ad47ca27d5a7ad7a021528c2a38ef Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Fri, 17 Nov 2023 14:34:30 +0900 Subject: [PATCH 598/600] Update ja.json --- assets/translations/ja.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 385de2d..ec33cfd 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -258,14 +258,14 @@ "autoExportOnChanges": "変更があった際に自動でエクスポートする", "filterVersionsByRegEx": "正規表現でバージョンをフィルタリングする", "trySelectingSuggestedVersionCode": "提案されたバージョンコードのAPKを選択する", - "dontSortReleasesList": "Retain release order from API", - "reverseSort": "Reverse sorting", - "debugMenu": "Debug Menu", - "bgTaskStarted": "Background task started - check logs.", - "runBgCheckNow": "Run Background Update Check Now", - "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", - "installing": "Installing", - "skipUpdateNotifications": "Skip update notifications", + "dontSortReleasesList": "APIからのリリース順を保持する", + "reverseSort": "逆順ソート", + "debugMenu": "デバッグメニュー", + "bgTaskStarted": "バックグラウンドタスクが開始されました - ログを確認してください。", + "runBgCheckNow": "今すぐバックグラウンドでのアップデート確認を開始する", + "versionExtractWholePage": "バージョン抽出の正規表現をページ全体に適用する", + "installing": "インストール中", + "skipUpdateNotifications": "アップデート通知をスキップする", "updatesAvailableNotifChannel": "アップデートが利用可能", "appsUpdatedNotifChannel": "アプリをアップデートしました", "appsPossiblyUpdatedNotifChannel": "アプリのアップデートを試行", @@ -274,7 +274,7 @@ "downloadingXNotifChannel": "{} をダウンロード中", "completeAppInstallationNotifChannel": "アプリのインストールを完了する", "checkingForUpdatesNotifChannel": "アップデートを確認中", - "onlyCheckInstalledOrTrackOnlyApps": "Only check installed and Track-Only apps for updates", + "onlyCheckInstalledOrTrackOnlyApps": "インストール済みのアプリと「追跡のみ」のアプリのアップデートのみを確認する", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" From 3d162f33df9371ab91f4333033669465b4ade8af Mon Sep 17 00:00:00 2001 From: bluefly000 <101441707+bluefly000@users.noreply.github.com> Date: Fri, 17 Nov 2023 20:35:33 +0900 Subject: [PATCH 599/600] Update ja.json --- assets/translations/ja.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/translations/ja.json b/assets/translations/ja.json index ec33cfd..e176194 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -265,7 +265,7 @@ "runBgCheckNow": "今すぐバックグラウンドでのアップデート確認を開始する", "versionExtractWholePage": "バージョン抽出の正規表現をページ全体に適用する", "installing": "インストール中", - "skipUpdateNotifications": "アップデート通知をスキップする", + "skipUpdateNotifications": "アップデート通知を行わない", "updatesAvailableNotifChannel": "アップデートが利用可能", "appsUpdatedNotifChannel": "アプリをアップデートしました", "appsPossiblyUpdatedNotifChannel": "アプリのアップデートを試行", From bd8aae5fbf5b046e6139b5c79213ae13fa2ae317 Mon Sep 17 00:00:00 2001 From: ngocanhtve <125894401+ngocanhtve@users.noreply.github.com> Date: Sat, 18 Nov 2023 13:57:28 +0700 Subject: [PATCH 600/600] Rename vn.json to vi.json Correct the country code. --- assets/translations/{vn.json => vi.json} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename assets/translations/{vn.json => vi.json} (99%) diff --git a/assets/translations/vn.json b/assets/translations/vi.json similarity index 99% rename from assets/translations/vn.json rename to assets/translations/vi.json index 886879d..4b66a9e 100644 --- a/assets/translations/vn.json +++ b/assets/translations/vi.json @@ -327,4 +327,4 @@ "one": "{} và 1 ứng dụng khác có thể đã được cập nhật.", "other": "{} và {} ứng dụng khác có thể đã được cập nhật." } -} \ No newline at end of file +}

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 diff --git a/assets/screenshots/3.material_you.png b/assets/screenshots/3.material_you.png index aee7e759f0bccf8923794c276f4d7edd1987c237..04b0ae16954a5d1b9957ad72d31a42e0a8f913e2 100644 GIT binary patch literal 143732 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