From cbcc8c4eafd346582ccd090495250271122b43f0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 1 Oct 2024 15:49:00 -0400 Subject: [PATCH 1/5] Added "skip latest" option to APKPure (also fallback toggle) --- assets/translations/bs.json | 1 + assets/translations/cs.json | 1 + assets/translations/da.json | 1 + assets/translations/de.json | 1 + assets/translations/en-EO.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/id.json | 5 +- assets/translations/it.json | 1 + assets/translations/ja.json | 1 + assets/translations/nl.json | 1 + assets/translations/pl.json | 1 + assets/translations/pt.json | 1 + assets/translations/ru.json | 1 + assets/translations/sv.json | 1 + assets/translations/tr.json | 1 + assets/translations/uk.json | 1 + assets/translations/vi.json | 1 + assets/translations/zh-Hant-TW.json | 1 + assets/translations/zh.json | 1 + lib/app_sources/apkpure.dart | 193 ++++++++++++++++------------ 24 files changed, 137 insertions(+), 83 deletions(-) diff --git a/assets/translations/bs.json b/assets/translations/bs.json index b08151c..88eee65 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -315,6 +315,7 @@ "wiki": "Pomoć/Wiki", "crowdsourcedConfigsLabel": "Konfiguracije aplikacije obezbeđene pomoću velikog broja ljudi (crowdsourcing) (koristite na svoju odgovornost)", "allowInsecure": "Allow insecure HTTP requests", + "stayOneVersionBehind": "Stay one version behind latest", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index 11552ce..fab05fb 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -315,6 +315,7 @@ "wiki": "Nápověda/Wiki", "crowdsourcedConfigsLabel": "Konfigurace aplikací s využitím crowdsourcingu (použití na vlastní nebezpečí)", "allowInsecure": "Povolení nezabezpečených požadavků HTTP", + "stayOneVersionBehind": "Zůstaňte o jednu verzi pozadu za nejnovější", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/da.json b/assets/translations/da.json index 7bc0450..8a44d59 100644 --- a/assets/translations/da.json +++ b/assets/translations/da.json @@ -315,6 +315,7 @@ "wiki": "Hjælp/Wiki", "crowdsourcedConfigsLabel": "Crowdsourcede app-konfigurationer (brug på egen risiko)", "allowInsecure": "Tillad usikre HTTP-anmodninger", + "stayOneVersionBehind": "Vær en version bagud i forhold til den nyeste", "removeAppQuestion": { "one": "Fjern app?", "other": "Fjern apps?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 425b22d..089d3e1 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -315,6 +315,7 @@ "wiki": "Hilfe/Wiki", "crowdsourcedConfigsLabel": "Crowdsourced App-Konfigurationen (Verwendung auf eigene Gefahr)", "allowInsecure": "Unsichere HTTP-Anfragen zulassen", + "stayOneVersionBehind": "Eine Version hinter der neuesten Version bleiben", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en-EO.json b/assets/translations/en-EO.json index 4d14b33..77efc72 100644 --- a/assets/translations/en-EO.json +++ b/assets/translations/en-EO.json @@ -315,6 +315,7 @@ "wiki": "Helpo/Vikio", "crowdsourcedConfigsLabel": "Komunumaj apo-agordoj (uzu kun singardo)", "allowInsecure": "Allow insecure HTTP requests", + "stayOneVersionBehind": "Stay one version behind latest", "removeAppQuestion": { "one": "Forigi la aplikaĵon?", "other": "Forigi la aplikaĵojn?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 661a035..d82f059 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -315,6 +315,7 @@ "wiki": "Help/Wiki", "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)", "allowInsecure": "Allow insecure HTTP requests", + "stayOneVersionBehind": "Stay one version behind latest", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 1899fc2..88751a4 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -315,6 +315,7 @@ "wiki": "Ayuda/Wiki", "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (uso bajo su propia responsabilidad)", "allowInsecure": "Permitir peticiones HTTP inseguras", + "stayOneVersionBehind": "Mantenerse una versión por detrás de la última", "removeAppQuestion": { "one": "¿Eliminar aplicación?", "other": "¿Eliminar aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 7df4dfb..1cde7a0 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -315,6 +315,7 @@ "wiki": "راهنما/ویکی", "crowdsourcedConfigsLabel": "تنظیمات برنامه Crowdsourced (با مسئولیت خود استفاده کنید)", "allowInsecure": "درخواست های HTTP ناامن را مجاز کنید", + "stayOneVersionBehind": "Stay one version behind latest", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 8b4dab6..acfa6dd 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -315,6 +315,7 @@ "wiki": "Aide/Wiki", "crowdsourcedConfigsLabel": "Configurations d'applications par la communauté (à utiliser à vos risques et périls)", "allowInsecure": "Autoriser les requêtes HTTP non sécurisées", + "stayOneVersionBehind": "Rester à une version de la dernière", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 0e5a9b7..b2521ba 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -315,6 +315,7 @@ "wiki": "Súgó/Wiki", "crowdsourcedConfigsLabel": "Crowdsource-ből származó alkalmazások beállítása (saját felelősségére használja)", "allowInsecure": "Nem biztonságos HTTP-kérések engedélyezése", + "stayOneVersionBehind": "Maradjon egy verzióval a legfrissebb mögött", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazásokat?" diff --git a/assets/translations/id.json b/assets/translations/id.json index 1c842de..1c8e4c9 100644 --- a/assets/translations/id.json +++ b/assets/translations/id.json @@ -204,7 +204,7 @@ "categoryDeleteWarning": "Semua aplikasi dalam kategori yang dihapus akan diatur sebagai tidak terkategori.", "addCategory": "Tambah kategori", "label": "Label", - "language": "Language", + "language": "Bahasa", "copiedToClipboard": "Disalin ke papan klip", "storagePermissionDenied": "Izin penyimpanan ditolak", "selectedCategorizeWarning": "Ini akan mengganti pengaturan kategori yang ada untuk aplikasi terpilih.", @@ -315,6 +315,7 @@ "wiki": "Bantuan/Wiki", "crowdsourcedConfigsLabel": "Konfigurasi aplikasi Crowdsourced (risiko penggunaan ditanggung sendiri)", "allowInsecure": "Izinkan permintaan HTTP yang tidak aman", + "stayOneVersionBehind": "Tetap satu versi di belakang versi terbaru", "removeAppQuestion": { "one": "Hapus aplikasi?", "other": "Hapus aplikasi?" @@ -375,4 +376,4 @@ "one": "{} APK", "other": "{} APK" } -} \ No newline at end of file +} diff --git a/assets/translations/it.json b/assets/translations/it.json index 3d930d3..7801941 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -315,6 +315,7 @@ "wiki": "Aiuto/Wiki", "crowdsourcedConfigsLabel": "Configurazioni di app in crowdsourcing (uso a proprio rischio)", "allowInsecure": "Consentire le richieste HTTP non sicure", + "stayOneVersionBehind": "Rimanere una versione indietro rispetto alla più recente", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 1c58b3a..13134d0 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -315,6 +315,7 @@ "wiki": "ヘルプ/ウィキ", "crowdsourcedConfigsLabel": "クラウドソーシングによるアプリの設定(利用は自己責任で)", "allowInsecure": "安全でないHTTPリクエストを許可する", + "stayOneVersionBehind": "最新バージョンから1つ遅れ", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/nl.json b/assets/translations/nl.json index 543f953..5c45ed6 100644 --- a/assets/translations/nl.json +++ b/assets/translations/nl.json @@ -315,6 +315,7 @@ "wiki": "Help/Wiki", "crowdsourcedConfigsLabel": "Crowdsourced App-configuraties (gebruik op eigen risico)", "allowInsecure": "Onveilige HTTP-verzoeken toestaan", + "stayOneVersionBehind": "Blijf een versie achter op de nieuwste", "removeAppQuestion": { "one": "App verwijderen?", "other": "Apps verwijderen?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 3e64f8d..b26f11f 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -315,6 +315,7 @@ "wiki": "Pomoc/Wiki", "crowdsourcedConfigsLabel": "Konfiguracje aplikacji pochodzące z crowdsourcingu (korzystanie na własne ryzyko)", "allowInsecure": "Zezwalaj na niezabezpieczone żądania HTTP", + "stayOneVersionBehind": "Pozostań jedną wersję za najnowszą", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index 0012515..e223226 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -315,6 +315,7 @@ "wiki": "Ajuda/Wiki", "crowdsourcedConfigsLabel": "Configurações de aplicações de crowdsourcing (utilização por sua conta e risco)", "allowInsecure": "Permitir pedidos HTTP inseguros", + "stayOneVersionBehind": "Manter-se uma versão atrás da mais recente", "removeAppQuestion": { "one": "Remover aplicativo?", "other": "Remover aplicativos?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 5bd4b93..631ecb5 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -315,6 +315,7 @@ "wiki": "Помощь/Вики", "crowdsourcedConfigsLabel": "Конфигурации приложений на основе краудсорсинга (используйте на свой страх и риск)", "allowInsecure": "Разрешить небезопасные HTTP-запросы", + "stayOneVersionBehind": "Не отставайте от последней версии", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/sv.json b/assets/translations/sv.json index 490cbc3..807348c 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -315,6 +315,7 @@ "wiki": "Hjälp/Wiki", "crowdsourcedConfigsLabel": "Crowdsourcade appkonfigurationer (använd på egen risk)", "allowInsecure": "Tillåt osäkra HTTP-förfrågningar", + "stayOneVersionBehind": "Håll dig en version bakom den senaste", "removeAppQuestion": { "one": "Ta Bort App?", "other": "Ta Bort Appar?" diff --git a/assets/translations/tr.json b/assets/translations/tr.json index 745d59f..3c58a21 100644 --- a/assets/translations/tr.json +++ b/assets/translations/tr.json @@ -315,6 +315,7 @@ "wiki": "Yardım/Wiki", "crowdsourcedConfigsLabel": "Kitle Kaynaklı Uygulama Yapılandırmaları (riski size ait olmak üzere kullanın)", "allowInsecure": "Güvensiz HTTP isteklerine izin ver", + "stayOneVersionBehind": "En son sürümün bir sürüm gerisinde kalın", "removeAppQuestion": { "one": "Uygulamayı Kaldır?", "other": "Uygulamaları Kaldır?" diff --git a/assets/translations/uk.json b/assets/translations/uk.json index 9754ebe..d335700 100644 --- a/assets/translations/uk.json +++ b/assets/translations/uk.json @@ -315,6 +315,7 @@ "wiki": "Довідка/Вікі", "crowdsourcedConfigsLabel": "Краудсорсингові конфігурації додатків (використовуйте на свій страх і ризик)", "allowInsecure": "Дозволити незахищені HTTP-запити", + "stayOneVersionBehind": "Залишайтеся на одну версію актуальнішою", "removeAppQuestion": { "one": "Видалити застосунок?", "other": "Видалити застосунки?" diff --git a/assets/translations/vi.json b/assets/translations/vi.json index 1f09f12..22a88b2 100644 --- a/assets/translations/vi.json +++ b/assets/translations/vi.json @@ -315,6 +315,7 @@ "wiki": "Trợ giúp/Wiki", "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)", "allowInsecure": "Allow insecure HTTP requests", + "stayOneVersionBehind": "Stay one version behind latest", "removeAppQuestion": { "one": "Gỡ ứng dụng?", "other": "Gỡ ứng dụng?" diff --git a/assets/translations/zh-Hant-TW.json b/assets/translations/zh-Hant-TW.json index 7f38e49..1f411bc 100644 --- a/assets/translations/zh-Hant-TW.json +++ b/assets/translations/zh-Hant-TW.json @@ -315,6 +315,7 @@ "wiki": "幫助/維基", "crowdsourcedConfigsLabel": "群眾外包的應用程式設定(使用風險自負)", "allowInsecure": "Allow insecure HTTP requests", + "stayOneVersionBehind": "Stay one version behind latest", "removeAppQuestion": { "one": "移除應用程式?", "other": "移除應用程式?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index ea41bf7..9b50e6d 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -315,6 +315,7 @@ "wiki": "帮助/Wiki", "crowdsourcedConfigsLabel": "众包应用程序配置(使用风险自负)", "allowInsecure": "允许不安全的 HTTP 请求", + "stayOneVersionBehind": "比最新版本晚一个版本", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index 89c2523..7d181ab 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -2,6 +2,7 @@ import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:html/parser.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/source_provider.dart'; @@ -26,6 +27,16 @@ class APKPure extends AppSource { allowSubDomains = true; naiveStandardVersionDetection = true; showReleaseDateAsVersionToggle = true; + additionalSourceAppSpecificSettingFormItems = [ + [ + GeneratedFormSwitch('fallbackToOlderReleases', + label: tr('fallbackToOlderReleases'), defaultValue: true) + ], + [ + GeneratedFormSwitch('stayOneVersionBehind', + label: tr('stayOneVersionBehind'), defaultValue: false) + ] + ]; } @override @@ -54,6 +65,97 @@ class APKPure extends AppSource { return Uri.parse(standardUrl).pathSegments.last; } + getDetailsForVersionLink( + String standardUrl, + String appId, + String host, + List supportedArchs, + String link, + Map additionalSettings) async { + var res = await sourceRequest(link, additionalSettings); + if (res.statusCode == 200) { + var html = parse(res.body); + var apksDiv = + html.querySelector('#version-list div div.show-more-content'); + DateTime? topReleaseDate; + var apkUrls = apksDiv + ?.querySelectorAll('div.group-title') + .map((e) { + String architectureString = e.text.trim(); + if (architectureString.toLowerCase() == 'unlimited' || + architectureString.toLowerCase() == 'universal') { + architectureString = ''; + } + List architectures = architectureString + .split(',') + .map((e) => e.trim()) + .where((e) => e.isNotEmpty) + .toList(); + // Only take the first APK for each architecture, ignore others for now, for simplicity + // Unclear why there can even be multiple APKs for the same version and arch + var apkInfo = e.nextElementSibling?.querySelector('div.info'); + String? versionCode = RegExp('[0-9]+') + .firstMatch(apkInfo + ?.querySelector('div.info-top span.code') + ?.text ?? + '') + ?.group(0) + ?.trim(); + var types = apkInfo + ?.querySelectorAll('div.info-top span.tag') + .map((e) => e.text.trim()) + .map((t) => t == 'APKs' ? 'APK' : t) ?? + []; + String type = types.isEmpty + ? 'APK' + : types.length == 1 + ? types.first + : types.last; + String? dateString = apkInfo + ?.querySelector('div.info-bottom span.time') + ?.text + .trim(); + DateTime? releaseDate = parseDateTimeMMMddCommayyyy(dateString); + if (additionalSettings['autoApkFilterByArch'] == true && + architectures.isNotEmpty && + architectures + .where((a) => supportedArchs.contains(a)) + .isEmpty) { + return const MapEntry('', ''); + } + topReleaseDate ??= + releaseDate; // Just use the release date of the first APK in the list as the release date for this version + return MapEntry( + '$appId-$versionCode-$architectureString.${type.toLowerCase()}', + 'https://d.${hosts.contains(host) ? 'cdnpure.com' : host}/b/$type/$appId?versionCode=$versionCode'); + }) + .where((e) => e.key.isNotEmpty) + .toList() ?? + []; + if (apkUrls.isEmpty) { + throw NoAPKError(); + } + String version = Uri.parse(link).pathSegments.last; + 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; + String? changeLog = html + .querySelector('div.module.change-log') + ?.innerHtml + .trim() + .replaceAll("
", " \n"); + return APKDetails(version, apkUrls, AppNames(author, appName), + releaseDate: topReleaseDate, changeLog: changeLog); + } else { + throw getObtainiumHttpError(res); + } + } + @override Future getLatestAPKDetails( String standardUrl, @@ -80,88 +182,17 @@ class APKPure extends AppSource { for (var i = 0; i < versionLinks.length; i++) { var link = versionLinks[i]; - var res = await sourceRequest(link.key, additionalSettings); - if (res.statusCode == 200) { - var html = parse(res.body); - var apksDiv = - html.querySelector('#version-list div div.show-more-content'); - DateTime? topReleaseDate; - var apkUrls = apksDiv - ?.querySelectorAll('div.group-title') - .map((e) { - String architectureString = e.text.trim(); - if (architectureString.toLowerCase() == 'unlimited' || - architectureString.toLowerCase() == 'universal') { - architectureString = ''; - } - List architectures = architectureString - .split(',') - .map((e) => e.trim()) - .where((e) => e.isNotEmpty) - .toList(); - // Only take the first APK for each architecture, ignore others for now, for simplicity - // Unclear why there can even be multiple APKs for the same version and arch - var apkInfo = e.nextElementSibling?.querySelector('div.info'); - String? versionCode = RegExp('[0-9]+') - .firstMatch(apkInfo - ?.querySelector('div.info-top span.code') - ?.text ?? - '') - ?.group(0) - ?.trim(); - var types = apkInfo - ?.querySelectorAll('div.info-top span.tag') - .map((e) => e.text.trim()) - .map((t) => t == 'APKs' ? 'APK' : t) ?? - []; - String type = types.isEmpty - ? 'APK' - : types.length == 1 - ? types.first - : types.last; - String? dateString = apkInfo - ?.querySelector('div.info-bottom span.time') - ?.text - .trim(); - DateTime? releaseDate = - parseDateTimeMMMddCommayyyy(dateString); - if (additionalSettings['autoApkFilterByArch'] == true && - architectures.isNotEmpty && - architectures - .where((a) => supportedArchs.contains(a)) - .isEmpty) { - return const MapEntry('', ''); - } - topReleaseDate ??= - releaseDate; // Just use the release date of the first APK in the list as the release date for this version - return MapEntry( - '$appId-$versionCode-$architectureString.${type.toLowerCase()}', - 'https://d.${hosts.contains(host) ? 'cdnpure.com' : host}/b/$type/$appId?versionCode=$versionCode'); - }) - .where((e) => e.key.isNotEmpty) - .toList() ?? - []; - if (apkUrls.isEmpty) { - continue; + try { + if (i == 0 && additionalSettings['stayOneVersionBehind'] == true) { + throw NoReleasesError(); + } + return await getDetailsForVersionLink(standardUrl, appId, host, + supportedArchs, link.key, additionalSettings); + } catch (e) { + if (additionalSettings['fallbackToOlderReleases'] != true || + i == versionLinks.length - 1) { + rethrow; } - String version = Uri.parse(link.key).pathSegments.last; - 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; - String? changeLog = html - .querySelector('div.module.change-log') - ?.innerHtml - .trim() - .replaceAll("
", " \n"); - return APKDetails(version, apkUrls, AppNames(author, appName), - releaseDate: topReleaseDate, changeLog: changeLog); - } else { - throw getObtainiumHttpError(res); } } throw NoAPKError(); From eeb57dbe357065e8c1cbf3ad6199c080a6bccb58 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 1 Oct 2024 15:57:18 -0400 Subject: [PATCH 2/5] UI tweaks (#1871, #1872) --- lib/pages/app.dart | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 00a4b2e..dc735e9 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -242,11 +242,11 @@ class _AppPageState extends State { ); } - getFullInfoColumn() => Column( + getFullInfoColumn({bool small = false}) => Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - const SizedBox(height: 20), + SizedBox(height: small ? 5 : 20), FutureBuilder( future: appsProvider.updateAppIcon(app?.app.id, ignoreCache: true), @@ -261,24 +261,28 @@ class _AppPageState extends State { : () => pm.openApp(app.app.id), child: Image.memory( app!.icon!, - height: 150, + height: small ? 70 : 150, gaplessPlayback: true, ), ) ]) : Container(); }), - const SizedBox( - height: 25, + SizedBox( + height: small ? 10 : 25, ), Text( app?.name ?? tr('app'), textAlign: TextAlign.center, - style: Theme.of(context).textTheme.displayLarge, + style: small + ? Theme.of(context).textTheme.displaySmall + : Theme.of(context).textTheme.displayLarge, ), Text(tr('byX', args: [app?.app.author ?? tr('unknown')]), textAlign: TextAlign.center, - style: Theme.of(context).textTheme.headlineMedium), + style: small + ? Theme.of(context).textTheme.headlineSmall + : Theme.of(context).textTheme.headlineMedium), const SizedBox( height: 24, ), @@ -496,11 +500,8 @@ class _AppPageState extends State { builder: (BuildContext ctx) { return AlertDialog( scrollable: true, - content: getInfoColumn(), - title: Text( - '${app.name} ${tr('byX', args: [ - app.app.author - ])}'), + content: getFullInfoColumn(small: true), + title: Text(app.name), actions: [ TextButton( onPressed: () { From 9f50d8db2d77a0a7ca2c420453095002614b3b8e Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 1 Oct 2024 16:59:28 -0400 Subject: [PATCH 3/5] UI bugfixes on add app page (#1866) --- lib/pages/add_app.dart | 8 +++++++- lib/providers/source_provider.dart | 15 +++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index faa610c..9717dec 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -30,6 +30,7 @@ class AddAppPageState extends State { String userInput = ''; String searchQuery = ''; String? pickedSourceOverride; + String? previousPickedSourceOverride; AppSource? pickedSource; Map additionalSettings = {}; bool additionalSettingsValid = true; @@ -58,6 +59,9 @@ class AddAppPageState extends State { if (overrideSource != null) { pickedSourceOverride = overrideSource; } + bool overrideChanged = + pickedSourceOverride != previousPickedSourceOverride; + previousPickedSourceOverride = pickedSourceOverride; if (updateUrlInput) { urlInputKey++; } @@ -69,6 +73,7 @@ class AddAppPageState extends State { overrideSource: pickedSourceOverride) : null; if (pickedSource.runtimeType != source.runtimeType || + overrideChanged || (prevHost != null && prevHost != source?.hosts[0])) { pickedSource = source; pickedSource?.runOnAddAppInputChange(userInput); @@ -487,7 +492,8 @@ class AddAppPageState extends State { height: 16, ), GeneratedForm( - key: Key(pickedSource.runtimeType.toString()), + key: Key( + '${pickedSource.runtimeType.toString()}-${pickedSource?.hostChanged.toString()}-${pickedSource?.hostIdenticalDespiteAnyChange.toString()}'), items: [ ...pickedSource!.combinedAppSpecificSettingFormItems, ...(pickedSourceOverride != null diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 3c59297..8e77f54 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -414,6 +414,7 @@ HttpClient createHttpClient(bool insecure) { abstract class AppSource { List hosts = []; bool hostChanged = false; + bool hostIdenticalDespiteAnyChange = false; late String name; bool enforceTrackOnly = false; bool changeLogIfAnyIsMarkDown = true; @@ -628,9 +629,10 @@ abstract class AppSource { SettingsProvider settingsProvider) async { Map results = {}; for (var e in sourceConfigSettingFormItems) { - var val = hostChanged + var val = hostChanged && !hostIdenticalDespiteAnyChange ? additionalSettings[e.key] - : settingsProvider.getSettingString(e.key); + : additionalSettings[e.key] ?? + settingsProvider.getSettingString(e.key); if (val != null) { results[e.key] = val; } @@ -813,9 +815,14 @@ class SourceProvider { throw UnsupportedURLError(); } var res = srcs.first; - res.hosts = [Uri.parse(url).host]; + var originalHosts = res.hosts; + var newHost = Uri.parse(url).host; + res.hosts = [newHost]; res.hostChanged = true; - return srcs.first; + if (originalHosts.contains(newHost)) { + res.hostIdenticalDespiteAnyChange = true; + } + return res; } AppSource? source; for (var s in sources.where((element) => element.hosts.isNotEmpty)) { From 738dd5649f976e2eea556473b10c1e8b27c80ae7 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 1 Oct 2024 17:07:11 -0400 Subject: [PATCH 4/5] App-wide "pretend to be GPlay" option (#1859) --- lib/pages/settings.dart | 16 ++++++++++++++++ lib/providers/apps_provider.dart | 19 +++++++------------ lib/providers/settings_provider.dart | 14 +++++++++++--- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index d37f494..1b8e9c1 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -578,6 +578,22 @@ class _SettingsPageState extends State { }) ], ), + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Text( + tr('shizukuPretendToBeGooglePlay'))), + Switch( + value: settingsProvider + .shizukuPretendToBeGooglePlay, + onChanged: (value) { + settingsProvider + .shizukuPretendToBeGooglePlay = value; + }) + ], + ), height32, Text( tr('sourceSpecific'), diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index bea62d1..d0855c2 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -879,22 +879,20 @@ class AppsProvider with ChangeNotifier { apps[id]?.installedInfo == null ? context : null; bool needBGWorkaround = willBeSilent && context == null && !settingsProvider.useShizuku; + bool shizukuPretendToBeGooglePlay = settingsProvider + .shizukuPretendToBeGooglePlay || + apps[id]!.app.additionalSettings['shizukuPretendToBeGooglePlay'] == + true; if (downloadedFile != null) { if (needBGWorkaround) { // ignore: use_build_context_synchronously installApk(downloadedFile, contextIfNewInstall, needsBGWorkaround: true, - shizukuPretendToBeGooglePlay: apps[id]! - .app - .additionalSettings['shizukuPretendToBeGooglePlay'] == - true); + shizukuPretendToBeGooglePlay: shizukuPretendToBeGooglePlay); } else { // ignore: use_build_context_synchronously sayInstalled = await installApk(downloadedFile, contextIfNewInstall, - shizukuPretendToBeGooglePlay: apps[id]! - .app - .additionalSettings['shizukuPretendToBeGooglePlay'] == - true); + shizukuPretendToBeGooglePlay: shizukuPretendToBeGooglePlay); } } else { if (needBGWorkaround) { @@ -905,10 +903,7 @@ class AppsProvider with ChangeNotifier { // ignore: use_build_context_synchronously sayInstalled = await installXApkDir( downloadedDir!, contextIfNewInstall, - shizukuPretendToBeGooglePlay: apps[id]! - .app - .additionalSettings['shizukuPretendToBeGooglePlay'] == - true); + shizukuPretendToBeGooglePlay: shizukuPretendToBeGooglePlay); } } if (willBeSilent && context == null) { diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index f12dfbe..bef37b3 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -48,7 +48,7 @@ class SettingsProvider with ChangeNotifier { notifyListeners(); } - bool get useShizuku{ + bool get useShizuku { return prefs?.getBool('useShizuku') ?? false; } @@ -69,8 +69,7 @@ class SettingsProvider with ChangeNotifier { Color get themeColor { int? colorCode = prefs?.getInt('themeColor'); - return (colorCode != null) ? - Color(colorCode) : obtainiumThemeColor; + return (colorCode != null) ? Color(colorCode) : obtainiumThemeColor; } set themeColor(Color themeColor) { @@ -469,4 +468,13 @@ class SettingsProvider with ChangeNotifier { prefs?.setBool('beforeNewInstallsShareToAppVerifier', val); notifyListeners(); } + + bool get shizukuPretendToBeGooglePlay { + return prefs?.getBool('shizukuPretendToBeGooglePlay') ?? false; + } + + set shizukuPretendToBeGooglePlay(bool val) { + prefs?.setBool('shizukuPretendToBeGooglePlay', val); + notifyListeners(); + } } From 9a354ecf0e898be578933ac8a9ee34e24f63b9cf Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Tue, 1 Oct 2024 17:12:10 -0400 Subject: [PATCH 5/5] Increment version, upgrade package --- pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 2137698..0cdbe4e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1097,10 +1097,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "6e64fcb1c19d92024da8f33503aaeeda35825d77142c01d0ea2aa32edc79fdc8" + sha256: ed021f27ae621bc97a6019fb601ab16331a3db4bf8afa305e9f6689bdb3edced url: "https://pub.dev" source: hosted - version: "3.16.7" + version: "3.16.8" webview_flutter_platform_interface: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index cea583d..76cbb7a 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: 1.1.25+2282 +version: 1.1.26+2283 environment: sdk: '>=3.0.0 <4.0.0'