Compare commits

...

48 Commits

Author SHA1 Message Date
a5b3b9d1d0 Merge pull request #1408 from ImranR98/dev
- Improved URL handling for F-Droid third party repos (#1399)
- Fixed F-Droid repo search (#1400) + general search bugfixes
- Improved APK filter for F-Droid (#1386)
- Don't remove storage permission (#1391)
- Jump in versionCode to fix updates in x86 versions (#1370)
2024-02-18 18:20:54 -05:00
13cd7e76c1 Update Flutter + packages, increment version 2024-02-18 18:19:29 -05:00
6e7ccfba37 Merge remote-tracking branch 'origin/main' into dev 2024-02-18 18:18:40 -05:00
34fd673e25 Jump in versionCode to fix updates in x86 versions (#1370) 2024-02-18 18:16:33 -05:00
db484f7b28 Don't remove storage permission (#1391) 2024-02-18 18:13:17 -05:00
b4cf0f5d29 Improved APK filter for F-Droid (#1386) 2024-02-18 18:00:03 -05:00
4db205dd9a Fixed F-Droid repo search (#1400) + general search bugfixes 2024-02-18 17:43:24 -05:00
64f8e2a57b Improved URL handling for F-Droid third party repos (#1399) 2024-02-18 17:00:56 -05:00
eddc245ff4 Update issue templates 2024-02-15 17:13:02 -05:00
ed2f0f2c0c Merge pull request #1368 from gidano/main
Update hu.json
2024-02-03 15:47:45 -05:00
7d5a422855 Merge pull request #1371 from inson1/patch-1
Add F-droid badge to README.md
2024-02-03 15:47:28 -05:00
e420862546 Add F-droid badge to README.md 2024-02-03 17:45:32 +01:00
2cc59948a7 Update hu.json 2024-02-03 10:59:10 +01:00
188d33199e Merge pull request #1365 from heuwerk/patch-1
Update de.json
2024-02-03 04:29:36 -05:00
24928261bb Merge pull request #1367 from ImranR98/dev
Updated a package
2024-02-03 04:29:26 -05:00
4c7bda8343 Updated a package 2024-02-03 04:24:59 -05:00
d88709c999 Update de.json
Added forgotten translation
2024-02-02 11:30:20 +01:00
29e1481a3b Update de.json
Changed "Update" in translated text to "Aktualisierung", since it is used everywhere else.
2024-02-02 11:24:47 +01:00
9d76359543 Merge pull request #1364 from ImranR98/dev
Add DeepL translations as placeholders
2024-02-01 20:34:46 -05:00
f50e791221 Add DeepL translations as placeholders 2024-02-01 20:34:32 -05:00
7d08e5225c Merge pull request #1363 from ImranR98/dev
Correctly report and auto-delete bad APKs (#1251)
2024-02-01 19:32:15 -05:00
3842c1e2df Update packages, increment version 2024-02-01 19:31:32 -05:00
21b1990991 Merge remote-tracking branch 'origin/main' into dev 2024-02-01 19:31:19 -05:00
e278c9fb5a Correctly report and auto-delete bad APKs (#1251) 2024-02-01 19:26:36 -05:00
bfa29bb7c2 Merge pull request #1361 from DwainZwerg/patch-12
Translation of the Note of the sources window
2024-02-01 19:00:41 -05:00
efa55a9696 Update de.json
Okay → OK because it’s shorter and more common
2024-01-31 14:55:23 +00:00
8888cd6264 Update de.json
Translation of the note of the Sources Menu
2024-01-31 14:51:08 +00:00
34e2c014e3 Merge pull request #1357 from jont4/main
Update pt translation
2024-01-29 18:44:36 -05:00
5d92a6d013 Update pt translation 2024-01-28 22:58:17 -03:00
fb03b2e95c Merge pull request #1356 from ImranR98/dev
Better support for SourceForge (#1352), Remove READ_EXTERNAL_STORAGE again (#1309) + fix typo
2024-01-28 17:00:10 -05:00
5a1e09564c Merge pull request #1350 from gidano/main
Update hu.json
2024-01-28 16:58:53 -05:00
3783eba401 Merge pull request #1351 from unbranched/patch-5
Update it.json
2024-01-28 16:58:39 -05:00
a3530ce6bb Remove READ_EXTERNAL_STORAGE again (#1309) + fix typo 2024-01-28 16:58:09 -05:00
27d8655d58 Better support for SourceForge (#1352) 2024-01-28 16:32:58 -05:00
fb845ce601 Update it.json 2024-01-28 10:59:15 +00:00
dbd433df9d Update hu.json 2024-01-28 09:15:28 +01:00
badf32ff11 Merge pull request #1349 from ImranR98/dev
- Allow existing '/refs' in SourceHut URLs (#1347)
- Revert to showing App URL separately again (#1336)
- F-Droid: Don't pull changelog text if it isn't a raw file from GitHub/GitLab (#1340)
- Add a note on self-hosted instances of sources (#1342)
- versionCode changes
2024-01-27 22:00:54 -05:00
5e40f3264e Merge pull request #1337 from jont4/main
Translation: pt update
2024-01-27 21:58:41 -05:00
71bb6d9410 Merge pull request #1338 from teaminh/main
Update vi.json
2024-01-27 21:58:14 -05:00
731b682fc9 Merge pull request #1339 from DwainZwerg/patch-11
Update de.json
2024-01-27 21:57:03 -05:00
c9751227a5 Flutter upgrade + versionCode changes + increment version 2024-01-27 21:56:26 -05:00
6ef2a26e94 Add a note on self-hosted instances of sources (#1342) 2024-01-27 21:26:32 -05:00
5a8efa2388 F-Droid: Don't pull changelog text if it isn't a raw file from GitHub/GitLab (#1340) 2024-01-27 21:01:44 -05:00
d25895fa28 Revert to showing App URL separately again (#1336) 2024-01-27 20:13:01 -05:00
de09f3ece2 Allow existing '/refs' in SourceHut URLs (#1347) 2024-01-27 20:08:05 -05:00
1135ffb30f Update de.json
Better Translation of "latest"
2024-01-25 13:49:57 +00:00
5379cb31e8 Update vi.json 2024-01-25 18:31:46 +07:00
7d41ab44b7 Minor update 2024-01-24 23:21:42 -03:00
40 changed files with 557 additions and 219 deletions

View File

@ -10,6 +10,7 @@ assignees: ''
**Prerequisites** **Prerequisites**
<!-- Please ensure your request is not part of an existing issue. --> <!-- Please ensure your request is not part of an existing issue. -->
<!-- Please ensure you have checked the Obtainium Wiki. --> <!-- Please ensure you have checked the Obtainium Wiki. -->
<!-- Please ensure your request is an actual bug and not intended behaviour (this is frequently the case for issues involving version strings and the HTML source. -->
**Describe the bug** **Describe the bug**
<!-- A clear and concise description of what the bug is. --> <!-- A clear and concise description of what the bug is. -->

View File

@ -14,11 +14,14 @@ assignees: ''
**Describe the feature** **Describe the feature**
<!-- A clear and concise description of what you want to happen. <!-- A clear and concise description of what you want to happen.
For new Sources, it's preferable (not required) if you suggest how the following details can be extracted from the Source in a reliable way (like an API or through web scraping): For new Sources, please ensure:
1. It is not already possible to use the HTML Source for your purposes.
2. It must be possible to extract the following details from the Source in a reliable way:
- The App version (or any release-specific identifier - a "pseudo-version") for the latest release - The App version (or any release-specific identifier - a "pseudo-version") for the latest release
- One or more APK URL(s) for the latest release - One or more APK URL(s) for the latest release
- Above details for previous releases (optional) - Above details for previous releases (optional)
If you're not sure about 1 or 2, open a discussion item instead.
Note that the Web scraper cannot deal with JavaScript-enabled content. --> Note that the Web scraper cannot deal with JavaScript-enabled content. -->
**Describe alternatives you've considered (if applicable)** **Describe alternatives you've considered (if applicable)**

View File

@ -42,6 +42,9 @@ Currently supported App sources:
[<img src="https://github.com/machiav3lli/oandbackupx/blob/034b226cea5c1b30eb4f6a6f313e4dadcbb0ece4/badge_github.png" [<img src="https://github.com/machiav3lli/oandbackupx/blob/034b226cea5c1b30eb4f6a6f313e4dadcbb0ece4/badge_github.png"
alt="Get it on GitHub" alt="Get it on GitHub"
height="80">](https://github.com/ImranR98/Obtainium/releases) height="80">](https://github.com/ImranR98/Obtainium/releases)
[<img src="https://gitlab.com/fdroid/artwork/-/raw/master/badge/get-it-on.png"
alt="Get it on F-Droid"
height="80">](https://f-droid.org/packages/dev.imranr.obtainium.fdroid/)
[PGP Public Key](https://keyserver.ubuntu.com/pks/lookup?search=contact%40imranr.dev&fingerprint=on&op=index) [PGP Public Key](https://keyserver.ubuntu.com/pks/lookup?search=contact%40imranr.dev&fingerprint=on&op=index)

View File

@ -108,3 +108,16 @@ dependencies {
implementation "com.github.topjohnwu.libsu:core:5.2.2" implementation "com.github.topjohnwu.libsu:core:5.2.2"
} }
ext.abiCodes = ["x86_64": 1, "armeabi-v7a": 2, "arm64-v8a": 3]
import com.android.build.OutputFile
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def abiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
if (abiVersionCode != null) {
output.versionCodeOverride = variant.versionCode * 10 + abiVersionCode
} else {
output.versionCodeOverride = variant.versionCode * 10
}
}
}

View File

@ -70,6 +70,6 @@
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" /> <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission <uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="29" /> android:maxSdkVersion="29" />\
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
</manifest> </manifest>

View File

@ -298,6 +298,9 @@
"installed": "Instalirano", "installed": "Instalirano",
"latest": "Najnoviji", "latest": "Najnoviji",
"invertRegEx": "Obrni regularni izraz", "invertRegEx": "Obrni regularni izraz",
"note": "Note",
"selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
"badDownload": "The APK could not be parsed (incompatible or partial download)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Želite li ukloniti aplikaciju?", "one": "Želite li ukloniti aplikaciju?",
"other": "Želite li ukloniti aplikacije?" "other": "Želite li ukloniti aplikacije?"

View File

@ -292,12 +292,15 @@
"useLatestAssetDateAsReleaseDate": "Použít poslední nahrané dílo jako datum vydání", "useLatestAssetDateAsReleaseDate": "Použít poslední nahrané dílo jako datum vydání",
"defaultPseudoVersioningMethod": "Výchozí metoda pseudoverze", "defaultPseudoVersioningMethod": "Výchozí metoda pseudoverze",
"partialAPKHash": "Částečný hash APK", "partialAPKHash": "Částečný hash APK",
"APKLinkHash": "APK Link Hash", "APKLinkHash": "Odkaz APK Hash",
"directAPKLink": "Přímý odkaz APK", "directAPKLink": "Přímý odkaz APK",
"pseudoVersionInUse": "Pseudoverze se používá", "pseudoVersionInUse": "Pseudoverze se používá",
"installed": "Instalováno", "installed": "Instalováno",
"latest": "Nejnovější", "latest": "Nejnovější",
"invertRegEx": "Invertovat regulární výraz", "invertRegEx": "Invertovat regulární výraz",
"note": "Poznámka",
"selfHostedNote": "Rozbalovací seznam \"{}\" lze použít k dosažení vlastních/obvyklých instancí libovolného zdroje.",
"badDownload": "APK nelze analyzovat (nekompatibilní nebo částečné stažení)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Odstranit Apku?", "one": "Odstranit Apku?",
"other": "Odstranit Apky?" "other": "Odstranit Apky?"

View File

@ -9,7 +9,7 @@
"placeholder": "Platzhalter", "placeholder": "Platzhalter",
"someErrors": "Es traten einige Fehler auf", "someErrors": "Es traten einige Fehler auf",
"unexpectedError": "Unerwarteter Fehler", "unexpectedError": "Unerwarteter Fehler",
"ok": "Okay", "ok": "OK",
"and": "und", "and": "und",
"githubPATLabel": "GitHub Personal Access Token (Erhöht das Ratenlimit)", "githubPATLabel": "GitHub Personal Access Token (Erhöht das Ratenlimit)",
"includePrereleases": "Vorabversionen einbeziehen", "includePrereleases": "Vorabversionen einbeziehen",
@ -30,7 +30,7 @@
"app": "App", "app": "App",
"appsFromSourceAreTrackOnly": "Apps aus dieser Quelle sind nur zum Nachverfolgen.", "appsFromSourceAreTrackOnly": "Apps aus dieser Quelle sind nur zum Nachverfolgen.",
"youPickedTrackOnly": "Sie haben die Option „Nur Nachverfolgen“ gewählt.", "youPickedTrackOnly": "Sie haben die Option „Nur Nachverfolgen“ gewählt.",
"trackOnlyAppDescription": "Die App wird auf Updates überwacht, aber Obtainium wird sie nicht herunterladen oder installieren.", "trackOnlyAppDescription": "Die App wird auf Aktualisierungen überwacht, aber Obtainium wird sie nicht herunterladen oder installieren.",
"cancelled": "Abgebrochen", "cancelled": "Abgebrochen",
"appAlreadyAdded": "App bereits hinzugefügt", "appAlreadyAdded": "App bereits hinzugefügt",
"alreadyUpToDateQuestion": "App bereits auf dem neuesten Stand?", "alreadyUpToDateQuestion": "App bereits auf dem neuesten Stand?",
@ -226,7 +226,7 @@
"tryInferAppIdFromCode": "Versuche, die App-ID aus dem Quellcode zu ermitteln", "tryInferAppIdFromCode": "Versuche, die App-ID aus dem Quellcode zu ermitteln",
"removeOnExternalUninstall": "Automatisches Entfernen von extern deinstallierten Apps", "removeOnExternalUninstall": "Automatisches Entfernen von extern deinstallierten Apps",
"pickHighestVersionCode": "Automatische Auswahl des APK mit höchstem Versionscode", "pickHighestVersionCode": "Automatische Auswahl des APK mit höchstem Versionscode",
"checkUpdateOnDetailPage": "Nach Updates suchen, wenn eine App-Detailseite geöffnet wird", "checkUpdateOnDetailPage": "Nach Aktualisierungen suchen, wenn eine App-Detailseite geöffnet wird",
"disablePageTransitions": "Animationen für Seitenübergänge deaktivieren", "disablePageTransitions": "Animationen für Seitenübergänge deaktivieren",
"reversePageTransitions": "Umgekehrte Animationen für Seitenübergänge", "reversePageTransitions": "Umgekehrte Animationen für Seitenübergänge",
"minStarCount": "Minimale Anzahl von Sternen", "minStarCount": "Minimale Anzahl von Sternen",
@ -238,7 +238,7 @@
"filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck filtern", "filterReleaseNotesByRegEx": "Versionshinweise nach regulärem Ausdruck filtern",
"customLinkFilterRegex": "Benutzerdefinierter APK Link Filter nach Regulärem Ausdruck (Standard '.apk$')", "customLinkFilterRegex": "Benutzerdefinierter APK Link Filter nach Regulärem Ausdruck (Standard '.apk$')",
"appsPossiblyUpdated": "App Aktualisierungen wurden versucht", "appsPossiblyUpdated": "App Aktualisierungen wurden versucht",
"appsPossiblyUpdatedNotifDescription": "Benachrichtigt den Benutzer, dass Updates für eine oder mehrere Apps möglicherweise im Hintergrund durchgeführt wurden", "appsPossiblyUpdatedNotifDescription": "Benachrichtigt den Benutzer, dass Aktualisierungen für eine oder mehrere Apps möglicherweise im Hintergrund durchgeführt wurden",
"xWasPossiblyUpdatedToY": "{} wurde möglicherweise aktualisiert auf {}.", "xWasPossiblyUpdatedToY": "{} wurde möglicherweise aktualisiert auf {}.",
"enableBackgroundUpdates": "Aktiviere Hintergrundaktualisierungen", "enableBackgroundUpdates": "Aktiviere Hintergrundaktualisierungen",
"backgroundUpdateReqsExplanation": "Die Hintergrundaktualisierung ist möglicherweise nicht für alle Apps möglich.", "backgroundUpdateReqsExplanation": "Die Hintergrundaktualisierung ist möglicherweise nicht für alle Apps möglich.",
@ -268,7 +268,7 @@
"runBgCheckNow": "Hintergrundaktualisierungsprüfung jetzt durchführen", "runBgCheckNow": "Hintergrundaktualisierungsprüfung jetzt durchführen",
"versionExtractWholePage": "Versions-Extraktion per RegEx auf die gesamte Seite anwenden", "versionExtractWholePage": "Versions-Extraktion per RegEx auf die gesamte Seite anwenden",
"installing": "Installiere", "installing": "Installiere",
"skipUpdateNotifications": "Keine Benachrichtigung zu App-Updates geben", "skipUpdateNotifications": "Keine Benachrichtigung zu App-Aktualisierungen geben",
"updatesAvailableNotifChannel": "Aktualisierungen verfügbar", "updatesAvailableNotifChannel": "Aktualisierungen verfügbar",
"appsUpdatedNotifChannel": "Apps aktualisiert", "appsUpdatedNotifChannel": "Apps aktualisiert",
"appsPossiblyUpdatedNotifChannel": "App Aktualisierungen wurden versucht", "appsPossiblyUpdatedNotifChannel": "App Aktualisierungen wurden versucht",
@ -294,10 +294,13 @@
"partialAPKHash": "partieller APK-Hash", "partialAPKHash": "partieller APK-Hash",
"APKLinkHash": "APK-Link-Hash", "APKLinkHash": "APK-Link-Hash",
"directAPKLink": "Direkter APK-Link", "directAPKLink": "Direkter APK-Link",
"pseudoVersionInUse": "Pseudoversionen sind in Benutzung", "pseudoVersionInUse": "Es werden Pseudoversionen verwendet",
"installed": "Installiert", "installed": "Installiert",
"latest": "Neueste(r)", "latest": "Neueste Version",
"invertRegEx": "Regulären Ausdruck invertieren", "invertRegEx": "Regulären Ausdruck invertieren",
"note": "Hinweis",
"selfHostedNote": "Das „{}“-Dropdown-Menü kann verwendet werden, um selbst gehostete/angepasste Instanzen einer beliebigen Quelle zu erreichen.",
"badDownload": "Die APK konnte nicht geparst werden (inkompatibler oder teilweiser Download)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "App entfernen?", "one": "App entfernen?",
"other": "Apps entfernen?" "other": "Apps entfernen?"

View File

@ -80,7 +80,6 @@
"removeOutdatedFilter": "Remove Out-of-Date App Filter", "removeOutdatedFilter": "Remove Out-of-Date App Filter",
"showOutdatedOnly": "Show Out-of-Date Apps Only", "showOutdatedOnly": "Show Out-of-Date Apps Only",
"filter": "Filter", "filter": "Filter",
"filterActive": "Filter *",
"filterApps": "Filter Apps", "filterApps": "Filter Apps",
"appName": "App Name", "appName": "App Name",
"author": "Author", "author": "Author",
@ -298,6 +297,9 @@
"installed": "Installed", "installed": "Installed",
"latest": "Latest", "latest": "Latest",
"invertRegEx": "Invert regular expression", "invertRegEx": "Invert regular expression",
"note": "Note",
"selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
"badDownload": "The APK could not be parsed (incompatible or partial download)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Remove App?", "one": "Remove App?",
"other": "Remove Apps?" "other": "Remove Apps?"

View File

@ -298,6 +298,9 @@
"installed": "Instalado", "installed": "Instalado",
"latest": "Versión más reciente", "latest": "Versión más reciente",
"invertRegEx": "Invertir expresión regular", "invertRegEx": "Invertir expresión regular",
"note": "Nota",
"selfHostedNote": "El desplegable \"{}\" puede utilizarse para acceder a instancias autoalojadas/personalizadas de cualquier fuente.",
"badDownload": "No se ha podido analizar el APK (incompatible o descarga parcial)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "¿Eliminar Aplicación?", "one": "¿Eliminar Aplicación?",
"other": "¿Eliminar Aplicaciones?" "other": "¿Eliminar Aplicaciones?"

View File

@ -298,6 +298,9 @@
"installed": "نصب شده است", "installed": "نصب شده است",
"latest": "آخرین", "latest": "آخرین",
"invertRegEx": "معکوس کردن عبارت منظم", "invertRegEx": "معکوس کردن عبارت منظم",
"note": "Note",
"selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
"badDownload": "The APK could not be parsed (incompatible or partial download)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "برنامه حذف شود؟", "one": "برنامه حذف شود؟",
"other": "برنامه ها حذف شوند؟" "other": "برنامه ها حذف شوند؟"

View File

@ -298,6 +298,9 @@
"installed": "Installée", "installed": "Installée",
"latest": "Dernier", "latest": "Dernier",
"invertRegEx": "Inverser l'expression régulière", "invertRegEx": "Inverser l'expression régulière",
"note": "Note",
"selfHostedNote": "La liste déroulante \"{}\" peut être utilisée pour accéder aux instances auto-hébergées/personnalisées de n'importe quelle source.",
"badDownload": "L'APK n'a pas pu être analysé (téléchargement incompatible ou partiel)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Supprimer l'application ?", "one": "Supprimer l'application ?",
"other": "Supprimer les applications ?" "other": "Supprimer les applications ?"

View File

@ -287,7 +287,7 @@
"shizukuBinderNotFound": "A Shizuku nem fut", "shizukuBinderNotFound": "A Shizuku nem fut",
"useSystemFont": "Használja a rendszer betűtípusát", "useSystemFont": "Használja a rendszer betűtípusát",
"systemFontError": "Hiba a rendszer betűtípusának betöltésekor: {}", "systemFontError": "Hiba a rendszer betűtípusának betöltésekor: {}",
"useVersionCodeAsOSVersion": "Az app versionCode használata a rendszer által észlelt verzióként", "useVersionCodeAsOSVersion": "Az app verziókód használata a rendszer által észlelt verzióként",
"requestHeader": "Kérelem fejléc", "requestHeader": "Kérelem fejléc",
"useLatestAssetDateAsReleaseDate": "Használja a legújabb tartalomfeltöltést megjelenési dátumként", "useLatestAssetDateAsReleaseDate": "Használja a legújabb tartalomfeltöltést megjelenési dátumként",
"defaultPseudoVersioningMethod": "Alapértelmezett álversziós módszer", "defaultPseudoVersioningMethod": "Alapértelmezett álversziós módszer",
@ -298,9 +298,12 @@
"installed": "Telepített", "installed": "Telepített",
"latest": "Legújabb", "latest": "Legújabb",
"invertRegEx": "Invertált reguláris kifejezés", "invertRegEx": "Invertált reguláris kifejezés",
"note": "Megjegyzés:",
"selfHostedNote": "A \"{}\" legördülő menü használható bármely forrás saját üzemeltetésű/egyéni példányainak eléréséhez.",
"badDownload": "Az APK-t nem lehetett elemezni (inkompatibilis vagy részleges letöltés)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Eltávolítja az alkalmazást?", "one": "Eltávolítja az alkalmazást?",
"other": "Eltávolítja az alkalmazást?" "other": "Eltávolítja az alkalmazásokat?"
}, },
"tooManyRequestsTryAgainInMinutes": { "tooManyRequestsTryAgainInMinutes": {
"one": "Túl sok kérés (korlátozott arány) próbálja újra {} perc múlva", "one": "Túl sok kérés (korlátozott arány) próbálja újra {} perc múlva",

View File

@ -111,7 +111,7 @@
"dark": "Scuro", "dark": "Scuro",
"light": "Chiaro", "light": "Chiaro",
"followSystem": "Segui il sistema", "followSystem": "Segui il sistema",
"useBlackTheme": "Usa il tema Nero puro", "useBlackTheme": "Usa il tema nero puro",
"appSortBy": "App ordinate per", "appSortBy": "App ordinate per",
"authorName": "Autore/Nome", "authorName": "Autore/Nome",
"nameAuthor": "Nome/Autore", "nameAuthor": "Nome/Autore",
@ -283,13 +283,13 @@
"parallelDownloads": "Permetti download paralleli", "parallelDownloads": "Permetti download paralleli",
"installMethod": "Metodo d'installazione", "installMethod": "Metodo d'installazione",
"normal": "Normale", "normal": "Normale",
"root": "Radice", "root": "Root",
"shizukuBinderNotFound": "Shizuku non è in esecuzione", "shizukuBinderNotFound": "Shizuku non è in esecuzione",
"useSystemFont": "Utilizza il carattere di sistema", "useSystemFont": "Usa i caratteri di sistema",
"systemFontError": "Errore durante il caricamento del carattere di sistema: {}", "systemFontError": "Errore durante il caricamento dei caratteri di sistema: {}",
"useVersionCodeAsOSVersion": "Utilizza il codice versione dell'app come versione rilevata dal sistema operativo", "useVersionCodeAsOSVersion": "Usa il codice versione dell'app come versione rilevata dal sistema operativo",
"requestHeader": "Intestazione della richiesta", "requestHeader": "Intestazione della richiesta",
"useLatestAssetDateAsReleaseDate": "Utilizza l'ultimo caricamento della risorsa come data di rilascio", "useLatestAssetDateAsReleaseDate": "Usa l'ultimo caricamento della risorsa come data di rilascio",
"defaultPseudoVersioningMethod": "Metodo di pseudoversione predefinito", "defaultPseudoVersioningMethod": "Metodo di pseudoversione predefinito",
"partialAPKHash": "Hash APK parziale", "partialAPKHash": "Hash APK parziale",
"APKLinkHash": "Hash collegamento APK", "APKLinkHash": "Hash collegamento APK",
@ -298,6 +298,9 @@
"installed": "Installato", "installed": "Installato",
"latest": "Ultimo", "latest": "Ultimo",
"invertRegEx": "Inverti espressione regolare", "invertRegEx": "Inverti espressione regolare",
"note": "Nota",
"selfHostedNote": "Il menu a tendina \"{}\" può essere usato per raggiungere istanze autogestite/personali di qualsiasi fonte.",
"badDownload": "Non è stato possibile analizzare l'APK (download incompatibile o parziale).",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Rimuovere l'app?", "one": "Rimuovere l'app?",
"other": "Rimuovere le app?" "other": "Rimuovere le app?"

View File

@ -298,6 +298,9 @@
"installed": "インストール済み", "installed": "インストール済み",
"latest": "最新", "latest": "最新",
"invertRegEx": "正規表現を反転", "invertRegEx": "正規表現を反転",
"note": "注",
"selfHostedNote": "ドロップダウン\"{}\"を使用すると、あらゆるソースのセルフホスト/カスタムインスタンスにアクセスできます。",
"badDownload": "APK を解析できませんでした(互換性がないか、部分的にダウンロードされています)。",
"removeAppQuestion": { "removeAppQuestion": {
"one": "アプリを削除しますか?", "one": "アプリを削除しますか?",
"other": "アプリを削除しますか?" "other": "アプリを削除しますか?"

View File

@ -298,6 +298,9 @@
"installed": "Geïnstalleerd", "installed": "Geïnstalleerd",
"latest": "Laatste", "latest": "Laatste",
"invertRegEx": "Reguliere expressie omkeren", "invertRegEx": "Reguliere expressie omkeren",
"note": "Opmerking",
"selfHostedNote": "De \"{}\" dropdown kan gebruikt worden om zelf gehoste/aangepaste instanties van elke bron te bereiken.",
"badDownload": "De APK kon niet worden verwerkt (incompatibele of gedeeltelijke download)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "App verwijderen?", "one": "App verwijderen?",
"other": "Apps verwijderen?" "other": "Apps verwijderen?"

View File

@ -298,6 +298,9 @@
"installed": "Zainstalowano", "installed": "Zainstalowano",
"latest": "Najnowszy", "latest": "Najnowszy",
"invertRegEx": "Odwróć wyrażenie regularne", "invertRegEx": "Odwróć wyrażenie regularne",
"note": "Uwaga",
"selfHostedNote": "Lista rozwijana \"{}\" może być używana do uzyskiwania dostępu do samodzielnie hostowanych / niestandardowych instancji dowolnego źródła.",
"badDownload": "Nie można przeanalizować pliku APK (niekompatybilny lub częściowo pobrany).",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Usunąć aplikację?", "one": "Usunąć aplikację?",
"few": "Usunąć aplikacje?", "few": "Usunąć aplikacje?",

View File

@ -2,7 +2,7 @@
"invalidURLForSource": "URL {} inválida", "invalidURLForSource": "URL {} inválida",
"noReleaseFound": "Não foi possível encontrar uma versão adequada", "noReleaseFound": "Não foi possível encontrar uma versão adequada",
"noVersionFound": "Não foi possível encontrar uma versão", "noVersionFound": "Não foi possível encontrar uma versão",
"urlMatchesNoSource": "URL não corresponde a uma fonte conhecida", "urlMatchesNoSource": "A URL não corresponde a uma fonte conhecida",
"cantInstallOlderVersion": "Não é permitido instalar uma versão anterior de um aplicativo", "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", "appIdMismatch": "ID do pacote baixado não é igual ao ID do aplicativo instalado",
"functionNotImplemented": "Esta classe não implementou essa função", "functionNotImplemented": "Esta classe não implementou essa função",
@ -11,10 +11,10 @@
"unexpectedError": "Erro inesperado", "unexpectedError": "Erro inesperado",
"ok": "OK", "ok": "OK",
"and": "e", "and": "e",
"githubPATLabel": "Token de acesso pessoal do GitHub (Reduz tempos de espera)", "githubPATLabel": "Token de acesso pessoal do GitHub\n(Reduz tempos de espera)",
"includePrereleases": "Incluir pré-lançamentos", "includePrereleases": "Incluir pré-lançamentos",
"fallbackToOlderReleases": "Retornar para versões anteriores", "fallbackToOlderReleases": "Retornar para versões anteriores",
"filterReleaseTitlesByRegEx": "Filtrar títulos de versões por expressão regular", "filterReleaseTitlesByRegEx": "Filtrar títulos de versões usando expressão regular",
"invalidRegEx": "Expressão regular inválida", "invalidRegEx": "Expressão regular inválida",
"noDescription": "Sem descrição", "noDescription": "Sem descrição",
"cancel": "Cancelar", "cancel": "Cancelar",
@ -22,7 +22,7 @@
"requiredInBrackets": "(Necessário)", "requiredInBrackets": "(Necessário)",
"dropdownNoOptsError": "ERRO: O DROPDOWN DEVE TER PELO MENOS UMA OPÇÃO", "dropdownNoOptsError": "ERRO: O DROPDOWN DEVE TER PELO MENOS UMA OPÇÃO",
"colour": "Cor", "colour": "Cor",
"githubStarredRepos": "Favoritados no GitHub", "githubStarredRepos": "repositórios favoritos no GitHub",
"uname": "Nome de usuário", "uname": "Nome de usuário",
"wrongArgNum": "Número de argumentos errado", "wrongArgNum": "Número de argumentos errado",
"xIsTrackOnly": "{} é 'Apenas monitorar'", "xIsTrackOnly": "{} é 'Apenas monitorar'",
@ -38,12 +38,12 @@
"appSourceURL": "URL de origem do aplicativo", "appSourceURL": "URL de origem do aplicativo",
"error": "Erro", "error": "Erro",
"add": "Adicionar", "add": "Adicionar",
"searchSomeSourcesLabel": "Procurar (Apenas algumas fontes)", "searchSomeSourcesLabel": "Procurar (apenas algumas fontes)",
"search": "Procurar", "search": "Procurar",
"additionalOptsFor": "Opções adicionais para {}", "additionalOptsFor": "Opções adicionais para {}",
"supportedSources": "Fontes compatíveis", "supportedSources": "Fontes compatíveis",
"trackOnlyInBrackets": "(Apenas monitorar)", "trackOnlyInBrackets": "(apenas monitorar)",
"searchableInBrackets": "(Pesquisável)", "searchableInBrackets": "(pesquisável)",
"appsString": "Aplicativos", "appsString": "Aplicativos",
"noApps": "Não há aplicativos", "noApps": "Não há aplicativos",
"noAppsForFilter": "Sem aplicativos para filtrar", "noAppsForFilter": "Sem aplicativos para filtrar",
@ -70,12 +70,12 @@
"markSelectedAppsUpdated": "Marcar aplicativos selecionados como Atualizados", "markSelectedAppsUpdated": "Marcar aplicativos selecionados como Atualizados",
"pinToTop": "Fixar no topo", "pinToTop": "Fixar no topo",
"unpinFromTop": "Desafixar do topo", "unpinFromTop": "Desafixar do topo",
"resetInstallStatusForSelectedAppsQuestion": "Reiniciar status de instalação para aplicativos selecionados?", "resetInstallStatusForSelectedAppsQuestion": "Reiniciar status de instalação nos 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.", "installStatusOfXWillBeResetExplanation": "O status de instalação de todos os aplicativos selecionados 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": "Esses links funcionam em dispositivos com o Obtainium instalado", "customLinkMessage": "Esses links funcionam em dispositivos com o Obtainium instalado",
"shareAppConfigLinks": "Compartilhar configuração do aplicativo como link HTML", "shareAppConfigLinks": "Compartilhar configuração do aplicativo como link HTML",
"shareSelectedAppURLs": "Compartilhar URLs de aplicativos selecionados", "shareSelectedAppURLs": "Compartilhar URLs de aplicativos selecionados",
"resetInstallStatus": "Reiniciar status de Iistalação", "resetInstallStatus": "Reiniciar status de instalação",
"more": "Mais", "more": "Mais",
"removeOutdatedFilter": "Remover filtro de aplicativos desatualizados", "removeOutdatedFilter": "Remover filtro de aplicativos desatualizados",
"showOutdatedOnly": "Mostrar apenas aplicativos desatualizados", "showOutdatedOnly": "Mostrar apenas aplicativos desatualizados",
@ -84,20 +84,20 @@
"filterApps": "Filtrar aplicativos", "filterApps": "Filtrar aplicativos",
"appName": "Nome do aplicativo", "appName": "Nome do aplicativo",
"author": "Autor", "author": "Autor",
"upToDateApps": "Aplicativos tualizados", "upToDateApps": "Aplicativos atualizados",
"nonInstalledApps": "Aplicativos não instalados", "nonInstalledApps": "Aplicativos não instalados",
"importExport": "Importar/Exportar", "importExport": "Importar/Exportar",
"settings": "Configurações", "settings": "Configurações",
"exportedTo": "Exportado para {}", "exportedTo": "Exportado para {}",
"obtainiumExport": "Exportar Obtainium", "obtainiumExport": "Exportar dados do Obtainium",
"invalidInput": "Input Inválido", "invalidInput": "Entrada inválida",
"importedX": "Importado {}", "importedX": "Importado {}",
"obtainiumImport": "Importar Obtainium", "obtainiumImport": "Importar dados do Obtainium",
"importFromURLList": "Importar de lista de URLs", "importFromURLList": "Importar de lista de URLs",
"searchQuery": "Pesquisa", "searchQuery": "Pesquisa",
"appURLList": "Lista de URLs de aplicativos", "appURLList": "Lista de URLs de aplicativos",
"line": "Linha", "line": "Linha",
"searchX": "Pesquisa {}", "searchX": "Pesquisar na/o {}",
"noResults": "Nenhum resultado encontrado", "noResults": "Nenhum resultado encontrado",
"importX": "Importar {}", "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.", "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.",
@ -110,8 +110,8 @@
"theme": "Tema", "theme": "Tema",
"dark": "Escuro", "dark": "Escuro",
"light": "Claro", "light": "Claro",
"followSystem": "Seguir o sistema", "followSystem": "Padrão do sistema",
"useBlackTheme": "Usar tema preto completamente escuro", "useBlackTheme": "Usar tema preto AMOLED",
"appSortBy": "Classificar aplicativo por", "appSortBy": "Classificar aplicativo por",
"authorName": "Autor/Nome", "authorName": "Autor/Nome",
"nameAuthor": "Nome/Autor", "nameAuthor": "Nome/Autor",
@ -122,10 +122,10 @@
"bgUpdateCheckInterval": "Intervalo de verificação de atualizações em segundo-plano", "bgUpdateCheckInterval": "Intervalo de verificação de atualizações em segundo-plano",
"neverManualOnly": "Nunca - apenas manual", "neverManualOnly": "Nunca - apenas manual",
"appearance": "Aparência", "appearance": "Aparência",
"showWebInAppView": "Mostrar página da internet em informações do aplicativo", "showWebInAppView": "Mostrar página web do aplicativo em informações do aplicativo",
"pinUpdates": "Fixar atualizações no topo da janela de aplicativos", "pinUpdates": "Fixar atualizações no topo da janela de aplicativos",
"updates": "Atualizações", "updates": "Atualizações",
"sourceSpecific": "Específico a fonte", "sourceSpecific": "Token de acesso",
"appSource": "Fonte do aplicativo", "appSource": "Fonte do aplicativo",
"noLogs": "Sem logs", "noLogs": "Sem logs",
"appLogs": "Logs do aplicativo", "appLogs": "Logs do aplicativo",
@ -151,7 +151,7 @@
"appsRemoved": "Aplicativos removidos", "appsRemoved": "Aplicativos removidos",
"appsRemovedNotifDescription": "Notifica o usuário quando um ou mais aplicativos foram removidos devido a erros de carregamento", "appsRemovedNotifDescription": "Notifica o usuário quando um ou mais aplicativos foram removidos devido a erros de carregamento",
"xWasRemovedDueToErrorY": "{} foi removido devido a este erro: {}", "xWasRemovedDueToErrorY": "{} foi removido devido a este erro: {}",
"completeAppInstallation": "Instalação do aplicativo completa", "completeAppInstallation": "Instalação do aplicativo concluída",
"obtainiumMustBeOpenToInstallApps": "Obtainium deve estar aberto para instalar os aplicativos", "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", "completeAppInstallationNotifDescription": "Pede ao usuário que retorne ao Obtainium para finalizar a instalação de um aplicativo",
"checkingForUpdates": "Verificando atualizações", "checkingForUpdates": "Verificando atualizações",
@ -167,15 +167,15 @@
"installedVersionX": "Versão instalada: {}", "installedVersionX": "Versão instalada: {}",
"lastUpdateCheckX": "Última verificação de atualizações: {}", "lastUpdateCheckX": "Última verificação de atualizações: {}",
"remove": "Remover", "remove": "Remover",
"yesMarkUpdated": "Sim, marcar como Atualizado", "yesMarkUpdated": "Sim, marcar como atualizado",
"fdroid": "Oficial F-Droid", "fdroid": "Oficial F-Droid",
"appIdOrName": "ID do aplicativo ou nome", "appIdOrName": "ID do aplicativo ou nome",
"appId": "ID do aplicativo", "appId": "ID do aplicativo",
"appWithIdOrNameNotFound": "Nenhum aplicativo foi encontrado com esse ID ou nome", "appWithIdOrNameNotFound": "Nenhum aplicativo foi encontrado com esse ID ou nome",
"reposHaveMultipleApps": "Repositórios podem conter multiplos aplicativos", "reposHaveMultipleApps": "Repositórios podem conter múltiplos aplicativos",
"fdroidThirdPartyRepo": "Repositórios de terceiros F-Droid", "fdroidThirdPartyRepo": "Repositórios de terceiros F-Droid",
"steamMobile": "Vapor Móvel", "steamMobile": "Steam para celular",
"steamChat": "Bate-papo Steam", "steamChat": "Chat do Steam",
"install": "Instalar", "install": "Instalar",
"markInstalled": "Marcar instalado", "markInstalled": "Marcar instalado",
"update": "Atualizar", "update": "Atualizar",
@ -191,7 +191,7 @@
"categories": "Categorias", "categories": "Categorias",
"category": "Categoria", "category": "Categoria",
"noCategory": "Sem categoria", "noCategory": "Sem categoria",
"noCategories": "Sem categoria", "noCategories": "Sem categorias",
"deleteCategoriesQuestion": "Deletar categorias?", "deleteCategoriesQuestion": "Deletar categorias?",
"categoryDeleteWarning": "Todos os aplicativos em categorias removidas serão descategorizados.", "categoryDeleteWarning": "Todos os aplicativos em categorias removidas serão descategorizados.",
"addCategory": "Adicionar categoria", "addCategory": "Adicionar categoria",
@ -200,15 +200,15 @@
"copiedToClipboard": "Copiado para a área de transferência", "copiedToClipboard": "Copiado para a área de transferência",
"storagePermissionDenied": "Permissão de armazenamento negada", "storagePermissionDenied": "Permissão de armazenamento negada",
"selectedCategorizeWarning": "Isso vai substituir qualquer configuração de categoria para os aplicativos selecionados.", "selectedCategorizeWarning": "Isso vai substituir qualquer configuração de categoria para os aplicativos selecionados.",
"filterAPKsByRegEx": "Filtrar APKs por expressão regular", "filterAPKsByRegEx": "Filtrar APKs usando expressão regular",
"removeFromObtainium": "Remover do Obtainium", "removeFromObtainium": "Remover do Obtainium",
"uninstallFromDevice": "Desinstalar do dispositivo", "uninstallFromDevice": "Desinstalar do dispositivo",
"onlyWorksWithNonVersionDetectApps": "Apenas funciona para aplicativos com detecção de versão desativada.", "onlyWorksWithNonVersionDetectApps": "Apenas funciona para aplicativos com detecção de versão desativada.",
"releaseDateAsVersion": "Usar data de lançamento como versão", "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.", "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", "changes": "Alterações",
"releaseDate": "Data de lançamento", "releaseDate": "Data de lançamento",
"importFromURLsInFile": "Importar de URLs em arquivo (como OPML)", "importFromURLsInFile": "Importar de URLs em arquivo (formato OPML)",
"versionDetectionExplanation": "Reconciliar string de versão com versão detectada no sistema operacional", "versionDetectionExplanation": "Reconciliar string de versão com versão detectada no sistema operacional",
"versionDetection": "Detecção de versão", "versionDetection": "Detecção de versão",
"standardVersionDetection": "Detecção de versão padrão", "standardVersionDetection": "Detecção de versão padrão",
@ -216,10 +216,10 @@
"autoApkFilterByArch": "Tente filtrar APKs por arquitetura de CPU, se possível", "autoApkFilterByArch": "Tente filtrar APKs por arquitetura de CPU, se possível",
"overrideSource": "Substituir fonte", "overrideSource": "Substituir fonte",
"dontShowAgain": "Não mostrar isso novamente", "dontShowAgain": "Não mostrar isso novamente",
"dontShowTrackOnlyWarnings": "Não mostrar avisos 'Apenas Monitorar'", "dontShowTrackOnlyWarnings": "Não mostrar avisos 'Apenas monitorar'",
"dontShowAPKOriginWarnings": "Não mostrar avisos de origem da APK", "dontShowAPKOriginWarnings": "Não mostrar avisos de origem da APK",
"moveNonInstalledAppsToBottom": "Mover aplicativos não instalados para o fundo da lista de aplicativos", "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)", "gitlabPATLabel": "Token de acesso pessoal do Gitlab\n(Ativa pesquisa e melhora a descoberta de APKs)",
"about": "Sobre", "about": "Sobre",
"requiresCredentialsInSettings": "{}: Isso requer credenciais adicionais (em Configurações)", "requiresCredentialsInSettings": "{}: Isso requer credenciais adicionais (em Configurações)",
"checkOnStart": "Verificar se há atualizações ao iniciar", "checkOnStart": "Verificar se há atualizações ao iniciar",
@ -228,7 +228,7 @@
"pickHighestVersionCode": "Auto-selecionar o maior número de versão do APK", "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", "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", "disablePageTransitions": "Desativar animações de transição de página",
"reversePageTransitions": "Reverter animações de transição de página", "reversePageTransitions": "Animações de transição de página invertidas",
"minStarCount": "Contagem mínima de estrelas", "minStarCount": "Contagem mínima de estrelas",
"addInfoBelow": "Adicionar essa informação abaixo.", "addInfoBelow": "Adicionar essa informação abaixo.",
"addInfoInSettings": "Adicionar essa informação nas configurações.", "addInfoInSettings": "Adicionar essa informação nas configurações.",
@ -254,7 +254,7 @@
"versionExtractionRegEx": "Regex de extração de versão", "versionExtractionRegEx": "Regex de extração de versão",
"matchGroupToUse": "Grupo correspondente a ser usado no 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", "highlightTouchTargets": "Realçar áreas sensíveis ao toque que são menos óbvias",
"pickExportDir": "Escolher diretório para a exportação", "pickExportDir": "Escolher diretório para exportação",
"autoExportOnChanges": "Auto-exportar em mudanças", "autoExportOnChanges": "Auto-exportar em mudanças",
"includeSettings": "Incluir configurações", "includeSettings": "Incluir configurações",
"filterVersionsByRegEx": "Filtrar versões por expressão regular", "filterVersionsByRegEx": "Filtrar versões por expressão regular",
@ -272,18 +272,18 @@
"updatesAvailableNotifChannel": "Atualizações disponíveis", "updatesAvailableNotifChannel": "Atualizações disponíveis",
"appsUpdatedNotifChannel": "Aplicativos atualizados", "appsUpdatedNotifChannel": "Aplicativos atualizados",
"appsPossiblyUpdatedNotifChannel": "Tentativas de atualização de aplicativos", "appsPossiblyUpdatedNotifChannel": "Tentativas de atualização de aplicativos",
"errorCheckingUpdatesNotifChannel": "Erro ao Procurar por Atualizações", "errorCheckingUpdatesNotifChannel": "Erro ao procurar por atualizações",
"appsRemovedNotifChannel": "Aplicativos removidos", "appsRemovedNotifChannel": "Aplicativos removidos",
"downloadingXNotifChannel": "Baixando {}", "downloadingXNotifChannel": "Baixando {}",
"completeAppInstallationNotifChannel": "Instalação completa do aplicativo", "completeAppInstallationNotifChannel": "Instalação completa do aplicativo",
"checkingForUpdatesNotifChannel": "Checando por Atualizações", "checkingForUpdatesNotifChannel": "Checando por atualizações",
"onlyCheckInstalledOrTrackOnlyApps": "Apenas checar aplicativos instalados e 'Apenas Seguir' por updates", "onlyCheckInstalledOrTrackOnlyApps": "Apenas verificar atualizações de aplicativos instalados e 'Apenas monitorar'",
"supportFixedAPKURL": "Suporte a APK com URLs fixas", "supportFixedAPKURL": "Suporte a APK com URLs fixas",
"selectX": "Selecionar {}", "selectX": "Selecionar {}",
"parallelDownloads": "Permitir downloads paralelos", "parallelDownloads": "Permitir downloads paralelos",
"installMethod": "Método de instalação", "installMethod": "Método de instalação",
"normal": "Normal", "normal": "Normal",
"root": "Raiz", "root": "Root",
"shizukuBinderNotFound": "O Shizuku não está rodando", "shizukuBinderNotFound": "O Shizuku não está rodando",
"useSystemFont": "Usar fonte padrão do sistema", "useSystemFont": "Usar fonte padrão do sistema",
"systemFontError": "Erro ao carregar a fonte do sistema: {}", "systemFontError": "Erro ao carregar a fonte do sistema: {}",
@ -298,6 +298,9 @@
"installed": "Instalado", "installed": "Instalado",
"latest": "Mais recente", "latest": "Mais recente",
"invertRegEx": "Inverter expressão regular", "invertRegEx": "Inverter expressão regular",
"note": "Nota",
"selfHostedNote": "O menu suspenso \"{}\" pode ser usado para acessar instâncias auto-hospedadas/personalizadas de qualquer fonte.",
"badDownload": "Não foi possível analisar o APK (transferência incompatível ou parcial)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Remover aplicativo?", "one": "Remover aplicativo?",
"other": "Remover aplicativos?" "other": "Remover aplicativos?"
@ -339,15 +342,15 @@
"other": "Foram limpos {n} logs (antes = {antes}, depois = {depois})" "other": "Foram limpos {n} logs (antes = {antes}, depois = {depois})"
}, },
"xAndNMoreUpdatesAvailable": { "xAndNMoreUpdatesAvailable": {
"one": "{} e 1 outro aplicativo possui atualizações.", "one": "{} e um outro aplicativo possui atualizações.",
"other": "{} e {} outros aplicativo possuem atualizações." "other": "{} e {} outros aplicativo possuem atualizações."
}, },
"xAndNMoreUpdatesInstalled": { "xAndNMoreUpdatesInstalled": {
"one": "{} e um outro aplicativo foi atualizado.", "one": "{} e um outro aplicativo foram atualizado.",
"other": "{} e {} outros aplicativos foram atualizados." "other": "{} e {} outros aplicativos foram atualizados."
}, },
"xAndNMoreUpdatesPossiblyInstalled": { "xAndNMoreUpdatesPossiblyInstalled": {
"one": "{} e 1 outro aplicativo pode ter sido atualizado.", "one": "{} e um outro aplicativo podem ter sido atualizados.",
"other": "{} e {} outros aplicativos podem ter sido atualizados." "other": "{} e {} outros aplicativos podem ter sido atualizados."
} }
} }

View File

@ -298,6 +298,9 @@
"installed": "Установлен", "installed": "Установлен",
"latest": "Последний", "latest": "Последний",
"invertRegEx": "Инвертировать регулярное выражение", "invertRegEx": "Инвертировать регулярное выражение",
"note": "Примечание",
"selfHostedNote": "Выпадающий список \"{}\" можно использовать для доступа к самостоятельно размещенным/настроенным экземплярам любого источника.",
"badDownload": "APK не удалось разобрать (несовместимая или неполная загрузка)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Удалить приложение?", "one": "Удалить приложение?",
"other": "Удалить приложения?" "other": "Удалить приложения?"

View File

@ -1,8 +1,57 @@
// Take one (hardcoded) translation file and ensure that all other translation files have the same keys in the same order // Take one (hardcoded) translation file and ensure that all other translation files have the same keys in the same order
// Then report which other translation files have identical items // Then report which other translation files have identical items (or auto-translate them if a DeepL API key is provided)
const fs = require('fs') const fs = require('fs')
const https = require('https')
const deeplAPIKey = process.argv[2]
const neverAutoTranslate = {
steamMobile: ['*'],
steamChat: ['*'],
root: ['*'],
obtainiumExportHyphenatedLowercase: ['*'],
theme: ['de'],
appId: ['de']
}
const translateText = async (text, targetLang, authKey) => {
return new Promise((resolve, reject) => {
const postData = `text=${encodeURIComponent(text)}&target_lang=${encodeURIComponent(targetLang)}&source_lang=EN`
const options = {
hostname: 'api-free.deepl.com',
port: 443,
path: '/v2/translate',
method: 'POST',
headers: {
'Authorization': `DeepL-Auth-Key ${authKey}`,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
}
const req = https.request(options, (res) => {
let responseData = ''
res.on('data', (chunk) => {
responseData += chunk
})
res.on('end', () => {
try {
const jsonResponse = JSON.parse(responseData)
resolve(jsonResponse)
} catch (error) {
reject(error)
}
})
})
req.on('error', (error) => {
reject(error)
})
req.write(postData)
req.end()
})
}
const main = async () => {
const translationsDir = __dirname const translationsDir = __dirname
const templateFile = `${translationsDir}/en.json` const templateFile = `${translationsDir}/en.json`
const otherFiles = fs.readdirSync(translationsDir).map(f => { const otherFiles = fs.readdirSync(translationsDir).map(f => {
@ -11,6 +60,7 @@ const otherFiles = fs.readdirSync(translationsDir).map(f => {
const templateTranslation = require(templateFile) const templateTranslation = require(templateFile)
otherFiles.forEach(file => { otherFiles.forEach(file => {
const thisTranslationOriginal = require(file) const thisTranslationOriginal = require(file)
const thisTranslationNew = {} const thisTranslationNew = {}
@ -18,13 +68,52 @@ otherFiles.forEach(file => {
thisTranslationNew[k] = thisTranslationOriginal[k] || templateTranslation[k] thisTranslationNew[k] = thisTranslationOriginal[k] || templateTranslation[k]
}) })
fs.writeFileSync(file, `${JSON.stringify(thisTranslationNew, null, ' ')}\n`) fs.writeFileSync(file, `${JSON.stringify(thisTranslationNew, null, ' ')}\n`)
});
otherFiles.forEach(file => {
const thisTranslation = require(file)
Object.keys(templateTranslation).forEach(k => {
if (JSON.stringify(thisTranslation[k]) == JSON.stringify(templateTranslation[k])) {
console.log(`${file} :::: ${k} :::: ${JSON.stringify(thisTranslation[k])}`)
}
}) })
});
for (let i in otherFiles) {
const file = otherFiles[i]
const thisTranslation = require(file)
const translationKeys = Object.keys(templateTranslation)
for (let j in translationKeys) {
const k = translationKeys[j]
if (JSON.stringify(thisTranslation[k]) == JSON.stringify(templateTranslation[k])) {
const lang = file.split('/').pop().split('.')[0]
if (!neverAutoTranslate[k] || (neverAutoTranslate[k].indexOf('*') < 0 && neverAutoTranslate[k].indexOf(lang) < 0)) {
const reportLine = `${file} :::: ${k} :::: ${JSON.stringify(thisTranslation[k])}`
if (deeplAPIKey) {
const translateFunc = async (str) => {
const response = await translateText(str, lang, deeplAPIKey)
if (response.translations) {
return response.translations[0].text
} else {
throw JSON.stringify(response)
}
}
try {
if (typeof templateTranslation[k] == 'string') {
thisTranslation[k] = await translateFunc(thisTranslation[k])
} else {
const subKeys = Object.keys(templateTranslation[k])
for (let n in subKeys) {
const kk = subKeys[n]
thisTranslation[k][kk] = await translateFunc(thisTranslation[k][kk])
}
}
} catch (e) {
if (typeof e == 'string') {
console.log(`${reportLine} :::: ${e}`)
} else {
throw e
}
}
} else {
console.log(reportLine)
}
}
}
}
fs.writeFileSync(file, `${JSON.stringify(thisTranslation, null, ' ')}\n`)
}
}
main().catch(e => console.error)

View File

@ -288,16 +288,19 @@
"useSystemFont": "Använd systemteckensnittet", "useSystemFont": "Använd systemteckensnittet",
"systemFontError": "Fel vid laddning av systemteckensnittet: {}", "systemFontError": "Fel vid laddning av systemteckensnittet: {}",
"useVersionCodeAsOSVersion": "Använd appversionskoden som OS-upptäckt version", "useVersionCodeAsOSVersion": "Använd appversionskoden som OS-upptäckt version",
"requestHeader": "Request header", "requestHeader": "Rubrik för begäran",
"useLatestAssetDateAsReleaseDate": "Använd senaste tillgångsuppladdning som releasedatum", "useLatestAssetDateAsReleaseDate": "Använd senaste tillgångsuppladdning som releasedatum",
"defaultPseudoVersioningMethod": "Standard pseudoversionsmetod", "defaultPseudoVersioningMethod": "Standard pseudoversionsmetod",
"partialAPKHash": "Delvis APK-hash", "partialAPKHash": "Delvis APK-hash",
"APKLinkHash": "APK Link Hash", "APKLinkHash": "APK-länk Hash",
"directAPKLink": "Direkt APK-länk", "directAPKLink": "Direkt APK-länk",
"pseudoVersionInUse": "En pseudoversion används", "pseudoVersionInUse": "En pseudoversion används",
"installed": "Installerad", "installed": "Installerad",
"latest": "Senast", "latest": "Senast",
"invertRegEx": "Invertera reguljärt uttryck", "invertRegEx": "Invertera reguljärt uttryck",
"note": "Anmärkning",
"selfHostedNote": "Rullgardinsmenyn \"{}\" kan användas för att nå självhostade/anpassade instanser av valfri källa.",
"badDownload": "APK kunde inte analyseras (inkompatibel eller partiell nedladdning)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Ta Bort App?", "one": "Ta Bort App?",
"other": "Ta Bort Appar?" "other": "Ta Bort Appar?"

View File

@ -298,6 +298,9 @@
"installed": "Kurulmuş", "installed": "Kurulmuş",
"latest": "En sonuncu", "latest": "En sonuncu",
"invertRegEx": "Normal ifadeyi ters çevir", "invertRegEx": "Normal ifadeyi ters çevir",
"note": "Not",
"selfHostedNote": "\"{}\" açılır menüsü, herhangi bir kaynağın kendi kendine barındırılan/özel örneklerine ulaşmak için kullanılabilir.",
"badDownload": "APK ayrıştırılamadı (uyumsuz veya kısmi indirme)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Uygulamayı Kaldır?", "one": "Uygulamayı Kaldır?",
"other": "Uygulamaları Kaldır?" "other": "Uygulamaları Kaldır?"

View File

@ -25,11 +25,11 @@
"githubStarredRepos": "Kho lưu trữ có gắn dấu sao GitHub", "githubStarredRepos": "Kho lưu trữ có gắn dấu sao GitHub",
"uname": "Tên người dùng", "uname": "Tên người dùng",
"wrongArgNum": "Số lượng đối số được cung cấp sai", "wrongArgNum": "Số lượng đối số được cung cấp sai",
"xIsTrackOnly": "{}là Chỉ-Theo dõi", "xIsTrackOnly": "{} là Chỉ theo dõi",
"source": "Nguồn", "source": "Nguồn",
"app": "Ứng dụng", "app": "Ứng dụng",
"appsFromSourceAreTrackOnly": "Các ứng dụng từ nguồn này là 'Chỉ-Theo dõi'.", "appsFromSourceAreTrackOnly": "Các ứng dụng từ nguồn này là 'Chỉ theo dõi'.",
"youPickedTrackOnly": "Bạn đã chọn tùy chọn 'Chỉ-Theo dõi'.", "youPickedTrackOnly": "Bạn đã chọn tùy chọn 'Chỉ theo dõi'.",
"trackOnlyAppDescription": "Ứng dụng sẽ được theo dõi để cập nhật, nhưng Obtainium sẽ không thể tải xuống hoặc cài đặt nó.", "trackOnlyAppDescription": "Ứng dụng sẽ được theo dõi để cập nhật, nhưng Obtainium sẽ không thể tải xuống hoặc cài đặt nó.",
"cancelled": "Đã hủy", "cancelled": "Đã hủy",
"appAlreadyAdded": "Ứng dụng được thêm rồi", "appAlreadyAdded": "Ứng dụng được thêm rồi",
@ -42,7 +42,7 @@
"search": "Tìm kiếm", "search": "Tìm kiếm",
"additionalOptsFor": "Tùy chọn bổ sung cho {}", "additionalOptsFor": "Tùy chọn bổ sung cho {}",
"supportedSources": "Nguồn được hỗ trợ", "supportedSources": "Nguồn được hỗ trợ",
"trackOnlyInBrackets": "(Chỉ-Theo dõi)", "trackOnlyInBrackets": "(Chỉ theo dõi)",
"searchableInBrackets": "(Có thể tìm kiếm)", "searchableInBrackets": "(Có thể tìm kiếm)",
"appsString": "Ứng dụng", "appsString": "Ứng dụng",
"noApps": "Không có ứng dụng", "noApps": "Không có ứng dụng",
@ -60,7 +60,7 @@
"removeSelectedApps": "Xóa ứng dụng đã chọn", "removeSelectedApps": "Xóa ứng dụng đã chọn",
"updateX": "Cập nhật {}", "updateX": "Cập nhật {}",
"installX": "Cài đặt {}", "installX": "Cài đặt {}",
"markXTrackOnlyAsUpdated": "Đánh dấu {}\n(Chỉ-Theo dõi)\nnhư là đã cập nhật", "markXTrackOnlyAsUpdated": "Đánh dấu {}\n(Chỉ theo dõi)\nnhư là đã cập nhật",
"changeX": "Thay đổi {}", "changeX": "Thay đổi {}",
"installUpdateApps": "Cài đặt/Cập nhật ứng dụng", "installUpdateApps": "Cài đặt/Cập nhật ứng dụng",
"installUpdateSelectedApps": "Cài đặt/Cập nhật ứng dụng đã chọn", "installUpdateSelectedApps": "Cài đặt/Cập nhật ứng dụng đã chọn",
@ -277,7 +277,7 @@
"downloadingXNotifChannel": "Đang tải xuống {}", "downloadingXNotifChannel": "Đang tải xuống {}",
"completeAppInstallationNotifChannel": "Hoàn tất cài đặt ứng dụng", "completeAppInstallationNotifChannel": "Hoàn tất cài đặt ứng dụng",
"checkingForUpdatesNotifChannel": "Đang kiểm tra cập nhật", "checkingForUpdatesNotifChannel": "Đang kiểm tra cập nhật",
"onlyCheckInstalledOrTrackOnlyApps": "Chỉ kiểm tra cập nhật các ứng dụng đã cài đặt và Chỉ-Theo dõi", "onlyCheckInstalledOrTrackOnlyApps": "Chỉ kiểm tra cập nhật các ứng dụng đã cài đặt và Chỉ theo dõi",
"supportFixedAPKURL": "Hỗ trợ URL APK cố định", "supportFixedAPKURL": "Hỗ trợ URL APK cố định",
"selectX": "Lựa chọn {}", "selectX": "Lựa chọn {}",
"parallelDownloads": "Cho phép tải đa luồng", "parallelDownloads": "Cho phép tải đa luồng",
@ -295,9 +295,12 @@
"APKLinkHash": "Băm liên kết APK", "APKLinkHash": "Băm liên kết APK",
"directAPKLink": "Liên kết APK trực tiếp", "directAPKLink": "Liên kết APK trực tiếp",
"pseudoVersionInUse": "Phiên bản giả đang được sử dụng", "pseudoVersionInUse": "Phiên bản giả đang được sử dụng",
"installed": "Cài đặt", "installed": "Đã cài đặt",
"latest": "Mới nhất", "latest": "Mới nhất",
"invertRegEx": "Đảo ngược biểu thức chính quy", "invertRegEx": "Đảo ngược biểu thức chính quy",
"note": "Note",
"selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
"badDownload": "The APK could not be parsed (incompatible or partial download)",
"removeAppQuestion": { "removeAppQuestion": {
"one": "Gỡ ứng dụng?", "one": "Gỡ ứng dụng?",
"other": "Gỡ ứng dụng?" "other": "Gỡ ứng dụng?"

View File

@ -298,6 +298,9 @@
"installed": "已安装", "installed": "已安装",
"latest": "最新的", "latest": "最新的",
"invertRegEx": "反转正则表达式", "invertRegEx": "反转正则表达式",
"note": "备注",
"selfHostedNote": "{}\"下拉菜单可用于访问任何来源的自托管/自定义实例。",
"badDownload": "无法解析 APK不兼容或部分下载",
"removeAppQuestion": { "removeAppQuestion": {
"one": "是否删除应用?", "one": "是否删除应用?",
"other": "是否删除应用?" "other": "是否删除应用?"

View File

@ -8,6 +8,7 @@ if [ -z "$1" ]; then
git fetch && git merge origin/main && git push # Typically run after a PR to main, so bring dev up to date git fetch && git merge origin/main && git push # Typically run after a PR to main, so bring dev up to date
fi fi
cd .flutter cd .flutter
git fetch
git checkout "$(flutter --version | head -2 | tail -1 | awk '{print $4}')" # Ensure included Flutter submodule version equals my environment git checkout "$(flutter --version | head -2 | tail -1 | awk '{print $4}')" # Ensure included Flutter submodule version equals my environment
cd .. cd ..
rm ./build/app/outputs/flutter-apk/* 2>/dev/null # Get rid of older builds if any rm ./build/app/outputs/flutter-apk/* 2>/dev/null # Get rid of older builds if any

View File

@ -3,6 +3,8 @@ import 'dart:convert';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:html/parser.dart'; import 'package:html/parser.dart';
import 'package:http/http.dart'; import 'package:http/http.dart';
import 'package:obtainium/app_sources/github.dart';
import 'package:obtainium/app_sources/gitlab.dart';
import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/components/generated_form.dart';
import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/providers/source_provider.dart'; import 'package:obtainium/providers/source_provider.dart';
@ -74,16 +76,7 @@ class FDroid extends AppSource {
'https://$host/repo/$appId', 'https://$host/repo/$appId',
standardUrl, standardUrl,
name, name,
autoSelectHighestVersionCode: additionalSettings: additionalSettings);
additionalSettings['autoSelectHighestVersionCode'] == true,
trySelectingSuggestedVersionCode:
additionalSettings['trySelectingSuggestedVersionCode'] == true,
filterVersionsByRegEx:
(additionalSettings['filterVersionsByRegEx'] as String?)
?.isNotEmpty ==
true
? additionalSettings['filterVersionsByRegEx']
: null);
if (!hostChanged) { if (!hostChanged) {
try { try {
var res = await sourceRequest( var res = await sourceRequest(
@ -95,18 +88,33 @@ class FDroid extends AppSource {
details.names.author = details.names.author =
authorLines.first.split(': ').sublist(1).join(': '); authorLines.first.split(': ').sublist(1).join(': ');
} }
var changelogUrls = lines.where((l) => l.startsWith('Changelog: ')); var changelogUrls = lines
.where((l) => l.startsWith('Changelog: '))
.map((e) => e.split(' ').sublist(1).join(' '));
if (changelogUrls.isNotEmpty) { if (changelogUrls.isNotEmpty) {
details.changeLog = changelogUrls.first; details.changeLog = changelogUrls.first;
bool isGitHub = false;
bool isGitLab = false;
try {
GitHub().sourceSpecificStandardizeURL(details.changeLog!);
isGitHub = true;
} catch (e) {
//
}
try {
GitLab().sourceSpecificStandardizeURL(details.changeLog!);
isGitLab = true;
} catch (e) {
//
}
if ((isGitHub || isGitLab) &&
(details.changeLog?.indexOf('/blob/') ?? -1) >= 0) {
details.changeLog = (await sourceRequest( details.changeLog = (await sourceRequest(
details.changeLog! details.changeLog!.replaceFirst('/blob/', '/raw/'),
.split(': ')
.sublist(1)
.join(': ')
.replaceFirst('/blob/', '/raw/'),
additionalSettings)) additionalSettings))
.body; .body;
} }
}
} catch (e) { } catch (e) {
// Fail silently // Fail silently
} }
@ -149,12 +157,30 @@ class FDroid extends AppSource {
APKDetails getAPKUrlsFromFDroidPackagesAPIResponse( APKDetails getAPKUrlsFromFDroidPackagesAPIResponse(
Response res, String apkUrlPrefix, String standardUrl, String sourceName, Response res, String apkUrlPrefix, String standardUrl, String sourceName,
{bool autoSelectHighestVersionCode = false, {Map<String, dynamic> additionalSettings = const {}}) {
bool trySelectingSuggestedVersionCode = false, var autoSelectHighestVersionCode =
String? filterVersionsByRegEx}) { additionalSettings['autoSelectHighestVersionCode'] == true;
var trySelectingSuggestedVersionCode =
additionalSettings['trySelectingSuggestedVersionCode'] == true;
var filterVersionsByRegEx =
(additionalSettings['filterVersionsByRegEx'] as String?)?.isNotEmpty ==
true
? additionalSettings['filterVersionsByRegEx']
: null;
var apkFilterRegEx =
(additionalSettings['apkFilterRegEx'] as String?)?.isNotEmpty == true
? additionalSettings['apkFilterRegEx']
: null;
if (res.statusCode == 200) { if (res.statusCode == 200) {
var response = jsonDecode(res.body); var response = jsonDecode(res.body);
List<dynamic> releases = response['packages'] ?? []; List<dynamic> releases = response['packages'] ?? [];
if (apkFilterRegEx != null) {
releases = releases.where((rel) {
String apk = '${apkUrlPrefix}_${rel['versionCode']}.apk';
return filterApks([MapEntry(apk, apk)], apkFilterRegEx, false)
.isNotEmpty;
}).toList();
}
if (releases.isEmpty) { if (releases.isEmpty) {
throw NoReleasesError(); throw NoReleasesError();
} }

View File

@ -1,5 +1,6 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:html/parser.dart'; import 'package:html/parser.dart';
import 'package:http/http.dart';
import 'package:obtainium/components/generated_form.dart'; import 'package:obtainium/components/generated_form.dart';
import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/custom_errors.dart';
import 'package:obtainium/providers/source_provider.dart'; import 'package:obtainium/providers/source_provider.dart';
@ -45,7 +46,7 @@ class FDroidRepo extends AppSource {
String sourceSpecificStandardizeURL(String url) { String sourceSpecificStandardizeURL(String url) {
var standardUri = Uri.parse(url); var standardUri = Uri.parse(url);
var pathSegments = standardUri.pathSegments; var pathSegments = standardUri.pathSegments;
if (pathSegments.last == 'index.xml') { if (pathSegments.isNotEmpty && pathSegments.last == 'index.xml') {
pathSegments.removeLast(); pathSegments.removeLast();
standardUri = standardUri.replace(path: pathSegments.join('/')); standardUri = standardUri.replace(path: pathSegments.join('/'));
} }
@ -60,7 +61,7 @@ class FDroidRepo extends AppSource {
throw NoReleasesError(); throw NoReleasesError();
} }
url = removeQueryParamsFromUrl(standardizeUrl(url)); url = removeQueryParamsFromUrl(standardizeUrl(url));
var res = await sourceRequest('$url/index.xml', {}); var res = await sourceRequestWithURLVariants(url, {});
if (res.statusCode == 200) { if (res.statusCode == 200) {
var body = parse(res.body); var body = parse(res.body);
Map<String, List<String>> results = {}; Map<String, List<String>> results = {};
@ -72,7 +73,11 @@ class FDroidRepo extends AppSource {
appId.contains(query) || appId.contains(query) ||
appName.contains(query) || appName.contains(query) ||
appDesc.contains(query)) { appDesc.contains(query)) {
results['$url?appId=$appId'] = [appName, appDesc]; results[
'${res.request!.url.toString().split('/').reversed.toList().sublist(1).reversed.join('/')}?appId=$appId'] = [
appName,
appDesc
];
} }
}); });
return results; return results;
@ -102,6 +107,26 @@ class FDroidRepo extends AppSource {
return app; return app;
} }
Future<Response> sourceRequestWithURLVariants(
String url,
Map<String, dynamic> additionalSettings,
) async {
var res = await sourceRequest(
'$url${url.endsWith('/index.xml') ? '' : '/index.xml'}',
additionalSettings);
if (res.statusCode != 200) {
var base = url.endsWith('/index.xml')
? url.split('/').reversed.toList().sublist(1).reversed.join('/')
: url;
res = await sourceRequest('$base/repo/index.xml', additionalSettings);
if (res.statusCode != 200) {
res = await sourceRequest(
'$base/fdroid/repo/index.xml', additionalSettings);
}
}
return res;
}
@override @override
Future<APKDetails> getLatestAPKDetails( Future<APKDetails> getLatestAPKDetails(
String standardUrl, String standardUrl,
@ -117,9 +142,8 @@ class FDroidRepo extends AppSource {
if (appIdOrName == null) { if (appIdOrName == null) {
throw NoReleasesError(); throw NoReleasesError();
} }
var res = await sourceRequest( var res =
'$standardUrl${standardUrl.endsWith('/index.xml') ? '' : '/index.xml'}', await sourceRequestWithURLVariants(standardUrl, additionalSettings);
additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
var body = parse(res.body); var body = parse(res.body);
var foundApps = body.querySelectorAll('application').where((element) { var foundApps = body.querySelectorAll('application').where((element) {
@ -168,7 +192,8 @@ class FDroidRepo extends AppSource {
latestVersionReleases = [latestVersionReleases[0]]; latestVersionReleases = [latestVersionReleases[0]];
} }
List<String> apkUrls = latestVersionReleases List<String> apkUrls = latestVersionReleases
.map((e) => '$standardUrl/${e.querySelector('apkname')!.innerHtml}') .map((e) =>
'${res.request!.url.toString().split('/').reversed.toList().sublist(1).reversed.join('/')}/${e.querySelector('apkname')!.innerHtml}')
.toList(); .toList();
return APKDetails(latestVersion, getApkUrlsFromUrls(apkUrls), return APKDetails(latestVersion, getApkUrlsFromUrls(apkUrls),
AppNames(authorName, appName), AppNames(authorName, appName),

View File

@ -319,7 +319,7 @@ class HTML extends AppSource {
version ??= version ??=
additionalSettings['defaultPseudoVersioningMethod'] == 'APKLinkHash' additionalSettings['defaultPseudoVersioningMethod'] == 'APKLinkHash'
? rel.hashCode.toString() ? rel.hashCode.toString()
: (await checkPartialDownloadHashDynamc(rel)).toString(); : (await checkPartialDownloadHashDynamic(rel)).toString();
return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(), return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(),
AppNames(uri.host, tr('app'))); AppNames(uri.host, tr('app')));
} }

View File

@ -50,10 +50,6 @@ class IzzyOnDroid extends AppSource {
'https://android.izzysoft.de/frepo/$appId', 'https://android.izzysoft.de/frepo/$appId',
standardUrl, standardUrl,
name, name,
autoSelectHighestVersionCode: additionalSettings: additionalSettings);
additionalSettings['autoSelectHighestVersionCode'] == true,
trySelectingSuggestedVersionCode:
additionalSettings['trySelectingSuggestedVersionCode'] == true,
filterVersionsByRegEx: additionalSettings['filterVersionsByRegEx']);
} }
} }

View File

@ -10,16 +10,23 @@ class SourceForge extends AppSource {
@override @override
String sourceSpecificStandardizeURL(String url) { String sourceSpecificStandardizeURL(String url) {
RegExp standardUrlRegExB = RegExp( var sourceRegex = getSourceRegex(hosts);
'^https?://(www\\.)?${getSourceRegex(hosts)}/p/[^/]+', RegExp standardUrlRegExC =
caseSensitive: false); RegExp('^https?://(www\\.)?$sourceRegex/p/.+', caseSensitive: false);
RegExpMatch? match = standardUrlRegExB.firstMatch(url); RegExpMatch? match = standardUrlRegExC.firstMatch(url);
if (match != null) { if (match != null) {
url = url =
'https://${Uri.parse(match.group(0)!).host}/projects/${url.substring(Uri.parse(match.group(0)!).host.length + '/projects/'.length + 1)}'; 'https://${Uri.parse(match.group(0)!).host}/projects/${url.substring(Uri.parse(match.group(0)!).host.length + '/projects/'.length + 1)}';
} }
RegExp standardUrlRegExB = RegExp(
'^https?://(www\\.)?$sourceRegex/projects/[^/]+',
caseSensitive: false);
match = standardUrlRegExB.firstMatch(url);
if (match != null && match.group(0) == url) {
url = '$url/files';
}
RegExp standardUrlRegExA = RegExp( RegExp standardUrlRegExA = RegExp(
'^https?://(www\\.)?${getSourceRegex(hosts)}/projects/[^/]+', '^https?://(www\\.)?$sourceRegex/projects/[^/]+/files(/.+)?',
caseSensitive: false); caseSensitive: false);
match = standardUrlRegExA.firstMatch(url); match = standardUrlRegExA.firstMatch(url);
if (match == null) { if (match == null) {
@ -33,38 +40,79 @@ class SourceForge extends AppSource {
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
Response res = var standardUri = Uri.parse(standardUrl);
await sourceRequest('$standardUrl/rss?path=/', additionalSettings); if (standardUri.pathSegments.length == 2) {
standardUrl = '$standardUrl/files';
standardUri = Uri.parse(standardUrl);
}
Response res = await sourceRequest(
'${standardUri.origin}/${standardUri.pathSegments.sublist(0, 2).join('/')}/rss?path=/',
additionalSettings);
if (res.statusCode == 200) { if (res.statusCode == 200) {
var parsedHtml = parse(res.body); var parsedHtml = parse(res.body);
var allDownloadLinks = var allDownloadLinks = parsedHtml
parsedHtml.querySelectorAll('guid').map((e) => e.innerHtml).toList(); .querySelectorAll('guid')
.map((e) => e.innerHtml)
.where((element) => element.startsWith(standardUrl))
.toList();
getVersion(String url) { getVersion(String url) {
try { try {
var tokens = url.split('/'); var segments = url
var fi = tokens.indexOf('files'); .substring(standardUrl.length)
return tokens[tokens[fi + 2] == 'download' ? fi - 1 : fi + 1]; .split('/')
.where((element) => element.isNotEmpty)
.toList()
.reversed
.toList()
.sublist(1)
.reversed
.toList();
segments = segments.length > 1
? segments.reversed.toList().sublist(1).reversed.toList()
: segments;
var version = segments.isNotEmpty ? segments.join('/') : null;
if (version != null) {
try {
var extractedVersion = extractVersion(
additionalSettings['versionExtractionRegEx'] as String?,
additionalSettings['matchGroupToUse'] as String?,
version);
if (extractedVersion != null) {
version = extractedVersion;
}
} catch (e) {
if (e is NoVersionError) {
version = null;
} else {
rethrow;
}
}
}
return version;
} catch (e) { } catch (e) {
return null; return null;
} }
} }
String? version = getVersion(allDownloadLinks[0]); var apkUrlListAllReleases = allDownloadLinks
.where((element) => element.toLowerCase().endsWith('.apk/download'))
.where((element) => getVersion(element) != null)
.toList();
if (apkUrlListAllReleases.isEmpty) {
throw NoReleasesError();
}
String? version = getVersion(apkUrlListAllReleases[0]);
if (version == null) { if (version == null) {
throw NoVersionError(); throw NoVersionError();
} }
var apkUrlListAllReleases = allDownloadLinks
.where((element) => element.toLowerCase().endsWith('.apk/download'))
.toList();
var apkUrlList = var apkUrlList =
apkUrlListAllReleases // This can be used skipped for fallback support later apkUrlListAllReleases // This can be used skipped for fallback support later
.where((element) => getVersion(element) == version) .where((element) => getVersion(element) == version)
.toList(); .toList();
return APKDetails( var segments = standardUrl.split('/');
version, return APKDetails(version, getApkUrlsFromUrls(apkUrlList),
getApkUrlsFromUrls(apkUrlList), AppNames(name, segments[segments.indexOf('files') - 1]));
AppNames(
name, standardUrl.substring(standardUrl.lastIndexOf('/') + 1)));
} else { } else {
throw getObtainiumHttpError(res); throw getObtainiumHttpError(res);
} }

View File

@ -39,6 +39,15 @@ class SourceHut extends AppSource {
String standardUrl, String standardUrl,
Map<String, dynamic> additionalSettings, Map<String, dynamic> additionalSettings,
) async { ) async {
if (standardUrl.endsWith('/refs')) {
standardUrl = standardUrl
.split('/')
.reversed
.toList()
.sublist(1)
.reversed
.join('/');
}
Uri standardUri = Uri.parse(standardUrl); Uri standardUri = Uri.parse(standardUrl);
String appName = standardUri.pathSegments.last; String appName = standardUri.pathSegments.last;
bool fallbackToOlderReleases = bool fallbackToOlderReleases =

View File

@ -163,7 +163,7 @@ class AddAppPageState extends State<AddAppPage> {
app = await sourceProvider.getApp( app = await sourceProvider.getApp(
pickedSource!, userInput.trim(), additionalSettings, pickedSource!, userInput.trim(), additionalSettings,
trackOnlyOverride: trackOnly, trackOnlyOverride: trackOnly,
overrideSource: pickedSourceOverride, sourceIsOverriden: pickedSourceOverride != null,
inferAppIdIfOptional: inferAppIdIfOptional); inferAppIdIfOptional: inferAppIdIfOptional);
// Only download the APK here if you need to for the package ID // Only download the APK here if you need to for the package ID
if (isTempId(app) && app.additionalSettings['trackOnly'] != true) { if (isTempId(app) && app.additionalSettings['trackOnly'] != true) {
@ -530,7 +530,20 @@ class AddAppPageState extends State<AddAppPage> {
? TextDecoration.underline ? TextDecoration.underline
: TextDecoration.none), : TextDecoration.none),
))), ))),
) ),
const SizedBox(
height: 16,
),
Text(
'${tr('note')}:',
style:
const TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(
height: 4,
),
Text(tr('selfHostedNote',
args: [tr('overrideSource')])),
], ],
); );
}, },

View File

@ -205,6 +205,12 @@ class _AppPageState extends State<AppPage> {
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.displayLarge, style: Theme.of(context).textTheme.displayLarge,
), ),
Text(tr('byX', args: [app?.app.author ?? tr('unknown')]),
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineMedium),
const SizedBox(
height: 24,
),
GestureDetector( GestureDetector(
onTap: () { onTap: () {
if (app?.app.url != null) { if (app?.app.url != null) {
@ -219,15 +225,12 @@ class _AppPageState extends State<AppPage> {
)); ));
}, },
child: Text( child: Text(
tr('byX', args: [app?.app.author ?? tr('unknown')]), app?.app.url ?? '',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineMedium!.copyWith( style: Theme.of(context).textTheme.labelSmall!.copyWith(
decoration: TextDecoration.underline, decoration: TextDecoration.underline,
fontStyle: FontStyle.italic), fontStyle: FontStyle.italic),
)), )),
const SizedBox(
height: 8,
),
Text( Text(
app?.app.id ?? '', app?.app.id ?? '',
textAlign: TextAlign.center, textAlign: TextAlign.center,

View File

@ -358,6 +358,16 @@ class AppsPageState extends State<AppsPage> {
String? changesUrl = String? changesUrl =
appSource.changeLogPageFromStandardUrl(listedApps[appIndex].app.url); appSource.changeLogPageFromStandardUrl(listedApps[appIndex].app.url);
String? changeLog = listedApps[appIndex].app.changeLog; String? changeLog = listedApps[appIndex].app.changeLog;
if (changeLog?.split('\n').length == 1) {
if (RegExp(
'(http|ftp|https)://([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?')
.hasMatch(changeLog!)) {
if (changesUrl == null) {
changesUrl = changeLog;
changeLog = null;
}
}
}
return (changeLog == null && changesUrl == null) return (changeLog == null && changesUrl == null)
? null ? null
: () { : () {
@ -1028,7 +1038,7 @@ class AppsPageState extends State<AppsPage> {
IconButton( IconButton(
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
style: const ButtonStyle(visualDensity: VisualDensity.compact), style: const ButtonStyle(visualDensity: VisualDensity.compact),
tooltip: isFilterOff ? tr('filter') : tr('filterActive'), tooltip: '${tr('filter')}${isFilterOff ? '' : ' *'}',
onPressed: isFilterOff onPressed: isFilterOff
? showFilterDialog ? showFilterDialog
: () { : () {

View File

@ -213,7 +213,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
setState(() { setState(() {
importInProgress = true; importInProgress = true;
}); });
if (values['url'] != source.hosts[0]) { if (source.hosts.isEmpty || values['url'] != source.hosts[0]) {
source = sourceProvider.getSource(values['url'], source = sourceProvider.getSource(values['url'],
overrideSource: source.runtimeType.toString()); overrideSource: source.runtimeType.toString());
} }

View File

@ -167,7 +167,7 @@ String hashListOfLists(List<List<int>> data) {
return hash.hashCode.toString(); return hash.hashCode.toString();
} }
Future<String> checkPartialDownloadHashDynamc(String url, Future<String> checkPartialDownloadHashDynamic(String url,
{int startingSize = 1024, {int startingSize = 1024,
int lowerLimit = 128, int lowerLimit = 128,
Map<String, String>? headers}) async { Map<String, String>? headers}) async {
@ -532,9 +532,18 @@ class AppsProvider with ChangeNotifier {
{bool needsBGWorkaround = false}) async { {bool needsBGWorkaround = false}) async {
var newInfo = var newInfo =
await pm.getPackageArchiveInfo(archiveFilePath: file.file.path); await pm.getPackageArchiveInfo(archiveFilePath: file.file.path);
if (newInfo == null) {
try {
file.file.deleteSync(recursive: true);
} catch (e) {
//
} finally {
throw ObtainiumError(tr('badDownload'));
}
}
PackageInfo? appInfo = await getInstalledInfo(apps[file.appId]!.app.id); PackageInfo? appInfo = await getInstalledInfo(apps[file.appId]!.app.id);
if (appInfo != null && if (appInfo != null &&
newInfo!.versionCode! < appInfo.versionCode! && newInfo.versionCode! < appInfo.versionCode! &&
!(await canDowngradeApps())) { !(await canDowngradeApps())) {
throw DowngradeError(); throw DowngradeError();
} }

View File

@ -819,7 +819,7 @@ class SourceProvider {
AppSource source, String url, Map<String, dynamic> additionalSettings, AppSource source, String url, Map<String, dynamic> additionalSettings,
{App? currentApp, {App? currentApp,
bool trackOnlyOverride = false, bool trackOnlyOverride = false,
String? overrideSource, bool sourceIsOverriden = false,
bool inferAppIdIfOptional = false}) async { bool inferAppIdIfOptional = false}) async {
if (trackOnlyOverride || source.enforceTrackOnly) { if (trackOnlyOverride || source.enforceTrackOnly) {
additionalSettings['trackOnly'] = true; additionalSettings['trackOnly'] = true;
@ -829,8 +829,9 @@ class SourceProvider {
APKDetails apk = APKDetails apk =
await source.getLatestAPKDetails(standardUrl, additionalSettings); await source.getLatestAPKDetails(standardUrl, additionalSettings);
if (source.runtimeType != HTML().runtimeType) { if (source.runtimeType !=
// HTML does it separately HTML().runtimeType && // Some sources do it separately
source.runtimeType != SourceForge().runtimeType) {
String? extractedVersion = extractVersion( String? extractedVersion = extractVersion(
additionalSettings['versionExtractionRegEx'] as String?, additionalSettings['versionExtractionRegEx'] as String?,
additionalSettings['matchGroupToUse'] as String?, additionalSettings['matchGroupToUse'] as String?,
@ -886,7 +887,9 @@ class SourceProvider {
categories: currentApp?.categories ?? const [], categories: currentApp?.categories ?? const [],
releaseDate: apk.releaseDate, releaseDate: apk.releaseDate,
changeLog: apk.changeLog, changeLog: apk.changeLog,
overrideSource: overrideSource ?? currentApp?.overrideSource, overrideSource: sourceIsOverriden
? source.runtimeType.toString()
: currentApp?.overrideSource,
allowIdChange: currentApp?.allowIdChange ?? allowIdChange: currentApp?.allowIdChange ??
trackOnly || trackOnly ||
(source.appIdInferIsOptional && (source.appIdInferIsOptional &&
@ -910,6 +913,7 @@ class SourceProvider {
apps.add(await getApp( apps.add(await getApp(
source, source,
url, url,
sourceIsOverriden: sourceOverride != null,
getDefaultValuesFromFormItems( getDefaultValuesFromFormItems(
source.combinedAppSpecificSettingFormItems))); source.combinedAppSpecificSettingFormItems)));
} catch (e) { } catch (e) {

View File

@ -22,10 +22,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: android_package_manager name: android_package_manager
sha256: e52ca607b9f19f95d5dae4211ed8fa93e67093f22ac570db47489c5bca512940 sha256: "2de859fae7226a7de1c1ff9a2308f1967599408800330501a1ce97927c051153"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.0" version: "0.7.1"
animations: animations:
dependency: "direct main" dependency: "direct main"
description: description:
@ -150,10 +150,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: cross_file name: cross_file
sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e sha256: "2f9d2cbccb76127ba28528cb3ae2c2326a122446a83de5a056aaa3880d3882c5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.3+8" version: "0.3.3+7"
crypto: crypto:
dependency: "direct main" dependency: "direct main"
description: description:
@ -190,10 +190,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: device_info_plus name: device_info_plus
sha256: "0042cb3b2a76413ea5f8a2b40cec2a33e01d0c937e91f0f7c211fde4f7739ba6" sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.1.1" version: "9.1.2"
device_info_plus_platform_interface: device_info_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -214,10 +214,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: easy_localization name: easy_localization
sha256: de63e3b422adfc97f256cbb3f8cf12739b6a4993d390f3cadb3f51837afaefe5 sha256: "9c86754b22aaa3e74e471635b25b33729f958dd6fb83df0ad6612948a7b231af"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.4"
easy_logger: easy_logger:
dependency: transitive dependency: transitive
description: description:
@ -238,10 +238,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: ffi name: ffi
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.0" version: "2.1.2"
file: file:
dependency: transitive dependency: transitive
description: description:
@ -336,10 +336,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_markdown name: flutter_markdown
sha256: "30088ce826b5b9cfbf9e8bece34c716c8a59fa54461dcae1e4ac01a94639e762" sha256: "21b085a1c185e46701373866144ced56cfb7a0c33f63c916bb8fe2d0c1491278"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.18+3" version: "0.6.19"
flutter_plugin_android_lifecycle: flutter_plugin_android_lifecycle:
dependency: transitive dependency: transitive
description: description:
@ -394,10 +394,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: http name: http
sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.2.1"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
@ -410,10 +410,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: image name: image
sha256: "004a2e90ce080f8627b5a04aecb4cdfac87d2c3f3b520aa291260be5a32c033d" sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.4" version: "4.1.7"
intl: intl:
dependency: transitive dependency: transitive
description: description:
@ -438,6 +438,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.8.1" version: "4.8.1"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
url: "https://pub.dev"
source: hosted
version: "10.0.0"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
url: "https://pub.dev"
source: hosted
version: "2.0.1"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
url: "https://pub.dev"
source: hosted
version: "2.0.1"
lints: lints:
dependency: transitive dependency: transitive
description: description:
@ -458,26 +482,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.16" version: "0.12.16+1"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.0" version: "0.8.0"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.10.0" version: "1.11.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@ -506,10 +530,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.8.3" version: "1.9.0"
path_provider: path_provider:
dependency: "direct main" dependency: "direct main"
description: description:
@ -562,26 +586,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: permission_handler name: permission_handler
sha256: "45ff3fbcb99040fde55c528d5e3e6ca29171298a85436274d49c6201002087d6" sha256: "74e962b7fad7ff75959161bb2c0ad8fe7f2568ee82621c9c2660b751146bfe44"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "11.2.0" version: "11.3.0"
permission_handler_android: permission_handler_android:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_android name: permission_handler_android
sha256: "758284a0976772f9c744d6384fc5dc4834aa61e3f7aa40492927f244767374eb" sha256: "1acac6bae58144b442f11e66621c062aead9c99841093c38f5bcdcc24c1c3474"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "12.0.3" version: "12.0.5"
permission_handler_apple: permission_handler_apple:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_apple name: permission_handler_apple
sha256: c6bf440f80acd2a873d3d91a699e4cc770f86e7e6b576dda98759e8b92b39830 sha256: bdafc6db74253abb63907f4e357302e6bb786ab41465e8635f362ee71fd8707b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.3.0" version: "9.4.0"
permission_handler_html: permission_handler_html:
dependency: transitive dependency: transitive
description: description:
@ -594,10 +618,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: permission_handler_platform_interface name: permission_handler_platform_interface
sha256: "5c43148f2bfb6d14c5a8162c0a712afe891f2d847f35fcff29c406b37da43c3c" sha256: "23dfba8447c076ab5be3dee9ceb66aad345c4a648f0cac292c77b1eb0e800b78"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.0" version: "4.2.0"
permission_handler_windows: permission_handler_windows:
dependency: transitive dependency: transitive
description: description:
@ -650,10 +674,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: share_plus name: share_plus
sha256: f74fc3f1cbd99f39760182e176802f693fa0ec9625c045561cfad54681ea93dd sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.2.1" version: "7.2.2"
share_plus_platform_interface: share_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -706,10 +730,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_web name: shared_preferences_web
sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.2" version: "2.2.1"
shared_preferences_windows: shared_preferences_windows:
dependency: transitive dependency: transitive
description: description:
@ -722,10 +746,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_storage name: shared_storage
sha256: "7c65a9d64f0f5521256be974cfd74010af12196657cec9f9fb7b03b2f11bcaf6" sha256: cf20428d06af065311b71e09cbfbbfe431e979a3bf9180001c1952129b7c708f
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.0" version: "0.8.1"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -751,18 +775,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: sqflite name: sqflite
sha256: c2c32eb0c74021d987336522acc3b6bf0082fbd0c540c36a9cf4ddb8ba891ddc sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.1" version: "2.3.2"
sqflite_common: sqflite_common:
dependency: transitive dependency: transitive
description: description:
name: sqflite_common name: sqflite_common
sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6 sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.0+2" version: "2.5.3"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -839,10 +863,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_android name: url_launcher_android
sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.2.2" version: "6.3.0"
url_launcher_ios: url_launcher_ios:
dependency: transitive dependency: transitive
description: description:
@ -871,18 +895,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_platform_interface name: url_launcher_platform_interface
sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.1" version: "2.3.2"
url_launcher_web: url_launcher_web:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.3" version: "2.2.0"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
@ -907,30 +931,38 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
url: "https://pub.dev"
source: hosted
version: "13.0.0"
web: web:
dependency: transitive dependency: transitive
description: description:
name: web name: web
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.0" version: "0.5.0"
webview_flutter: webview_flutter:
dependency: "direct main" dependency: "direct main"
description: description:
name: webview_flutter name: webview_flutter
sha256: "71e1bfaef41016c8d5954291df5e9f8c6172f1f6ff3af01b5656456ddb11f94c" sha256: "25e1b6e839e8cbfbd708abc6f85ed09d1727e24e08e08c6b8590d7c65c9a8932"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.4.4" version: "4.7.0"
webview_flutter_android: webview_flutter_android:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_android name: webview_flutter_android
sha256: "4ea3c4e1b8ed590162b15b8a61b41b1ef3ff179a314627c16ce40c086d94b8af" sha256: "3e5f4e9d818086b0d01a66fb1ff9cc72ab0cc58c71980e3d3661c5685ea0efb0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.14.0" version: "3.15.0"
webview_flutter_platform_interface: webview_flutter_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -943,10 +975,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_wkwebview name: webview_flutter_wkwebview
sha256: b99ca8d8bae9c6b43d568218691aa537fb0aeae1d7d34eadf112a6aa36d26506 sha256: "9bf168bccdf179ce90450b5f37e36fe263f591c9338828d6bf09b6f8d0f57f86"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.11.0" version: "3.12.0"
win32: win32:
dependency: transitive dependency: transitive
description: description:
@ -988,5 +1020,5 @@ packages:
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
sdks: sdks:
dart: ">=3.2.3 <4.0.0" dart: ">=3.3.0 <4.0.0"
flutter: ">=3.16.6" flutter: ">=3.16.6"

View File

@ -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 # 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 # 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. # of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+250 # When changing this, update the tag in main() accordingly version: 1.0.3+2253 # When changing this, update the tag in main() accordingly
environment: environment:
sdk: '>=3.0.0 <4.0.0' sdk: '>=3.0.0 <4.0.0'