diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 294654e..a3e935a 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -299,6 +299,8 @@ "note": "Note", "selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.", "badDownload": "The APK could not be parsed (incompatible or partial download)", + "beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)", + "appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index f403304..33fa372 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -218,7 +218,7 @@ "dontShowTrackOnlyWarnings": "Nezobrazovat varování pro 'Jen sledované'", "dontShowAPKOriginWarnings": "Nezobrazovat varování pro původ APK", "moveNonInstalledAppsToBottom": "Přesunout nenainstalované aplikace na konec zobrazení Aplikace", - "gitlabPATLabel": "GitLab Personal Access Token", + "gitlabPATLabel": "Osobní přístupový token GitLab", "about": "O", "requiresCredentialsInSettings": "{}: Vyžaduje další pověření (v nastavení)", "checkOnStart": "Zkontrolovat jednou při spuštění", @@ -299,6 +299,8 @@ "note": "Poznámka", "selfHostedNote": "Rozbalovací seznam \"{}\" lze použít k dosažení vlastních/obvyklých instancí libovolného zdroje.", "badDownload": "APK nelze analyzovat (nekompatibilní nebo částečné stažení)", + "beforeNewInstallsShareToAppVerifier": "Sdílení nových aplikací s aplikací AppVerifier (pokud je k dispozici)", + "appVerifierInstructionToast": "Sdílejte do aplikace AppVerifier a po dokončení se sem vraťte.", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/de.json b/assets/translations/de.json index 40d2315..4d711bf 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -299,6 +299,8 @@ "note": "Hinweis", "selfHostedNote": "Das „{}“-Dropdown-Menü kann verwendet werden, um selbst gehostete/angepasste Instanzen einer beliebigen Quelle zu erreichen.", "badDownload": "Die APK konnte nicht geparst werden (inkompatibler oder teilweiser Download)", + "beforeNewInstallsShareToAppVerifier": "Neue Apps mit AppVerifier teilen (falls verfügbar)", + "appVerifierInstructionToast": "Geben Sie die Daten an AppVerifier weiter und kehren Sie dann hierher zurück, wenn Sie fertig sind.", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index f6220bb..23b389e 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -299,6 +299,8 @@ "note": "Note", "selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.", "badDownload": "The APK could not be parsed (incompatible or partial download)", + "beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)", + "appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index 0f512e8..69b085c 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -299,6 +299,8 @@ "note": "Nota", "selfHostedNote": "El desplegable \"{}\" puede utilizarse para acceder a instancias autoalojadas/personalizadas de cualquier fuente.", "badDownload": "No se ha podido analizar el APK (incompatible o descarga parcial)", + "beforeNewInstallsShareToAppVerifier": "Compartir nuevas aplicaciones con AppVerifier (si está disponible)", + "appVerifierInstructionToast": "Comparta con AppVerifier y vuelva aquí cuando esté listo.", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 7929634..10731d6 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -299,6 +299,8 @@ "note": "Note", "selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.", "badDownload": "The APK could not be parsed (incompatible or partial download)", + "beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)", + "appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index f61527e..61be34e 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -299,6 +299,8 @@ "note": "Note", "selfHostedNote": "La liste déroulante \"{}\" peut être utilisée pour accéder aux instances auto-hébergées/personnalisées de n'importe quelle source.", "badDownload": "L'APK n'a pas pu être analysé (téléchargement incompatible ou partiel)", + "beforeNewInstallsShareToAppVerifier": "Partager les nouvelles applications avec AppVerifier (si disponible)", + "appVerifierInstructionToast": "Partagez avec AppVerifier, puis revenez ici lorsque vous êtes prêt.", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index 277f6a6..5e9c669 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -218,7 +218,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", + "gitlabPATLabel": "GitLab személyes hozzáférési token", "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", @@ -299,6 +299,8 @@ "note": "Megjegyzés:", "selfHostedNote": "A \"{}\" legördülő menü használható bármely forrás saját üzemeltetésű/egyéni példányainak eléréséhez.", "badDownload": "Az APK-t nem lehetett elemezni (inkompatibilis vagy részleges letöltés)", + "beforeNewInstallsShareToAppVerifier": "Új alkalmazások megosztása az AppVerifierrel (ha elérhető)", + "appVerifierInstructionToast": "Ossza meg az AppVerifierrel, majd térjen vissza ide, ha kész.", "removeAppQuestion": { "one": "Eltávolítja az alkalmazást?", "other": "Eltávolítja az alkalmazásokat?" diff --git a/assets/translations/it.json b/assets/translations/it.json index 2e4b0d1..e6aa2a4 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -218,7 +218,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", + "gitlabPATLabel": "GitLab Token di accesso personale", "about": "Informazioni", "requiresCredentialsInSettings": "{}: Servono credenziali aggiuntive (in Impostazioni)", "checkOnStart": "Controlla una volta all'avvio", @@ -299,6 +299,8 @@ "note": "Nota", "selfHostedNote": "Il menu a tendina \"{}\" può essere usato per raggiungere istanze autogestite/personali di qualsiasi fonte.", "badDownload": "Non è stato possibile analizzare l'APK (download incompatibile o parziale).", + "beforeNewInstallsShareToAppVerifier": "Condividere le nuove applicazioni con AppVerifier (se disponibile)", + "appVerifierInstructionToast": "Condividete con AppVerifier, quindi tornate qui quando siete pronti.", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index af5db0c..171167e 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -299,6 +299,8 @@ "note": "注", "selfHostedNote": "ドロップダウン\"{}\"を使用すると、あらゆるソースのセルフホスト/カスタムインスタンスにアクセスできます。", "badDownload": "APK を解析できませんでした(互換性がないか、部分的にダウンロードされています)。", + "beforeNewInstallsShareToAppVerifier": "AppVerifierで新しいアプリを共有する(利用可能な場合)", + "appVerifierInstructionToast": "AppVerifierに共有し、準備ができたらここに戻ってください。", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/nl.json b/assets/translations/nl.json index f946b5a..845676d 100644 --- a/assets/translations/nl.json +++ b/assets/translations/nl.json @@ -218,7 +218,7 @@ "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", + "gitlabPATLabel": "GitLab persoonlijk toegangskenmerk", "about": "Over", "requiresCredentialsInSettings": "{}: Dit vereist aanvullende referenties (in Instellingen)", "checkOnStart": "Controleren op updates bij opstarten", @@ -299,6 +299,8 @@ "note": "Opmerking", "selfHostedNote": "De \"{}\" dropdown kan gebruikt worden om zelf gehoste/aangepaste instanties van elke bron te bereiken.", "badDownload": "De APK kon niet worden verwerkt (incompatibele of gedeeltelijke download)", + "beforeNewInstallsShareToAppVerifier": "Nieuwe Apps delen met AppVerifier (indien beschikbaar)", + "appVerifierInstructionToast": "Deel naar AppVerifier en keer hier terug als je klaar bent.", "removeAppQuestion": { "one": "App verwijderen?", "other": "Apps verwijderen?" diff --git a/assets/translations/pl.json b/assets/translations/pl.json index f24aceb..c017f93 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -299,6 +299,8 @@ "note": "Uwaga", "selfHostedNote": "Lista rozwijana \"{}\" może być używana do uzyskiwania dostępu do samodzielnie hostowanych / niestandardowych instancji dowolnego źródła.", "badDownload": "Nie można przeanalizować pliku APK (niekompatybilny lub częściowo pobrany).", + "beforeNewInstallsShareToAppVerifier": "Udostępnianie nowych aplikacji za pomocą AppVerifier (jeśli dostępne)", + "appVerifierInstructionToast": "Udostępnij w AppVerifier, a następnie wróć tutaj, gdy będziesz gotowy.", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index 2473c73..c2281d9 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -299,6 +299,8 @@ "note": "Nota", "selfHostedNote": "O menu suspenso \"{}\" pode ser usado para acessar instâncias auto-hospedadas/personalizadas de qualquer fonte.", "badDownload": "Não foi possível analisar o APK (transferência incompatível ou parcial)", + "beforeNewInstallsShareToAppVerifier": "Partilhar novas aplicações com o AppVerifier (se disponível)", + "appVerifierInstructionToast": "Partilhe com o AppVerifier e, em seguida, regresse aqui quando estiver pronto.", "removeAppQuestion": { "one": "Remover aplicativo?", "other": "Remover aplicativos?" diff --git a/assets/translations/ru.json b/assets/translations/ru.json index 52a42fb..c5233d5 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -299,6 +299,8 @@ "note": "Примечание", "selfHostedNote": "Выпадающий список \"{}\" можно использовать для доступа к самостоятельно размещенным/настроенным экземплярам любого источника.", "badDownload": "APK не удалось разобрать (несовместимая или неполная загрузка)", + "beforeNewInstallsShareToAppVerifier": "Поделитесь новыми приложениями с AppVerifier (если доступно)", + "appVerifierInstructionToast": "Поделитесь с AppVerifier, а затем вернитесь сюда, когда будете готовы.", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/sv.json b/assets/translations/sv.json index 44baa29..5713536 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -218,7 +218,7 @@ "dontShowTrackOnlyWarnings": "Visa inte 'Följ-Endast' varningar", "dontShowAPKOriginWarnings": "Visa inte APK-ursprung varningar", "moveNonInstalledAppsToBottom": "Flytta icke-installerade appar till botten av appvyn", - "gitlabPATLabel": "GitLab Personal Access Token", + "gitlabPATLabel": "Personligt åtkomsttoken för GitLab", "about": "Om", "requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)", "checkOnStart": "Kolla efter uppdateringar vid start", @@ -299,6 +299,8 @@ "note": "Anmärkning", "selfHostedNote": "Rullgardinsmenyn \"{}\" kan användas för att nå självhostade/anpassade instanser av valfri källa.", "badDownload": "APK kunde inte analyseras (inkompatibel eller partiell nedladdning)", + "beforeNewInstallsShareToAppVerifier": "Dela nya appar med AppVerifier (om tillgängligt)", + "appVerifierInstructionToast": "Dela till AppVerifier och återvänd sedan hit när du är klar.", "removeAppQuestion": { "one": "Ta Bort App?", "other": "Ta Bort Appar?" diff --git a/assets/translations/tr.json b/assets/translations/tr.json index 240a0c1..176663a 100644 --- a/assets/translations/tr.json +++ b/assets/translations/tr.json @@ -299,6 +299,8 @@ "note": "Not", "selfHostedNote": "\"{}\" açılır menüsü, herhangi bir kaynağın kendi kendine barındırılan/özel örneklerine ulaşmak için kullanılabilir.", "badDownload": "APK ayrıştırılamadı (uyumsuz veya kısmi indirme)", + "beforeNewInstallsShareToAppVerifier": "Yeni Uygulamaları AppVerifier ile paylaşın (varsa)", + "appVerifierInstructionToast": "AppVerifier ile paylaşın, hazır olduğunuzda buraya dönün.", "removeAppQuestion": { "one": "Uygulamayı Kaldır?", "other": "Uygulamaları Kaldır?" diff --git a/assets/translations/uk.json b/assets/translations/uk.json index c971034..327d5fa 100644 --- a/assets/translations/uk.json +++ b/assets/translations/uk.json @@ -232,7 +232,6 @@ "addInfoBelow": "Додати цю інформацію нижче.", "addInfoInSettings": "Додати цю інформацію у налаштуваннях.", "githubSourceNote": "Лімітування швидкості GitHub можна уникнути, використовуючи ключ API.", - "gitlabSourceNote": "Вилучення APK з GitLab може не працювати без ключа API.", "sortByLastLinkSegment": "Сортувати лише за останнім сегментом посилання", "filterReleaseNotesByRegEx": "Фільтрувати примітки до релізу за регулярним виразом", "customLinkFilterRegex": "Фільтр кастомного посилання на APK за регулярним виразом (за замовчуванням '.apk$')", @@ -300,6 +299,8 @@ "note": "Примітка", "selfHostedNote": "Випадаючий список \"{}\" може використовуватися для доступу до власних/призначених для самостійного використання екземплярів будь-якого джерела.", "badDownload": "APK не вдалося розпарсити (несумісний або часткове завантаження)", + "beforeNewInstallsShareToAppVerifier": "Діліться новими додатками з AppVerifier (якщо доступно)", + "appVerifierInstructionToast": "Надішліть на AppVerifier, а потім поверніться сюди, коли будете готові.", "removeAppQuestion": { "one": "Видалити застосунок?", "other": "Видалити застосунки?" diff --git a/assets/translations/vi.json b/assets/translations/vi.json index 51b1f4f..951f209 100644 --- a/assets/translations/vi.json +++ b/assets/translations/vi.json @@ -299,6 +299,8 @@ "note": "Ghi chú", "selfHostedNote": "Trình đơn thả xuống \"{}\" có thể được dùng để tiếp cận các phiên bản tự lưu trữ/tùy chỉnh của bất kỳ nguồn nào.", "badDownload": "Không thể phân tích cú pháp APK (tải xuống một phần hoặc không tương thích)", + "beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)", + "appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.", "removeAppQuestion": { "one": "Gỡ ứng dụng?", "other": "Gỡ ứng dụng?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 8e7e8ad..ed1482c 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -299,6 +299,8 @@ "note": "备注", "selfHostedNote": "可以通过“{}”下拉菜单来指向任意来源的自托管/自定义实例。", "badDownload": "无法解析 APK 文件(不兼容或文件不完整)", + "beforeNewInstallsShareToAppVerifier": "与 AppVerifier 共享新应用程序(如有)", + "appVerifierInstructionToast": "分享到 AppVerifier,准备就绪后返回此处。", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 5cc56a2..bdf51e1 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -351,6 +351,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: [ @@ -363,6 +379,43 @@ class _SettingsPageState extends State { }) ], ), + height16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text(tr( + 'beforeNewInstallsShareToAppVerifier')), + GestureDetector( + onTap: () { + launchUrlString( + 'https://github.com/soupslurpr/AppVerifier', + mode: LaunchMode + .externalApplication); + }, + child: Text( + tr('about'), + style: const TextStyle( + decoration: + TextDecoration.underline, + fontSize: 12), + )), + ], + )), + Switch( + value: settingsProvider + .beforeNewInstallsShareToAppVerifier, + onChanged: (value) { + settingsProvider + .beforeNewInstallsShareToAppVerifier = + value; + }) + ], + ), installMethodDropdown, height32, Text( @@ -474,22 +527,6 @@ 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 7f4efed..be8ceb5 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:fluttertoast/fluttertoast.dart'; import 'package:http/http.dart' as http; import 'package:crypto/crypto.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:share_plus/share_plus.dart'; import 'package:shared_storage/shared_storage.dart' as saf; import 'native_provider.dart'; @@ -561,7 +563,8 @@ class AppsProvider with ChangeNotifier { zipFile: File(filePath), destinationDir: Directory(destinationPath)); } - Future installXApkDir(DownloadedXApkDir dir, + Future installXApkDir( + DownloadedXApkDir dir, BuildContext? firstTimeWithContext, {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 @@ -575,7 +578,8 @@ 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), firstTimeWithContext, needsBGWorkaround: needsBGWorkaround); } catch (e) { logs.add( @@ -597,8 +601,19 @@ class AppsProvider with ChangeNotifier { return somethingInstalled; } - Future installApk(DownloadedApk file, + Future installApk( + DownloadedApk file, BuildContext? firstTimeWithContext, {bool needsBGWorkaround = false}) async { + if (firstTimeWithContext != null && + settingsProvider.beforeNewInstallsShareToAppVerifier && + (await getInstalledInfo('dev.soupslurpr.appverifier')) != null) { + XFile f = XFile.fromData(file.file.readAsBytesSync(), + mimeType: 'application/vnd.android.package-archive'); + Fluttertoast.showToast( + msg: tr('appVerifierInstructionToast'), + toastLength: Toast.LENGTH_LONG); + await Share.shareXFiles([f]); + } var newInfo = await pm.getPackageArchiveInfo(archiveFilePath: file.file.path); if (newInfo == null) { @@ -834,17 +849,23 @@ class AppsProvider with ChangeNotifier { try { if (!skipInstalls) { bool sayInstalled = true; + var contextIfNewInstall = + apps[id]?.installedInfo == null ? context : null; if (downloadedFile != null) { if (willBeSilent && context == null) { - installApk(downloadedFile, needsBGWorkaround: true); + installApk(downloadedFile, contextIfNewInstall, + needsBGWorkaround: true); } else { - sayInstalled = await installApk(downloadedFile); + sayInstalled = + await installApk(downloadedFile, contextIfNewInstall); } } else { if (willBeSilent && context == null) { - installXApkDir(downloadedDir!, needsBGWorkaround: true); + installXApkDir(downloadedDir!, contextIfNewInstall, + needsBGWorkaround: true); } else { - sayInstalled = await installXApkDir(downloadedDir!); + sayInstalled = + await installXApkDir(downloadedDir!, contextIfNewInstall); } } if (willBeSilent && context == null) { diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 1b0edcc..b9b910a 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -479,4 +479,13 @@ class SettingsProvider with ChangeNotifier { prefs?.setStringList('searchDeselected', list); notifyListeners(); } + + bool get beforeNewInstallsShareToAppVerifier { + return prefs?.getBool('beforeNewInstallsShareToAppVerifier') ?? true; + } + + set beforeNewInstallsShareToAppVerifier(bool val) { + prefs?.setBool('beforeNewInstallsShareToAppVerifier', val); + notifyListeners(); + } }