diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a3f6101..d3b5a05 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,6 +39,7 @@ jobs: sed -i 's/signingConfig signingConfigs.release//g' android/app/build.gradle flutter build apk --flavor normal && flutter build apk --split-per-abi --flavor normal for file in build/app/outputs/flutter-apk/app-*normal*.apk*; do mv "$file" "${file//-normal/}"; done + flutter build apk --flavor fdroid -t lib/main_fdroid.dart && flutter build apk --split-per-abi --flavor fdroid -t lib/main_fdroid.dart rm ./build/app/outputs/flutter-apk/*.sha1 ls -l ./build/app/outputs/flutter-apk/ diff --git a/assets/translations/bs.json b/assets/translations/bs.json index 9dc697d..c68ac07 100644 --- a/assets/translations/bs.json +++ b/assets/translations/bs.json @@ -51,9 +51,8 @@ "percentProgress": "Napredak: {}%", "pleaseWait": "Molimo sačekajte", "updateAvailable": "Ažuriranje dostupno", - "estimateInBracketsShort": "(Procjena)", "notInstalled": "Nije instalirano", - "estimateInBrackets": "(Procjena)", + "pseudoVersion": "pseudo-version", "selectAll": "Označi sve", "deselectX": "Poništi odabir {}", "xWillBeRemovedButRemainInstalled": "{} će biti uklonjen iz Obtainiuma, ali će ostati instaliran na uređaju.", @@ -213,6 +212,7 @@ "changes": "Promjene", "releaseDate": "Datum izdavanja", "importFromURLsInFile": "Uvoz iz URL-ova u datoteci (kao što je OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Otkrivanje verzije", "standardVersionDetection": "Detekcija standardne verzije", "groupByCategory": "Grupiši po kategoriji", @@ -292,6 +292,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "Želite li ukloniti aplikaciju?", "other": "Želite li ukloniti aplikacije?" diff --git a/assets/translations/cs.json b/assets/translations/cs.json index cd4378c..9dfac99 100644 --- a/assets/translations/cs.json +++ b/assets/translations/cs.json @@ -51,9 +51,8 @@ "percentProgress": "Pokrok: {}%", "pleaseWait": "Počkejte prosím", "updateAvailable": "Aktualizace je k dispozici", - "estimateInBracketsShort": "(approx.)", "notInstalled": "Není nainstalováno", - "estimateInBrackets": "(přibližně)", + "pseudoVersion": "pseudo-version", "selectAll": "Vybrat vše", "deselectX": "{} deselected", "xWillBeRemovedButRemainInstalled": "{} bude odstraněn z Obtainium, ale zůstane nainstalován v zařízení.", @@ -213,6 +212,7 @@ "changes": "Změny", "releaseDate": "Datum vydání", "importFromURLsInFile": "Importovat adresy URL ze souboru (např. OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Detekce verze", "standardVersionDetection": "Standardní detekce verze", "groupByCategory": "Seskupit podle kategorie", @@ -292,6 +292,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "Odstranit Apku?", "other": "Odstranit Apky?" diff --git a/assets/translations/de.json b/assets/translations/de.json index a7028c4..fe843d4 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -51,9 +51,8 @@ "percentProgress": "Fortschritt: {}%", "pleaseWait": "Bitte warten", "updateAvailable": "Aktualisierung verfügbar", - "estimateInBracketsShort": "(ca.)", "notInstalled": "Nicht installiert", - "estimateInBrackets": "(Ungefähr)", + "pseudoVersion": "pseudo-version", "selectAll": "Alle auswählen", "deselectX": "{} abgewählt", "xWillBeRemovedButRemainInstalled": "{} wird aus Obtainium entfernt, bleibt aber auf dem Gerät installiert.", @@ -213,6 +212,7 @@ "changes": "Änderungen", "releaseDate": "Veröffentlichungsdatum", "importFromURLsInFile": "Importieren von URLs aus Datei (z. B. OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Versionserkennung", "standardVersionDetection": "Standardversionserkennung", "groupByCategory": "Nach Kategorie gruppieren", @@ -294,6 +294,14 @@ "useVersionCodeAsOSVersion": "Verwende die Appversion als erkannte Version vom Betriebssystem", "requestHeader": "Request Header", "useLatestAssetDateAsReleaseDate": "Den letzten Asset-Upload als Veröffentlichungsdatum verwenden", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "App entfernen?", "other": "Apps entfernen?" diff --git a/assets/translations/en.json b/assets/translations/en.json index 74a25d7..e17fd51 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -51,9 +51,8 @@ "percentProgress": "Progress: {}%", "pleaseWait": "Please Wait", "updateAvailable": "Update Available", - "estimateInBracketsShort": "(Est.)", "notInstalled": "Not Installed", - "estimateInBrackets": "(Estimate)", + "pseudoVersion": "pseudo-version", "selectAll": "Select All", "deselectX": "Deselect {}", "xWillBeRemovedButRemainInstalled": "{} will be removed from Obtainium but remain installed on device.", @@ -166,8 +165,8 @@ "unknown": "Unknown", "none": "None", "never": "Never", - "latestVersionX": "Latest Version: {}", - "installedVersionX": "Installed Version: {}", + "latestVersionX": "Latest: {}", + "installedVersionX": "Installed: {}", "lastUpdateCheckX": "Last Update Check: {}", "remove": "Remove", "yesMarkUpdated": "Yes, Mark as Updated", @@ -208,11 +207,12 @@ "removeFromObtainium": "Remove from Obtainium", "uninstallFromDevice": "Uninstall from Device", "onlyWorksWithNonVersionDetectApps": "Only works for Apps with version detection disabled.", - "releaseDateAsVersion": "Use Release Date as Version", + "releaseDateAsVersion": "Use release date as version string", "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)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Version Detection", "standardVersionDetection": "Standard version detection", "groupByCategory": "Group by Category", @@ -254,8 +254,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 for Version Extraction Regex", + "versionExtractionRegEx": "Version String Extraction RegEx", + "matchGroupToUse": "Match Group to Use for Version String Extraction Regex", "highlightTouchTargets": "Highlight less obvious touch targets", "pickExportDir": "Pick Export Directory", "autoExportOnChanges": "Auto-export on changes", @@ -269,7 +269,7 @@ "debugMenu": "Debug Menu", "bgTaskStarted": "Background task started - check logs.", "runBgCheckNow": "Run Background Update Check Now", - "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page", + "versionExtractWholePage": "Apply version string extraction Regex to entire page", "installing": "Installing", "skipUpdateNotifications": "Skip update notifications", "updatesAvailableNotifChannel": "Updates Available", @@ -294,6 +294,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "Remove App?", "other": "Remove Apps?" diff --git a/assets/translations/es.json b/assets/translations/es.json index b02120a..9b3601e 100644 --- a/assets/translations/es.json +++ b/assets/translations/es.json @@ -51,9 +51,8 @@ "percentProgress": "Progreso: {}%", "pleaseWait": "Por favor, espere", "updateAvailable": "Actualización Disponible", - "estimateInBracketsShort": "(Aprox.)", "notInstalled": "No Instalado", - "estimateInBrackets": "(Aproximado)", + "pseudoVersion": "pseudo-version", "selectAll": "Seleccionar Todo", "deselectX": "Deseleccionar {}", "xWillBeRemovedButRemainInstalled": "{} será eliminada de Obtainium pero continuará instalada en el dispositivo.", @@ -213,6 +212,7 @@ "changes": "Cambios", "releaseDate": "Fecha de Publicación", "importFromURLsInFile": "Importar URLs desde archivo (como OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Detección de Versiones", "standardVersionDetection": "Por versión", "groupByCategory": "Agrupar por categoría", @@ -292,6 +292,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "¿Eliminar Aplicación?", "other": "¿Eliminar Aplicaciones?" diff --git a/assets/translations/fa.json b/assets/translations/fa.json index 30c9881..439d540 100644 --- a/assets/translations/fa.json +++ b/assets/translations/fa.json @@ -51,9 +51,8 @@ "percentProgress": "پیش رفتن: {}%", "pleaseWait": "لطفا صبر کنید", "updateAvailable": "بروزرسانی در دسترس", - "estimateInBracketsShort": "(تخمین)", "notInstalled": "نصب نشده", - "estimateInBrackets": "(تخمین زدن)", + "pseudoVersion": "pseudo-version", "selectAll": "انتخاب همه", "deselectX": "لغو انتخاب {}", "xWillBeRemovedButRemainInstalled": "{} از Obtainium حذف می‌شود اما روی دستگاه نصب می‌ماند.", @@ -213,6 +212,7 @@ "changes": "تغییرات", "releaseDate": "تاریخ انتشار", "importFromURLsInFile": "درون ریزی از آدرس های اینترنتی موجود در فایل (مانند OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "تشخیص نسخه", "standardVersionDetection": "تشخیص نسخه استاندارد", "groupByCategory": "گروه بر اساس دسته", @@ -292,6 +292,14 @@ "useVersionCodeAsOSVersion": "استفاده کد نسخه برنامه به جای نسخه شناسایی شده توسط سیستم عامل استفاده کنید", "requestHeader": "درخواست سطر بالایی", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "برنامه حذف شود؟", "other": "برنامه ها حذف شوند؟" diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 3a3fa7e..2524274 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -51,9 +51,8 @@ "percentProgress": "Progrès: {}%", "pleaseWait": "Veuillez patienter", "updateAvailable": "Mise à jour disponible", - "estimateInBracketsShort": "(Est.)", "notInstalled": "Pas installé", - "estimateInBrackets": "(Estimation)", + "pseudoVersion": "pseudo-version", "selectAll": "Tout sélectionner", "deselectX": "Déselectionner {}", "xWillBeRemovedButRemainInstalled": "{} sera supprimé d'Obtainium mais restera installé sur l'appareil.", @@ -213,6 +212,7 @@ "changes": "Changements", "releaseDate": "Date de sortie", "importFromURLsInFile": "Importer à partir d'URL dans un fichier (comme OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Détection des versions", "standardVersionDetection": "Détection de version standard", "groupByCategory": "Group by Category", @@ -292,6 +292,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "Supprimer l'application ?", "other": "Supprimer les applications ?" diff --git a/assets/translations/hu.json b/assets/translations/hu.json index ecf9bf2..37388f2 100644 --- a/assets/translations/hu.json +++ b/assets/translations/hu.json @@ -51,9 +51,8 @@ "percentProgress": "Folyamat: {}%", "pleaseWait": "Kis türelmet", "updateAvailable": "Frissítés érhető el", - "estimateInBracketsShort": "(Becsült)", "notInstalled": "Nem telepített", - "estimateInBrackets": "(Becslés)", + "pseudoVersion": "pseudo-version", "selectAll": "Mindet kiválaszt", "deselectX": "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.", @@ -213,6 +212,7 @@ "changes": "Változtatások", "releaseDate": "Kiadás dátuma", "importFromURLsInFile": "Importálás fájlban található URL-ből (mint pl. OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Verzió érzékelés", "standardVersionDetection": "Alapért. verzió érzékelés", "groupByCategory": "Csoportosítás Kategória alapján", @@ -292,6 +292,14 @@ "useVersionCodeAsOSVersion": "Az app versionCode használata a rendszer által észlelt verzióként", "requestHeader": "Kérelem fejléc", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert 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 48dfc9b..179fa00 100644 --- a/assets/translations/it.json +++ b/assets/translations/it.json @@ -51,9 +51,8 @@ "percentProgress": "Avanzamento: {}%", "pleaseWait": "In attesa", "updateAvailable": "Aggiornamento disponibile", - "estimateInBracketsShort": "(stim.)", "notInstalled": "Non installato", - "estimateInBrackets": "(stimato)", + "pseudoVersion": "pseudo-version", "selectAll": "Seleziona tutto", "deselectX": "Deseleziona {}", "xWillBeRemovedButRemainInstalled": "Verà effettuata la rimozione di {}, ma non la disinstallazione.", @@ -213,6 +212,7 @@ "changes": "Novità", "releaseDate": "Data di rilascio", "importFromURLsInFile": "Importa da URL in file (come OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Rilevamento di versione", "standardVersionDetection": "Rilevamento di versione standard", "groupByCategory": "Raggruppa per categoria", @@ -292,6 +292,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "Rimuovere l'app?", "other": "Rimuovere le app?" diff --git a/assets/translations/ja.json b/assets/translations/ja.json index 0cfbf76..375a286 100644 --- a/assets/translations/ja.json +++ b/assets/translations/ja.json @@ -51,9 +51,8 @@ "percentProgress": "ダウンロード中: {}%", "pleaseWait": "しばらくお待ちください", "updateAvailable": "アップデートが利用可能", - "estimateInBracketsShort": "(推定)", "notInstalled": "未インストール", - "estimateInBrackets": "(推定)", + "pseudoVersion": "pseudo-version", "selectAll": "すべて選択", "deselectX": "{}件の選択を解除", "xWillBeRemovedButRemainInstalled": "{} はObtainiumから削除されますが、デバイスにはインストールされたままです。", @@ -213,6 +212,7 @@ "changes": "変更点", "releaseDate": "リリース日", "importFromURLsInFile": "ファイル(OPMLなど)内のURLからインポート", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "バージョン検出", "standardVersionDetection": "標準のバージョン検出", "groupByCategory": "カテゴリ別にグループ化する", @@ -294,6 +294,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "アプリを削除しますか?", "other": "アプリを削除しますか?" diff --git a/assets/translations/nl.json b/assets/translations/nl.json index ce7f62c..7d5c4a1 100644 --- a/assets/translations/nl.json +++ b/assets/translations/nl.json @@ -51,9 +51,8 @@ "percentProgress": "Vooruitgang: {}%", "pleaseWait": "Even geduld", "updateAvailable": "Update beschikbaar", - "estimateInBracketsShort": "(Ong.)", "notInstalled": "Niet geinstalleerd", - "estimateInBrackets": "(Ongeveer)", + "pseudoVersion": "pseudo-version", "selectAll": "Selecteer alles", "deselectX": "Deselecteer {}", "xWillBeRemovedButRemainInstalled": "{} zal worden verwijderd uit Obtainium, maar blijft geïnstalleerd op het apparaat.", @@ -213,6 +212,7 @@ "changes": "Veranderingen", "releaseDate": "Releasedatum", "importFromURLsInFile": "Importeren vanaf URL's in een bestand (zoals OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Versieherkenning", "standardVersionDetection": "Standaard versieherkenning", "groupByCategory": "Groepeer op categorie", @@ -292,6 +292,14 @@ "useVersionCodeAsOSVersion": "Gebruik app versieCode als door OS gedetecteerde versie", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Gebruik laatste upload als releasedatum", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "App verwijderen?", "other": "Apps verwijderen?" @@ -344,4 +352,4 @@ "one": "{} en nog 1 app zijn mogelijk bijgewerkt.", "other": "{} en {} meer apps zijn mogelijk bijgwerkt." } -} +} \ No newline at end of file diff --git a/assets/translations/pl.json b/assets/translations/pl.json index 574cc79..323a737 100644 --- a/assets/translations/pl.json +++ b/assets/translations/pl.json @@ -51,9 +51,8 @@ "percentProgress": "Postęp: {}%", "pleaseWait": "Proszę czekać", "updateAvailable": "Dostępna aktualizacja", - "estimateInBracketsShort": "(Szac.)", "notInstalled": "Nie zainstalowano", - "estimateInBrackets": "(Szacunkowo)", + "pseudoVersion": "pseudo-version", "selectAll": "Zaznacz wszystkie", "deselectX": "Odznacz {}", "xWillBeRemovedButRemainInstalled": "{} zostanie usunięty z Obtainium, ale pozostanie zainstalowany na urządzeniu.", @@ -213,6 +212,7 @@ "changes": "Zmiany", "releaseDate": "Data wydania", "importFromURLsInFile": "Importuj z adresów URL w pliku (typu OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Wykrywanie wersji", "standardVersionDetection": "Standardowe wykrywanie wersji", "groupByCategory": "Grupuj według kategorii", @@ -292,6 +292,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "Usunąć aplikację?", "few": "Usunąć aplikacje?", diff --git a/assets/translations/pt.json b/assets/translations/pt.json index 2f2620f..b01072c 100644 --- a/assets/translations/pt.json +++ b/assets/translations/pt.json @@ -1,348 +1,357 @@ -{ - "invalidURLForSource": "URL {} inválida", - "noReleaseFound": "Não foi possível encontrar uma versão adequada", - "noVersionFound": "Não foi possível encontrar uma versão", - "urlMatchesNoSource": "URL não corresponde a uma fonte conhecida", - "cantInstallOlderVersion": "Não é permitido instalar uma versão anterior de um aplicativo", - "appIdMismatch": "ID do pacote baixado não é igual ao ID do aplicativo 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 acesso pessoal do GitHub (Reduz tempos de espera)", - "includePrereleases": "Incluir pré-lançamentos", - "fallbackToOlderReleases": "Retornar para versões anteriores", - "filterReleaseTitlesByRegEx": "Filtrar títulos 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 monitorar'", - "source": "Fonte", - "app": "Aplicativo", - "appsFromSourceAreTrackOnly": "Os aplicativos desta fonte são 'Apenas monitorar'.", - "youPickedTrackOnly": "Você selecionou a opção 'Apenas monitorar'.", - "trackOnlyAppDescription": "As atualizações desse aplicativo serão monitoradas, mas o Obtainium não poderá baixá-lo ou instalá-lo.", - "cancelled": "Cancelado", - "appAlreadyAdded": "Aplicativo já adicionado", - "alreadyUpToDateQuestion": "Aplicativo já foi atualizado?", - "addApp": "Adicionar aplicativo", - "appSourceURL": "URL de origem do aplicativo", - "error": "Erro", - "add": "Adicionar", - "searchSomeSourcesLabel": "Procurar (Apenas algumas fontes)", - "search": "Procurar", - "additionalOptsFor": "Opções adicionais para {}", - "supportedSources": "Fontes compatíveis", - "trackOnlyInBrackets": "(Apenas monitorar)", - "searchableInBrackets": "(Pesquisável)", - "appsString": "Aplicativos", - "noApps": "Não há aplicativos", - "noAppsForFilter": "Sem aplicativos 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 todos", - "deselectX": "Deselecionar {}", - "xWillBeRemovedButRemainInstalled": "{} será removido do Obtainium mais permanecerá instalado no dispositivo.", - "removeSelectedAppsQuestion": "Remover aplicativos selecionados?", - "removeSelectedApps": "Remover aplicativos selecionados", - "updateX": "Atualizar {}", - "installX": "Instalar {}", - "markXTrackOnlyAsUpdated": "Marcar {}\n(Apenas monitorar)\ncomo Atualizado", - "changeX": "Mudar {}", - "installUpdateApps": "Instalar/Atualizar aplicativos", - "installUpdateSelectedApps": "Instalar/Atualizar aplicativos selecionados", - "markXSelectedAppsAsUpdated": "Marcar {} aplicativos selecionados como atualizados?", - "no": "Não", - "yes": "Sim", - "markSelectedAppsUpdated": "Marcar aplicativos selecionados como Atualizados", - "pinToTop": "Fixar no topo", - "unpinFromTop": "Desafixar do topo", - "resetInstallStatusForSelectedAppsQuestion": "Reiniciar status de instalação para aplicativos selecionados?", - "installStatusOfXWillBeResetExplanation": "O status de instalação de qualquer aplicativo selecionado será reiniciado.\n\nIsso pode ajudar quando uma versão de um aplicativo mostrada no Obtainium é incorreta devido a falhas ao atualizar ou outros problemas.", - "customLinkMessage": "These links work on devices with Obtainium installed", - "shareAppConfigLinks": "Share app configuration as HTML link", - "shareSelectedAppURLs": "Compartilhar URLs de aplicativos selecionados", - "resetInstallStatus": "Reiniciar status de Iistalação", - "more": "Mais", - "removeOutdatedFilter": "Remover filtro de aplicativos desatualizados", - "showOutdatedOnly": "Mostrar apenas aplicativos desatualizados", - "filter": "Filtro", - "filterActive": "Filtro *", - "filterApps": "Filtrar aplicativos", - "appName": "Nome do aplicativo", - "author": "Autor", - "upToDateApps": "Aplicativos tualizados", - "nonInstalledApps": "Aplicativos 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 aplicativos", - "line": "Linha", - "searchX": "Pesquisa {}", - "noResults": "Nenhum resultado encontrado", - "importX": "Importar {}", - "importedAppsIdDisclaimer": "Aplicativos Importados podem ser mostrados incorretamente como \"Não Instalado\".\nPara consertar, reinstale-os usando o Obtainium.\nIsso não deve afetar dados do aplicativo.\n\nAfeta apenas métodos de importação de URL e de terceiros.", - "importErrors": "Erros de importação", - "importedXOfYApps": "{} de {} aplicativos importados.", - "followingURLsHadErrors": "As seguintes URLs apresentaram erros:", - "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 aplicativo por", - "authorName": "Autor/Nome", - "nameAuthor": "Nome/Autor", - "asAdded": "Como adicionado", - "appSortOrder": "Ordem de classificação de aplicativos", - "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ágina da internet em informações do aplicativo", - "pinUpdates": "Fixar atualizações no topo da janela de aplicativos", - "updates": "Atualizações", - "sourceSpecific": "Específico a fonte", - "appSource": "Fonte do aplicativo", - "noLogs": "Sem logs", - "appLogs": "Logs do aplicativo", - "close": "Fechar", - "share": "Compartilhar", - "appNotFound": "Aplicativo 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 aplicativo é '{}' mas a origem do pacote é '{}'. Continuar?", - "updatesAvailable": "Atualizações disponíveis", - "updatesAvailableNotifDescription": "Notifica o usuário quando atualizações de um ou mais aplicativos monitorados pelo Obtainium estão disponíveis", - "noNewUpdates": "Sem novas atualizações.", - "xHasAnUpdate": "{} tem uma atualização.", - "appsUpdated": "Aplicativos atualizados", - "appsUpdatedNotifDescription": "Notifica o usuário quando atualizações foram aplicadas em segundo-plano para um ou mais aplicativos ", - "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": "Aplicativos removidos", - "appsRemovedNotifDescription": "Notifica o usuário quando um ou mais aplicativos foram removidos devido a erros de carregamento", - "xWasRemovedDueToErrorY": "{} foi removido devido a este erro: {}", - "completeAppInstallation": "Instalação do aplicativo completa", - "obtainiumMustBeOpenToInstallApps": "Obtainium deve estar aberto para instalar os aplicativos", - "completeAppInstallationNotifDescription": "Pede ao usuário que retorne ao Obtainium para finalizar a instalação de um aplicativo", - "checkingForUpdates": "Verificando atualizações", - "checkingForUpdatesNotifDescription": "Notificação transiente que aparece quando o Obtainium está verificando se há atualizações", - "pleaseAllowInstallPerm": "Por favor, permita que o Obtainium possa instalar aplicativos", - "trackOnly": "Apenas monitorar", - "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 verificação de atualizações: {}", - "remove": "Remover", - "yesMarkUpdated": "Sim, marcar como Atualizado", - "fdroid": "F-Droid Official", - "appIdOrName": "ID do aplicativo ou nome", - "appId": "ID do aplicativo", - "appWithIdOrNameNotFound": "Nenhum aplicativo foi encontrado com esse ID ou nome", - "reposHaveMultipleApps": "Repositórios podem conter multiplos aplicativos", - "fdroidThirdPartyRepo": "Repositórios de terceiros F-Droid", - "steam": "Steam", - "steamMobile": "Steam Mobile", - "steamChat": "Steam Chat", - "install": "Instalar", - "markInstalled": "Marcar instalado", - "update": "Atualizar", - "markUpdated": "Marcar como atualizado", - "additionalOptions": "Opções adicionais", - "disableVersionDetection": "Desativar detecção de versão", - "noVersionDetectionExplanation": "Essa opção deve apenas ser usada por aplicativos onde a detecção de versão não funciona corretamente.", - "downloadingX": "Baixando {}", - "downloadNotifDescription": "Notifica o usuário o progresso do download de um aplicativo", - "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 aplicativos em categorias removidas serão descategorizados.", - "addCategory": "Adicionar categoria", - "label": "Etiqueta", - "language": "Linguagem", - "copiedToClipboard": "Copiado para a área de transferência", - "storagePermissionDenied": "Permissão de armazenamento negada", - "selectedCategorizeWarning": "Isso vai substituir qualquer configuração de categoria para os aplicativos selecionados.", - "filterAPKsByRegEx": "Filtrar APKs por expressão regular", - "removeFromObtainium": "Remover do Obtainium", - "uninstallFromDevice": "Desinstalar do dispositivo", - "onlyWorksWithNonVersionDetectApps": "Apenas funciona para aplicativos 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 Monitorar'", - "dontShowAPKOriginWarnings": "Não mostrar avisos de origem da APK", - "moveNonInstalledAppsToBottom": "Mover aplicativos não instalados para o fundo da lista de aplicativos", - "gitlabPATLabel": "Token de Acesso Pessoal do Gitlab\n(Ativa pesquisa e melhora a descoberta de APKs)", - "about": "Sobre", - "requiresCredentialsInSettings": "{}: Isso requer credenciais adicionais (em Configurações)", - "checkOnStart": "Verificar se há atualizações ao iniciar", - "tryInferAppIdFromCode": "Tente inferir o ID do aplicativo pelo código-fonte", - "removeOnExternalUninstall": "Remover automaticamente aplicativos desinstalados externamente", - "pickHighestVersionCode": "Auto-selecionar o maior número de versão do APK", - "checkUpdateOnDetailPage": "Checar por atualizações ao abrir a página de detalhes de um aplicativo", - "disablePageTransitions": "Desativar animações de transição de página", - "reversePageTransitions": "Reverter animações de transição de página", - "minStarCount": "Contagem mínima 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 endereço de download do APK no GitLab provavelmente não funcione sem que seja fornecido uma chave de API.", - "sortByLastLinkSegment": "Ordenar apenas usando o último segmento do link", - "filterReleaseNotesByRegEx": "Filtrar notas de versão usando Regex", - "customLinkFilterRegex": "Filtro de link personalizado usando expressão regular (Padrão '.apk$')", - "appsPossiblyUpdated": "Tentativas de atualização de aplicativos", - "appsPossiblyUpdatedNotifDescription": "Notifica o usuário de que atualizações de um ou mais aplicativos 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 aplicativos.", - "backgroundUpdateLimitsExplanation": "O sucesso de uma instalação em segundo-plano só pode ser determinado quando o Obtainium é aberto.", - "verifyLatestTag": "Verifique a 'última' etiqueta", - "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit", - "filterByLinkText": "Filtrar links pelo texto do link", - "intermediateLinkNotFound": "Link intermediário não encontrado", - "intermediateLink": "Link intermediário", - "exemptFromBackgroundUpdates": "Isento de atualizações em segundo-plano (se ativadas)", - "bgUpdatesOnWiFiOnly": "Desative as atualizações em segundo-plano quando não estiver conectado no Wi-Fi", - "autoSelectHighestVersionCode": "Auto-selecionar a versão mais recente", - "versionExtractionRegEx": "Regex de extração de versão", - "matchGroupToUse": "Grupo correspondente a ser usado no Regex de extração de versão", - "highlightTouchTargets": "Realçar áreas sensíveis ao toque que são menos óbvias", - "pickExportDir": "Escolher diretório para a exportação", - "autoExportOnChanges": "Auto-exportar em mudanças", - "includeSettings": "Incluir configurações", - "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", - "takeFirstLink": "Obter primeiro link", - "skipSort": "Ignorar ordenação", - "debugMenu": "Menu debug", - "bgTaskStarted": "Tarefa em segundo-plano iniciada - verifique os logs.", - "runBgCheckNow": "Execute agora em segundo-plano a verificação de atualizações", - "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": "Aplicativos atualizados", - "appsPossiblyUpdatedNotifChannel": "Tentativas de atualização de aplicativos", - "errorCheckingUpdatesNotifChannel": "Erro ao Procurar por Atualizações", - "appsRemovedNotifChannel": "Aplicativos removidos", - "downloadingXNotifChannel": "Baixando {}", - "completeAppInstallationNotifChannel": "Instalação completa do aplicativo", - "checkingForUpdatesNotifChannel": "Checando por Atualizações", - "onlyCheckInstalledOrTrackOnlyApps": "Apenas checar aplicativos instalados e 'Apenas Seguir' por updates", - "supportFixedAPKURL": "Suporte a APK com URLs fixas", - "selectX": "Selecionar {}", - "parallelDownloads": "Permitir downloads paralelos", - "installMethod": "Método de instalação", - "normal": "Normal", - "shizuku": "Shizuku", - "root": "Root", - "shizukuBinderNotFound": "O Shizuku não está rodando", - "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", - "useSystemFont":"Usar fonte padrão do sistema", - "systemFontError": "Erro ao carregar a fonte do sistema: {}", - "requestHeader": "Requisitar cabeçalho", - "removeAppQuestion": { - "one": "Remover aplicativo?", - "other": "Remover aplicativos?" - }, - "tooManyRequestsTryAgainInMinutes": { - "one": "Muitas solicitações (taxa de solicitações 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": "{} Aplicativo", - "other": "{} Aplicativos" - }, - "url": { - "one": "{} URL", - "other": "{} URLs" - }, - "minute": { - "one": "{} Minuto", - "other": "{} Minutos" - }, - "hour": { - "one": "{} Hora", - "other": "{} Horas" - }, - "day": { - "one": "{} Dia", - "other": "{} Dias" - }, - "clearedNLogsBeforeXAfterY": { - "one": "Foi limpo {n} log (antes = {antes}, depois = {depois})", - "other": "Foram limpos {n} logs (antes = {antes}, depois = {depois})" - }, - "xAndNMoreUpdatesAvailable": { - "one": "{} e 1 outro aplicativo possui atualizações.", - "other": "{} e {} outros aplicativo possuem atualizações." - }, - "xAndNMoreUpdatesInstalled": { - "one": "{} e um outro aplicativo foi atualizado.", - "other": "{} e {} outros aplicativos foram atualizados." - }, - "xAndNMoreUpdatesPossiblyInstalled": { - "one": "{} e 1 outro aplicativo pode ter sido atualizado.", - "other": "{} e {} outros aplicativos podem ter sido atualizados." - } +{ + "invalidURLForSource": "URL {} inválida", + "noReleaseFound": "Não foi possível encontrar uma versão adequada", + "noVersionFound": "Não foi possível encontrar uma versão", + "urlMatchesNoSource": "URL não corresponde a uma fonte conhecida", + "cantInstallOlderVersion": "Não é permitido instalar uma versão anterior de um aplicativo", + "appIdMismatch": "ID do pacote baixado não é igual ao ID do aplicativo 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 acesso pessoal do GitHub (Reduz tempos de espera)", + "includePrereleases": "Incluir pré-lançamentos", + "fallbackToOlderReleases": "Retornar para versões anteriores", + "filterReleaseTitlesByRegEx": "Filtrar títulos 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 monitorar'", + "source": "Fonte", + "app": "Aplicativo", + "appsFromSourceAreTrackOnly": "Os aplicativos desta fonte são 'Apenas monitorar'.", + "youPickedTrackOnly": "Você selecionou a opção 'Apenas monitorar'.", + "trackOnlyAppDescription": "As atualizações desse aplicativo serão monitoradas, mas o Obtainium não poderá baixá-lo ou instalá-lo.", + "cancelled": "Cancelado", + "appAlreadyAdded": "Aplicativo já adicionado", + "alreadyUpToDateQuestion": "Aplicativo já foi atualizado?", + "addApp": "Adicionar aplicativo", + "appSourceURL": "URL de origem do aplicativo", + "error": "Erro", + "add": "Adicionar", + "searchSomeSourcesLabel": "Procurar (Apenas algumas fontes)", + "search": "Procurar", + "additionalOptsFor": "Opções adicionais para {}", + "supportedSources": "Fontes compatíveis", + "trackOnlyInBrackets": "(Apenas monitorar)", + "searchableInBrackets": "(Pesquisável)", + "appsString": "Aplicativos", + "noApps": "Não há aplicativos", + "noAppsForFilter": "Sem aplicativos para filtrar", + "byX": "Por {}", + "percentProgress": "Progresso: {}%", + "pleaseWait": "Por favor, espere", + "updateAvailable": "Atualização disponível", + "estimateInBracketsShort": "(Aprox.)", + "notInstalled": "Não instalado", + "estimateInBrackets": "(Aproximado)", + "pseudoVersion": "pseudo-version", + "selectAll": "Selecionar todos", + "deselectX": "Deselecionar {}", + "xWillBeRemovedButRemainInstalled": "{} será removido do Obtainium mais permanecerá instalado no dispositivo.", + "removeSelectedAppsQuestion": "Remover aplicativos selecionados?", + "removeSelectedApps": "Remover aplicativos selecionados", + "updateX": "Atualizar {}", + "installX": "Instalar {}", + "markXTrackOnlyAsUpdated": "Marcar {}\n(Apenas monitorar)\ncomo Atualizado", + "changeX": "Mudar {}", + "installUpdateApps": "Instalar/Atualizar aplicativos", + "installUpdateSelectedApps": "Instalar/Atualizar aplicativos selecionados", + "markXSelectedAppsAsUpdated": "Marcar {} aplicativos selecionados como atualizados?", + "no": "Não", + "yes": "Sim", + "markSelectedAppsUpdated": "Marcar aplicativos selecionados como Atualizados", + "pinToTop": "Fixar no topo", + "unpinFromTop": "Desafixar do topo", + "resetInstallStatusForSelectedAppsQuestion": "Reiniciar status de instalação para aplicativos selecionados?", + "installStatusOfXWillBeResetExplanation": "O status de instalação de qualquer aplicativo selecionado será reiniciado.\n\nIsso pode ajudar quando uma versão de um aplicativo mostrada no Obtainium é incorreta devido a falhas ao atualizar ou outros problemas.", + "customLinkMessage": "These links work on devices with Obtainium installed", + "shareAppConfigLinks": "Share app configuration as HTML link", + "shareSelectedAppURLs": "Compartilhar URLs de aplicativos selecionados", + "resetInstallStatus": "Reiniciar status de Iistalação", + "more": "Mais", + "removeOutdatedFilter": "Remover filtro de aplicativos desatualizados", + "showOutdatedOnly": "Mostrar apenas aplicativos desatualizados", + "filter": "Filtro", + "filterActive": "Filtro *", + "filterApps": "Filtrar aplicativos", + "appName": "Nome do aplicativo", + "author": "Autor", + "upToDateApps": "Aplicativos tualizados", + "nonInstalledApps": "Aplicativos 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 aplicativos", + "line": "Linha", + "searchX": "Pesquisa {}", + "noResults": "Nenhum resultado encontrado", + "importX": "Importar {}", + "importedAppsIdDisclaimer": "Aplicativos Importados podem ser mostrados incorretamente como \"Não Instalado\".\nPara consertar, reinstale-os usando o Obtainium.\nIsso não deve afetar dados do aplicativo.\n\nAfeta apenas métodos de importação de URL e de terceiros.", + "importErrors": "Erros de importação", + "importedXOfYApps": "{} de {} aplicativos importados.", + "followingURLsHadErrors": "As seguintes URLs apresentaram erros:", + "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 aplicativo por", + "authorName": "Autor/Nome", + "nameAuthor": "Nome/Autor", + "asAdded": "Como adicionado", + "appSortOrder": "Ordem de classificação de aplicativos", + "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ágina da internet em informações do aplicativo", + "pinUpdates": "Fixar atualizações no topo da janela de aplicativos", + "updates": "Atualizações", + "sourceSpecific": "Específico a fonte", + "appSource": "Fonte do aplicativo", + "noLogs": "Sem logs", + "appLogs": "Logs do aplicativo", + "close": "Fechar", + "share": "Compartilhar", + "appNotFound": "Aplicativo 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 aplicativo é '{}' mas a origem do pacote é '{}'. Continuar?", + "updatesAvailable": "Atualizações disponíveis", + "updatesAvailableNotifDescription": "Notifica o usuário quando atualizações de um ou mais aplicativos monitorados pelo Obtainium estão disponíveis", + "noNewUpdates": "Sem novas atualizações.", + "xHasAnUpdate": "{} tem uma atualização.", + "appsUpdated": "Aplicativos atualizados", + "appsUpdatedNotifDescription": "Notifica o usuário quando atualizações foram aplicadas em segundo-plano para um ou mais aplicativos ", + "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": "Aplicativos removidos", + "appsRemovedNotifDescription": "Notifica o usuário quando um ou mais aplicativos foram removidos devido a erros de carregamento", + "xWasRemovedDueToErrorY": "{} foi removido devido a este erro: {}", + "completeAppInstallation": "Instalação do aplicativo completa", + "obtainiumMustBeOpenToInstallApps": "Obtainium deve estar aberto para instalar os aplicativos", + "completeAppInstallationNotifDescription": "Pede ao usuário que retorne ao Obtainium para finalizar a instalação de um aplicativo", + "checkingForUpdates": "Verificando atualizações", + "checkingForUpdatesNotifDescription": "Notificação transiente que aparece quando o Obtainium está verificando se há atualizações", + "pleaseAllowInstallPerm": "Por favor, permita que o Obtainium possa instalar aplicativos", + "trackOnly": "Apenas monitorar", + "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 verificação de atualizações: {}", + "remove": "Remover", + "yesMarkUpdated": "Sim, marcar como Atualizado", + "fdroid": "F-Droid Official", + "appIdOrName": "ID do aplicativo ou nome", + "appId": "ID do aplicativo", + "appWithIdOrNameNotFound": "Nenhum aplicativo foi encontrado com esse ID ou nome", + "reposHaveMultipleApps": "Repositórios podem conter multiplos aplicativos", + "fdroidThirdPartyRepo": "Repositórios de terceiros F-Droid", + "steam": "Steam", + "steamMobile": "Steam Mobile", + "steamChat": "Steam Chat", + "install": "Instalar", + "markInstalled": "Marcar instalado", + "update": "Atualizar", + "markUpdated": "Marcar como atualizado", + "additionalOptions": "Opções adicionais", + "disableVersionDetection": "Desativar detecção de versão", + "noVersionDetectionExplanation": "Essa opção deve apenas ser usada por aplicativos onde a detecção de versão não funciona corretamente.", + "downloadingX": "Baixando {}", + "downloadNotifDescription": "Notifica o usuário o progresso do download de um aplicativo", + "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 aplicativos em categorias removidas serão descategorizados.", + "addCategory": "Adicionar categoria", + "label": "Etiqueta", + "language": "Linguagem", + "copiedToClipboard": "Copiado para a área de transferência", + "storagePermissionDenied": "Permissão de armazenamento negada", + "selectedCategorizeWarning": "Isso vai substituir qualquer configuração de categoria para os aplicativos selecionados.", + "filterAPKsByRegEx": "Filtrar APKs por expressão regular", + "removeFromObtainium": "Remover do Obtainium", + "uninstallFromDevice": "Desinstalar do dispositivo", + "onlyWorksWithNonVersionDetectApps": "Apenas funciona para aplicativos 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 Monitorar'", + "dontShowAPKOriginWarnings": "Não mostrar avisos de origem da APK", + "moveNonInstalledAppsToBottom": "Mover aplicativos não instalados para o fundo da lista de aplicativos", + "gitlabPATLabel": "Token de Acesso Pessoal do Gitlab\n(Ativa pesquisa e melhora a descoberta de APKs)", + "about": "Sobre", + "requiresCredentialsInSettings": "{}: Isso requer credenciais adicionais (em Configurações)", + "checkOnStart": "Verificar se há atualizações ao iniciar", + "tryInferAppIdFromCode": "Tente inferir o ID do aplicativo pelo código-fonte", + "removeOnExternalUninstall": "Remover automaticamente aplicativos desinstalados externamente", + "pickHighestVersionCode": "Auto-selecionar o maior número de versão do APK", + "checkUpdateOnDetailPage": "Checar por atualizações ao abrir a página de detalhes de um aplicativo", + "disablePageTransitions": "Desativar animações de transição de página", + "reversePageTransitions": "Reverter animações de transição de página", + "minStarCount": "Contagem mínima 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 endereço de download do APK no GitLab provavelmente não funcione sem que seja fornecido uma chave de API.", + "sortByLastLinkSegment": "Ordenar apenas usando o último segmento do link", + "filterReleaseNotesByRegEx": "Filtrar notas de versão usando Regex", + "customLinkFilterRegex": "Filtro de link personalizado usando expressão regular (Padrão '.apk$')", + "appsPossiblyUpdated": "Tentativas de atualização de aplicativos", + "appsPossiblyUpdatedNotifDescription": "Notifica o usuário de que atualizações de um ou mais aplicativos 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 aplicativos.", + "backgroundUpdateLimitsExplanation": "O sucesso de uma instalação em segundo-plano só pode ser determinado quando o Obtainium é aberto.", + "verifyLatestTag": "Verifique a 'última' etiqueta", + "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit", + "filterByLinkText": "Filtrar links pelo texto do link", + "intermediateLinkNotFound": "Link intermediário não encontrado", + "intermediateLink": "Link intermediário", + "exemptFromBackgroundUpdates": "Isento de atualizações em segundo-plano (se ativadas)", + "bgUpdatesOnWiFiOnly": "Desative as atualizações em segundo-plano quando não estiver conectado no Wi-Fi", + "autoSelectHighestVersionCode": "Auto-selecionar a versão mais recente", + "versionExtractionRegEx": "Regex de extração de versão", + "matchGroupToUse": "Grupo correspondente a ser usado no Regex de extração de versão", + "highlightTouchTargets": "Realçar áreas sensíveis ao toque que são menos óbvias", + "pickExportDir": "Escolher diretório para a exportação", + "autoExportOnChanges": "Auto-exportar em mudanças", + "includeSettings": "Incluir configurações", + "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", + "takeFirstLink": "Obter primeiro link", + "skipSort": "Ignorar ordenação", + "debugMenu": "Menu debug", + "bgTaskStarted": "Tarefa em segundo-plano iniciada - verifique os logs.", + "runBgCheckNow": "Execute agora em segundo-plano a verificação de atualizações", + "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": "Aplicativos atualizados", + "appsPossiblyUpdatedNotifChannel": "Tentativas de atualização de aplicativos", + "errorCheckingUpdatesNotifChannel": "Erro ao Procurar por Atualizações", + "appsRemovedNotifChannel": "Aplicativos removidos", + "downloadingXNotifChannel": "Baixando {}", + "completeAppInstallationNotifChannel": "Instalação completa do aplicativo", + "checkingForUpdatesNotifChannel": "Checando por Atualizações", + "onlyCheckInstalledOrTrackOnlyApps": "Apenas checar aplicativos instalados e 'Apenas Seguir' por updates", + "supportFixedAPKURL": "Suporte a APK com URLs fixas", + "selectX": "Selecionar {}", + "parallelDownloads": "Permitir downloads paralelos", + "installMethod": "Método de instalação", + "normal": "Normal", + "shizuku": "Shizuku", + "root": "Root", + "shizukuBinderNotFound": "O Shizuku não está rodando", + "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", + "useSystemFont": "Usar fonte padrão do sistema", + "systemFontError": "Erro ao carregar a fonte do sistema: {}", + "requestHeader": "Requisitar cabeçalho", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", + "removeAppQuestion": { + "one": "Remover aplicativo?", + "other": "Remover aplicativos?" + }, + "tooManyRequestsTryAgainInMinutes": { + "one": "Muitas solicitações (taxa de solicitações 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": "{} Aplicativo", + "other": "{} Aplicativos" + }, + "url": { + "one": "{} URL", + "other": "{} URLs" + }, + "minute": { + "one": "{} Minuto", + "other": "{} Minutos" + }, + "hour": { + "one": "{} Hora", + "other": "{} Horas" + }, + "day": { + "one": "{} Dia", + "other": "{} Dias" + }, + "clearedNLogsBeforeXAfterY": { + "one": "Foi limpo {n} log (antes = {antes}, depois = {depois})", + "other": "Foram limpos {n} logs (antes = {antes}, depois = {depois})" + }, + "xAndNMoreUpdatesAvailable": { + "one": "{} e 1 outro aplicativo possui atualizações.", + "other": "{} e {} outros aplicativo possuem atualizações." + }, + "xAndNMoreUpdatesInstalled": { + "one": "{} e um outro aplicativo foi atualizado.", + "other": "{} e {} outros aplicativos foram atualizados." + }, + "xAndNMoreUpdatesPossiblyInstalled": { + "one": "{} e 1 outro aplicativo pode ter sido atualizado.", + "other": "{} e {} outros aplicativos podem ter sido atualizados." + } } \ No newline at end of file diff --git a/assets/translations/ru.json b/assets/translations/ru.json index dbb281f..3f12321 100644 --- a/assets/translations/ru.json +++ b/assets/translations/ru.json @@ -51,9 +51,8 @@ "percentProgress": "Прогресс: {}%", "pleaseWait": "Пожалуйста, подождите", "updateAvailable": "Доступно обновление", - "estimateInBracketsShort": "(Оценка)", "notInstalled": "Не установлено", - "estimateInBrackets": "(Оценка)", + "pseudoVersion": "pseudo-version", "selectAll": "Выбрать всё", "deselectX": "Отменить выбор {}", "xWillBeRemovedButRemainInstalled": "{} будет удалено из Obtainium, но останется на устройстве", @@ -213,6 +212,7 @@ "changes": "Изменения", "releaseDate": "Дата выпуска", "importFromURLsInFile": "Импорт из файла URL-адресов (например: OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Определение версии", "standardVersionDetection": "Стандартное", "groupByCategory": "Группировать по категориям", @@ -294,6 +294,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "Удалить приложение?", "other": "Удалить приложения?" diff --git a/assets/translations/sv.json b/assets/translations/sv.json index 9c068c7..404fa9d 100644 --- a/assets/translations/sv.json +++ b/assets/translations/sv.json @@ -51,9 +51,8 @@ "percentProgress": "Progress: {}%", "pleaseWait": "Vänta", "updateAvailable": "Uppdatering Tillgänglig", - "estimateInBracketsShort": "(Est.)", "notInstalled": "Inte Installerad", - "estimateInBrackets": "(Uppskattning)", + "pseudoVersion": "pseudo-version", "selectAll": "Välj Alla", "deselectX": "Avmarkera {}", "xWillBeRemovedButRemainInstalled": "{} kommer tas bort från Obtainium men kommer vara fortsatt installerad på enheten.", @@ -213,6 +212,7 @@ "changes": "Ändringar", "releaseDate": "Releasedatum", "importFromURLsInFile": "Importera från URL:er i fil (som OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Versionsdetektering", "standardVersionDetection": "Standardversionsdetektering", "groupByCategory": "Gruppera via Kategori", @@ -278,6 +278,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "Ta Bort App?", "other": "Ta Bort Appar?" diff --git a/assets/translations/tr.json b/assets/translations/tr.json index 1b6ba32..debb8cf 100644 --- a/assets/translations/tr.json +++ b/assets/translations/tr.json @@ -51,9 +51,8 @@ "percentProgress": "İlerleme: {}%", "pleaseWait": "Lütfen Bekleyin", "updateAvailable": "Güncelleme Var", - "estimateInBracketsShort": "(Est.)", "notInstalled": "Yüklenmedi", - "estimateInBrackets": "(Tahmini)", + "pseudoVersion": "pseudo-version", "selectAll": "Hepsini Seç", "deselectX": "{}'yi Seçimden Kaldır", "xWillBeRemovedButRemainInstalled": "{} Obtainium'dan kaldırılacak ancak cihazınızda yüklü kalacaktır.", @@ -213,6 +212,7 @@ "changes": "Değişiklikler", "releaseDate": "Yayın Tarihi", "importFromURLsInFile": "Dosyadaki URL'lerden İçe Aktar", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "Sürüm Tespiti", "standardVersionDetection": "Standart sürüm tespiti", "groupByCategory": "Kategoriye Göre Grupla", @@ -292,6 +292,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "Uygulamayı Kaldır?", "other": "Uygulamaları Kaldır?" diff --git a/assets/translations/vi.json b/assets/translations/vi.json index 6bbbf1c..eb90c3c 100644 --- a/assets/translations/vi.json +++ b/assets/translations/vi.json @@ -51,9 +51,8 @@ "percentProgress": "Đang tải {}%", "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)", + "pseudoVersion": "pseudo-version", "selectAll": "Chọn tất cả", "deselectX": "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ị.", @@ -213,6 +212,7 @@ "changes": "Thay đổi", "releaseDate": "Ngày phát hành", "importFromURLsInFile": "Nhập từ URL trong Tệp (như OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "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", @@ -290,6 +290,14 @@ "root": "Root", "shizukuBinderNotFound": "Shizuku chưa khởi động", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion":{ "one": "Gỡ ứng dụng?", "other": "Gỡ ứng dụng?" diff --git a/assets/translations/zh.json b/assets/translations/zh.json index 07be631..391c429 100644 --- a/assets/translations/zh.json +++ b/assets/translations/zh.json @@ -51,9 +51,8 @@ "percentProgress": "进度:{}%", "pleaseWait": "请稍候", "updateAvailable": "更新可用", - "estimateInBracketsShort": "(推测)", "notInstalled": "未安装", - "estimateInBrackets": "(推测)", + "pseudoVersion": "pseudo-version", "selectAll": "全选", "deselectX": "取消选择 {}", "xWillBeRemovedButRemainInstalled": "“{}”将从 Obtainium 中删除,但仍安装在您的设备中。", @@ -213,6 +212,7 @@ "changes": "更新日志", "releaseDate": "发行日期", "importFromURLsInFile": "从文件中的 URL 导入(如 OPML)", + "versionDetectionExplanation": "Reconcile version string with version detected from OS", "versionDetection": "版本检测", "standardVersionDetection": "常规版本检测", "groupByCategory": "按类别分组显示", @@ -294,6 +294,14 @@ "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version", "requestHeader": "Request header", "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date", + "defaultPseudoVersioningMethod": "Default Pseudo-Versioning Method", + "partialAPKHash": "Partial APK Hash", + "APKLinkHash": "APK Link Hash", + "directAPKLink": "Direct APK Link", + "pseudoVersionInUse": "A Pseudo-Version is in Use", + "installed": "Installed", + "latest": "Latest", + "invertRegEx": "Invert regular expression", "removeAppQuestion": { "one": "是否删除应用?", "other": "是否删除应用?" diff --git a/lib/app_sources/apkcombo.dart b/lib/app_sources/apkcombo.dart index 1a58847..3a1ae49 100644 --- a/lib/app_sources/apkcombo.dart +++ b/lib/app_sources/apkcombo.dart @@ -6,6 +6,7 @@ import 'package:obtainium/providers/source_provider.dart'; class APKCombo extends AppSource { APKCombo() { hosts = ['apkcombo.com']; + showReleaseDateAsVersionToggle = true; } @override diff --git a/lib/app_sources/apkmirror.dart b/lib/app_sources/apkmirror.dart index 4e3cd1f..236a300 100644 --- a/lib/app_sources/apkmirror.dart +++ b/lib/app_sources/apkmirror.dart @@ -11,6 +11,7 @@ class APKMirror extends AppSource { APKMirror() { hosts = ['apkmirror.com']; enforceTrackOnly = true; + showReleaseDateAsVersionToggle = true; additionalSourceAppSpecificSettingFormItems = [ [ diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index f4c0026..715a8d3 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -23,6 +23,7 @@ class APKPure extends AppSource { hosts = ['apkpure.net', 'apkpure.com']; allowSubDomains = true; naiveStandardVersionDetection = true; + showReleaseDateAsVersionToggle = true; } @override diff --git a/lib/app_sources/aptoide.dart b/lib/app_sources/aptoide.dart index a2795d6..9daf57b 100644 --- a/lib/app_sources/aptoide.dart +++ b/lib/app_sources/aptoide.dart @@ -10,6 +10,7 @@ class Aptoide extends AppSource { name = 'Aptoide'; allowSubDomains = true; naiveStandardVersionDetection = true; + showReleaseDateAsVersionToggle = true; } @override diff --git a/lib/app_sources/directAPKLink.dart b/lib/app_sources/directAPKLink.dart new file mode 100644 index 0000000..def21dd --- /dev/null +++ b/lib/app_sources/directAPKLink.dart @@ -0,0 +1,44 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:obtainium/app_sources/html.dart'; +import 'package:obtainium/providers/source_provider.dart'; + +class DirectAPKLink extends AppSource { + HTML html = HTML(); + + DirectAPKLink() { + neverAutoSelect = true; + name = tr('directAPKLink'); + additionalSourceAppSpecificSettingFormItems = html + .additionalSourceAppSpecificSettingFormItems + .where((element) => element + .where((element) => element.key == 'requestHeader') + .isNotEmpty) + .toList(); + excludeCommonSettingKeys = [ + 'versionExtractionRegEx', + 'matchGroupToUse', + 'versionDetection', + 'useVersionCodeAsOSVersion', + 'apkFilterRegEx', + 'autoApkFilterByArch' + ]; + } + + @override + Future getLatestAPKDetails( + String standardUrl, + Map additionalSettings, + ) async { + var additionalSettingsNew = + getDefaultValuesFromFormItems(html.combinedAppSpecificSettingFormItems); + for (var s in additionalSettings.keys) { + if (additionalSettingsNew.containsKey(s)) { + additionalSettingsNew[s] = additionalSettings[s]; + } + } + additionalSettingsNew['defaultPseudoVersioningMethod'] = 'partialAPKHash'; + additionalSettingsNew['directAPKLink'] = true; + additionalSettings['versionDetection'] = false; + return html.getLatestAPKDetails(standardUrl, additionalSettingsNew); + } +} diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index a1c571b..7722d9f 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -10,6 +10,7 @@ class FDroidRepo extends AppSource { canSearch = true; excludeFromMassSearch = true; neverAutoSelect = true; + showReleaseDateAsVersionToggle = true; additionalSourceAppSpecificSettingFormItems = [ [ diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index c08ae5a..151e159 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -16,6 +16,7 @@ class GitHub extends AppSource { GitHub() { hosts = ['github.com']; appIdInferIsOptional = true; + showReleaseDateAsVersionToggle = true; sourceConfigSettingFormItems = [ GeneratedFormTextField('github-creds', @@ -381,11 +382,8 @@ class GitHub extends AppSource { continue; } var apkUrls = getReleaseAPKUrls(releases[i]); - if (additionalSettings['apkFilterRegEx'] != null) { - var reg = RegExp(additionalSettings['apkFilterRegEx']); - apkUrls = - apkUrls.where((element) => reg.hasMatch(element.key)).toList(); - } + apkUrls = filterApks(apkUrls, additionalSettings['apkFilterRegEx'], + additionalSettings['invertAPKFilter']); if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) { continue; } diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index 0b7776f..3e1e701 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -15,6 +15,7 @@ class GitLab extends AppSource { GitLab() { hosts = ['gitlab.com']; canSearch = true; + showReleaseDateAsVersionToggle = true; sourceConfigSettingFormItems = [ GeneratedFormTextField('gitlab-creds', diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index 106be54..db413ec 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -108,11 +108,7 @@ class HTML extends AppSource { [ GeneratedFormSwitch('versionExtractWholePage', label: tr('versionExtractWholePage')) - ], - [ - GeneratedFormSwitch('supportFixedAPKURL', - defaultValue: true, label: tr('supportFixedAPKURL')), - ], + ] ]; var commonFormItems = [ [GeneratedFormSwitch('filterByLinkText', label: tr('filterByLinkText'))], @@ -172,10 +168,18 @@ class HTML extends AppSource { 'User-Agent: Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36' } ]) + ], + [ + GeneratedFormDropdown( + 'defaultPseudoVersioningMethod', + [ + MapEntry('partialAPKHash', tr('partialAPKHash')), + MapEntry('APKLinkHash', tr('APKLinkHash')) + ], + label: tr('defaultPseudoVersioningMethod'), + defaultValue: 'partialAPKHash') ] ]; - overrideVersionDetectionFormDefault('noVersionDetection', - disableStandard: false, disableRelDate: true); } @override @@ -288,17 +292,21 @@ class HTML extends AppSource { currentUrl = intLinks.last.key; } } - var uri = Uri.parse(currentUrl); - Response res = await sourceRequest(currentUrl, additionalSettings); - var links = await grabLinksCommon(res, additionalSettings); - - if ((additionalSettings['apkFilterRegEx'] as String?)?.isNotEmpty == true) { - var reg = RegExp(additionalSettings['apkFilterRegEx']); - links = links.where((element) => reg.hasMatch(element.key)).toList(); - } - if (links.isEmpty) { - throw NoReleasesError(); + List> links = []; + String versionExtractionWholePageString = currentUrl; + if (additionalSettings['directAPKLink'] != true) { + Response res = await sourceRequest(currentUrl, additionalSettings); + versionExtractionWholePageString = + res.body.split('\r\n').join('\n').split('\n').join('\\n'); + links = await grabLinksCommon(res, additionalSettings); + links = filterApks(links, additionalSettings['apkFilterRegEx'], + additionalSettings['invertAPKFilter']); + if (links.isEmpty) { + throw NoReleasesError(); + } + } else { + links = [MapEntry(currentUrl, currentUrl)]; } var rel = links.last.key; String? version; @@ -306,11 +314,12 @@ class HTML extends AppSource { additionalSettings['versionExtractionRegEx'] as String?, additionalSettings['matchGroupToUse'] as String?, additionalSettings['versionExtractWholePage'] == true - ? res.body.split('\r\n').join('\n').split('\n').join('\\n') + ? versionExtractionWholePageString : rel); - version ??= additionalSettings['supportFixedAPKURL'] != true - ? rel.hashCode.toString() - : (await checkDownloadHash(rel)).toString(); + version ??= + additionalSettings['defaultPseudoVersioningMethod'] == 'APKLinkHash' + ? rel.hashCode.toString() + : (await checkPartialDownloadHashDynamc(rel)).toString(); return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(), AppNames(uri.host, tr('app'))); } diff --git a/lib/app_sources/huaweiappgallery.dart b/lib/app_sources/huaweiappgallery.dart index 54ab2ec..2c4d480 100644 --- a/lib/app_sources/huaweiappgallery.dart +++ b/lib/app_sources/huaweiappgallery.dart @@ -7,8 +7,8 @@ class HuaweiAppGallery extends AppSource { HuaweiAppGallery() { name = 'Huawei AppGallery'; hosts = ['appgallery.huawei.com']; - overrideVersionDetectionFormDefault('releaseDateAsVersion', - disableStandard: true); + versionDetectionDisallowed = true; + showReleaseDateAsVersionToggle = true; } @override diff --git a/lib/app_sources/jenkins.dart b/lib/app_sources/jenkins.dart index 8e817db..39a4f79 100644 --- a/lib/app_sources/jenkins.dart +++ b/lib/app_sources/jenkins.dart @@ -6,9 +6,9 @@ import 'package:obtainium/providers/source_provider.dart'; class Jenkins extends AppSource { Jenkins() { - overrideVersionDetectionFormDefault('releaseDateAsVersion', - disableStandard: true); + versionDetectionDisallowed = true; neverAutoSelect = true; + showReleaseDateAsVersionToggle = true; } String trimJobUrl(String url) { diff --git a/lib/app_sources/neutroncode.dart b/lib/app_sources/neutroncode.dart index b0f2d93..0429718 100644 --- a/lib/app_sources/neutroncode.dart +++ b/lib/app_sources/neutroncode.dart @@ -6,6 +6,7 @@ import 'package:obtainium/providers/source_provider.dart'; class NeutronCode extends AppSource { NeutronCode() { hosts = ['neutroncode.com']; + showReleaseDateAsVersionToggle = true; } @override diff --git a/lib/app_sources/sourcehut.dart b/lib/app_sources/sourcehut.dart index bb19b96..0c691c4 100644 --- a/lib/app_sources/sourcehut.dart +++ b/lib/app_sources/sourcehut.dart @@ -9,6 +9,7 @@ import 'package:easy_localization/easy_localization.dart'; class SourceHut extends AppSource { SourceHut() { hosts = ['git.sr.ht']; + showReleaseDateAsVersionToggle = true; additionalSourceAppSpecificSettingFormItems = [ [ diff --git a/lib/app_sources/uptodown.dart b/lib/app_sources/uptodown.dart index fe3d589..00de36c 100644 --- a/lib/app_sources/uptodown.dart +++ b/lib/app_sources/uptodown.dart @@ -9,6 +9,7 @@ class Uptodown extends AppSource { hosts = ['uptodown.com']; allowSubDomains = true; naiveStandardVersionDetection = true; + showReleaseDateAsVersionToggle = true; } @override diff --git a/lib/app_sources/whatsapp.dart b/lib/app_sources/whatsapp.dart index e9ad7c5..94b26d1 100644 --- a/lib/app_sources/whatsapp.dart +++ b/lib/app_sources/whatsapp.dart @@ -6,8 +6,7 @@ import 'package:obtainium/providers/source_provider.dart'; class WhatsApp extends AppSource { WhatsApp() { hosts = ['whatsapp.com']; - overrideVersionDetectionFormDefault('noVersionDetection', - disableStandard: true, disableRelDate: true); + versionDetectionDisallowed = true; } @override diff --git a/lib/components/generated_form.dart b/lib/components/generated_form.dart index 8c36b3f..c8d059a 100644 --- a/lib/components/generated_form.dart +++ b/lib/components/generated_form.dart @@ -96,11 +96,14 @@ class GeneratedFormDropdown extends GeneratedFormItem { } class GeneratedFormSwitch extends GeneratedFormItem { + bool disabled = false; + GeneratedFormSwitch( super.key, { super.label, super.belowWidgets, bool super.defaultValue = false, + bool disabled = false, List super.additionalValidators = const [], }); @@ -115,6 +118,7 @@ class GeneratedFormSwitch extends GeneratedFormItem { label: label, belowWidgets: belowWidgets, defaultValue: defaultValue, + disabled: false, additionalValidators: List.from(additionalValidators)); } } @@ -368,15 +372,51 @@ class _GeneratedFormState extends State { ), Switch( value: values[fieldKey], - onChanged: (value) { - setState(() { - values[fieldKey] = value; - someValueChanged(); - }); - }) + onChanged: + (widget.items[r][e] as GeneratedFormSwitch).disabled + ? null + : (value) { + setState(() { + values[fieldKey] = value; + someValueChanged(); + }); + }) ], ); } else if (widget.items[r][e] is GeneratedFormTagInput) { + onAddPressed() { + showDialog?>( + context: context, + builder: (BuildContext ctx) { + return GeneratedFormModal( + title: widget.items[r][e].label, + items: [ + [GeneratedFormTextField('label', label: tr('label'))] + ]); + }).then((value) { + String? label = value?['label']; + if (label != null) { + setState(() { + var temp = + values[fieldKey] as Map>?; + temp ??= {}; + if (temp[label] == null) { + var singleSelect = + (widget.items[r][e] as GeneratedFormTagInput) + .singleSelect; + var someSelected = temp.entries + .where((element) => element.value.value) + .isNotEmpty; + temp[label] = MapEntry(generateRandomLightColor().value, + !(someSelected && singleSelect)); + values[fieldKey] = temp; + someValueChanged(); + } + }); + } + }); + } + formInputs[r][e] = Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if ((values[fieldKey] as Map>?) @@ -402,14 +442,14 @@ class _GeneratedFormState extends State { (widget.items[r][e] as GeneratedFormTagInput).alignment, crossAxisAlignment: WrapCrossAlignment.center, children: [ - (values[fieldKey] as Map>?) - ?.isEmpty == - true - ? Text( - (widget.items[r][e] as GeneratedFormTagInput) - .emptyMessage, - ) - : const SizedBox.shrink(), + // (values[fieldKey] as Map>?) + // ?.isEmpty == + // true + // ? Text( + // (widget.items[r][e] as GeneratedFormTagInput) + // .emptyMessage, + // ) + // : const SizedBox.shrink(), ...(values[fieldKey] as Map>?) ?.entries .map((e2) { @@ -533,49 +573,26 @@ class _GeneratedFormState extends State { tooltip: tr('remove'), )) : const SizedBox.shrink(), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: IconButton( - onPressed: () { - showDialog?>( - context: context, - builder: (BuildContext ctx) { - return GeneratedFormModal( - title: widget.items[r][e].label, - items: [ - [ - GeneratedFormTextField('label', - label: tr('label')) - ] - ]); - }).then((value) { - String? label = value?['label']; - if (label != null) { - setState(() { - var temp = values[fieldKey] - as Map>?; - temp ??= {}; - if (temp[label] == null) { - var singleSelect = (widget.items[r][e] - as GeneratedFormTagInput) - .singleSelect; - var someSelected = temp.entries - .where((element) => element.value.value) - .isNotEmpty; - temp[label] = MapEntry( - generateRandomLightColor().value, - !(someSelected && singleSelect)); - values[fieldKey] = temp; - someValueChanged(); - } - }); - } - }); - }, - icon: const Icon(Icons.add), - visualDensity: VisualDensity.compact, - tooltip: tr('add'), - )), + (values[fieldKey] as Map>?) + ?.isEmpty == + true + ? Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: TextButton.icon( + onPressed: onAddPressed, + icon: const Icon(Icons.add), + label: Text( + (widget.items[r][e] as GeneratedFormTagInput) + .label), + )) + : Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: IconButton( + onPressed: onAddPressed, + icon: const Icon(Icons.add), + visualDensity: VisualDensity.compact, + tooltip: tr('add'), + )), ], ) ]); diff --git a/lib/main.dart b/lib/main.dart index c965ce2..52538d4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -185,7 +185,9 @@ class _ObtainiumState extends State { 0, { 'includePrereleases': true, - 'versionDetection': 'standardVersionDetection' + 'versionDetection': true, + 'apkFilterRegEx': 'fdroid', + 'invertAPKFilter': true }, null, false) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 41deae2..820e08d 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -135,8 +135,7 @@ class AddAppPageState extends State { getReleaseDateAsVersionConfirmationIfNeeded( bool userPickedTrackOnly) async { - return (!(additionalSettings['versionDetection'] == - 'releaseDateAsVersion' && + return (!(additionalSettings['releaseDateAsVersion'] == true && // ignore: use_build_context_synchronously await showDialog( context: context, @@ -192,8 +191,7 @@ class AddAppPageState extends State { throw ObtainiumError(tr('appAlreadyAdded')); } if (app.additionalSettings['trackOnly'] == true || - app.additionalSettings['versionDetection'] != - 'standardVersionDetection') { + app.additionalSettings['versionDetection'] != true) { app.installedVersion = app.latestVersion; } app.categories = pickedCategories; @@ -498,36 +496,61 @@ class AddAppPageState extends State { ], ); - Widget getSourcesListWidget() => Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, + Widget getSourcesListWidget() => Padding( + padding: const EdgeInsets.all(16), + child: Row( children: [ - Text( - tr('supportedSources'), - style: const TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox( - height: 16, - ), - ...sourceProvider.sources.map((e) => GestureDetector( - onTap: e.hosts.isNotEmpty - ? () { - launchUrlString('https://${e.hosts[0]}', - mode: LaunchMode.externalApplication); - } - : null, + GestureDetector( + onTap: () { + showDialog( + context: context, + builder: (context) { + return GeneratedFormModal( + singleNullReturnButton: tr('ok'), + title: tr('supportedSources'), + items: const [], + additionalWidgets: [ + ...sourceProvider.sources.map( + (e) => Padding( + padding: + const EdgeInsets.symmetric(vertical: 4), + child: GestureDetector( + onTap: e.hosts.isNotEmpty + ? () { + launchUrlString( + 'https://${e.hosts[0]}', + mode: LaunchMode + .externalApplication); + } + : null, + child: Text( + '${e.name}${e.enforceTrackOnly ? ' ${tr('trackOnlyInBrackets')}' : ''}${e.canSearch ? ' ${tr('searchableInBrackets')}' : ''}', + style: TextStyle( + decoration: e.hosts.isNotEmpty + ? TextDecoration.underline + : TextDecoration.none), + ))), + ) + ], + ); + }, + ); + }, child: Text( - '${e.name}${e.enforceTrackOnly ? ' ${tr('trackOnlyInBrackets')}' : ''}${e.canSearch ? ' ${tr('searchableInBrackets')}' : ''}', - style: TextStyle( - decoration: e.hosts.isNotEmpty - ? TextDecoration.underline - : TextDecoration.none, + tr('supportedSources'), + style: const TextStyle( + fontWeight: FontWeight.bold, + decoration: TextDecoration.underline, fontStyle: FontStyle.italic), - ))) - ]); + )) + ], + ), + ); return Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, + bottomNavigationBar: + pickedSource == null ? getSourcesListWidget() : null, body: CustomScrollView(shrinkWrap: true, slivers: [ CustomAppBar(title: tr('addApp')), SliverToBoxAdapter( @@ -559,18 +582,7 @@ class AddAppPageState extends State { : const SizedBox(); }, future: pickedSource?.getSourceNote()), - SizedBox( - height: pickedSource != null ? 16 : 96, - ), if (pickedSource != null) getAdditionalOptsCol(), - if (pickedSource == null) - const Divider( - height: 48, - ), - if (pickedSource == null) getSourcesListWidget(), - SizedBox( - height: pickedSource != null ? 8 : 2, - ), ])), ) ])); diff --git a/lib/pages/app.dart b/lib/pages/app.dart index 18bd1fe..ab957e7 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'; @@ -29,8 +28,18 @@ class _AppPageState extends State { Widget build(BuildContext context) { var appsProvider = context.watch(); var settingsProvider = context.watch(); - getUpdate(String id) { - appsProvider.checkUpdate(id).catchError((e) { + getUpdate(String id, {bool resetVersion = false}) { + appsProvider.checkUpdate(id).then((e) { + if (resetVersion) { + appsProvider.apps[id]?.app.additionalSettings['versionDetection'] = + true; + if (appsProvider.apps[id]?.app.installedVersion != null) { + appsProvider.apps[id]?.app.installedVersion = + appsProvider.apps[id]?.app.latestVersion; + } + appsProvider.saveApps([appsProvider.apps[id]!.app]); + } + }).catchError((e) { showError(e, context); return null; }); @@ -54,122 +63,113 @@ class _AppPageState extends State { var trackOnly = app?.app.additionalSettings['trackOnly'] == true; bool isVersionDetectionStandard = - app?.app.additionalSettings['versionDetection'] == - 'standardVersionDetection'; + app?.app.additionalSettings['versionDetection'] == true; bool installedVersionIsEstimate = trackOnly || (app?.app.installedVersion != null && - app?.app.additionalSettings['versionDetection'] == - 'noVersionDetection'); + app?.app.additionalSettings['versionDetection'] != true); - getInfoColumn() => Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - GestureDetector( - onTap: () { - if (app?.app.url != null) { - launchUrlString(app?.app.url ?? '', - 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, - style: const TextStyle( - decoration: TextDecoration.underline, - fontStyle: FontStyle.italic, - fontSize: 12), - )), - const SizedBox( - height: 32, - ), - Column( + getInfoColumn() { + String versionLines = ''; + bool installed = app?.app.installedVersion != null; + bool upToDate = app?.app.installedVersion == app?.app.latestVersion; + if (installed) { + versionLines = '${app?.app.installedVersion} ${tr('installed')}'; + if (upToDate) { + versionLines += '/${tr('latest')}'; + } + } else { + versionLines = tr('notInstalled'); + } + if (!upToDate) { + versionLines += '\n${app?.app.latestVersion} ${tr('latest')}'; + } + String infoLines = tr('lastUpdateCheckX', args: [ + app?.app.lastUpdateCheck == null + ? tr('never') + : '${app?.app.lastUpdateCheck?.toLocal()}' + ]); + if (trackOnly) { + infoLines = '${tr('xIsTrackOnly', args: [tr('app')])}\n$infoLines'; + } + if (installedVersionIsEstimate) { + infoLines = '${tr('pseudoVersionInUse')}\n$infoLines'; + } + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 24), + child: Column( children: [ - Text( - '${tr('latestVersionX', args: [ - app?.app.latestVersion ?? tr('unknown') - ])}\n${tr('installedVersionX', args: [ - app?.app.installedVersion ?? tr('none') - ])}${installedVersionIsEstimate ? '\n${tr('estimateInBrackets')}' : ''}', - textAlign: TextAlign.end, - style: Theme.of(context).textTheme.bodyLarge!, + const SizedBox( + height: 8, + ), + Text(versionLines, + textAlign: TextAlign.start, + style: Theme.of(context) + .textTheme + .bodyLarge! + .copyWith(fontWeight: FontWeight.bold)), + app?.app.releaseDate == null + ? const SizedBox.shrink() + : Text( + app!.app.releaseDate.toString(), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.labelSmall, + ), + const SizedBox( + height: 8, ), ], ), - if (app?.app.installedVersion != null && - !isVersionDetectionStandard) - Column( - children: [ - const SizedBox( - height: 16, - ), - Text( - '${trackOnly ? '${tr('xIsTrackOnly', args: [ - tr('app') - ])}\n' : ''}${tr('noVersionDetection')}', - style: Theme.of(context).textTheme.labelSmall, + ), + Text( + infoLines, + 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]); + } + }), + if (app?.app.additionalSettings['about'] is String && + app?.app.additionalSettings['about'].isNotEmpty) + Column( + children: [ + const SizedBox( + height: 48, + ), + GestureDetector( + onLongPress: () { + Clipboard.setData(ClipboardData( + text: app?.app.additionalSettings['about'] ?? '')); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(tr('copiedToClipboard')), + )); + }, + child: Text( + app?.app.additionalSettings['about'], textAlign: TextAlign.center, - ) - ], - ), - 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]); - } - }), - if (app?.app.additionalSettings['about'] is String && - app?.app.additionalSettings['about'].isNotEmpty) - Column( - children: [ - const SizedBox( - height: 48, + style: const TextStyle(fontStyle: FontStyle.italic), ), - GestureDetector( - onLongPress: () { - Clipboard.setData(ClipboardData( - text: app?.app.additionalSettings['about'] ?? '')); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(tr('copiedToClipboard')), - )); - }, - child: Text( - app?.app.additionalSettings['about'], - textAlign: TextAlign.center, - style: const TextStyle(fontStyle: FontStyle.italic), - ), - ) - ], - ), - ], - ); + ) + ], + ), + ], + ); + } getFullInfoColumn() => Column( mainAxisAlignment: MainAxisAlignment.center, @@ -196,11 +196,26 @@ class _AppPageState extends State { 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, - ), + GestureDetector( + onTap: () { + if (app?.app.url != null) { + launchUrlString(app?.app.url ?? '', + mode: LaunchMode.externalApplication); + } + }, + onLongPress: () { + Clipboard.setData(ClipboardData(text: app?.app.url ?? '')); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(tr('copiedToClipboard')), + )); + }, + child: Text( + tr('byX', args: [app?.app.author ?? tr('unknown')]), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.headlineMedium!.copyWith( + decoration: TextDecoration.underline, + fontStyle: FontStyle.italic), + )), const SizedBox( height: 8, ), @@ -209,16 +224,6 @@ 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, - ), getInfoColumn(), const SizedBox(height: 150) ], @@ -287,25 +292,6 @@ class _AppPageState extends State { 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 && - app?.app.additionalSettings['versionDetection'] != - 'releaseDateAsVersion' && - !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); }); @@ -320,26 +306,34 @@ class _AppPageState extends State { // ignore: use_build_context_synchronously showMessage(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; - } + var versionDetectionEnabled = + app.app.additionalSettings['versionDetection'] == true && + originalSettings['versionDetection'] != true; + var releaseDateVersionEnabled = + app.app.additionalSettings['releaseDateAsVersion'] == true && + originalSettings['releaseDateAsVersion'] != true; + var releaseDateVersionDisabled = + app.app.additionalSettings['releaseDateAsVersion'] != true && + originalSettings['releaseDateAsVersion'] == true; + if (releaseDateVersionEnabled) { + 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') { + } else if (releaseDateVersionDisabled) { app.app.installedVersion = app.installedInfo?.versionName ?? app.app.installedVersion; } + if (versionDetectionEnabled) { + app.app.additionalSettings['versionDetection'] = true; + app.app.additionalSettings['releaseDateAsVersion'] = false; + } appsProvider.saveApps([app.app]).then((value) { - getUpdate(app.app.id); + getUpdate(app.app.id, resetVersion: versionDetectionEnabled); }); } } diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index c5570c0..31adef5 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -421,7 +421,7 @@ class AppsPageState extends State { } getVersionText(int appIndex) { - return '${listedApps[appIndex].app.installedVersion ?? tr('notInstalled')}${listedApps[appIndex].app.additionalSettings['trackOnly'] == true ? ' ${tr('estimateInBrackets')}' : ''}'; + return '${listedApps[appIndex].app.installedVersion ?? tr('notInstalled')}${listedApps[appIndex].app.additionalSettings['trackOnly'] == true ? ' ${tr('pseudoVersion')}' : ''}'; } getChangesButtonString(int appIndex, bool hasChangeLogFn) { diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 4e0d69b..61fd7d6 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -416,13 +416,17 @@ class _SettingsPageState extends State { value: settingsProvider.useSystemFont, onChanged: (useSystemFont) { if (useSystemFont) { - NativeFeatures.loadSystemFont().then((fontLoadRes) { + NativeFeatures.loadSystemFont() + .then((fontLoadRes) { if (fontLoadRes == 'ok') { - settingsProvider.useSystemFont = true; + settingsProvider.useSystemFont = + true; } else { - showError(ObtainiumError( - tr('systemFontError', args: [fontLoadRes]) - ), context); + showError( + ObtainiumError(tr( + 'systemFontError', + args: [fontLoadRes])), + context); } }); } else { @@ -628,38 +632,9 @@ class _SettingsPageState extends State { label: Text(tr('appLogs'))), ], ), - const Divider( - height: 32, - ), - // Padding( - // padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), - // child: Column(children: [ - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // Flexible(child: Text(tr('debugMenu'))), - // Switch( - // value: settingsProvider.showDebugOpts, - // onChanged: (value) { - // settingsProvider.showDebugOpts = value; - // }) - // ], - // ), - // if (settingsProvider.showDebugOpts) - // Column( - // crossAxisAlignment: CrossAxisAlignment.stretch, - // children: [ - // height16, - // TextButton( - // onPressed: () { - // bgUpdateCheck('taskId', null); - // showMessage(tr('bgTaskStarted'), context); - // }, - // child: Text(tr('runBgCheckNow'))) - // ], - // ), - // ]), - // ), + const SizedBox( + height: 16, + ) ], ), ) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index 38f6417..c3fa50a 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -167,8 +167,24 @@ String hashListOfLists(List> data) { return hash.hashCode.toString(); } -Future checkDownloadHash(String url, - {int bytesToGrab = 1024, Map? headers}) async { +Future checkPartialDownloadHashDynamc(String url, + {int startingSize = 1024, + int lowerLimit = 128, + Map? headers}) async { + for (int i = startingSize; i >= lowerLimit; i -= 256) { + List ab = await Future.wait([ + checkPartialDownloadHash(url, i, headers: headers), + checkPartialDownloadHash(url, i, headers: headers) + ]); + if (ab[0] == ab[1]) { + return ab[0]; + } + } + throw NoVersionError(); +} + +Future checkPartialDownloadHash(String url, int bytesToGrab, + {Map? headers}) async { var req = Request('GET', Uri.parse(url)); if (headers != null) { req.headers.addAll(headers); @@ -804,8 +820,7 @@ class AppsProvider with ChangeNotifier { ? app.installedInfo?.versionCode.toString() : app.installedInfo?.versionName; return app.app.additionalSettings['trackOnly'] != true && - app.app.additionalSettings['versionDetection'] != - 'releaseDateAsVersion' && + app.app.additionalSettings['releaseDateAsVersion'] != true && realInstalledVersion != null && app.app.installedVersion != null && (reconcileVersionDifferences( @@ -821,8 +836,7 @@ class AppsProvider with ChangeNotifier { var modded = false; var trackOnly = app.additionalSettings['trackOnly'] == true; var versionDetectionIsStandard = - app.additionalSettings['versionDetection'] == - 'standardVersionDetection'; + app.additionalSettings['versionDetection'] == true; var naiveStandardVersionDetection = app.additionalSettings['naiveStandardVersionDetection'] == true || SourceProvider() @@ -876,7 +890,7 @@ class AppsProvider with ChangeNotifier { versionDetectionIsStandard && !isVersionDetectionPossible( AppInMemory(app, null, installedInfo, null))) { - app.additionalSettings['versionDetection'] = 'noVersionDetection'; + app.additionalSettings['versionDetection'] = false; logs.add('Could not reconcile version formats for: ${app.id}'); modded = true; } diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index c66b1d3..7930840 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -11,6 +11,7 @@ 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/directAPKLink.dart'; import 'package:obtainium/app_sources/fdroid.dart'; import 'package:obtainium/app_sources/fdroidrepo.dart'; import 'package:obtainium/app_sources/github.dart'; @@ -103,6 +104,21 @@ appJSONCompatibilityModifiers(Map json) { additionalSettings.remove('releaseDateAsVersion'); } } + // Convert dropdown style version detection options back into bool style + if (additionalSettings['versionDetection'] == 'standardVersionDetection') { + additionalSettings['versionDetection'] = true; + } else if (additionalSettings['versionDetection'] == 'noVersionDetection') { + additionalSettings['versionDetection'] = false; + } else if (additionalSettings['versionDetection'] == 'releaseDateAsVersion') { + additionalSettings['versionDetection'] = false; + additionalSettings['releaseDateAsVersion'] = true; + } + // Convert bool style pseudo version method to dropdown style + if (originalAdditionalSettings['supportFixedAPKURL'] == true) { + additionalSettings['defaultPseudoVersioningMethod'] = 'partialAPKHash'; + } else if (originalAdditionalSettings['supportFixedAPKURL'] == false) { + additionalSettings['defaultPseudoVersioningMethod'] = 'APKLinkHash'; + } // Ensure additionalSettings are correctly typed for (var item in formItems) { if (additionalSettings[item.key] != null) { @@ -380,28 +396,24 @@ abstract class AppSource { bool allowSubDomains = false; bool naiveStandardVersionDetection = false; bool neverAutoSelect = false; + bool showReleaseDateAsVersionToggle = false; + bool versionDetectionDisallowed = false; + List excludeCommonSettingKeys = []; AppSource() { name = runtimeType.toString(); } - overrideVersionDetectionFormDefault(String vd, - {bool disableStandard = false, bool disableRelDate = false}) { - additionalAppSpecificSourceAgnosticSettingFormItems = - additionalAppSpecificSourceAgnosticSettingFormItems.map((e) { + overrideAdditionalAppSpecificSourceAgnosticSettingSwitch(String key, + {bool disabled = true, bool defaultValue = true}) { + additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly = + additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly + .map((e) { return e.map((e2) { - if (e2.key == 'versionDetection') { - var item = e2 as GeneratedFormDropdown; - item.defaultValue = vd; - item.disabledOptKeys = []; - if (disableStandard) { - item.disabledOptKeys?.add('standardVersionDetection'); - } - if (disableRelDate) { - item.disabledOptKeys?.add('releaseDateAsVersion'); - } - item.disabledOptKeys = - item.disabledOptKeys?.where((element) => element != vd).toList(); + if (e2.key == key) { + var item = e2 as GeneratedFormSwitch; + item.disabled = disabled; + item.defaultValue = defaultValue; } return e2; }).toList(); @@ -457,7 +469,7 @@ abstract class AppSource { // Some additional data may be needed for Apps regardless of Source List> - additionalAppSpecificSourceAgnosticSettingFormItems = [ + additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly = [ [ GeneratedFormSwitch( 'trackOnly', @@ -475,16 +487,8 @@ abstract class AppSource { label: tr('matchGroupToUse'), required: false, hint: '\$0') ], [ - GeneratedFormDropdown( - 'versionDetection', - [ - MapEntry( - 'standardVersionDetection', tr('standardVersionDetection')), - MapEntry('releaseDateAsVersion', tr('releaseDateAsVersion')), - MapEntry('noVersionDetection', tr('noVersionDetection')) - ], - label: tr('versionDetection'), - defaultValue: 'standardVersionDetection') + GeneratedFormSwitch('versionDetection', + label: tr('versionDetectionExplanation'), defaultValue: true) ], [ GeneratedFormSwitch('useVersionCodeAsOSVersion', @@ -500,6 +504,11 @@ abstract class AppSource { } ]) ], + [ + GeneratedFormSwitch('invertAPKFilter', + label: '${tr('invertRegEx')} (${tr('filterAPKsByRegEx')})', + defaultValue: false) + ], [ GeneratedFormSwitch('autoApkFilterByArch', label: tr('autoApkFilterByArch'), defaultValue: true) @@ -518,9 +527,48 @@ abstract class AppSource { // Previous 2 variables combined into one at runtime for convenient usage List> get combinedAppSpecificSettingFormItems { + if (showReleaseDateAsVersionToggle == true) { + if (additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly + .indexWhere((List e) => + e.indexWhere((GeneratedFormItem i) => + i.key == 'releaseDateAsVersion') >= + 0) < + 0) { + additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly.insert( + additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly + .indexWhere((List e) => + e.indexWhere((GeneratedFormItem i) => + i.key == 'versionDetection') >= + 0) + + 1, + [ + GeneratedFormSwitch('releaseDateAsVersion', + label: + '${tr('releaseDateAsVersion')} (${tr('pseudoVersion')})', + defaultValue: false) + ]); + } + } + additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly = + additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly + .map((e) => e + .where((ee) => !excludeCommonSettingKeys.contains(ee.key)) + .toList()) + .where((e) => e.isNotEmpty) + .toList(); + if (versionDetectionDisallowed) { + overrideAdditionalAppSpecificSourceAgnosticSettingSwitch( + 'versionDetection', + disabled: true, + defaultValue: false); + overrideAdditionalAppSpecificSourceAgnosticSettingSwitch( + 'useVersionCodeAsOSVersion', + disabled: true, + defaultValue: false); + } return [ ...additionalSourceAppSpecificSettingFormItems, - ...additionalAppSpecificSourceAgnosticSettingFormItems + ...additionalAppSpecificSourceAgnosticSettingFormItemsNeverUseDirectly ]; } @@ -665,6 +713,20 @@ String? extractVersion(String? versionExtractionRegEx, String? matchGroupString, } } +List> filterApks( + List> apkUrls, + String? apkFilterRegEx, + bool? invert) { + if (apkFilterRegEx?.isNotEmpty == true) { + var reg = RegExp(apkFilterRegEx!); + apkUrls = apkUrls.where((element) { + var hasMatch = reg.hasMatch(element.key); + return invert == true ? !hasMatch : hasMatch; + }).toList(); + } + return apkUrls; +} + class SourceProvider { // Add more source classes here so they are available via the service List get sources => [ @@ -687,6 +749,7 @@ class SourceProvider { WhatsApp(), TelegramApp(), NeutronCode(), + DirectAPKLink(), HTML() // This should ALWAYS be the last option as they are tried in order ]; @@ -708,11 +771,15 @@ class SourceProvider { } AppSource? source; for (var s in sources.where((element) => element.hosts.isNotEmpty)) { - if (RegExp( - '://${s.allowSubDomains ? '([^\\.]+\\.)*' : '(www\\.)?'}(${getSourceRegex(s.hosts)})(/|\\z)?') - .hasMatch(url)) { - source = s; - break; + try { + if (RegExp( + '^${s.allowSubDomains ? '([^\\.]+\\.)*' : '(www\\.)?'}(${getSourceRegex(s.hosts)})\$') + .hasMatch(Uri.parse(url).host)) { + source = s; + break; + } + } catch (e) { + // Ignore } } if (source == null) { @@ -773,15 +840,12 @@ class SourceProvider { } } - if (additionalSettings['versionDetection'] == 'releaseDateAsVersion' && + if (additionalSettings['releaseDateAsVersion'] == true && apk.releaseDate != null) { apk.version = apk.releaseDate!.microsecondsSinceEpoch.toString(); } - if (additionalSettings['apkFilterRegEx'] != null) { - var reg = RegExp(additionalSettings['apkFilterRegEx']); - apk.apkUrls = - apk.apkUrls.where((element) => reg.hasMatch(element.key)).toList(); - } + apk.apkUrls = filterApks(apk.apkUrls, additionalSettings['apkFilterRegEx'], + additionalSettings['invertAPKFilter']); if (apk.apkUrls.isEmpty && !trackOnly) { throw NoAPKError(); } diff --git a/pubspec.lock b/pubspec.lock index aeed1b5..4052d77 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -307,10 +307,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: "892ada16046d641263f30c72e7432397088810a84f34479f6677494802a2b535" + sha256: "66cc2fe16bf4bca71d795939763ad3f1830ad85772dc3b1561613c501859826d" url: "https://pub.dev" source: hosted - version: "16.3.0" + version: "16.3.1+1" flutter_local_notifications_linux: dependency: transitive description: @@ -394,10 +394,10 @@ packages: dependency: "direct main" description: name: http - sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 + sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.2.0" http_parser: dependency: transitive description: @@ -450,10 +450,10 @@ packages: dependency: transitive description: name: markdown - sha256: acf35edccc0463a9d7384e437c015a3535772e09714cf60e07eeef3a15870dcd + sha256: "1b134d9f8ff2da15cb298efe6cd8b7d2a78958c1b00384ebcbdf13fe340a6c90" url: "https://pub.dev" source: hosted - version: "7.1.1" + version: "7.2.1" matcher: dependency: transitive description: @@ -562,50 +562,50 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "860c6b871c94c78e202dc69546d4d8fd84bd59faeb36f8fb9888668a53ff4f78" + sha256: "45ff3fbcb99040fde55c528d5e3e6ca29171298a85436274d49c6201002087d6" url: "https://pub.dev" source: hosted - version: "11.1.0" + version: "11.2.0" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "2f1bec180ee2f5665c22faada971a8f024761f632e93ddc23310487df52dcfa6" + sha256: "758284a0976772f9c744d6384fc5dc4834aa61e3f7aa40492927f244767374eb" url: "https://pub.dev" source: hosted - version: "12.0.1" + version: "12.0.3" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: "1a816084338ada8d574b1cb48390e6e8b19305d5120fe3a37c98825bacc78306" + sha256: c6bf440f80acd2a873d3d91a699e4cc770f86e7e6b576dda98759e8b92b39830 url: "https://pub.dev" source: hosted - version: "9.2.0" + version: "9.3.0" permission_handler_html: dependency: transitive description: name: permission_handler_html - sha256: "11b762a8c123dced6461933a88ea1edbbe036078c3f9f41b08886e678e7864df" + sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d" url: "https://pub.dev" source: hosted - version: "0.1.0+2" + version: "0.1.1" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: d87349312f7eaf6ce0adaf668daf700ac5b06af84338bd8b8574dfbd93ffe1a1 + sha256: "5c43148f2bfb6d14c5a8162c0a712afe891f2d847f35fcff29c406b37da43c3c" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "4.1.0" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - sha256: "1e8640c1e39121128da6b816d236e714d2cf17fac5a105dd6acdd3403a628004" + sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.2.1" petitparser: dependency: transitive description: @@ -634,10 +634,10 @@ packages: dependency: transitive description: name: pointycastle - sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" url: "https://pub.dev" source: hosted - version: "3.7.3" + version: "3.7.4" provider: dependency: "direct main" description: @@ -943,10 +943,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "4d062ad505390ecef1c4bfb6001cd857a51e00912cc9dfb66edb1886a9ebd80c" + sha256: b99ca8d8bae9c6b43d568218691aa537fb0aeae1d7d34eadf112a6aa36d26506 url: "https://pub.dev" source: hosted - version: "3.10.2" + version: "3.11.0" win32: dependency: transitive description: @@ -988,5 +988,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.2.3 <4.0.0" + flutter: ">=3.16.6" diff --git a/pubspec.yaml b/pubspec.yaml index a4a262b..8bd0278 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.15.11+247 # When changing this, update the tag in main() accordingly +version: 0.16.0+248 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0'