mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-15 06:06:44 +02:00
Compare commits
70 Commits
Author | SHA1 | Date | |
---|---|---|---|
d1a2831922 | |||
b042050ea3 | |||
2d43dfe0a7 | |||
b1a740223c | |||
41c98d97b1 | |||
ccc0e7696b | |||
6d41ed8011 | |||
c1476a7d58 | |||
b1ee39be3b | |||
c2ccdd3d05 | |||
a621f1dfb4 | |||
8527ad0007 | |||
377ecef1b4 | |||
1f9921e6ff | |||
00988ed04d | |||
3d1113c057 | |||
1c81f0c1e1 | |||
b26043ef5e | |||
e3ad144c06 | |||
fdb45c48ce | |||
8619cfa819 | |||
1fe4cdd648 | |||
ce22197ec9 | |||
f3d2dfe386 | |||
677790af9c | |||
85941349d8 | |||
db755e0f90 | |||
1019a01249 | |||
35da44bc64 | |||
b7ce07f965 | |||
f2c15c5c8e | |||
8f0a6b7635 | |||
491c42d68b | |||
a883857230 | |||
6468d0edcc | |||
48eeeb4f00 | |||
0b25f25669 | |||
d76b7375cb | |||
f76aa51b54 | |||
9e19a293d4 | |||
381758550c | |||
da496f7c53 | |||
f905aa7dfd | |||
0db27c773b | |||
4e968826ba | |||
e95f575530 | |||
3943caeedb | |||
4495051813 | |||
558d23b8c0 | |||
2e90d1fb18 | |||
9dae24ace6 | |||
b6e6568500 | |||
a8eae7f04b | |||
4902e0ef06 | |||
e6926a714f | |||
c9eee4331d | |||
9a8cc2e5c3 | |||
a7c9cd0f27 | |||
efc6846c1c | |||
89edddd38c | |||
e7c2112f41 | |||
d8cd3b6c92 | |||
bb1dd4ecfd | |||
3824b386d7 | |||
a9159fc8a0 | |||
7f4cf6e681 | |||
215f05fbc2 | |||
6d6afe9e69 | |||
66122f1608 | |||
0ad9bbdd8e |
2
.flutter
2
.flutter
Submodule .flutter updated: 7482962148...300451adae
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@ -15,6 +15,15 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: subosito/flutter-action@v2
|
- uses: subosito/flutter-action@v2
|
||||||
|
- uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
|
java-version: '17'
|
||||||
|
|
||||||
|
- name: Flutter Doctor
|
||||||
|
id: flutter_doctor
|
||||||
|
run: |
|
||||||
|
flutter doctor -v
|
||||||
|
|
||||||
- name: Import GPG key
|
- name: Import GPG key
|
||||||
id: import_pgp_key
|
id: import_pgp_key
|
||||||
@ -42,7 +51,6 @@ jobs:
|
|||||||
if [ ${{ inputs.beta }} == true ]; then BETA=true; else BETA=false; fi
|
if [ ${{ inputs.beta }} == true ]; then BETA=true; else BETA=false; fi
|
||||||
echo "beta=$BETA" >> $GITHUB_OUTPUT
|
echo "beta=$BETA" >> $GITHUB_OUTPUT
|
||||||
TAG="v$VERSION"
|
TAG="v$VERSION"
|
||||||
if [ $BETA == true ]; then TAG="$TAG"-beta; fi
|
|
||||||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Build APKs
|
- name: Build APKs
|
||||||
|
@ -18,7 +18,6 @@ Currently supported App sources:
|
|||||||
- [F-Droid](https://f-droid.org/)
|
- [F-Droid](https://f-droid.org/)
|
||||||
- Third Party F-Droid Repos
|
- Third Party F-Droid Repos
|
||||||
- [IzzyOnDroid](https://android.izzysoft.de/)
|
- [IzzyOnDroid](https://android.izzysoft.de/)
|
||||||
- [SourceForge](https://sourceforge.net/)
|
|
||||||
- [SourceHut](https://git.sr.ht/)
|
- [SourceHut](https://git.sr.ht/)
|
||||||
- Other - General:
|
- Other - General:
|
||||||
- [APKPure](https://apkpure.net/)
|
- [APKPure](https://apkpure.net/)
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
plugins {
|
||||||
|
id "com.android.application"
|
||||||
|
id "kotlin-android"
|
||||||
|
id "dev.flutter.flutter-gradle-plugin"
|
||||||
|
}
|
||||||
|
|
||||||
def localProperties = new Properties()
|
def localProperties = new Properties()
|
||||||
def localPropertiesFile = rootProject.file('local.properties')
|
def localPropertiesFile = rootProject.file('local.properties')
|
||||||
if (localPropertiesFile.exists()) {
|
if (localPropertiesFile.exists()) {
|
||||||
@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
|
||||||
if (flutterRoot == null) {
|
|
||||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
|
||||||
}
|
|
||||||
|
|
||||||
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
|
||||||
if (flutterVersionCode == null) {
|
if (flutterVersionCode == null) {
|
||||||
flutterVersionCode = '1'
|
flutterVersionCode = '1'
|
||||||
@ -21,11 +22,6 @@ if (flutterVersionName == null) {
|
|||||||
flutterVersionName = '1.0'
|
flutterVersionName = '1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
apply plugin: 'dev.rikka.tools.refine'
|
|
||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
|
||||||
|
|
||||||
def keystoreProperties = new Properties()
|
def keystoreProperties = new Properties()
|
||||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||||
if (keystorePropertiesFile.exists()) {
|
if (keystorePropertiesFile.exists()) {
|
||||||
@ -33,7 +29,8 @@ if (keystorePropertiesFile.exists()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
namespace "dev.imranr.obtainium"
|
||||||
|
compileSdk flutter.compileSdkVersion
|
||||||
ndkVersion flutter.ndkVersion
|
ndkVersion flutter.ndkVersion
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
@ -54,7 +51,7 @@ android {
|
|||||||
// You can update the following values to match your application needs.
|
// You can update the following values to match your application needs.
|
||||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
||||||
minSdkVersion 24
|
minSdkVersion 24
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion flutter.targetSdkVersion
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,3 @@
|
|||||||
buildscript {
|
|
||||||
ext.kotlin_version = '1.8.10'
|
|
||||||
ext {
|
|
||||||
compileSdkVersion = 34 // or latest
|
|
||||||
targetSdkVersion = 34 // or latest
|
|
||||||
appCompatVersion = "1.4.2" // or latest
|
|
||||||
}
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
classpath "com.android.tools.build:gradle:7.4.2"
|
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
||||||
classpath "dev.rikka.tools.refine:gradle-plugin:4.3.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
|
@ -1,11 +1,25 @@
|
|||||||
include ':app'
|
pluginManagement {
|
||||||
|
def flutterSdkPath = {
|
||||||
|
def properties = new Properties()
|
||||||
|
file("local.properties").withInputStream { properties.load(it) }
|
||||||
|
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||||
|
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||||
|
return flutterSdkPath
|
||||||
|
}()
|
||||||
|
|
||||||
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
|
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||||
def properties = new Properties()
|
|
||||||
|
|
||||||
assert localPropertiesFile.exists()
|
repositories {
|
||||||
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
plugins {
|
||||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||||
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
|
id "com.android.application" version "7.4.2" apply false
|
||||||
|
id "org.jetbrains.kotlin.android" version "1.8.10" apply false
|
||||||
|
}
|
||||||
|
|
||||||
|
include ":app"
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Onemogući detekciju verzije",
|
"disableVersionDetection": "Onemogući detekciju verzije",
|
||||||
"noVersionDetectionExplanation": "Ova opcija bi se trebala koristiti samo za aplikacije gdje detekcija verzije ne radi ispravno.",
|
"noVersionDetectionExplanation": "Ova opcija bi se trebala koristiti samo za aplikacije gdje detekcija verzije ne radi ispravno.",
|
||||||
"downloadingX": "Preuzimanje {}",
|
"downloadingX": "Preuzimanje {}",
|
||||||
|
"downloadX": "Download {}",
|
||||||
|
"downloadedX": "Downloaded {}",
|
||||||
|
"releaseAsset": "Release Asset",
|
||||||
"downloadNotifDescription": "Obavještava korisnika o napretku u preuzimanju aplikacije",
|
"downloadNotifDescription": "Obavještava korisnika o napretku u preuzimanju aplikacije",
|
||||||
"noAPKFound": "APK nije pronađen",
|
"noAPKFound": "APK nije pronađen",
|
||||||
"noVersionDetection": "Nema detekcije verzije",
|
"noVersionDetection": "Nema detekcije verzije",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Ne prikazuj upozorenja „Samo za praćenje”",
|
"dontShowTrackOnlyWarnings": "Ne prikazuj upozorenja „Samo za praćenje”",
|
||||||
"dontShowAPKOriginWarnings": "Ne prikazuj upozorenja o porijeklu APK-a",
|
"dontShowAPKOriginWarnings": "Ne prikazuj upozorenja o porijeklu APK-a",
|
||||||
"moveNonInstalledAppsToBottom": "Premjesti neinstalirane aplikacije na dno prikaza aplikacija",
|
"moveNonInstalledAppsToBottom": "Premjesti neinstalirane aplikacije na dno prikaza aplikacija",
|
||||||
"gitlabPATLabel": "GitLab token za lični pristup\n(Omogućava pretraživanje i bolje otkrivanje APK-a)",
|
"gitlabPATLabel": "GitLab token za lični pristup",
|
||||||
"about": "O nama",
|
"about": "O nama",
|
||||||
"requiresCredentialsInSettings": "{}: Za ovo su potrebni dodatni akreditivi (u Postavkama)",
|
"requiresCredentialsInSettings": "{}: Za ovo su potrebni dodatni akreditivi (u Postavkama)",
|
||||||
"checkOnStart": "Provjerite ima li novosti pri pokretanju",
|
"checkOnStart": "Provjerite ima li novosti pri pokretanju",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Dodajte ove informacije ispod.",
|
"addInfoBelow": "Dodajte ove informacije ispod.",
|
||||||
"addInfoInSettings": "Dodajte ove informacije u Postavkama.",
|
"addInfoInSettings": "Dodajte ove informacije u Postavkama.",
|
||||||
"githubSourceNote": "GitHub ograničavanje se može izbjeći korišćenjem tokena za lični pristup.",
|
"githubSourceNote": "GitHub ograničavanje se može izbjeći korišćenjem tokena za lični pristup.",
|
||||||
"gitlabSourceNote": "GitLab APK preuzimanje možda neće raditi bez tokena za lični pristup.",
|
|
||||||
"sortByLastLinkSegment": "Sortiraj samo po zadnjem segmentu veze",
|
"sortByLastLinkSegment": "Sortiraj samo po zadnjem segmentu veze",
|
||||||
"filterReleaseNotesByRegEx": "Filtirajte promjene u izdanju po regularnom izrazu",
|
"filterReleaseNotesByRegEx": "Filtirajte promjene u izdanju po regularnom izrazu",
|
||||||
"customLinkFilterRegex": "Prilagođeni APK link filtrira se po regularnom izrazu (Zadano '.apk$')",
|
"customLinkFilterRegex": "Prilagođeni APK link filtrira se po regularnom izrazu (Zadano '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Note",
|
"note": "Note",
|
||||||
"selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
|
"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)",
|
"badDownload": "The APK could not be parsed (incompatible or partial download)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)",
|
||||||
|
"appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Želite li ukloniti aplikaciju?",
|
"one": "Želite li ukloniti aplikaciju?",
|
||||||
"other": "Želite li ukloniti aplikacije?"
|
"other": "Želite li ukloniti aplikacije?"
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Deaktivovat detekci verze",
|
"disableVersionDetection": "Deaktivovat detekci verze",
|
||||||
"noVersionDetectionExplanation": "Tato možnost by měla být použita pouze u aplikace, kde detekce verzí nefunguje správně.",
|
"noVersionDetectionExplanation": "Tato možnost by měla být použita pouze u aplikace, kde detekce verzí nefunguje správně.",
|
||||||
"downloadingX": "Stáhnout {}",
|
"downloadingX": "Stáhnout {}",
|
||||||
|
"downloadX": "Stáhnout {}",
|
||||||
|
"downloadedX": "Staženo {}",
|
||||||
|
"releaseAsset": "Vydání aktiva",
|
||||||
"downloadNotifDescription": "Informuje uživatele o průběhu stahování aplikace",
|
"downloadNotifDescription": "Informuje uživatele o průběhu stahování aplikace",
|
||||||
"noAPKFound": "Žádná APK nebyla nalezena",
|
"noAPKFound": "Žádná APK nebyla nalezena",
|
||||||
"noVersionDetection": "Žádná detekce verze",
|
"noVersionDetection": "Žádná detekce verze",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Nezobrazovat varování pro 'Jen sledované'",
|
"dontShowTrackOnlyWarnings": "Nezobrazovat varování pro 'Jen sledované'",
|
||||||
"dontShowAPKOriginWarnings": "Nezobrazovat varování pro původ APK",
|
"dontShowAPKOriginWarnings": "Nezobrazovat varování pro původ APK",
|
||||||
"moveNonInstalledAppsToBottom": "Přesunout nenainstalované aplikace na konec zobrazení Aplikace",
|
"moveNonInstalledAppsToBottom": "Přesunout nenainstalované aplikace na konec zobrazení Aplikace",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Umožňuje vyhledávání a lepší zjišťování APK)",
|
"gitlabPATLabel": "Osobní přístupový token GitLab",
|
||||||
"about": "O",
|
"about": "O",
|
||||||
"requiresCredentialsInSettings": "{}: Vyžaduje další pověření (v nastavení)",
|
"requiresCredentialsInSettings": "{}: Vyžaduje další pověření (v nastavení)",
|
||||||
"checkOnStart": "Zkontrolovat jednou při spuštění",
|
"checkOnStart": "Zkontrolovat jednou při spuštění",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Přidat tuto informaci na konec stránky.",
|
"addInfoBelow": "Přidat tuto informaci na konec stránky.",
|
||||||
"addInfoInSettings": "Přidat tuto informaci do nastavení.",
|
"addInfoInSettings": "Přidat tuto informaci do nastavení.",
|
||||||
"githubSourceNote": "Omezení rychlosti GitHub lze obejít pomocí klíče API.",
|
"githubSourceNote": "Omezení rychlosti GitHub lze obejít pomocí klíče API.",
|
||||||
"gitlabSourceNote": "Extrakce GitLab APK nemusí fungovat bez klíče API",
|
|
||||||
"sortByLastLinkSegment": "Seřadit pouze podle poslední části odkazu",
|
"sortByLastLinkSegment": "Seřadit pouze podle poslední části odkazu",
|
||||||
"filterReleaseNotesByRegEx": "Filtrovat poznámky k vydání podle regulárního výrazu",
|
"filterReleaseNotesByRegEx": "Filtrovat poznámky k vydání podle regulárního výrazu",
|
||||||
"customLinkFilterRegex": "Vlastní filtr odkazů APK podle regulárního výrazu (výchozí '.apk$')",
|
"customLinkFilterRegex": "Vlastní filtr odkazů APK podle regulárního výrazu (výchozí '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Poznámka",
|
"note": "Poznámka",
|
||||||
"selfHostedNote": "Rozbalovací seznam \"{}\" lze použít k dosažení vlastních/obvyklých instancí libovolného zdroje.",
|
"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í)",
|
"badDownload": "APK nelze analyzovat (nekompatibilní nebo částečné stažení)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Sdílení nových aplikací s aplikací AppVerifier (pokud je k dispozici)",
|
||||||
|
"appVerifierInstructionToast": "Sdílejte do aplikace AppVerifier a po dokončení se sem vraťte.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Odstranit Apku?",
|
"one": "Odstranit Apku?",
|
||||||
"other": "Odstranit Apky?"
|
"other": "Odstranit Apky?"
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
"noDescription": "Keine Beschreibung",
|
"noDescription": "Keine Beschreibung",
|
||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
"continue": "Weiter",
|
"continue": "Weiter",
|
||||||
"requiredInBrackets": "(Benötigt)",
|
"requiredInBrackets": "(wird benötigt)",
|
||||||
"dropdownNoOptsError": "FEHLER: DROPDOWN MUSS MINDESTENS EINE OPTION HABEN",
|
"dropdownNoOptsError": "FEHLER: DROPDOWN MUSS MINDESTENS EINE OPTION HABEN",
|
||||||
"colour": "Farbe",
|
"colour": "Farbe",
|
||||||
"githubStarredRepos": "GitHub Starred Repos",
|
"githubStarredRepos": "GitHub Starred Repos",
|
||||||
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Versionsermittlung deaktivieren",
|
"disableVersionDetection": "Versionsermittlung deaktivieren",
|
||||||
"noVersionDetectionExplanation": "Diese Option sollte nur für Apps verwendet werden, bei denen die Versionserkennung nicht korrekt funktioniert.",
|
"noVersionDetectionExplanation": "Diese Option sollte nur für Apps verwendet werden, bei denen die Versionserkennung nicht korrekt funktioniert.",
|
||||||
"downloadingX": "Lade {} herunter",
|
"downloadingX": "Lade {} herunter",
|
||||||
|
"downloadX": "{} herunterladen",
|
||||||
|
"downloadedX": "{} heruntergeladen",
|
||||||
|
"releaseAsset": "release Asset",
|
||||||
"downloadNotifDescription": "Benachrichtigt den Nutzer über den Fortschritt beim Herunterladen einer App",
|
"downloadNotifDescription": "Benachrichtigt den Nutzer über den Fortschritt beim Herunterladen einer App",
|
||||||
"noAPKFound": "Keine APK gefunden",
|
"noAPKFound": "Keine APK gefunden",
|
||||||
"noVersionDetection": "Keine Versionserkennung",
|
"noVersionDetection": "Keine Versionserkennung",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Warnung für 'Nur Nachverfolgen' nicht anzeigen",
|
"dontShowTrackOnlyWarnings": "Warnung für 'Nur Nachverfolgen' nicht anzeigen",
|
||||||
"dontShowAPKOriginWarnings": "Warnung für APK-Herkunft nicht anzeigen",
|
"dontShowAPKOriginWarnings": "Warnung für APK-Herkunft nicht anzeigen",
|
||||||
"moveNonInstalledAppsToBottom": "Nicht installierte Apps ans Ende der Apps Ansicht verschieben",
|
"moveNonInstalledAppsToBottom": "Nicht installierte Apps ans Ende der Apps Ansicht verschieben",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Aktiviert Suche und bessere APK Entdeckung)",
|
"gitlabPATLabel": "GitLab Personal Access Token",
|
||||||
"about": "Über",
|
"about": "Über",
|
||||||
"requiresCredentialsInSettings": "{}: Benötigt zusätzliche Anmeldedaten (in den Einstellungen)",
|
"requiresCredentialsInSettings": "{}: Benötigt zusätzliche Anmeldedaten (in den Einstellungen)",
|
||||||
"checkOnStart": "Überprüfe einmalig beim Start",
|
"checkOnStart": "Überprüfe einmalig beim Start",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Fügen Sie diese Informationen unten hinzu.",
|
"addInfoBelow": "Fügen Sie diese Informationen unten hinzu.",
|
||||||
"addInfoInSettings": "Fügen Sie diese Info in den Einstellungen hinzu.",
|
"addInfoInSettings": "Fügen Sie diese Info in den Einstellungen hinzu.",
|
||||||
"githubSourceNote": "Die GitHub-Ratenbegrenzung kann mit einem API-Schlüssel umgangen werden.",
|
"githubSourceNote": "Die GitHub-Ratenbegrenzung kann mit einem API-Schlüssel umgangen werden.",
|
||||||
"gitlabSourceNote": "GitLab APK-Extraktion funktioniert möglicherweise nicht ohne API-Schlüssel",
|
|
||||||
"sortByLastLinkSegment": "Sortiere nur nach dem letzten Teil des Links",
|
"sortByLastLinkSegment": "Sortiere nur nach dem letzten Teil des Links",
|
||||||
"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$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Hinweis",
|
"note": "Hinweis",
|
||||||
"selfHostedNote": "Das „{}“-Dropdown-Menü kann verwendet werden, um selbst gehostete/angepasste Instanzen einer beliebigen Quelle zu erreichen.",
|
"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)",
|
"badDownload": "Die APK konnte nicht geparst werden (inkompatibler oder teilweiser Download)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Neue Apps mit AppVerifier teilen (falls verfügbar)",
|
||||||
|
"appVerifierInstructionToast": "Geben Sie die Daten an AppVerifier weiter und kehren Sie dann hierher zurück, wenn Sie fertig sind.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "App entfernen?",
|
"one": "App entfernen?",
|
||||||
"other": "Apps entfernen?"
|
"other": "Apps entfernen?"
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Disable Version Detection",
|
"disableVersionDetection": "Disable Version Detection",
|
||||||
"noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.",
|
"noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.",
|
||||||
"downloadingX": "Downloading {}",
|
"downloadingX": "Downloading {}",
|
||||||
|
"downloadX": "Download {}",
|
||||||
|
"downloadedX": "Downloaded {}",
|
||||||
|
"releaseAsset": "Release Asset",
|
||||||
"downloadNotifDescription": "Notifies the user of the progress in downloading an App",
|
"downloadNotifDescription": "Notifies the user of the progress in downloading an App",
|
||||||
"noAPKFound": "No APK found",
|
"noAPKFound": "No APK found",
|
||||||
"noVersionDetection": "No version detection",
|
"noVersionDetection": "No version detection",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Don't show 'Track-Only' warnings",
|
"dontShowTrackOnlyWarnings": "Don't show 'Track-Only' warnings",
|
||||||
"dontShowAPKOriginWarnings": "Don't show APK origin warnings",
|
"dontShowAPKOriginWarnings": "Don't show APK origin warnings",
|
||||||
"moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view",
|
"moveNonInstalledAppsToBottom": "Move non-installed Apps to bottom of Apps view",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Enables Search and Better APK Discovery)",
|
"gitlabPATLabel": "GitLab Personal Access Token",
|
||||||
"about": "About",
|
"about": "About",
|
||||||
"requiresCredentialsInSettings": "{} needs additional credentials (in Settings)",
|
"requiresCredentialsInSettings": "{} needs additional credentials (in Settings)",
|
||||||
"checkOnStart": "Check for updates on startup",
|
"checkOnStart": "Check for updates on startup",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Add this info below.",
|
"addInfoBelow": "Add this info below.",
|
||||||
"addInfoInSettings": "Add this info in the Settings.",
|
"addInfoInSettings": "Add this info in the Settings.",
|
||||||
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
"githubSourceNote": "GitHub rate limiting can be avoided using an API key.",
|
||||||
"gitlabSourceNote": "GitLab APK extraction may not work without an API key.",
|
|
||||||
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
"sortByLastLinkSegment": "Sort by only the last segment of the link",
|
||||||
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
"filterReleaseNotesByRegEx": "Filter Release Notes by Regular Expression",
|
||||||
"customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')",
|
"customLinkFilterRegex": "Custom APK Link Filter by Regular Expression (Default '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Note",
|
"note": "Note",
|
||||||
"selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
|
"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)",
|
"badDownload": "The APK could not be parsed (incompatible or partial download)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)",
|
||||||
|
"appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Remove App?",
|
"one": "Remove App?",
|
||||||
"other": "Remove Apps?"
|
"other": "Remove Apps?"
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"invalidURLForSource": "URL de la aplicación {} no es válida",
|
"invalidURLForSource": "El URL de la aplicación {} no es válido",
|
||||||
"noReleaseFound": "No se ha podido encontrar una versión válida",
|
"noReleaseFound": "No se ha podido encontrar una versión válida",
|
||||||
"noVersionFound": "No se ha podido determinar la versión",
|
"noVersionFound": "No se ha podido determinar la versión",
|
||||||
"urlMatchesNoSource": "La URL no coincide con ninguna fuente conocida",
|
"urlMatchesNoSource": "El URL no coincide con ninguna fuente conocida",
|
||||||
"cantInstallOlderVersion": "No se puede instalar una versión previa de la aplicación",
|
"cantInstallOlderVersion": "No se puede instalar una versión previa de la aplicación",
|
||||||
"appIdMismatch": "La ID del paquete descargado no coincide con la ID de la aplicación instalada",
|
"appIdMismatch": "El id. del paquete descargado no coincide con la ID de la aplicación instalada",
|
||||||
"functionNotImplemented": "Esta clase no ha implementado esta función",
|
"functionNotImplemented": "Esta clase no ha implementado esta función",
|
||||||
"placeholder": "Espacio reservado",
|
"placeholder": "Espacio reservado",
|
||||||
"someErrors": "Han ocurrido algunos errores",
|
"someErrors": "Han ocurrido algunos errores",
|
||||||
"unexpectedError": "Error inesperado",
|
"unexpectedError": "Error inesperado",
|
||||||
"ok": "OK",
|
"ok": "Aceptar",
|
||||||
"and": "y",
|
"and": "y",
|
||||||
"githubPATLabel": "Token de acceso personal a GitHub\n(reduce tiempos de espera)",
|
"githubPATLabel": "Token de acceso personal a GitHub\n(reduce tiempos de espera)",
|
||||||
"includePrereleases": "Incluir versiones preliminares",
|
"includePrereleases": "Incluir versiones preliminares",
|
||||||
@ -34,75 +34,75 @@
|
|||||||
"cancelled": "Cancelado",
|
"cancelled": "Cancelado",
|
||||||
"appAlreadyAdded": "Aplicación añadida anteriormente",
|
"appAlreadyAdded": "Aplicación añadida anteriormente",
|
||||||
"alreadyUpToDateQuestion": "¿Aplicación actualizada previamente?",
|
"alreadyUpToDateQuestion": "¿Aplicación actualizada previamente?",
|
||||||
"addApp": "Añadir Aplicación",
|
"addApp": "Añadir aplicación",
|
||||||
"appSourceURL": "URL de origen de la aplicación",
|
"appSourceURL": "URL de origen de la aplicación",
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
"add": "Añadir",
|
"add": "Añadir",
|
||||||
"searchSomeSourcesLabel": "Buscar (solo algunas fuentes)",
|
"searchSomeSourcesLabel": "Buscar (solo algunas fuentes)",
|
||||||
"search": "Buscar",
|
"search": "Buscar",
|
||||||
"additionalOptsFor": "Opciones Adicionales para {}",
|
"additionalOptsFor": "Opciones adicionales para {}",
|
||||||
"supportedSources": "Fuentes Soportadas",
|
"supportedSources": "Fuentes admitidas",
|
||||||
"trackOnlyInBrackets": "(Solo seguimiento)",
|
"trackOnlyInBrackets": "(Solo seguimiento)",
|
||||||
"searchableInBrackets": "(soporta búsqueda)",
|
"searchableInBrackets": "(permite búsqueda)",
|
||||||
"appsString": "Aplicaciones",
|
"appsString": "Aplicaciones",
|
||||||
"noApps": "Sin Aplicaciones",
|
"noApps": "Sin Aplicaciones",
|
||||||
"noAppsForFilter": "Sin aplicaciones para filtrar",
|
"noAppsForFilter": "Sin aplicaciones para filtrar",
|
||||||
"byX": "por: {}",
|
"byX": "por: {}",
|
||||||
"percentProgress": "Progreso: {}%",
|
"percentProgress": "Progreso: {} %",
|
||||||
"pleaseWait": "Por favor, espere",
|
"pleaseWait": "Espere un momento",
|
||||||
"updateAvailable": "Actualización Disponible",
|
"updateAvailable": "Actualización disponible",
|
||||||
"notInstalled": "No Instalado",
|
"notInstalled": "No instalado",
|
||||||
"pseudoVersion": "pseudoversión",
|
"pseudoVersion": "pseudoversión",
|
||||||
"selectAll": "Seleccionar Todo",
|
"selectAll": "Seleccionar todo",
|
||||||
"deselectX": "Deseleccionar {}",
|
"deselectX": "Deseleccionar {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "{} será eliminada de Obtainium pero continuará instalada en el dispositivo.",
|
"xWillBeRemovedButRemainInstalled": "{} se eliminará de Obtainium pero continuará instalada en el dispositivo.",
|
||||||
"removeSelectedAppsQuestion": "¿Eliminar aplicaciones seleccionadas?",
|
"removeSelectedAppsQuestion": "¿Eliminar aplicaciones seleccionadas?",
|
||||||
"removeSelectedApps": "Eliminar Aplicaciones Seleccionadas",
|
"removeSelectedApps": "Eliminar aplicaciones seleccionadas",
|
||||||
"updateX": "Actualizar {}",
|
"updateX": "Actualizar {}",
|
||||||
"installX": "Instalar {}",
|
"installX": "Instalar {}",
|
||||||
"markXTrackOnlyAsUpdated": "Marcar {}\n(Solo seguimiento)\ncomo actualizada",
|
"markXTrackOnlyAsUpdated": "Marcar {}\n(Solo seguimiento)\ncomo actualizada",
|
||||||
"changeX": "Cambiar {}",
|
"changeX": "Cambiar {}",
|
||||||
"installUpdateApps": "Instalar/Actualizar aplicaciones",
|
"installUpdateApps": "Instalar/actualizar aplicaciones",
|
||||||
"installUpdateSelectedApps": "Instalar/Actualizar aplicaciones seleccionadas",
|
"installUpdateSelectedApps": "Instalar/actualizar aplicaciones seleccionadas",
|
||||||
"markXSelectedAppsAsUpdated": "¿Marcar {} aplicaciones seleccionadas como actualizadas?",
|
"markXSelectedAppsAsUpdated": "¿Marcar {} aplicaciones seleccionadas como actualizadas?",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
"yes": "Sí",
|
"yes": "Sí",
|
||||||
"markSelectedAppsUpdated": "Marcar aplicaciones seleccionadas como actualizadas",
|
"markSelectedAppsUpdated": "Marcar aplicaciones seleccionadas como actualizadas",
|
||||||
"pinToTop": "Fijar arriba",
|
"pinToTop": "Anclar al principio",
|
||||||
"unpinFromTop": "Desfijar de arriba",
|
"unpinFromTop": "Desanclar del principio",
|
||||||
"resetInstallStatusForSelectedAppsQuestion": "¿Restuarar estado de instalación para las aplicaciones seleccionadas?",
|
"resetInstallStatusForSelectedAppsQuestion": "¿Restuarar estado de instalación para las aplicaciones seleccionadas?",
|
||||||
"installStatusOfXWillBeResetExplanation": "Se restaurará el estado de instalación de las aplicaciones seleccionadas.\n\nEsto puede ser de útil cuando la versión de la aplicación mostrada en Obtainium es incorrecta por actualizaciones fallidas u otros motivos.",
|
"installStatusOfXWillBeResetExplanation": "Se restaurará el estado de instalación de las aplicaciones seleccionadas.\n\nEsto puede ser de útil cuando la versión de la aplicación mostrada en Obtainium es incorrecta por actualizaciones fallidas u otros motivos.",
|
||||||
"customLinkMessage": "Estos enlaces funcionan en dispositivos con Obtainium instalado",
|
"customLinkMessage": "Estos enlaces funcionan en dispositivos con Obtainium instalado",
|
||||||
"shareAppConfigLinks": "Compartir la configuración de la aplicación como enlace HTML",
|
"shareAppConfigLinks": "Compartir la configuración de la aplicación como enlace HTML",
|
||||||
"shareSelectedAppURLs": "Compartir URLs de las aplicaciones seleccionadas",
|
"shareSelectedAppURLs": "Compartir URL de las aplicaciones seleccionadas",
|
||||||
"resetInstallStatus": "Restaurar estado de instalación",
|
"resetInstallStatus": "Restaurar estado de instalación",
|
||||||
"more": "Más",
|
"more": "Más",
|
||||||
"removeOutdatedFilter": "Elimiar filtro de aplicaciones desactualizado",
|
"removeOutdatedFilter": "Eliminar filtro de aplicaciones desactualizado",
|
||||||
"showOutdatedOnly": "Mostrar solo aplicaciones desactualizadas",
|
"showOutdatedOnly": "Mostrar solo aplicaciones desactualizadas",
|
||||||
"filter": "Filtrar",
|
"filter": "Filtrar",
|
||||||
"filterApps": "Filtrar Actualizaciones",
|
"filterApps": "Filtrar actualizaciones",
|
||||||
"appName": "Nombre de la aplicación",
|
"appName": "Nombre de la aplicación",
|
||||||
"author": "Autor",
|
"author": "Autor",
|
||||||
"upToDateApps": "Aplicaciones Actualizadas",
|
"upToDateApps": "Aplicaciones actualizadas",
|
||||||
"nonInstalledApps": "Aplicaciones No Instaladas",
|
"nonInstalledApps": "Aplicaciones no instaladas",
|
||||||
"importExport": "Importar/Exportar",
|
"importExport": "Importar/exportar",
|
||||||
"settings": "Ajustes",
|
"settings": "Ajustes",
|
||||||
"exportedTo": "Exportado a {}",
|
"exportedTo": "Exportado a {}",
|
||||||
"obtainiumExport": "Exportar Obtainium",
|
"obtainiumExport": "Exportar Obtainium",
|
||||||
"invalidInput": "Input incorrecto",
|
"invalidInput": "Entrada no válida",
|
||||||
"importedX": "Importado {}",
|
"importedX": "Importado {}",
|
||||||
"obtainiumImport": "Importar Obtainium",
|
"obtainiumImport": "Importar Obtainium",
|
||||||
"importFromURLList": "Importar desde lista de URLs",
|
"importFromURLList": "Importar desde lista de URL",
|
||||||
"searchQuery": "Consulta de Búsqueda",
|
"searchQuery": "Término de búsqueda",
|
||||||
"appURLList": "Lista de URLs de Aplicaciones",
|
"appURLList": "Lista de URL de aplicaciones",
|
||||||
"line": "Línea",
|
"line": "Línea",
|
||||||
"searchX": "Buscar {}",
|
"searchX": "Buscar {}",
|
||||||
"noResults": "Resultados no encontrados",
|
"noResults": "No se encontró ningún resultado",
|
||||||
"importX": "Importar desde {}",
|
"importX": "Importar desde {}",
|
||||||
"importedAppsIdDisclaimer": "Las aplicaciones importadas podrían mostrarse incorrectamente como \"No Instalada\".\nPara solucionarlo, reinstálalas a través de Obtainium.\nEsto no debería afectar a los datos de las aplicaciones.\n\nSolo afecta a las URLs y a los métodos de importación mediante terceros.",
|
"importedAppsIdDisclaimer": "Las aplicaciones importadas podrían mostrarse incorrectamente como «No instalada».\nPara solucionarlo, reinstálelas a través de Obtainium.\nEsto no debería afectar a los datos de las aplicaciones.\n\nSolo afecta a los URL y a los métodos de importación mediante terceros.",
|
||||||
"importErrors": "Errores de Importación",
|
"importErrors": "Errores de Importación",
|
||||||
"importedXOfYApps": "{} de {} Aplicaciones importadas.",
|
"importedXOfYApps": "{} de {} aplicaciones importadas.",
|
||||||
"followingURLsHadErrors": "Las siguientes URLs han tenido problemas:",
|
"followingURLsHadErrors": "Los URL siguientes han tenido problemas:",
|
||||||
"selectURL": "Seleccionar URL",
|
"selectURL": "Seleccionar URL",
|
||||||
"selectURLs": "Seleccionar URLs",
|
"selectURLs": "Seleccionar URLs",
|
||||||
"pick": "Escoger",
|
"pick": "Escoger",
|
||||||
@ -110,9 +110,9 @@
|
|||||||
"dark": "Oscuro",
|
"dark": "Oscuro",
|
||||||
"light": "Claro",
|
"light": "Claro",
|
||||||
"followSystem": "Seguir al sistema",
|
"followSystem": "Seguir al sistema",
|
||||||
"useBlackTheme": "Negro puro en tema Oscuro",
|
"useBlackTheme": "Negro puro en tema oscuro",
|
||||||
"appSortBy": "Ordenar Apps Por",
|
"appSortBy": "Ordenar aplicaciones por",
|
||||||
"authorName": "Autor/Nombre",
|
"authorName": "Autor/nombre",
|
||||||
"nameAuthor": "Nombre/Autor",
|
"nameAuthor": "Nombre/Autor",
|
||||||
"asAdded": "Según se Añadieron",
|
"asAdded": "Según se Añadieron",
|
||||||
"appSortOrder": "Orden de Clasificación",
|
"appSortOrder": "Orden de Clasificación",
|
||||||
@ -122,22 +122,22 @@
|
|||||||
"neverManualOnly": "Nunca, solo manual",
|
"neverManualOnly": "Nunca, solo manual",
|
||||||
"appearance": "Apariencia",
|
"appearance": "Apariencia",
|
||||||
"showWebInAppView": "Mostrar vista de la web de origen",
|
"showWebInAppView": "Mostrar vista de la web de origen",
|
||||||
"pinUpdates": "Fijar actualizaciones al principio",
|
"pinUpdates": "Anclar actualizaciones al principio",
|
||||||
"updates": "Actualizaciones",
|
"updates": "Actualizaciones",
|
||||||
"sourceSpecific": "Fuente Específica",
|
"sourceSpecific": "Fuente específica",
|
||||||
"appSource": "Obtainium en GitHub",
|
"appSource": "Obtainium en GitHub",
|
||||||
"noLogs": "Sin Logs",
|
"noLogs": "Ningún registro",
|
||||||
"appLogs": "Logs",
|
"appLogs": "Registros",
|
||||||
"close": "Cerrar",
|
"close": "Cerrar",
|
||||||
"share": "Compartir",
|
"share": "Compartir",
|
||||||
"appNotFound": "Aplicación no encontrada",
|
"appNotFound": "Aplicación no encontrada",
|
||||||
"obtainiumExportHyphenatedLowercase": "obtainium-exportación",
|
"obtainiumExportHyphenatedLowercase": "obtainium-exportación",
|
||||||
"pickAnAPK": "Seleccione una APK",
|
"pickAnAPK": "Seleccione una APK",
|
||||||
"appHasMoreThanOnePackage": "{} tiene más de un paquete:",
|
"appHasMoreThanOnePackage": "{} tiene más de un paquete:",
|
||||||
"deviceSupportsXArch": "Su dispositivo soporta las siguientes arquitecturas de procesador: {}.",
|
"deviceSupportsXArch": "Su dispositivo admite las siguientes arquitecturas de procesador: {}.",
|
||||||
"deviceSupportsFollowingArchs": "Su dispositivo soporta las siguientes arquitecturas de procesador:",
|
"deviceSupportsFollowingArchs": "Su dispositivo admite las siguientes arquitecturas de procesador:",
|
||||||
"warning": "Aviso",
|
"warning": "Aviso",
|
||||||
"sourceIsXButPackageFromYPrompt": "La fuente de la aplicación es '{}' pero el paquete de la actualización viene de '{}'. ¿Desea continuar?",
|
"sourceIsXButPackageFromYPrompt": "La fuente de la aplicación es «{}» pero el paquete de la actualización viene de «{}». ¿Desea continuar?",
|
||||||
"updatesAvailable": "Actualizaciones Disponibles",
|
"updatesAvailable": "Actualizaciones Disponibles",
|
||||||
"updatesAvailableNotifDescription": "Notifica al usuario de que hay actualizaciones para una o más aplicaciones monitoreadas por Obtainium",
|
"updatesAvailableNotifDescription": "Notifica al usuario de que hay actualizaciones para una o más aplicaciones monitoreadas por Obtainium",
|
||||||
"noNewUpdates": "No hay nuevas actualizaciones.",
|
"noNewUpdates": "No hay nuevas actualizaciones.",
|
||||||
@ -145,17 +145,17 @@
|
|||||||
"appsUpdated": "Aplicaciones actualizadas",
|
"appsUpdated": "Aplicaciones actualizadas",
|
||||||
"appsUpdatedNotifDescription": "Notifica al usuario de que una o más aplicaciones han sido actualizadas en segundo plano",
|
"appsUpdatedNotifDescription": "Notifica al usuario de que una o más aplicaciones han sido actualizadas en segundo plano",
|
||||||
"xWasUpdatedToY": "{} ha sido actualizada a {}.",
|
"xWasUpdatedToY": "{} ha sido actualizada a {}.",
|
||||||
"errorCheckingUpdates": "Error buscando ectualizaciones",
|
"errorCheckingUpdates": "Error al buscar actualizaciones",
|
||||||
"errorCheckingUpdatesNotifDescription": "Una notificación que muestra cuándo la comprobación de actualizaciones en segundo plano falla",
|
"errorCheckingUpdatesNotifDescription": "Una notificación que muestra cuándo la comprobación de actualizaciones en segundo plano falla",
|
||||||
"appsRemoved": "Aplicaciones eliminadas",
|
"appsRemoved": "Aplicaciones eliminadas",
|
||||||
"appsRemovedNotifDescription": "Notifica al usuario que una o más aplicaciones fueron eliminadas por problemas al cargarlas",
|
"appsRemovedNotifDescription": "Notifica al usuario que una o más aplicaciones fueron eliminadas por problemas al cargarlas",
|
||||||
"xWasRemovedDueToErrorY": "{} ha sido eliminada por: {}",
|
"xWasRemovedDueToErrorY": "{} ha sido eliminada por: {}",
|
||||||
"completeAppInstallation": "Instalación completa de la aplicación",
|
"completeAppInstallation": "Instalación completa de la aplicación",
|
||||||
"obtainiumMustBeOpenToInstallApps": "Obtainium debe estar abierto para instalar aplicaciones",
|
"obtainiumMustBeOpenToInstallApps": "Obtainium debe estar abierto para instalar aplicaciones",
|
||||||
"completeAppInstallationNotifDescription": "Pide al usuario volver a Obtainium para terminar de instalar una aplicación",
|
"completeAppInstallationNotifDescription": "Le pide volver a Obtainium para terminar de instalar una aplicación",
|
||||||
"checkingForUpdates": "Buscando actualizaciones...",
|
"checkingForUpdates": "Buscando actualizaciones...",
|
||||||
"checkingForUpdatesNotifDescription": "Notificación temporal que aparece al buscar actualizaciones",
|
"checkingForUpdatesNotifDescription": "Notificación temporal que aparece al buscar actualizaciones",
|
||||||
"pleaseAllowInstallPerm": "Por favor, permita que Obtainium instale aplicaciones",
|
"pleaseAllowInstallPerm": "Permita que Obtainium instale aplicaciones",
|
||||||
"trackOnly": "Solo para seguimiento",
|
"trackOnly": "Solo para seguimiento",
|
||||||
"errorWithHttpStatusCode": "Error {}",
|
"errorWithHttpStatusCode": "Error {}",
|
||||||
"versionCorrectionDisabled": "Corrección de versiones desactivada (el plugin parece no funcionar)",
|
"versionCorrectionDisabled": "Corrección de versiones desactivada (el plugin parece no funcionar)",
|
||||||
@ -173,8 +173,8 @@
|
|||||||
"appWithIdOrNameNotFound": "No se han encontrado aplicaciones con esa ID o nombre",
|
"appWithIdOrNameNotFound": "No se han encontrado aplicaciones con esa ID o nombre",
|
||||||
"reposHaveMultipleApps": "Los repositorios pueden contener varias aplicaciones",
|
"reposHaveMultipleApps": "Los repositorios pueden contener varias aplicaciones",
|
||||||
"fdroidThirdPartyRepo": "Repositorio de tercera parte F-Droid",
|
"fdroidThirdPartyRepo": "Repositorio de tercera parte F-Droid",
|
||||||
"steamMobile": "Móvil de vapor",
|
"steamMobile": "Steam para móviles",
|
||||||
"steamChat": "Chat de vapor",
|
"steamChat": "Chat de Steam",
|
||||||
"install": "Instalar",
|
"install": "Instalar",
|
||||||
"markInstalled": "Marcar como instalada",
|
"markInstalled": "Marcar como instalada",
|
||||||
"update": "Actualizar",
|
"update": "Actualizar",
|
||||||
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Desactivar la detección de versiones",
|
"disableVersionDetection": "Desactivar la detección de versiones",
|
||||||
"noVersionDetectionExplanation": "Esta opción solo se debe usar en aplicaciones en las que la deteción de versiones pueda que no funcionar correctamente.",
|
"noVersionDetectionExplanation": "Esta opción solo se debe usar en aplicaciones en las que la deteción de versiones pueda que no funcionar correctamente.",
|
||||||
"downloadingX": "Descargando {}",
|
"downloadingX": "Descargando {}",
|
||||||
|
"downloadX": "Descargar {}",
|
||||||
|
"downloadedX": "Descargado {}",
|
||||||
|
"releaseAsset": "Liberar activos",
|
||||||
"downloadNotifDescription": "Notifica al usuario del progreso de descarga de una aplicación",
|
"downloadNotifDescription": "Notifica al usuario del progreso de descarga de una aplicación",
|
||||||
"noAPKFound": "No se encontró el paquete de instalación APK",
|
"noAPKFound": "No se encontró el paquete de instalación APK",
|
||||||
"noVersionDetection": "Sin detección de versiones",
|
"noVersionDetection": "Sin detección de versiones",
|
||||||
@ -192,14 +195,14 @@
|
|||||||
"noCategory": "Sin categoría",
|
"noCategory": "Sin categoría",
|
||||||
"noCategories": "Sin categorías",
|
"noCategories": "Sin categorías",
|
||||||
"deleteCategoriesQuestion": "¿Eliminar categorías?",
|
"deleteCategoriesQuestion": "¿Eliminar categorías?",
|
||||||
"categoryDeleteWarning": "Todas las aplicaciones en las categorías eliminadas serán marcadas como 'Sin categoría'.",
|
"categoryDeleteWarning": "Todas las aplicaciones en las categorías eliminadas se marcarán como «Sin categoría».",
|
||||||
"addCategory": "Añadir categoría",
|
"addCategory": "Añadir categoría",
|
||||||
"label": "Nombre",
|
"label": "Nombre",
|
||||||
"language": "Idioma",
|
"language": "Idioma",
|
||||||
"copiedToClipboard": "Copiado al portapapeles",
|
"copiedToClipboard": "Se copió en el portapapeles",
|
||||||
"storagePermissionDenied": "Permiso de almacenamiento rechazado",
|
"storagePermissionDenied": "Permiso de almacenamiento rechazado",
|
||||||
"selectedCategorizeWarning": "Esto reemplazará cualquier ajuste de categoría para las aplicaciones seleccionadas.",
|
"selectedCategorizeWarning": "Esto reemplazará cualquier ajuste de categoría para las aplicaciones seleccionadas.",
|
||||||
"filterAPKsByRegEx": "Filtrar por APKs",
|
"filterAPKsByRegEx": "Filtrar por APK",
|
||||||
"removeFromObtainium": "Eliminar de Obtainium",
|
"removeFromObtainium": "Eliminar de Obtainium",
|
||||||
"uninstallFromDevice": "Desinstalar del dispositivo",
|
"uninstallFromDevice": "Desinstalar del dispositivo",
|
||||||
"onlyWorksWithNonVersionDetectApps": "Solo funciona para aplicaciones con la detección de versiones desactivada.",
|
"onlyWorksWithNonVersionDetectApps": "Solo funciona para aplicaciones con la detección de versiones desactivada.",
|
||||||
@ -212,13 +215,13 @@
|
|||||||
"versionDetection": "Detección de versiones",
|
"versionDetection": "Detección de versiones",
|
||||||
"standardVersionDetection": "Por versión",
|
"standardVersionDetection": "Por versión",
|
||||||
"groupByCategory": "Agrupar por categoría",
|
"groupByCategory": "Agrupar por categoría",
|
||||||
"autoApkFilterByArch": "Filtrar APKs por arquitectura del procesador (si es posible)",
|
"autoApkFilterByArch": "Filtrar APK por arquitectura del procesador (si es posible)",
|
||||||
"overrideSource": "Sobrescribir Fuente",
|
"overrideSource": "Anular fuente",
|
||||||
"dontShowAgain": "No mostrar de nuevo",
|
"dontShowAgain": "No mostrar de nuevo",
|
||||||
"dontShowTrackOnlyWarnings": "No mostrar avisos sobre apps en 'solo seguimiento'",
|
"dontShowTrackOnlyWarnings": "No mostrar avisos sobre apps en 'solo seguimiento'",
|
||||||
"dontShowAPKOriginWarnings": "No mostrar avisos sobre las fuentes de las APKs",
|
"dontShowAPKOriginWarnings": "No mostrar avisos sobre las fuentes de las APKs",
|
||||||
"moveNonInstalledAppsToBottom": "Mover Apps no instaladas al final",
|
"moveNonInstalledAppsToBottom": "Mover Apps no instaladas al final",
|
||||||
"gitlabPATLabel": "Token de acceso personal a GitLab\n(habilita la búsqueda y mejor detección de APKs)",
|
"gitlabPATLabel": "Token de acceso personal a GitLab",
|
||||||
"about": "Acerca",
|
"about": "Acerca",
|
||||||
"requiresCredentialsInSettings": "{}: Esto requiere credenciales adicionales (en ajustes)",
|
"requiresCredentialsInSettings": "{}: Esto requiere credenciales adicionales (en ajustes)",
|
||||||
"checkOnStart": "Comprobar actualizaciones al inicio",
|
"checkOnStart": "Comprobar actualizaciones al inicio",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Añadir esta información debajo.",
|
"addInfoBelow": "Añadir esta información debajo.",
|
||||||
"addInfoInSettings": "Puede añadir esta información en Ajustes.",
|
"addInfoInSettings": "Puede añadir esta información en Ajustes.",
|
||||||
"githubSourceNote": "La limitación de velocidad de GitHub puede evitarse con un 'token de acceso personal'.",
|
"githubSourceNote": "La limitación de velocidad de GitHub puede evitarse con un 'token de acceso personal'.",
|
||||||
"gitlabSourceNote": "La extracción de APK de GitLab podría no funcionar sin un 'token de acceso personal'.",
|
|
||||||
"sortByLastLinkSegment": "Ordenar sólo por el último segmento del enlace",
|
"sortByLastLinkSegment": "Ordenar sólo por el último segmento del enlace",
|
||||||
"filterReleaseNotesByRegEx": "Filtrar por notas de versión (release notes)",
|
"filterReleaseNotesByRegEx": "Filtrar por notas de versión (release notes)",
|
||||||
"customLinkFilterRegex": "Filtro personalizado de enlace APK (por defecto '.apk$')",
|
"customLinkFilterRegex": "Filtro personalizado de enlace APK (por defecto '.apk$')",
|
||||||
@ -263,7 +265,7 @@
|
|||||||
"takeFirstLink": "Usar primer enlace",
|
"takeFirstLink": "Usar primer enlace",
|
||||||
"skipSort": "Omitir orden",
|
"skipSort": "Omitir orden",
|
||||||
"debugMenu": "Menu Depurar",
|
"debugMenu": "Menu Depurar",
|
||||||
"bgTaskStarted": "Iniciada tarea en segundo plano - revisa los logs.",
|
"bgTaskStarted": "Iniciada tarea en segundo plano; revise los registros.",
|
||||||
"runBgCheckNow": "Ejecutar verficiación de actualizaciones en segundo plano",
|
"runBgCheckNow": "Ejecutar verficiación de actualizaciones en segundo plano",
|
||||||
"versionExtractWholePage": "Aplicar la versión de extracción regex a la página entera",
|
"versionExtractWholePage": "Aplicar la versión de extracción regex a la página entera",
|
||||||
"installing": "Instalando",
|
"installing": "Instalando",
|
||||||
@ -298,23 +300,25 @@
|
|||||||
"latest": "Versión más reciente",
|
"latest": "Versión más reciente",
|
||||||
"invertRegEx": "Invertir expresión regular",
|
"invertRegEx": "Invertir expresión regular",
|
||||||
"note": "Nota",
|
"note": "Nota",
|
||||||
"selfHostedNote": "El desplegable \"{}\" puede utilizarse para acceder a instancias autoalojadas/personalizadas de cualquier fuente.",
|
"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)",
|
"badDownload": "No se ha podido analizar el APK (incompatible o descarga parcial)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Compartir nuevas aplicaciones con AppVerifier (si está disponible)",
|
||||||
|
"appVerifierInstructionToast": "Comparta con AppVerifier y vuelva aquí cuando esté listo.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "¿Eliminar Aplicación?",
|
"one": "¿Eliminar aplicación?",
|
||||||
"other": "¿Eliminar Aplicaciones?"
|
"other": "¿Eliminar aplicaciones?"
|
||||||
},
|
},
|
||||||
"tooManyRequestsTryAgainInMinutes": {
|
"tooManyRequestsTryAgainInMinutes": {
|
||||||
"one": "Muchas peticiones (limitado) - prueba de nuevo en {} minuto",
|
"one": "Muchas peticiones (limitado); pruebe de nuevo en {} minuto",
|
||||||
"other": "Muchas peticiones (limitado) - prueba de nuevo en {} minutos"
|
"other": "Muchas peticiones (limitado); pruebe de nuevo en {} minutos"
|
||||||
},
|
},
|
||||||
"bgUpdateGotErrorRetryInMinutes": {
|
"bgUpdateGotErrorRetryInMinutes": {
|
||||||
"one": "La comprobación de actualizaciones en segundo plano se ha encontrado un {}, se volverá a probar en {} minuto",
|
"one": "La comprobación de actualizaciones en segundo plano se ha encontrado un {}; se volverá a probar en {} minuto",
|
||||||
"other": "La comprobación de actualizaciones en segundo plano se ha encontrado un {}, se volverá a probar en {} minutos"
|
"other": "La comprobación de actualizaciones en segundo plano se ha encontrado un {}; se volverá a probar en {} minutos"
|
||||||
},
|
},
|
||||||
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
||||||
"one": "La comprobación de actualizaciones en segundo plano ha encontrado {} actualización - se notificará al usuario si es necesario",
|
"one": "La comprobación de actualizaciones en segundo plano ha encontrado {} actualización; se le notificará si es necesario",
|
||||||
"other": "La comprobación de actualizaciones en segundo plano ha encontrado {} actualizaciones - se notificará al usuario si es necesario"
|
"other": "La comprobación de actualizaciones en segundo plano ha encontrado {} actualizaciones; se le notificará si es necesario"
|
||||||
},
|
},
|
||||||
"apps": {
|
"apps": {
|
||||||
"one": "{} Aplicación",
|
"one": "{} Aplicación",
|
||||||
@ -337,16 +341,16 @@
|
|||||||
"other": "{} días"
|
"other": "{} días"
|
||||||
},
|
},
|
||||||
"clearedNLogsBeforeXAfterY": {
|
"clearedNLogsBeforeXAfterY": {
|
||||||
"one": "Eliminado {n} log (previo a = {before}, posterior a = {after})",
|
"one": "Eliminado {n} registro (previo a = {before}, posterior a = {after})",
|
||||||
"other": "Eliminados {n} logs (previos a = {before}, posteriores a = {after})"
|
"other": "Eliminados {n} registros (previos a = {before}, posteriores a = {after})"
|
||||||
},
|
},
|
||||||
"xAndNMoreUpdatesAvailable": {
|
"xAndNMoreUpdatesAvailable": {
|
||||||
"one": "{} y 1 aplicación más tiene actualizaciones.",
|
"one": "{} y 1 aplicación más tiene actualizaciones.",
|
||||||
"other": "{} y {} aplicaciones más tienen actualizaciones."
|
"other": "{} y {} aplicaciones más tienen actualizaciones."
|
||||||
},
|
},
|
||||||
"xAndNMoreUpdatesInstalled": {
|
"xAndNMoreUpdatesInstalled": {
|
||||||
"one": "{} y 1 aplicación más han sido actualizadas.",
|
"one": "{} y 1 aplicación más se han actualizado.",
|
||||||
"other": "{} y {} aplicaciones más han sido actualizadas."
|
"other": "{} y {} aplicaciones más se han actualizado."
|
||||||
},
|
},
|
||||||
"xAndNMoreUpdatesPossiblyInstalled": {
|
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||||
"one": "{} y 1 aplicación más podría haber sido actualizada.",
|
"one": "{} y 1 aplicación más podría haber sido actualizada.",
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "غیرفعال کردن تشخیص نسخه",
|
"disableVersionDetection": "غیرفعال کردن تشخیص نسخه",
|
||||||
"noVersionDetectionExplanation": "این گزینه فقط باید برای برنامه هایی استفاده شود که تشخیص نسخه به درستی کار نمی کند.",
|
"noVersionDetectionExplanation": "این گزینه فقط باید برای برنامه هایی استفاده شود که تشخیص نسخه به درستی کار نمی کند.",
|
||||||
"downloadingX": "در حال دانلود {}",
|
"downloadingX": "در حال دانلود {}",
|
||||||
|
"downloadX": "Download {}",
|
||||||
|
"downloadedX": "Downloaded {}",
|
||||||
|
"releaseAsset": "Release Asset",
|
||||||
"downloadNotifDescription": "کاربر را از پیشرفت دانلود یک برنامه مطلع می کند",
|
"downloadNotifDescription": "کاربر را از پیشرفت دانلود یک برنامه مطلع می کند",
|
||||||
"noAPKFound": "APK پیدا نشد فایل",
|
"noAPKFound": "APK پیدا نشد فایل",
|
||||||
"noVersionDetection": "بدون تشخیص نسخه",
|
"noVersionDetection": "بدون تشخیص نسخه",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "هشدار 'فقط ردیابی' را نشان ندهید",
|
"dontShowTrackOnlyWarnings": "هشدار 'فقط ردیابی' را نشان ندهید",
|
||||||
"dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید",
|
"dontShowAPKOriginWarnings": "هشدارهای منبع APK را نشان ندهید",
|
||||||
"moveNonInstalledAppsToBottom": "برنامه های نصب نشده را به نمای پایین برنامه ها منتقل کنید",
|
"moveNonInstalledAppsToBottom": "برنامه های نصب نشده را به نمای پایین برنامه ها منتقل کنید",
|
||||||
"gitlabPATLabel": "رمز دسترسی شخصی GitLab\n(جستجو و کشف بهتر APK را فعال میکند)",
|
"gitlabPATLabel": "رمز دسترسی شخصی GitLab",
|
||||||
"about": "درباره",
|
"about": "درباره",
|
||||||
"requiresCredentialsInSettings": "{}: این به اعتبارنامه های اضافی نیاز دارد (در تنظیمات)",
|
"requiresCredentialsInSettings": "{}: این به اعتبارنامه های اضافی نیاز دارد (در تنظیمات)",
|
||||||
"checkOnStart": "بررسی در شروع",
|
"checkOnStart": "بررسی در شروع",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "این اطلاعات را در زیر اضافه کنید",
|
"addInfoBelow": "این اطلاعات را در زیر اضافه کنید",
|
||||||
"addInfoInSettings": "این اطلاعات را در تنظیمات اضافه کنید.",
|
"addInfoInSettings": "این اطلاعات را در تنظیمات اضافه کنید.",
|
||||||
"githubSourceNote": "با استفاده از کلید API می توان از محدودیت نرخ GitHub جلوگیری کرد.",
|
"githubSourceNote": "با استفاده از کلید API می توان از محدودیت نرخ GitHub جلوگیری کرد.",
|
||||||
"gitlabSourceNote": "استخراج APK GitLab ممکن است بدون کلید API کار نکند.",
|
|
||||||
"sortByLastLinkSegment": "فقط بر اساس آخرین بخش پیوند مرتب کنید",
|
"sortByLastLinkSegment": "فقط بر اساس آخرین بخش پیوند مرتب کنید",
|
||||||
"filterReleaseNotesByRegEx": "یادداشت های انتشار را با بیان منظم فیلتر کنید",
|
"filterReleaseNotesByRegEx": "یادداشت های انتشار را با بیان منظم فیلتر کنید",
|
||||||
"customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیشفرض '.apk$')",
|
"customLinkFilterRegex": "فیلتر پیوند سفارشی بر اساس عبارت منظم (پیشفرض '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Note",
|
"note": "Note",
|
||||||
"selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
|
"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)",
|
"badDownload": "The APK could not be parsed (incompatible or partial download)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)",
|
||||||
|
"appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "برنامه حذف شود؟",
|
"one": "برنامه حذف شود؟",
|
||||||
"other": "برنامه ها حذف شوند؟"
|
"other": "برنامه ها حذف شوند؟"
|
||||||
|
@ -167,7 +167,7 @@
|
|||||||
"lastUpdateCheckX": "Vérification de la dernière mise à jour : {}",
|
"lastUpdateCheckX": "Vérification de la dernière mise à jour : {}",
|
||||||
"remove": "Retirer",
|
"remove": "Retirer",
|
||||||
"yesMarkUpdated": "Oui, marquer comme mis à jour",
|
"yesMarkUpdated": "Oui, marquer comme mis à jour",
|
||||||
"fdroid": "F-Droïde Officiel",
|
"fdroid": "F-Droid Officiel",
|
||||||
"appIdOrName": "ID ou nom de l'application",
|
"appIdOrName": "ID ou nom de l'application",
|
||||||
"appId": "ID de l'application",
|
"appId": "ID de l'application",
|
||||||
"appWithIdOrNameNotFound": "Aucune application n'a été trouvée avec cet identifiant ou ce nom",
|
"appWithIdOrNameNotFound": "Aucune application n'a été trouvée avec cet identifiant ou ce nom",
|
||||||
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Désactiver la détection de version",
|
"disableVersionDetection": "Désactiver la détection de version",
|
||||||
"noVersionDetectionExplanation": "Cette option ne doit être utilisée que pour les applications où la détection de version ne fonctionne pas correctement.",
|
"noVersionDetectionExplanation": "Cette option ne doit être utilisée que pour les applications où la détection de version ne fonctionne pas correctement.",
|
||||||
"downloadingX": "Téléchargement {}",
|
"downloadingX": "Téléchargement {}",
|
||||||
|
"downloadX": "Télécharger {}",
|
||||||
|
"downloadedX": "Téléchargé {}",
|
||||||
|
"releaseAsset": "Actif libéré",
|
||||||
"downloadNotifDescription": "Avertit l'utilisateur de la progression du téléchargement d'une application",
|
"downloadNotifDescription": "Avertit l'utilisateur de la progression du téléchargement d'une application",
|
||||||
"noAPKFound": "Aucun APK trouvé",
|
"noAPKFound": "Aucun APK trouvé",
|
||||||
"noVersionDetection": "Pas de détection de version",
|
"noVersionDetection": "Pas de détection de version",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning",
|
"dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning",
|
||||||
"dontShowAPKOriginWarnings": "Ne pas afficher les avertissements sur l'origine de l'APK",
|
"dontShowAPKOriginWarnings": "Ne pas afficher les avertissements sur l'origine de l'APK",
|
||||||
"moveNonInstalledAppsToBottom": "Déplacer les applications non installées vers le bas de la vue Applications",
|
"moveNonInstalledAppsToBottom": "Déplacer les applications non installées vers le bas de la vue Applications",
|
||||||
"gitlabPATLabel": "Jeton d'accès personnel GitLab\\n (permet la recherche et une meilleure découverte d'APK)",
|
"gitlabPATLabel": "Jeton d'accès personnel GitLab",
|
||||||
"about": "À propos de",
|
"about": "À propos de",
|
||||||
"requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
|
"requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
|
||||||
"checkOnStart": "Vérifier les mises à jour au démarrage",
|
"checkOnStart": "Vérifier les mises à jour au démarrage",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Ajoutez ces informations ci-dessous.",
|
"addInfoBelow": "Ajoutez ces informations ci-dessous.",
|
||||||
"addInfoInSettings": "Ajoutez ces informations dans les paramètres.",
|
"addInfoInSettings": "Ajoutez ces informations dans les paramètres.",
|
||||||
"githubSourceNote": "La limitation du débit GitHub peut être évitée à l'aide d'une clé API.",
|
"githubSourceNote": "La limitation du débit GitHub peut être évitée à l'aide d'une clé API.",
|
||||||
"gitlabSourceNote": "L'extraction d'APK GitLab peut ne pas fonctionner sans clé API.",
|
|
||||||
"sortByLastLinkSegment": "Trier uniquement sur le dernier segment du lien",
|
"sortByLastLinkSegment": "Trier uniquement sur le dernier segment du lien",
|
||||||
"filterReleaseNotesByRegEx": "Filtrer les notes de version par expression régulière",
|
"filterReleaseNotesByRegEx": "Filtrer les notes de version par expression régulière",
|
||||||
"customLinkFilterRegex": "Filtre de lien APK personnalisé par expression régulière (par défaut '.apk$')",
|
"customLinkFilterRegex": "Filtre de lien APK personnalisé par expression régulière (par défaut '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Note",
|
"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.",
|
"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)",
|
"badDownload": "L'APK n'a pas pu être analysé (téléchargement incompatible ou partiel)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Partager les nouvelles applications avec AppVerifier (si disponible)",
|
||||||
|
"appVerifierInstructionToast": "Partagez avec AppVerifier, puis revenez ici lorsque vous êtes prêt.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Supprimer l'application ?",
|
"one": "Supprimer l'application ?",
|
||||||
"other": "Supprimer les applications ?"
|
"other": "Supprimer les applications ?"
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Verzió érzékelés letiltása",
|
"disableVersionDetection": "Verzió érzékelés letiltása",
|
||||||
"noVersionDetectionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzióérzékelés nem működik megfelelően.",
|
"noVersionDetectionExplanation": "Ezt a beállítást csak olyan alkalmazásoknál szabad használni, ahol a verzióérzékelés nem működik megfelelően.",
|
||||||
"downloadingX": "{} letöltés",
|
"downloadingX": "{} letöltés",
|
||||||
|
"downloadX": "Letöltés {}",
|
||||||
|
"downloadedX": "Letöltés {}",
|
||||||
|
"releaseAsset": "Kiadási tartalom",
|
||||||
"downloadNotifDescription": "Értesíti a felhasználót az app letöltésének előrehaladásáról",
|
"downloadNotifDescription": "Értesíti a felhasználót az app letöltésének előrehaladásáról",
|
||||||
"noAPKFound": "Nem található APK",
|
"noAPKFound": "Nem található APK",
|
||||||
"noVersionDetection": "Nincs verzió érzékelés",
|
"noVersionDetection": "Nincs verzió érzékelés",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést",
|
"dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést",
|
||||||
"dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket",
|
"dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket",
|
||||||
"moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára",
|
"moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Engedélyezi a Keresést és jobb APK felfedezés)",
|
"gitlabPATLabel": "GitLab személyes hozzáférési token",
|
||||||
"about": "Rólunk",
|
"about": "Rólunk",
|
||||||
"requiresCredentialsInSettings": "{}: Ehhez további hitelesítő adatokra van szükség (a Beállításokban)",
|
"requiresCredentialsInSettings": "{}: Ehhez további hitelesítő adatokra van szükség (a Beállításokban)",
|
||||||
"checkOnStart": "Egyszer az alkalmazás indításakor is",
|
"checkOnStart": "Egyszer az alkalmazás indításakor is",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Adja hozzá ezt az infót alább.",
|
"addInfoBelow": "Adja hozzá ezt az infót alább.",
|
||||||
"addInfoInSettings": "Adja hozzá ezt az infót a Beállításokban.",
|
"addInfoInSettings": "Adja hozzá ezt az infót a Beállításokban.",
|
||||||
"githubSourceNote": "A GitHub sebességkorlátozás elkerülhető API-kulcs használatával.",
|
"githubSourceNote": "A GitHub sebességkorlátozás elkerülhető API-kulcs használatával.",
|
||||||
"gitlabSourceNote": "Előfordulhat, hogy a GitLab APK kibontása nem működik API-kulcs nélkül.",
|
|
||||||
"sortByLastLinkSegment": "Rendezés csak a link utolsó szegmense szerint",
|
"sortByLastLinkSegment": "Rendezés csak a link utolsó szegmense szerint",
|
||||||
"filterReleaseNotesByRegEx": "Kiadási megjegyzések szűrése reguláris kifejezéssel",
|
"filterReleaseNotesByRegEx": "Kiadási megjegyzések szűrése reguláris kifejezéssel",
|
||||||
"customLinkFilterRegex": "Egyéni APK hivatkozásszűrő reguláris kifejezéssel (Alapérték '.apk$')",
|
"customLinkFilterRegex": "Egyéni APK hivatkozásszűrő reguláris kifejezéssel (Alapérték '.apk$')",
|
||||||
@ -282,14 +284,14 @@
|
|||||||
"parallelDownloads": "Párhuzamos letöltéseket enged",
|
"parallelDownloads": "Párhuzamos letöltéseket enged",
|
||||||
"installMethod": "Telepítési mód",
|
"installMethod": "Telepítési mód",
|
||||||
"normal": "Normál",
|
"normal": "Normál",
|
||||||
"root": "Gyökér",
|
"root": "Root",
|
||||||
"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 verziókód 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 álverziós módszer",
|
||||||
"partialAPKHash": "Részleges APK Hash",
|
"partialAPKHash": "Részleges APK Hash",
|
||||||
"APKLinkHash": "APK Link Hash",
|
"APKLinkHash": "APK Link Hash",
|
||||||
"directAPKLink": "Közvetlen APK Link",
|
"directAPKLink": "Közvetlen APK Link",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Megjegyzé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.",
|
"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)",
|
"badDownload": "Az APK-t nem lehetett elemezni (inkompatibilis vagy részleges letöltés)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Új alkalmazások megosztása az AppVerifierrel (ha elérhető)",
|
||||||
|
"appVerifierInstructionToast": "Ossza meg az AppVerifierrel, majd térjen vissza ide, ha kész.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Eltávolítja az alkalmazást?",
|
"one": "Eltávolítja az alkalmazást?",
|
||||||
"other": "Eltávolítja az alkalmazásokat?"
|
"other": "Eltávolítja az alkalmazásokat?"
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Disattiva il rilevamento della versione",
|
"disableVersionDetection": "Disattiva il rilevamento della versione",
|
||||||
"noVersionDetectionExplanation": "Questa opzione dovrebbe essere usata solo per le app la cui versione non viene rilevata correttamente.",
|
"noVersionDetectionExplanation": "Questa opzione dovrebbe essere usata solo per le app la cui versione non viene rilevata correttamente.",
|
||||||
"downloadingX": "Scaricamento di {} in corso",
|
"downloadingX": "Scaricamento di {} in corso",
|
||||||
|
"downloadX": "Scarica {}",
|
||||||
|
"downloadedX": "Scaricato {}",
|
||||||
|
"releaseAsset": "Rilascio Asset",
|
||||||
"downloadNotifDescription": "Notifica all'utente lo stato di avanzamento del download di un'app",
|
"downloadNotifDescription": "Notifica all'utente lo stato di avanzamento del download di un'app",
|
||||||
"noAPKFound": "Nessun APK trovato",
|
"noAPKFound": "Nessun APK trovato",
|
||||||
"noVersionDetection": "Disattiva rilevamento di versione",
|
"noVersionDetection": "Disattiva rilevamento di versione",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Non mostrare gli avvisi 'Solo-Monitoraggio'",
|
"dontShowTrackOnlyWarnings": "Non mostrare gli avvisi 'Solo-Monitoraggio'",
|
||||||
"dontShowAPKOriginWarnings": "Non mostrare gli avvisi di origine dell'APK",
|
"dontShowAPKOriginWarnings": "Non mostrare gli avvisi di origine dell'APK",
|
||||||
"moveNonInstalledAppsToBottom": "Sposta le app non installate in fondo alla lista",
|
"moveNonInstalledAppsToBottom": "Sposta le app non installate in fondo alla lista",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\n(attiva la ricerca e migliora la rilevazione di apk)",
|
"gitlabPATLabel": "GitLab Token di accesso personale",
|
||||||
"about": "Informazioni",
|
"about": "Informazioni",
|
||||||
"requiresCredentialsInSettings": "{}: Servono credenziali aggiuntive (in Impostazioni)",
|
"requiresCredentialsInSettings": "{}: Servono credenziali aggiuntive (in Impostazioni)",
|
||||||
"checkOnStart": "Controlla una volta all'avvio",
|
"checkOnStart": "Controlla una volta all'avvio",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Aggiungi questa info sotto.",
|
"addInfoBelow": "Aggiungi questa info sotto.",
|
||||||
"addInfoInSettings": "Aggiungi questa info nelle impostazioni.",
|
"addInfoInSettings": "Aggiungi questa info nelle impostazioni.",
|
||||||
"githubSourceNote": "Il limite di ricerca GitHub può essere evitato usando una chiave API.",
|
"githubSourceNote": "Il limite di ricerca GitHub può essere evitato usando una chiave API.",
|
||||||
"gitlabSourceNote": "L'estrazione di APK da GitLab potrebbe non funzionare senza chiave API.",
|
|
||||||
"sortByLastLinkSegment": "Ordina solo in base all'ultimo segmento del collegamento",
|
"sortByLastLinkSegment": "Ordina solo in base all'ultimo segmento del collegamento",
|
||||||
"filterReleaseNotesByRegEx": "Filtra le note di rilascio con espressione regolare",
|
"filterReleaseNotesByRegEx": "Filtra le note di rilascio con espressione regolare",
|
||||||
"customLinkFilterRegex": "Filtra link APK personalizzato con espressione regolare (predefinito '.apk$')",
|
"customLinkFilterRegex": "Filtra link APK personalizzato con espressione regolare (predefinito '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Nota",
|
"note": "Nota",
|
||||||
"selfHostedNote": "Il menu a tendina \"{}\" può essere usato per raggiungere istanze autogestite/personali di qualsiasi fonte.",
|
"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).",
|
"badDownload": "Non è stato possibile analizzare l'APK (download incompatibile o parziale).",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Condividere le nuove applicazioni con AppVerifier (se disponibile)",
|
||||||
|
"appVerifierInstructionToast": "Condividete con AppVerifier, quindi tornate qui quando siete pronti.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Rimuovere l'app?",
|
"one": "Rimuovere l'app?",
|
||||||
"other": "Rimuovere le app?"
|
"other": "Rimuovere le app?"
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "バージョン検出を無効にする",
|
"disableVersionDetection": "バージョン検出を無効にする",
|
||||||
"noVersionDetectionExplanation": "このオプションは、バージョン検出が正しく機能しないアプリにのみ使用する必要があります。",
|
"noVersionDetectionExplanation": "このオプションは、バージョン検出が正しく機能しないアプリにのみ使用する必要があります。",
|
||||||
"downloadingX": "{} をダウンロード中",
|
"downloadingX": "{} をダウンロード中",
|
||||||
|
"downloadX": "ダウンロード",
|
||||||
|
"downloadedX": "ダウンロード",
|
||||||
|
"releaseAsset": "リリース資産",
|
||||||
"downloadNotifDescription": "アプリのダウンロード状況を通知する",
|
"downloadNotifDescription": "アプリのダウンロード状況を通知する",
|
||||||
"noAPKFound": "APKが見つかりません",
|
"noAPKFound": "APKが見つかりません",
|
||||||
"noVersionDetection": "バージョン検出を行わない",
|
"noVersionDetection": "バージョン検出を行わない",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "「追跡のみ」の警告を表示しない",
|
"dontShowTrackOnlyWarnings": "「追跡のみ」の警告を表示しない",
|
||||||
"dontShowAPKOriginWarnings": "APKのダウンロード元の警告を表示しない",
|
"dontShowAPKOriginWarnings": "APKのダウンロード元の警告を表示しない",
|
||||||
"moveNonInstalledAppsToBottom": "未インストールのアプリをアプリ一覧の下部に移動させる",
|
"moveNonInstalledAppsToBottom": "未インストールのアプリをアプリ一覧の下部に移動させる",
|
||||||
"gitlabPATLabel": "GitLab パーソナルアクセストークン\n(検索とより良いAPK検出の有効化)",
|
"gitlabPATLabel": "GitLab パーソナルアクセストークン",
|
||||||
"about": "概要",
|
"about": "概要",
|
||||||
"requiresCredentialsInSettings": "{}: これには追加の認証が必要です (設定にて)",
|
"requiresCredentialsInSettings": "{}: これには追加の認証が必要です (設定にて)",
|
||||||
"checkOnStart": "起動時にアップデートを確認する",
|
"checkOnStart": "起動時にアップデートを確認する",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "下部でこの情報を追加してください。",
|
"addInfoBelow": "下部でこの情報を追加してください。",
|
||||||
"addInfoInSettings": "設定でこの情報を追加してください。",
|
"addInfoInSettings": "設定でこの情報を追加してください。",
|
||||||
"githubSourceNote": "GitHubのレート制限はAPIキーを使うことで回避できます。",
|
"githubSourceNote": "GitHubのレート制限はAPIキーを使うことで回避できます。",
|
||||||
"gitlabSourceNote": "GitLabのAPK抽出はAPIキーがないと動作しない場合があります。",
|
|
||||||
"sortByLastLinkSegment": "リンクの最後のセグメントのみでソートする",
|
"sortByLastLinkSegment": "リンクの最後のセグメントのみでソートする",
|
||||||
"filterReleaseNotesByRegEx": "正規表現でリリースノートをフィルタリングする",
|
"filterReleaseNotesByRegEx": "正規表現でリリースノートをフィルタリングする",
|
||||||
"customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')",
|
"customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "注",
|
"note": "注",
|
||||||
"selfHostedNote": "ドロップダウン\"{}\"を使用すると、あらゆるソースのセルフホスト/カスタムインスタンスにアクセスできます。",
|
"selfHostedNote": "ドロップダウン\"{}\"を使用すると、あらゆるソースのセルフホスト/カスタムインスタンスにアクセスできます。",
|
||||||
"badDownload": "APK を解析できませんでした(互換性がないか、部分的にダウンロードされています)。",
|
"badDownload": "APK を解析できませんでした(互換性がないか、部分的にダウンロードされています)。",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "AppVerifierで新しいアプリを共有する(利用可能な場合)",
|
||||||
|
"appVerifierInstructionToast": "AppVerifierに共有し、準備ができたらここに戻ってください。",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "アプリを削除しますか?",
|
"one": "アプリを削除しますか?",
|
||||||
"other": "アプリを削除しますか?"
|
"other": "アプリを削除しますか?"
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Versieherkenning uitschakelen",
|
"disableVersionDetection": "Versieherkenning uitschakelen",
|
||||||
"noVersionDetectionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt.",
|
"noVersionDetectionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt.",
|
||||||
"downloadingX": "Downloaden {}",
|
"downloadingX": "Downloaden {}",
|
||||||
|
"downloadX": "Downloaden",
|
||||||
|
"downloadedX": "Gedownload {}",
|
||||||
|
"releaseAsset": "Release Activa",
|
||||||
"downloadNotifDescription": "Stelt de gebruiker op de hoogte van de voortgang bij het downloaden van een app",
|
"downloadNotifDescription": "Stelt de gebruiker op de hoogte van de voortgang bij het downloaden van een app",
|
||||||
"noAPKFound": "Geen APK gevonden",
|
"noAPKFound": "Geen APK gevonden",
|
||||||
"noVersionDetection": "Geen versieherkenning",
|
"noVersionDetection": "Geen versieherkenning",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Geen waarschuwingen voor 'Track-Only' weergeven",
|
"dontShowTrackOnlyWarnings": "Geen waarschuwingen voor 'Track-Only' weergeven",
|
||||||
"dontShowAPKOriginWarnings": "APK-herkomstwaarschuwingen niet weergeven",
|
"dontShowAPKOriginWarnings": "APK-herkomstwaarschuwingen niet weergeven",
|
||||||
"moveNonInstalledAppsToBottom": "Verplaats niet-geïnstalleerde apps naar de onderkant van de apps-weergave",
|
"moveNonInstalledAppsToBottom": "Verplaats niet-geïnstalleerde apps naar de onderkant van de apps-weergave",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\n(Maakt het mogelijk beter te zoeken naar APK's)",
|
"gitlabPATLabel": "GitLab persoonlijk toegangskenmerk",
|
||||||
"about": "Over",
|
"about": "Over",
|
||||||
"requiresCredentialsInSettings": "{}: Dit vereist aanvullende referenties (in Instellingen)",
|
"requiresCredentialsInSettings": "{}: Dit vereist aanvullende referenties (in Instellingen)",
|
||||||
"checkOnStart": "Controleren op updates bij opstarten",
|
"checkOnStart": "Controleren op updates bij opstarten",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Voeg deze informatie hieronder toe.",
|
"addInfoBelow": "Voeg deze informatie hieronder toe.",
|
||||||
"addInfoInSettings": "Voeg deze informatie toe in de instellingen.",
|
"addInfoInSettings": "Voeg deze informatie toe in de instellingen.",
|
||||||
"githubSourceNote": "Beperkingen van GitHub kunnen worden vermeden door het gebruik van een API-sleutel.",
|
"githubSourceNote": "Beperkingen van GitHub kunnen worden vermeden door het gebruik van een API-sleutel.",
|
||||||
"gitlabSourceNote": "GitLab APK-extractie werkt mogelijk niet zonder een API-sleutel.",
|
|
||||||
"sortByLastLinkSegment": "Sorteren op alleen het laatste segment van de link",
|
"sortByLastLinkSegment": "Sorteren op alleen het laatste segment van de link",
|
||||||
"filterReleaseNotesByRegEx": "Filter release-opmerkingen met een reguliere expressie.",
|
"filterReleaseNotesByRegEx": "Filter release-opmerkingen met een reguliere expressie.",
|
||||||
"customLinkFilterRegex": "Aangepaste APK-linkfilter met een reguliere expressie (Standaard '.apk$').",
|
"customLinkFilterRegex": "Aangepaste APK-linkfilter met een reguliere expressie (Standaard '.apk$').",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Opmerking",
|
"note": "Opmerking",
|
||||||
"selfHostedNote": "De \"{}\" dropdown kan gebruikt worden om zelf gehoste/aangepaste instanties van elke bron te bereiken.",
|
"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)",
|
"badDownload": "De APK kon niet worden verwerkt (incompatibele of gedeeltelijke download)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Nieuwe Apps delen met AppVerifier (indien beschikbaar)",
|
||||||
|
"appVerifierInstructionToast": "Deel naar AppVerifier en keer hier terug als je klaar bent.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "App verwijderen?",
|
"one": "App verwijderen?",
|
||||||
"other": "Apps verwijderen?"
|
"other": "Apps verwijderen?"
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Wyłącz wykrywanie wersji",
|
"disableVersionDetection": "Wyłącz wykrywanie wersji",
|
||||||
"noVersionDetectionExplanation": "Opcja ta powinna być używana tylko w przypadku aplikacji, w których wykrywanie wersji nie działa poprawnie.",
|
"noVersionDetectionExplanation": "Opcja ta powinna być używana tylko w przypadku aplikacji, w których wykrywanie wersji nie działa poprawnie.",
|
||||||
"downloadingX": "Pobieranie {}",
|
"downloadingX": "Pobieranie {}",
|
||||||
|
"downloadX": "Pobierz {}",
|
||||||
|
"downloadedX": "Pobrano {}",
|
||||||
|
"releaseAsset": "Release Asset",
|
||||||
"downloadNotifDescription": "Informuje o postępach w pobieraniu aplikacji",
|
"downloadNotifDescription": "Informuje o postępach w pobieraniu aplikacji",
|
||||||
"noAPKFound": "Nie znaleziono pakietu APK",
|
"noAPKFound": "Nie znaleziono pakietu APK",
|
||||||
"noVersionDetection": "Bez wykrywania wersji",
|
"noVersionDetection": "Bez wykrywania wersji",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Nie pokazuj ostrzeżeń \"Tylko obserwowana\"",
|
"dontShowTrackOnlyWarnings": "Nie pokazuj ostrzeżeń \"Tylko obserwowana\"",
|
||||||
"dontShowAPKOriginWarnings": "Nie pokazuj ostrzeżeń o pochodzeniu APK",
|
"dontShowAPKOriginWarnings": "Nie pokazuj ostrzeżeń o pochodzeniu APK",
|
||||||
"moveNonInstalledAppsToBottom": "Przenieś niezainstalowane aplikacje na dół widoku aplikacji",
|
"moveNonInstalledAppsToBottom": "Przenieś niezainstalowane aplikacje na dół widoku aplikacji",
|
||||||
"gitlabPATLabel": "Osobisty token dostępu GitLab\n(Umożliwia wyszukiwanie i lepsze wykrywanie APK)",
|
"gitlabPATLabel": "Osobisty token dostępu GitLab",
|
||||||
"about": "Więcej informacji",
|
"about": "Więcej informacji",
|
||||||
"requiresCredentialsInSettings": "{}: Wymaga to dodatkowych poświadczeń (w Ustawieniach)",
|
"requiresCredentialsInSettings": "{}: Wymaga to dodatkowych poświadczeń (w Ustawieniach)",
|
||||||
"checkOnStart": "Sprawdź aktualizacje przy uruchomieniu",
|
"checkOnStart": "Sprawdź aktualizacje przy uruchomieniu",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Dodaj tę informację poniżej.",
|
"addInfoBelow": "Dodaj tę informację poniżej.",
|
||||||
"addInfoInSettings": "Dodaj tę informację w Ustawieniach.",
|
"addInfoInSettings": "Dodaj tę informację w Ustawieniach.",
|
||||||
"githubSourceNote": "Limit żądań GitHub można ominąć za pomocą klucza API.",
|
"githubSourceNote": "Limit żądań GitHub można ominąć za pomocą klucza API.",
|
||||||
"gitlabSourceNote": "Pozyskiwanie pliku APK z GitLab może nie działać bez klucza API.",
|
|
||||||
"sortByLastLinkSegment": "Sortuj tylko według ostatniego segmentu łącza",
|
"sortByLastLinkSegment": "Sortuj tylko według ostatniego segmentu łącza",
|
||||||
"filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego",
|
"filterReleaseNotesByRegEx": "Filtruj informacje o wersji według wyrażenia regularnego",
|
||||||
"customLinkFilterRegex": "Filtruj linki APK według wyrażenia regularnego (domyślnie \".apk$\")",
|
"customLinkFilterRegex": "Filtruj linki APK według wyrażenia regularnego (domyślnie \".apk$\")",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Uwaga",
|
"note": "Uwaga",
|
||||||
"selfHostedNote": "Lista rozwijana \"{}\" może być używana do uzyskiwania dostępu do samodzielnie hostowanych / niestandardowych instancji dowolnego źródła.",
|
"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).",
|
"badDownload": "Nie można przeanalizować pliku APK (niekompatybilny lub częściowo pobrany).",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Udostępnianie nowych aplikacji za pomocą AppVerifier (jeśli dostępne)",
|
||||||
|
"appVerifierInstructionToast": "Udostępnij w AppVerifier, a następnie wróć tutaj, gdy będziesz gotowy.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Usunąć aplikację?",
|
"one": "Usunąć aplikację?",
|
||||||
"few": "Usunąć aplikacje?",
|
"few": "Usunąć aplikacje?",
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Desativar detecção de versão",
|
"disableVersionDetection": "Desativar detecção de versão",
|
||||||
"noVersionDetectionExplanation": "Essa opção deve apenas ser usada por aplicativos onde a detecção de versão não funciona corretamente.",
|
"noVersionDetectionExplanation": "Essa opção deve apenas ser usada por aplicativos onde a detecção de versão não funciona corretamente.",
|
||||||
"downloadingX": "Baixando {}",
|
"downloadingX": "Baixando {}",
|
||||||
|
"downloadX": "Descarregar {}",
|
||||||
|
"downloadedX": "Descarregado {}",
|
||||||
|
"releaseAsset": "Libertação de activos",
|
||||||
"downloadNotifDescription": "Notifica o usuário o progresso do download de um aplicativo",
|
"downloadNotifDescription": "Notifica o usuário o progresso do download de um aplicativo",
|
||||||
"noAPKFound": "APK não encontrado",
|
"noAPKFound": "APK não encontrado",
|
||||||
"noVersionDetection": "Sem detecção de versão",
|
"noVersionDetection": "Sem detecção de versão",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"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",
|
||||||
"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",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"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.",
|
||||||
"githubSourceNote": "A limitação de taxa do GitHub pode ser evitada usando uma chave de API.",
|
"githubSourceNote": "A limitação de taxa do GitHub pode ser evitada usando uma chave de API.",
|
||||||
"gitlabSourceNote": "A extração de endereço de download do APK no GitLab provavelmente não funcione sem que seja fornecido uma chave de API.",
|
|
||||||
"sortByLastLinkSegment": "Ordenar apenas usando o último segmento do link",
|
"sortByLastLinkSegment": "Ordenar apenas usando o último segmento do link",
|
||||||
"filterReleaseNotesByRegEx": "Filtrar notas de versão usando Regex",
|
"filterReleaseNotesByRegEx": "Filtrar notas de versão usando Regex",
|
||||||
"customLinkFilterRegex": "Filtro de link personalizado usando expressão regular (Padrão '.apk$')",
|
"customLinkFilterRegex": "Filtro de link personalizado usando expressão regular (Padrão '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Nota",
|
"note": "Nota",
|
||||||
"selfHostedNote": "O menu suspenso \"{}\" pode ser usado para acessar instâncias auto-hospedadas/personalizadas de qualquer fonte.",
|
"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)",
|
"badDownload": "Não foi possível analisar o APK (transferência incompatível ou parcial)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Partilhar novas aplicações com o AppVerifier (se disponível)",
|
||||||
|
"appVerifierInstructionToast": "Partilhe com o AppVerifier e, em seguida, regresse aqui quando estiver pronto.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Remover aplicativo?",
|
"one": "Remover aplicativo?",
|
||||||
"other": "Remover aplicativos?"
|
"other": "Remover aplicativos?"
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Отключить обнаружение версии",
|
"disableVersionDetection": "Отключить обнаружение версии",
|
||||||
"noVersionDetectionExplanation": "Эта настройка должна использоваться только для приложений, где обнаружение версии не работает корректно",
|
"noVersionDetectionExplanation": "Эта настройка должна использоваться только для приложений, где обнаружение версии не работает корректно",
|
||||||
"downloadingX": "Загрузка {}",
|
"downloadingX": "Загрузка {}",
|
||||||
|
"downloadX": "Скачать {}",
|
||||||
|
"downloadedX": "Загружено {}",
|
||||||
|
"releaseAsset": "Освобождение актива",
|
||||||
"downloadNotifDescription": "Уведомляет пользователя о прогрессе загрузки приложения",
|
"downloadNotifDescription": "Уведомляет пользователя о прогрессе загрузки приложения",
|
||||||
"noAPKFound": "APK не найден",
|
"noAPKFound": "APK не найден",
|
||||||
"noVersionDetection": "Обнаружение версий отключено",
|
"noVersionDetection": "Обнаружение версий отключено",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Не показывать предупреждения о только отслеживаемых приложениях",
|
"dontShowTrackOnlyWarnings": "Не показывать предупреждения о только отслеживаемых приложениях",
|
||||||
"dontShowAPKOriginWarnings": "Не показывать предупреждения об отличающемся источнике APK-файлов",
|
"dontShowAPKOriginWarnings": "Не показывать предупреждения об отличающемся источнике APK-файлов",
|
||||||
"moveNonInstalledAppsToBottom": "Отображать неустановленные приложения внизу списка",
|
"moveNonInstalledAppsToBottom": "Отображать неустановленные приложения внизу списка",
|
||||||
"gitlabPATLabel": "Персональный токен доступа GitLab\n(включает поиск и улучшает обнаружение APK)",
|
"gitlabPATLabel": "Персональный токен доступа GitLab",
|
||||||
"about": "Описание",
|
"about": "Описание",
|
||||||
"requiresCredentialsInSettings": "{}: Для этого требуются дополнительные учетные данные (в настройках)",
|
"requiresCredentialsInSettings": "{}: Для этого требуются дополнительные учетные данные (в настройках)",
|
||||||
"checkOnStart": "Проверять наличие обновлений при запуске",
|
"checkOnStart": "Проверять наличие обновлений при запуске",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Добавьте эту информацию ниже",
|
"addInfoBelow": "Добавьте эту информацию ниже",
|
||||||
"addInfoInSettings": "Добавьте эту информацию в Настройки",
|
"addInfoInSettings": "Добавьте эту информацию в Настройки",
|
||||||
"githubSourceNote": "Используя ключ API можно обойти лимит запросов GitHub",
|
"githubSourceNote": "Используя ключ API можно обойти лимит запросов GitHub",
|
||||||
"gitlabSourceNote": "Без ключа API может не работать извлечение APK с GitLab",
|
|
||||||
"sortByLastLinkSegment": "Сортировать только по последнему сегменту ссылки",
|
"sortByLastLinkSegment": "Сортировать только по последнему сегменту ссылки",
|
||||||
"filterReleaseNotesByRegEx": "Фильтровать примечания к выпуску\n(регулярное выражение)",
|
"filterReleaseNotesByRegEx": "Фильтровать примечания к выпуску\n(регулярное выражение)",
|
||||||
"customLinkFilterRegex": "Пользовательский фильтр ссылок APK\n(регулярное выражение, по умолчанию: '.apk$')",
|
"customLinkFilterRegex": "Пользовательский фильтр ссылок APK\n(регулярное выражение, по умолчанию: '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Примечание",
|
"note": "Примечание",
|
||||||
"selfHostedNote": "Выпадающий список \"{}\" можно использовать для доступа к самостоятельно размещенным/настроенным экземплярам любого источника.",
|
"selfHostedNote": "Выпадающий список \"{}\" можно использовать для доступа к самостоятельно размещенным/настроенным экземплярам любого источника.",
|
||||||
"badDownload": "APK не удалось разобрать (несовместимая или неполная загрузка)",
|
"badDownload": "APK не удалось разобрать (несовместимая или неполная загрузка)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Поделитесь новыми приложениями с AppVerifier (если доступно)",
|
||||||
|
"appVerifierInstructionToast": "Поделитесь с AppVerifier, а затем вернитесь сюда, когда будете готовы.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Удалить приложение?",
|
"one": "Удалить приложение?",
|
||||||
"other": "Удалить приложения?"
|
"other": "Удалить приложения?"
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Inaktivera versionsdetektering",
|
"disableVersionDetection": "Inaktivera versionsdetektering",
|
||||||
"noVersionDetectionExplanation": "Det här alternativet bör endast användas för appar där versionsidentifiering inte fungerar korrekt.",
|
"noVersionDetectionExplanation": "Det här alternativet bör endast användas för appar där versionsidentifiering inte fungerar korrekt.",
|
||||||
"downloadingX": "Laddar ner {}",
|
"downloadingX": "Laddar ner {}",
|
||||||
|
"downloadX": "Ladda ner {}",
|
||||||
|
"downloadedX": "Nedladdad {}",
|
||||||
|
"releaseAsset": "Frigör tillgång",
|
||||||
"downloadNotifDescription": "Meddelar användaren om framstegen med att ladda ner en app",
|
"downloadNotifDescription": "Meddelar användaren om framstegen med att ladda ner en app",
|
||||||
"noAPKFound": "Ingen APK funnen",
|
"noAPKFound": "Ingen APK funnen",
|
||||||
"noVersionDetection": "Ingen versiondetektering",
|
"noVersionDetection": "Ingen versiondetektering",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Visa inte 'Följ-Endast' varningar",
|
"dontShowTrackOnlyWarnings": "Visa inte 'Följ-Endast' varningar",
|
||||||
"dontShowAPKOriginWarnings": "Visa inte APK-ursprung varningar",
|
"dontShowAPKOriginWarnings": "Visa inte APK-ursprung varningar",
|
||||||
"moveNonInstalledAppsToBottom": "Flytta icke-installerade appar till botten av appvyn",
|
"moveNonInstalledAppsToBottom": "Flytta icke-installerade appar till botten av appvyn",
|
||||||
"gitlabPATLabel": "GitLab Personal Access Token\\n(Möjliggör sökning och bättre APK-upptäckt)",
|
"gitlabPATLabel": "Personligt åtkomsttoken för GitLab",
|
||||||
"about": "Om",
|
"about": "Om",
|
||||||
"requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
|
"requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
|
||||||
"checkOnStart": "Kolla efter uppdateringar vid start",
|
"checkOnStart": "Kolla efter uppdateringar vid start",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Lägg till denna information nedanför.",
|
"addInfoBelow": "Lägg till denna information nedanför.",
|
||||||
"addInfoInSettings": "Lägg till denna information i Inställningar.",
|
"addInfoInSettings": "Lägg till denna information i Inställningar.",
|
||||||
"githubSourceNote": "GitHub-hastighetsbegränsning kan undvikas med en API-nyckel.",
|
"githubSourceNote": "GitHub-hastighetsbegränsning kan undvikas med en API-nyckel.",
|
||||||
"gitlabSourceNote": "GitLab APK-extraktion kanske inte fungerar utan en API-nyckel.",
|
|
||||||
"sortByLastLinkSegment": "Sortera endast efter det sista segmentet av länken",
|
"sortByLastLinkSegment": "Sortera endast efter det sista segmentet av länken",
|
||||||
"filterReleaseNotesByRegEx": "Filtrera versionskommentarer efter reguljärt uttryck",
|
"filterReleaseNotesByRegEx": "Filtrera versionskommentarer efter reguljärt uttryck",
|
||||||
"customLinkFilterRegex": "Anpassad APK-länkfiltrera efter reguljärt uttryck (standard '.apk$')",
|
"customLinkFilterRegex": "Anpassad APK-länkfiltrera efter reguljärt uttryck (standard '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Anmärkning",
|
"note": "Anmärkning",
|
||||||
"selfHostedNote": "Rullgardinsmenyn \"{}\" kan användas för att nå självhostade/anpassade instanser av valfri källa.",
|
"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)",
|
"badDownload": "APK kunde inte analyseras (inkompatibel eller partiell nedladdning)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Dela nya appar med AppVerifier (om tillgängligt)",
|
||||||
|
"appVerifierInstructionToast": "Dela till AppVerifier och återvänd sedan hit när du är klar.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Ta Bort App?",
|
"one": "Ta Bort App?",
|
||||||
"other": "Ta Bort Appar?"
|
"other": "Ta Bort Appar?"
|
||||||
|
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Sürüm Algılama Devre Dışı",
|
"disableVersionDetection": "Sürüm Algılama Devre Dışı",
|
||||||
"noVersionDetectionExplanation": "Bu seçenek, sürüm algılamanın doğru çalışmadığı uygulamalar için kullanılmalıdır.",
|
"noVersionDetectionExplanation": "Bu seçenek, sürüm algılamanın doğru çalışmadığı uygulamalar için kullanılmalıdır.",
|
||||||
"downloadingX": "{} İndiriliyor",
|
"downloadingX": "{} İndiriliyor",
|
||||||
|
"downloadX": "İndir {}",
|
||||||
|
"downloadedX": "İndirildi {}",
|
||||||
|
"releaseAsset": "Varlık Serbest Bırakma",
|
||||||
"downloadNotifDescription": "Bir uygulamanın indirme sürecinde ilerlemeyi bildiren bir bildirim",
|
"downloadNotifDescription": "Bir uygulamanın indirme sürecinde ilerlemeyi bildiren bir bildirim",
|
||||||
"noAPKFound": "APK bulunamadı",
|
"noAPKFound": "APK bulunamadı",
|
||||||
"noVersionDetection": "Sürüm Algılanamıyor",
|
"noVersionDetection": "Sürüm Algılanamıyor",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "'Yalnızca Takip Edilen' uyarılarını gösterme",
|
"dontShowTrackOnlyWarnings": "'Yalnızca Takip Edilen' uyarılarını gösterme",
|
||||||
"dontShowAPKOriginWarnings": "APK kaynağı uyarılarını gösterme",
|
"dontShowAPKOriginWarnings": "APK kaynağı uyarılarını gösterme",
|
||||||
"moveNonInstalledAppsToBottom": "Yüklenmemiş Uygulamaları Uygulamalar Görünümünün Altına Taşı",
|
"moveNonInstalledAppsToBottom": "Yüklenmemiş Uygulamaları Uygulamalar Görünümünün Altına Taşı",
|
||||||
"gitlabPATLabel": "GitLab Kişisel Erişim Belirteci\n(Arama ve Daha İyi APK Keşfi İçin)",
|
"gitlabPATLabel": "GitLab Kişisel Erişim Belirteci",
|
||||||
"about": "Hakkında",
|
"about": "Hakkında",
|
||||||
"requiresCredentialsInSettings": "{}: Bu, ek kimlik bilgilerine ihtiyaç duyar (Ayarlar'da)",
|
"requiresCredentialsInSettings": "{}: Bu, ek kimlik bilgilerine ihtiyaç duyar (Ayarlar'da)",
|
||||||
"checkOnStart": "Başlangıçta güncellemeleri kontrol et",
|
"checkOnStart": "Başlangıçta güncellemeleri kontrol et",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Bu bilgiyi aşağıya ekle.",
|
"addInfoBelow": "Bu bilgiyi aşağıya ekle.",
|
||||||
"addInfoInSettings": "Bu bilgiyi Ayarlar'da ekleyin.",
|
"addInfoInSettings": "Bu bilgiyi Ayarlar'da ekleyin.",
|
||||||
"githubSourceNote": "GitHub hız sınırlaması bir API anahtarı kullanılarak atlanabilir.",
|
"githubSourceNote": "GitHub hız sınırlaması bir API anahtarı kullanılarak atlanabilir.",
|
||||||
"gitlabSourceNote": "GitLab APK çıkarma işlemi bir API anahtarı olmadan çalışmayabilir.",
|
|
||||||
"sortByLastLinkSegment": "Bağlantının yalnızca son bölümüne göre sırala",
|
"sortByLastLinkSegment": "Bağlantının yalnızca son bölümüne göre sırala",
|
||||||
"filterReleaseNotesByRegEx": "Sürüm Notlarını Düzenli İfade ile Filtrele",
|
"filterReleaseNotesByRegEx": "Sürüm Notlarını Düzenli İfade ile Filtrele",
|
||||||
"customLinkFilterRegex": "Özel APK Bağlantı Filtresi Düzenli İfade ile (Varsayılan '.apk$')",
|
"customLinkFilterRegex": "Özel APK Bağlantı Filtresi Düzenli İfade ile (Varsayılan '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Not",
|
"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.",
|
"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)",
|
"badDownload": "APK ayrıştırılamadı (uyumsuz veya kısmi indirme)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Yeni Uygulamaları AppVerifier ile paylaşın (varsa)",
|
||||||
|
"appVerifierInstructionToast": "AppVerifier ile paylaşın, hazır olduğunuzda buraya dönün.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Uygulamayı Kaldır?",
|
"one": "Uygulamayı Kaldır?",
|
||||||
"other": "Uygulamaları Kaldır?"
|
"other": "Uygulamaları Kaldır?"
|
||||||
|
363
assets/translations/uk.json
Normal file
363
assets/translations/uk.json
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
{
|
||||||
|
"invalidURLForSource": "Неправильна URL-адреса для джерела застосунку {}",
|
||||||
|
"noReleaseFound": "Не вдалося знайти відповідне видання",
|
||||||
|
"noVersionFound": "Не вдалося визначити версію видання",
|
||||||
|
"urlMatchesNoSource": "URL не відповідає відомому джерелу",
|
||||||
|
"cantInstallOlderVersion": "Не можна встановити старішу версію застосунку",
|
||||||
|
"appIdMismatch": "Ідентифікатор пакета, завантажений, не відповідає ідентифікатору існуючого застосунку",
|
||||||
|
"functionNotImplemented": "Цей клас не реалізував цю функцію",
|
||||||
|
"placeholder": "Заповнювач",
|
||||||
|
"someErrors": "Виникла деяка помилка",
|
||||||
|
"unexpectedError": "Неочікувана помилка",
|
||||||
|
"ok": "Добре",
|
||||||
|
"and": "та",
|
||||||
|
"githubPATLabel": "Персональний ключ доступу GitHub (збільшує обмеження на швидкість)",
|
||||||
|
"includePrereleases": "Включити попередні видання",
|
||||||
|
"fallbackToOlderReleases": "Повернутися до старіших видань",
|
||||||
|
"filterReleaseTitlesByRegEx": "Фільтрувати заголовки видань за допомогою регулярного виразу",
|
||||||
|
"invalidRegEx": "Неприпустимий регулярний вираз",
|
||||||
|
"noDescription": "Немає опису",
|
||||||
|
"cancel": "Скасувати",
|
||||||
|
"continue": "Продовжити",
|
||||||
|
"requiredInBrackets": "(Обов'язково)",
|
||||||
|
"dropdownNoOptsError": "ПОМИЛКА: В ВИПАДАЮЧОМУ СПИСКУ МАЄ БУТИ ХОЧА Б ОДИН ЕЛЕМЕНТ",
|
||||||
|
"colour": "Колір",
|
||||||
|
"githubStarredRepos": "Відзначені репозиторії GitHub",
|
||||||
|
"uname": "Ім'я користувача",
|
||||||
|
"wrongArgNum": "Надано неправильну кількість аргументів",
|
||||||
|
"xIsTrackOnly": "{} - тільки відстежування",
|
||||||
|
"source": "Джерело",
|
||||||
|
"app": "застосунок",
|
||||||
|
"appsFromSourceAreTrackOnly": "Застосунки з цього джерела є лише для відстежування.",
|
||||||
|
"youPickedTrackOnly": "Ви вибрали опцію лише для відстежування.",
|
||||||
|
"trackOnlyAppDescription": "Застосунок буде відстежуватися для оновлень, але Obtainium не зможе його завантажити або встановити.",
|
||||||
|
"cancelled": "Скасовано",
|
||||||
|
"appAlreadyAdded": "Застосунок вже додано",
|
||||||
|
"alreadyUpToDateQuestion": "Застосунок вже оновлено?",
|
||||||
|
"addApp": "Додати",
|
||||||
|
"appSourceURL": "URL-адреса джерела застосунку",
|
||||||
|
"error": "Помилка",
|
||||||
|
"add": "Додати",
|
||||||
|
"searchSomeSourcesLabel": "Пошук (Лише деякі джерела)",
|
||||||
|
"search": "Пошук",
|
||||||
|
"additionalOptsFor": "Додаткові опції для {}",
|
||||||
|
"supportedSources": "Підтримувані джерела",
|
||||||
|
"trackOnlyInBrackets": "(Тільки для відстеження)",
|
||||||
|
"searchableInBrackets": "(Можливий пошук)",
|
||||||
|
"appsString": "Застосунки",
|
||||||
|
"noApps": "Застосунків немає",
|
||||||
|
"noAppsForFilter": "Застосунків для фільтрації немає",
|
||||||
|
"byX": "Від {}",
|
||||||
|
"percentProgress": "Прогрес: {}%",
|
||||||
|
"pleaseWait": "Будь ласка, зачекайте",
|
||||||
|
"updateAvailable": "Доступно оновлення",
|
||||||
|
"notInstalled": "Не встановлено",
|
||||||
|
"pseudoVersion": "псевдо-версія",
|
||||||
|
"selectAll": "Вибрати все",
|
||||||
|
"deselectX": "Скасувати вибір {}",
|
||||||
|
"xWillBeRemovedButRemainInstalled": "{} буде видалено з Obtainium, але залишиться встановленим на пристрої.",
|
||||||
|
"removeSelectedAppsQuestion": "Видалити вибрані застосунки?",
|
||||||
|
"removeSelectedApps": "Видалити вибрані застосунки",
|
||||||
|
"updateX": "Оновити {}",
|
||||||
|
"installX": "Встановити {}",
|
||||||
|
"markXTrackOnlyAsUpdated": "Позначити {}\n(Тільки відстежування)\nяк оновлено",
|
||||||
|
"changeX": "Змінити {}",
|
||||||
|
"installUpdateApps": "Встановити/Оновити застосунки",
|
||||||
|
"installUpdateSelectedApps": "Встановити/Оновити вибрані застосунки",
|
||||||
|
"markXSelectedAppsAsUpdated": "Позначити {} вибрані застосунки як оновлені?",
|
||||||
|
"no": "Ні",
|
||||||
|
"yes": "Так",
|
||||||
|
"markSelectedAppsUpdated": "Позначити вибрані застосунки як оновлені",
|
||||||
|
"pinToTop": "Закріпити угорі",
|
||||||
|
"unpinFromTop": "Відкріпити зверху",
|
||||||
|
"resetInstallStatusForSelectedAppsQuestion": "Скинути статус встановлення для вибраних застосунків?",
|
||||||
|
"installStatusOfXWillBeResetExplanation": "Статус встановлення будь-яких вибраних застосунків буде скинутий.\n\nЦе може допомогти, коли версія застосунку, відображена в Obtainium, є неправильною через невдалі оновлення або інші проблеми.",
|
||||||
|
"customLinkMessage": "Ці посилання працюють на пристроях з встановленим Obtainium",
|
||||||
|
"shareAppConfigLinks": "Поділитися посиланнями на конфігурацію Застосунку як HTML",
|
||||||
|
"shareSelectedAppURLs": "Поділитися вибраними URL-адресами застосунків",
|
||||||
|
"resetInstallStatus": "Скинути статус встановлення",
|
||||||
|
"more": "Більше",
|
||||||
|
"removeOutdatedFilter": "Видалити фільтр застарілих застосунків",
|
||||||
|
"showOutdatedOnly": "Показати лише застарілі застосунки",
|
||||||
|
"filter": "Фільтр",
|
||||||
|
"filterApps": "Фільтрувати застосунки",
|
||||||
|
"appName": "Назва застосунку",
|
||||||
|
"author": "Автор",
|
||||||
|
"upToDateApps": "Актуальні застосунки",
|
||||||
|
"nonInstalledApps": "Невстановлені застосунки",
|
||||||
|
"importExport": "Імпорт/Експорт",
|
||||||
|
"settings": "Налаштування",
|
||||||
|
"exportedTo": "Експортовано в {}",
|
||||||
|
"obtainiumExport": "Експорт з Obtainium",
|
||||||
|
"invalidInput": "Недійсний ввід",
|
||||||
|
"importedX": "Імпортовано {}",
|
||||||
|
"obtainiumImport": "Імпорт в Obtainium",
|
||||||
|
"importFromURLList": "Імпорт зі списку URL-адрес",
|
||||||
|
"searchQuery": "Пошуковий запит",
|
||||||
|
"appURLList": "Список URL-адрес застосунків",
|
||||||
|
"line": "Лінія",
|
||||||
|
"searchX": "Пошук {}",
|
||||||
|
"noResults": "Результати відсутні",
|
||||||
|
"importX": "Імпорт {}",
|
||||||
|
"importedAppsIdDisclaimer": "Імпортовані застосунки можуть неправильно відображатися як \"Не встановлені\".\nДля виправлення цього перевстановіть їх через Obtainium.\nЦе не повинно вплинути на дані застосунків.\n\nПов'язано лише з URL-адресами та імпортом від третіх сторін.",
|
||||||
|
"importErrors": "Помилки імпорту",
|
||||||
|
"importedXOfYApps": "Імпортовано {} з {} застосунків.",
|
||||||
|
"followingURLsHadErrors": "Помилки в наступних URL-адресах:",
|
||||||
|
"selectURL": "Вибрати URL",
|
||||||
|
"selectURLs": "Вибрати URL-адреси",
|
||||||
|
"pick": "Вибрати",
|
||||||
|
"theme": "Тема",
|
||||||
|
"dark": "Темна",
|
||||||
|
"light": "Світла",
|
||||||
|
"followSystem": "Дотримуватися системи",
|
||||||
|
"useBlackTheme": "Використовувати чорну тему (Amoled)",
|
||||||
|
"appSortBy": "Сортувати застосунки за",
|
||||||
|
"authorName": "Автор/Назва",
|
||||||
|
"nameAuthor": "Назва/Автор",
|
||||||
|
"asAdded": "За додаванням",
|
||||||
|
"appSortOrder": "Порядок сортування застосунків",
|
||||||
|
"ascending": "За зростанням",
|
||||||
|
"descending": "За спаданням",
|
||||||
|
"bgUpdateCheckInterval": "Інтервал перевірки оновлень у фоновому режимі",
|
||||||
|
"neverManualOnly": "Ніколи - Тільки вручну",
|
||||||
|
"appearance": "Вигляд",
|
||||||
|
"showWebInAppView": "Показати джерело застосунку у вигляді веб-сторінки",
|
||||||
|
"pinUpdates": "Закріпити оновлення у верхній частині вигляду застосунків",
|
||||||
|
"updates": "Оновлення",
|
||||||
|
"sourceSpecific": "Певне джерело",
|
||||||
|
"appSource": "Джерело застосунку",
|
||||||
|
"noLogs": "Немає логів",
|
||||||
|
"appLogs": "Лог застосунку",
|
||||||
|
"close": "Закрити",
|
||||||
|
"share": "Поділитися",
|
||||||
|
"appNotFound": "Застосунок не знайдено",
|
||||||
|
"obtainiumExportHyphenatedLowercase": "експорт з Obtainium",
|
||||||
|
"pickAnAPK": "Вибрати APK",
|
||||||
|
"appHasMoreThanOnePackage": "{} має більше одного пакету:",
|
||||||
|
"deviceSupportsXArch": "Ваш пристрій підтримує архітектуру процесора {}.",
|
||||||
|
"deviceSupportsFollowingArchs": "Ваш пристрій підтримує наступні архітектури процесора:",
|
||||||
|
"warning": "Попередження",
|
||||||
|
"sourceIsXButPackageFromYPrompt": "Джерело застосунку - '{}' але пакет випуску походить з '{}'. Продовжити?",
|
||||||
|
"updatesAvailable": "Доступні оновлення",
|
||||||
|
"updatesAvailableNotifDescription": "Повідомляє користувача, що доступні оновлення для одного чи декількох застосунків, які відстежує Obtainium",
|
||||||
|
"noNewUpdates": "Немає нових оновлень.",
|
||||||
|
"xHasAnUpdate": "{} має оновлення.",
|
||||||
|
"appsUpdated": "Застосунки оновлено",
|
||||||
|
"appsUpdatedNotifDescription": "Повідомляє користувача, що оновлення одного чи декількох застосунків було застосовано в фоновому режимі",
|
||||||
|
"xWasUpdatedToY": "{} було оновлено до {}.",
|
||||||
|
"errorCheckingUpdates": "Помилка перевірки оновлень",
|
||||||
|
"errorCheckingUpdatesNotifDescription": "Повідомлення, яке з'являється, коли перевірка оновлень в фоновому режимі завершується невдачею",
|
||||||
|
"appsRemoved": "Застосунки видалено",
|
||||||
|
"appsRemovedNotifDescription": "Повідомляє користувача, що один чи декілька застосунків були видалені через помилки при завантаженні",
|
||||||
|
"xWasRemovedDueToErrorY": "{} було видалено через цю помилку: {}",
|
||||||
|
"completeAppInstallation": "Завершення установки застосунку",
|
||||||
|
"obtainiumMustBeOpenToInstallApps": "Для встановлення застосунків Obtainium має бути відкритий",
|
||||||
|
"completeAppInstallationNotifDescription": "Прохання користувача повернутися до Obtainium для завершення установки застосунку",
|
||||||
|
"checkingForUpdates": "Перевірка оновлень",
|
||||||
|
"checkingForUpdatesNotifDescription": "Тимчасове повідомлення, яке з'являється при перевірці оновлень",
|
||||||
|
"pleaseAllowInstallPerm": "Будь ласка, дозвольте Obtainium встановлювати застосунки",
|
||||||
|
"trackOnly": "Тільки відстеження",
|
||||||
|
"errorWithHttpStatusCode": "Помилка {} HTTP-коду",
|
||||||
|
"versionCorrectionDisabled": "Виправлення версії вимкнено (здається, плагін не працює)",
|
||||||
|
"unknown": "Невідомо",
|
||||||
|
"none": "Нічого",
|
||||||
|
"never": "Ніколи",
|
||||||
|
"latestVersionX": "Остання версія: {}",
|
||||||
|
"installedVersionX": "Встановлено: {}",
|
||||||
|
"lastUpdateCheckX": "Остання перевірка оновлень: {}",
|
||||||
|
"remove": "Видалити",
|
||||||
|
"yesMarkUpdated": "Так, позначити як оновлене",
|
||||||
|
"fdroid": "F-Droid Офіційний",
|
||||||
|
"appIdOrName": "Ідентифікатор або назва застосунку",
|
||||||
|
"appId": "Ідентифікатор застосунку",
|
||||||
|
"appWithIdOrNameNotFound": "Застосунок з таким ідентифікатором або назвою не знайдено",
|
||||||
|
"reposHaveMultipleApps": "Сховища можуть містити кілька застосунків",
|
||||||
|
"fdroidThirdPartyRepo": "F-Droid Стороннє сховище",
|
||||||
|
"steamMobile": "Мобільний Steam",
|
||||||
|
"steamChat": "Чат Steam",
|
||||||
|
"install": "Встановити",
|
||||||
|
"markInstalled": "Позначити як встановлене",
|
||||||
|
"update": "Оновити",
|
||||||
|
"markUpdated": "Позначити як оновлене",
|
||||||
|
"additionalOptions": "Додаткові опції",
|
||||||
|
"disableVersionDetection": "Вимкнути визначення версії",
|
||||||
|
"noVersionDetectionExplanation": "Цю опцію слід використовувати лише для застосунків, де визначення версії працює неправильно.",
|
||||||
|
"downloadingX": "Завантаження {}",
|
||||||
|
"downloadX": "Завантажити {}",
|
||||||
|
"downloadedX": "Завантажено {}",
|
||||||
|
"releaseAsset": "Звільнити актив",
|
||||||
|
"downloadNotifDescription": "Повідомляє користувача про прогрес завантаження застосунку",
|
||||||
|
"noAPKFound": "APK не знайдено",
|
||||||
|
"noVersionDetection": "Визначення версії відключено",
|
||||||
|
"categorize": "Категоризувати",
|
||||||
|
"categories": "Категорії",
|
||||||
|
"category": "Категорія",
|
||||||
|
"noCategory": "Без категорії",
|
||||||
|
"noCategories": "Немає категорій",
|
||||||
|
"deleteCategoriesQuestion": "Видалити категорії?",
|
||||||
|
"categoryDeleteWarning": "Усі застосунки у видалених категоріях будуть переведені у некатегоризовані.",
|
||||||
|
"addCategory": "Додати категорію",
|
||||||
|
"label": "Мітка",
|
||||||
|
"language": "Мова",
|
||||||
|
"copiedToClipboard": "Скопійовано в буфер обміну",
|
||||||
|
"storagePermissionDenied": "Відмовлено у дозволі на доступ до сховища",
|
||||||
|
"selectedCategorizeWarning": "Це замінить будь-які існуючі налаштування категорій для вибраних застосунків.",
|
||||||
|
"filterAPKsByRegEx": "Фільтрувати APK за регулярним виразом",
|
||||||
|
"removeFromObtainium": "Видалити з Obtainium",
|
||||||
|
"uninstallFromDevice": "Видалити з пристрою",
|
||||||
|
"onlyWorksWithNonVersionDetectApps": "Працює лише з застосунками з вимкненим визначенням версії.",
|
||||||
|
"releaseDateAsVersion": "Використовувати дату випуску як рядок версії",
|
||||||
|
"releaseDateAsVersionExplanation": "Цю опцію слід використовувати лише для застосунків, де визначення версії працює неправильно, але є дата випуску.",
|
||||||
|
"changes": "Зміни",
|
||||||
|
"releaseDate": "Дата випуску",
|
||||||
|
"importFromURLsInFile": "Імпорт з URL-адрес у файлі (наприклад, OPML)",
|
||||||
|
"versionDetectionExplanation": "Порівняти рядок версії з версією, визначеною операційною системою",
|
||||||
|
"versionDetection": "Визначення версії",
|
||||||
|
"standardVersionDetection": "Стандартне визначення версії",
|
||||||
|
"groupByCategory": "Групувати за категоріями",
|
||||||
|
"autoApkFilterByArch": "Спробувати фільтрувати APK за архітектурою ЦП, якщо можливо",
|
||||||
|
"overrideSource": "Перевизначити джерело",
|
||||||
|
"dontShowAgain": "Не показувати це знову",
|
||||||
|
"dontShowTrackOnlyWarnings": "Не показувати попередження про 'Тільки відстеження'",
|
||||||
|
"dontShowAPKOriginWarnings": "Не показувати попередження про походження APK",
|
||||||
|
"moveNonInstalledAppsToBottom": "Перемістити невстановлені застосунки вниз у перегляді застосунків",
|
||||||
|
"gitlabPATLabel": "Особистий токен GitLab (Увімкнення пошуку та краще виявлення APK)",
|
||||||
|
"about": "Про програму",
|
||||||
|
"requiresCredentialsInSettings": "{} потребує додаткових облікових даних (у налаштуваннях)",
|
||||||
|
"checkOnStart": "Перевірити наявність оновлень при запуску",
|
||||||
|
"tryInferAppIdFromCode": "Спробувати вивести ідентифікатор застосунку з вихідного коду",
|
||||||
|
"removeOnExternalUninstall": "Автоматично видаляти застосунки, які було видалено зовнішнім чином",
|
||||||
|
"pickHighestVersionCode": "Автоматично вибрати APK з найвищим кодом версії",
|
||||||
|
"checkUpdateOnDetailPage": "Перевіряти наявність оновлень при відкритті сторінки деталей застосунку",
|
||||||
|
"disablePageTransitions": "Вимкнути анімації переходів між сторінками",
|
||||||
|
"reversePageTransitions": "Зворотні анімації переходів між сторінками",
|
||||||
|
"minStarCount": "Мінімальна кількість зірок",
|
||||||
|
"addInfoBelow": "Додати цю інформацію нижче.",
|
||||||
|
"addInfoInSettings": "Додати цю інформацію у налаштуваннях.",
|
||||||
|
"githubSourceNote": "Лімітування швидкості GitHub можна уникнути, використовуючи ключ API.",
|
||||||
|
"sortByLastLinkSegment": "Сортувати лише за останнім сегментом посилання",
|
||||||
|
"filterReleaseNotesByRegEx": "Фільтрувати примітки до релізу за регулярним виразом",
|
||||||
|
"customLinkFilterRegex": "Фільтр кастомного посилання на APK за регулярним виразом (за замовчуванням '.apk$')",
|
||||||
|
"appsPossiblyUpdated": "Спроб оновлення застосунків",
|
||||||
|
"appsPossiblyUpdatedNotifDescription": "Повідомляє користувача, що оновлення одного або декількох застосунків можливо були застосовані в фоновому режимі",
|
||||||
|
"xWasPossiblyUpdatedToY": "{} можливо було оновлено до {}.",
|
||||||
|
"enableBackgroundUpdates": "Увімкнути оновлення в фоновому режимі",
|
||||||
|
"backgroundUpdateReqsExplanation": "Оновлення в фоновому режимі може бути неможливим для всіх застосунків.",
|
||||||
|
"backgroundUpdateLimitsExplanation": "Успіх фонової установки може бути визначений лише після відкриття Obtainium.",
|
||||||
|
"verifyLatestTag": "Перевірити тег 'latest'",
|
||||||
|
"intermediateLinkRegex": "Фільтр для 'Проміжного' Посилання для Відвідування",
|
||||||
|
"filterByLinkText": "Фільтрувати посилання за текстом посилання",
|
||||||
|
"intermediateLinkNotFound": "Проміжне посилання не знайдено",
|
||||||
|
"intermediateLink": "Проміжне посилання",
|
||||||
|
"exemptFromBackgroundUpdates": "Виключено з фонових оновлень (якщо ввімкнено)",
|
||||||
|
"bgUpdatesOnWiFiOnly": "Вимкнути фонові оновлення поза Wi-Fi",
|
||||||
|
"autoSelectHighestVersionCode": "Автоматичний вибір APK з найвищим кодом версії",
|
||||||
|
"versionExtractionRegEx": "Регулярний вираз для вилучення рядка версії",
|
||||||
|
"matchGroupToUse": "Група співпадінь для використання в регулярному виразі вилучення версії",
|
||||||
|
"highlightTouchTargets": "Підсвічувати менш очевидні області дотику",
|
||||||
|
"pickExportDir": "Вибрати каталог експорту",
|
||||||
|
"autoExportOnChanges": "Автоматичний експорт при змінах",
|
||||||
|
"includeSettings": "Включити налаштування",
|
||||||
|
"filterVersionsByRegEx": "Фільтрувати версії за регулярним виразом",
|
||||||
|
"trySelectingSuggestedVersionCode": "Спробуйте вибрати запропонований код версії APK",
|
||||||
|
"dontSortReleasesList": "Зберігати порядок випуску з API",
|
||||||
|
"reverseSort": "Зворотне сортування",
|
||||||
|
"takeFirstLink": "Вибрати перше посилання",
|
||||||
|
"skipSort": "Пропустити сортування",
|
||||||
|
"debugMenu": "Меню налагодження",
|
||||||
|
"bgTaskStarted": "Запущено фонове завдання - перевірте журнали.",
|
||||||
|
"runBgCheckNow": "Запустити перевірку оновлень в фоновому режимі зараз",
|
||||||
|
"versionExtractWholePage": "Застосувати регулярний вираз вилучення версії до всієї сторінки",
|
||||||
|
"installing": "Встановлення",
|
||||||
|
"skipUpdateNotifications": "Пропустити сповіщення про оновлення",
|
||||||
|
"updatesAvailableNotifChannel": "Доступні оновлення",
|
||||||
|
"appsUpdatedNotifChannel": "Застосунки оновлені",
|
||||||
|
"appsPossiblyUpdatedNotifChannel": "Спроба оновлення застосунків",
|
||||||
|
"errorCheckingUpdatesNotifChannel": "Помилка перевірки оновлень",
|
||||||
|
"appsRemovedNotifChannel": "Застосунки видалені",
|
||||||
|
"downloadingXNotifChannel": "Завантаження {}",
|
||||||
|
"completeAppInstallationNotifChannel": "Завершення встановлення застосунку",
|
||||||
|
"checkingForUpdatesNotifChannel": "Перевірка оновлень",
|
||||||
|
"onlyCheckInstalledOrTrackOnlyApps": "Перевіряти лише встановлені та застосунки, які відстежуються для оновлень",
|
||||||
|
"supportFixedAPKURL": "Підтримка фіксованих посилань на APK",
|
||||||
|
"selectX": "Вибрати {}",
|
||||||
|
"parallelDownloads": "Дозволити паралельні завантаження",
|
||||||
|
"installMethod": "Метод встановлення",
|
||||||
|
"normal": "Звичайний",
|
||||||
|
"root": "Root",
|
||||||
|
"shizukuBinderNotFound": "Сумісний сервіс Shizuku не було знайдено",
|
||||||
|
"useSystemFont": "Використовувати системний шрифт",
|
||||||
|
"systemFontError": "Помилка завантаження системного шрифту: {}",
|
||||||
|
"useVersionCodeAsOSVersion": "Використовувати код версії застосунку як версію, визначену операційною системою",
|
||||||
|
"requestHeader": "Заголовок запиту",
|
||||||
|
"useLatestAssetDateAsReleaseDate": "Використовувати останню дату завантаження ресурсу як дату випуску",
|
||||||
|
"defaultPseudoVersioningMethod": "Метод за замовчуванням псевдо-версіонування",
|
||||||
|
"partialAPKHash": "Хеш часткового APK",
|
||||||
|
"APKLinkHash": "Хеш посилання на APK",
|
||||||
|
"directAPKLink": "Пряме посилання на APK",
|
||||||
|
"pseudoVersionInUse": "Використовується псевдо-версія",
|
||||||
|
"installed": "Встановлено",
|
||||||
|
"latest": "Остання",
|
||||||
|
"invertRegEx": "Інвертувати регулярний вираз",
|
||||||
|
"note": "Примітка",
|
||||||
|
"selfHostedNote": "Випадаючий список \"{}\" може використовуватися для доступу до власних/призначених для самостійного використання екземплярів будь-якого джерела.",
|
||||||
|
"badDownload": "APK не вдалося розпарсити (несумісний або часткове завантаження)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Діліться новими додатками з AppVerifier (якщо доступно)",
|
||||||
|
"appVerifierInstructionToast": "Надішліть на AppVerifier, а потім поверніться сюди, коли будете готові.",
|
||||||
|
"removeAppQuestion": {
|
||||||
|
"one": "Видалити застосунок?",
|
||||||
|
"other": "Видалити застосунки?"
|
||||||
|
},
|
||||||
|
"tooManyRequestsTryAgainInMinutes": {
|
||||||
|
"one": "Забагато запитів (обмеження швидкості) - повторіть спробу через {} хвилину",
|
||||||
|
"other": "Забагато запитів (обмеження швидкості) - повторіть спробу через {} хвилин"
|
||||||
|
},
|
||||||
|
"bgUpdateGotErrorRetryInMinutes": {
|
||||||
|
"one": "Помилка перевірки оновлень у фоновому режимі - спробую знову через {} хвилину",
|
||||||
|
"other": "Помилка перевірки оновлень у фоновому режимі - спробую знову через {} хвилин"
|
||||||
|
},
|
||||||
|
"bgCheckFoundUpdatesWillNotifyIfNeeded": {
|
||||||
|
"one": "Фонова перевірка оновлень знайшла {} оновлення - сповістити користувача, якщо це необхідно",
|
||||||
|
"other": "Фонова перевірка оновлень знайшла {} оновлень - сповістити користувача, якщо це необхідно"
|
||||||
|
},
|
||||||
|
"apps": {
|
||||||
|
"one": "{} застосунок",
|
||||||
|
"other": "{} застосунки"
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"one": "{} URL-адреса",
|
||||||
|
"other": "{} URL-адреси"
|
||||||
|
},
|
||||||
|
"minute": {
|
||||||
|
"one": "{} хвилина",
|
||||||
|
"other": "{} хвилин"
|
||||||
|
},
|
||||||
|
"hour": {
|
||||||
|
"one": "{} година",
|
||||||
|
"other": "{} годин"
|
||||||
|
},
|
||||||
|
"day": {
|
||||||
|
"one": "{} день",
|
||||||
|
"other": "{} днів"
|
||||||
|
},
|
||||||
|
"clearedNLogsBeforeXAfterY": {
|
||||||
|
"one": "Очищено {n} журнал (до = {before}, після = {after})",
|
||||||
|
"other": "Очищено {n} журналів (до = {before}, після = {after})"
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesAvailable": {
|
||||||
|
"one": "{} та ще 1 застосунок мають оновлення.",
|
||||||
|
"other": "{} та ще {} застосунки мають оновлення."
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesInstalled": {
|
||||||
|
"one": "{} та ще 1 застосунок було оновлено.",
|
||||||
|
"other": "{} та ще {} застосунків було оновлено."
|
||||||
|
},
|
||||||
|
"xAndNMoreUpdatesPossiblyInstalled": {
|
||||||
|
"one": "{} та ще 1 застосунок можливо було оновлено.",
|
||||||
|
"other": "{} та ще {} застосунків можливо було оновлено."
|
||||||
|
},
|
||||||
|
"apk": {
|
||||||
|
"one": "{} APK",
|
||||||
|
"other": "{} APK-файли"
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,7 @@
|
|||||||
"unexpectedError": "Lỗi không mong đợi",
|
"unexpectedError": "Lỗi không mong đợi",
|
||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"and": "và",
|
"and": "và",
|
||||||
"githubPATLabel": "GitHub Token (Tăng tốc độ, giới hạn)",
|
"githubPATLabel": "Token truy cập cá nhân GitHub (Cải thiện tốc độ giới hạn)",
|
||||||
"includePrereleases": "Bao gồm các bản phát hành trước",
|
"includePrereleases": "Bao gồm các bản phát hành trước",
|
||||||
"fallbackToOlderReleases": "Dự phòng về bản phát hành cũ hơn",
|
"fallbackToOlderReleases": "Dự phòng về bản phát hành cũ hơn",
|
||||||
"filterReleaseTitlesByRegEx": "Lọc tiêu đề bản phát hành theo biểu thức chính quy",
|
"filterReleaseTitlesByRegEx": "Lọc tiêu đề bản phát hành theo biểu thức chính quy",
|
||||||
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "Tắt tính năng phát hiện phiên bản",
|
"disableVersionDetection": "Tắt tính năng phát hiện phiên bản",
|
||||||
"noVersionDetectionExplanation": "Chỉ nên sử dụng tùy chọn này cho Ứng dụng mà tính năng phát hiện phiên bản không hoạt động chính xác.",
|
"noVersionDetectionExplanation": "Chỉ nên sử dụng tùy chọn này cho Ứng dụng mà tính năng phát hiện phiên bản không hoạt động chính xác.",
|
||||||
"downloadingX": "Đang tải xuống {}",
|
"downloadingX": "Đang tải xuống {}",
|
||||||
|
"downloadX": "Download {}",
|
||||||
|
"downloadedX": "Downloaded {}",
|
||||||
|
"releaseAsset": "Release Asset",
|
||||||
"downloadNotifDescription": "Thông báo cho người dùng về tiến trình tải xuống Ứng dụng",
|
"downloadNotifDescription": "Thông báo cho người dùng về tiến trình tải xuống Ứng dụng",
|
||||||
"noAPKFound": "Không tìm thấy APK",
|
"noAPKFound": "Không tìm thấy APK",
|
||||||
"noVersionDetection": "Không phát hiện phiên bản",
|
"noVersionDetection": "Không phát hiện phiên bản",
|
||||||
@ -218,7 +221,7 @@
|
|||||||
"dontShowTrackOnlyWarnings": "Không hiển thị cảnh báo 'Chỉ theo dõi'",
|
"dontShowTrackOnlyWarnings": "Không hiển thị cảnh báo 'Chỉ theo dõi'",
|
||||||
"dontShowAPKOriginWarnings": "Không hiển thị cảnh báo nguồn gốc APK",
|
"dontShowAPKOriginWarnings": "Không hiển thị cảnh báo nguồn gốc APK",
|
||||||
"moveNonInstalledAppsToBottom": "Chuyển Ứng dụng chưa được cài đặt xuống cuối danh sách",
|
"moveNonInstalledAppsToBottom": "Chuyển Ứng dụng chưa được cài đặt xuống cuối danh sách",
|
||||||
"gitlabPATLabel": "GitLab Token\n(Cho phép tìm kiếm và lọc APK tốt hơn)",
|
"gitlabPATLabel": "Token truy cập cá nhân GitLab",
|
||||||
"about": "Giới thiệu",
|
"about": "Giới thiệu",
|
||||||
"requiresCredentialsInSettings": "{}: Điều này cần thông tin xác thực bổ sung (trong Thiết đặt)",
|
"requiresCredentialsInSettings": "{}: Điều này cần thông tin xác thực bổ sung (trong Thiết đặt)",
|
||||||
"checkOnStart": "Kiểm tra các bản cập nhật khi khởi động",
|
"checkOnStart": "Kiểm tra các bản cập nhật khi khởi động",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "Thêm thông tin này vào bên dưới.",
|
"addInfoBelow": "Thêm thông tin này vào bên dưới.",
|
||||||
"addInfoInSettings": "Thêm thông tin này vào Thiết đặt.",
|
"addInfoInSettings": "Thêm thông tin này vào Thiết đặt.",
|
||||||
"githubSourceNote": "Có thể tránh được việc giới hạn tốc độ GitHub bằng cách sử dụng khóa API.",
|
"githubSourceNote": "Có thể tránh được việc giới hạn tốc độ GitHub bằng cách sử dụng khóa API.",
|
||||||
"gitlabSourceNote": "Trích xuất APK GitLab có thể không hoạt động nếu không có khóa API.",
|
|
||||||
"sortByLastLinkSegment": "Chỉ sắp xếp theo đoạn cuối của liên kết",
|
"sortByLastLinkSegment": "Chỉ sắp xếp theo đoạn cuối của liên kết",
|
||||||
"filterReleaseNotesByRegEx": "Lọc ghi chú phát hành theo biểu thức chính quy",
|
"filterReleaseNotesByRegEx": "Lọc ghi chú phát hành theo biểu thức chính quy",
|
||||||
"customLinkFilterRegex": "Bộ lọc liên kết APK tùy chỉnh theo biểu thức chính quy (Mặc định '.apk$')",
|
"customLinkFilterRegex": "Bộ lọc liên kết APK tùy chỉnh theo biểu thức chính quy (Mặc định '.apk$')",
|
||||||
@ -300,6 +302,8 @@
|
|||||||
"note": "Ghi chú",
|
"note": "Ghi chú",
|
||||||
"selfHostedNote": "Trình đơn thả xuống \"{}\" có thể được dùng để tiếp cận các phiên bản tự lưu trữ/tùy chỉnh của bất kỳ nguồn nào.",
|
"selfHostedNote": "Trình đơn thả xuống \"{}\" có thể được dùng để tiếp cận các phiên bản tự lưu trữ/tùy chỉnh của bất kỳ nguồn nào.",
|
||||||
"badDownload": "Không thể phân tích cú pháp APK (tải xuống một phần hoặc không tương thích)",
|
"badDownload": "Không thể phân tích cú pháp APK (tải xuống một phần hoặc không tương thích)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "Chia sẻ ứng dụng mới với AppVerifier (nếu có)",
|
||||||
|
"appVerifierInstructionToast": "Chia sẻ lên AppVerifier, sau đó quay lại đây khi sẵn sàng.",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "Gỡ ứng dụng?",
|
"one": "Gỡ ứng dụng?",
|
||||||
"other": "Gỡ ứng dụng?"
|
"other": "Gỡ ứng dụng?"
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
"pleaseWait": "请稍候",
|
"pleaseWait": "请稍候",
|
||||||
"updateAvailable": "更新可用",
|
"updateAvailable": "更新可用",
|
||||||
"notInstalled": "未安装",
|
"notInstalled": "未安装",
|
||||||
"pseudoVersion": "伪版本",
|
"pseudoVersion": "虚拟版本号",
|
||||||
"selectAll": "全选",
|
"selectAll": "全选",
|
||||||
"deselectX": "取消选择 {}",
|
"deselectX": "取消选择 {}",
|
||||||
"xWillBeRemovedButRemainInstalled": "“{}”将从 Obtainium 中删除,但仍安装在您的设备中。",
|
"xWillBeRemovedButRemainInstalled": "“{}”将从 Obtainium 中删除,但仍安装在您的设备中。",
|
||||||
@ -183,6 +183,9 @@
|
|||||||
"disableVersionDetection": "禁用版本检测",
|
"disableVersionDetection": "禁用版本检测",
|
||||||
"noVersionDetectionExplanation": "此选项应该仅用于无法进行版本检测的应用。",
|
"noVersionDetectionExplanation": "此选项应该仅用于无法进行版本检测的应用。",
|
||||||
"downloadingX": "正在下载“{}”",
|
"downloadingX": "正在下载“{}”",
|
||||||
|
"downloadX": "下载 {}",
|
||||||
|
"downloadedX": "下载 {}",
|
||||||
|
"releaseAsset": "释放资产",
|
||||||
"downloadNotifDescription": "提示应用的下载进度",
|
"downloadNotifDescription": "提示应用的下载进度",
|
||||||
"noAPKFound": "未找到 APK 文件",
|
"noAPKFound": "未找到 APK 文件",
|
||||||
"noVersionDetection": "禁用版本检测",
|
"noVersionDetection": "禁用版本检测",
|
||||||
@ -208,7 +211,7 @@
|
|||||||
"changes": "更新日志",
|
"changes": "更新日志",
|
||||||
"releaseDate": "发行日期",
|
"releaseDate": "发行日期",
|
||||||
"importFromURLsInFile": "从文件中的 URL 导入(如 OPML)",
|
"importFromURLsInFile": "从文件中的 URL 导入(如 OPML)",
|
||||||
"versionDetectionExplanation": "将版本字符串与操作系统检测到的版本进行协调",
|
"versionDetectionExplanation": "使发行版本号与应用定义的版本号一致",
|
||||||
"versionDetection": "版本检测",
|
"versionDetection": "版本检测",
|
||||||
"standardVersionDetection": "常规版本检测",
|
"standardVersionDetection": "常规版本检测",
|
||||||
"groupByCategory": "按类别分组显示",
|
"groupByCategory": "按类别分组显示",
|
||||||
@ -218,13 +221,13 @@
|
|||||||
"dontShowTrackOnlyWarnings": "忽略“仅追踪”模式警告",
|
"dontShowTrackOnlyWarnings": "忽略“仅追踪”模式警告",
|
||||||
"dontShowAPKOriginWarnings": "忽略 APK 文件来源警告",
|
"dontShowAPKOriginWarnings": "忽略 APK 文件来源警告",
|
||||||
"moveNonInstalledAppsToBottom": "将未安装应用置底",
|
"moveNonInstalledAppsToBottom": "将未安装应用置底",
|
||||||
"gitlabPATLabel": "GitLab 个人访问令牌(启用搜索功能并增强 APK 发现)",
|
"gitlabPATLabel": "GitLab 个人访问令牌",
|
||||||
"about": "相关文档",
|
"about": "相关文档",
|
||||||
"requiresCredentialsInSettings": "{}:此功能需要额外的凭据(在“设置”中添加)",
|
"requiresCredentialsInSettings": "{}:此功能需要额外的凭据(在“设置”中添加)",
|
||||||
"checkOnStart": "启动时进行一次检查",
|
"checkOnStart": "启动时进行一次检查",
|
||||||
"tryInferAppIdFromCode": "尝试从源代码推断应用 ID",
|
"tryInferAppIdFromCode": "尝试从源代码推断应用 ID",
|
||||||
"removeOnExternalUninstall": "自动删除列表中已卸载的应用",
|
"removeOnExternalUninstall": "自动删除列表中已卸载的应用",
|
||||||
"pickHighestVersionCode": "自动选择版本号最高的 APK 文件",
|
"pickHighestVersionCode": "自动选取内部版本号最高的 APK 文件",
|
||||||
"checkUpdateOnDetailPage": "打开应用详情页时进行检查",
|
"checkUpdateOnDetailPage": "打开应用详情页时进行检查",
|
||||||
"disablePageTransitions": "禁用页面过渡动画效果",
|
"disablePageTransitions": "禁用页面过渡动画效果",
|
||||||
"reversePageTransitions": "反转页面过渡动画效果",
|
"reversePageTransitions": "反转页面过渡动画效果",
|
||||||
@ -232,7 +235,6 @@
|
|||||||
"addInfoBelow": "在下方添加此凭据。",
|
"addInfoBelow": "在下方添加此凭据。",
|
||||||
"addInfoInSettings": "在“设置”中添加此凭据。",
|
"addInfoInSettings": "在“设置”中添加此凭据。",
|
||||||
"githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。",
|
"githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。",
|
||||||
"gitlabSourceNote": "未使用访问令牌时可能无法从 GitLab 获取 APK 文件。",
|
|
||||||
"sortByLastLinkSegment": "仅根据链接的末尾部分进行筛选",
|
"sortByLastLinkSegment": "仅根据链接的末尾部分进行筛选",
|
||||||
"filterReleaseNotesByRegEx": "筛选发行说明(正则表达式)",
|
"filterReleaseNotesByRegEx": "筛选发行说明(正则表达式)",
|
||||||
"customLinkFilterRegex": "筛选自定义来源的 APK 文件链接\n(正则表达式,默认匹配模式为“.apk$”)",
|
"customLinkFilterRegex": "筛选自定义来源的 APK 文件链接\n(正则表达式,默认匹配模式为“.apk$”)",
|
||||||
@ -249,7 +251,7 @@
|
|||||||
"intermediateLink": "中转链接",
|
"intermediateLink": "中转链接",
|
||||||
"exemptFromBackgroundUpdates": "禁用后台更新(如果已经全局启用)",
|
"exemptFromBackgroundUpdates": "禁用后台更新(如果已经全局启用)",
|
||||||
"bgUpdatesOnWiFiOnly": "未连接 Wi-Fi 时禁用后台更新",
|
"bgUpdatesOnWiFiOnly": "未连接 Wi-Fi 时禁用后台更新",
|
||||||
"autoSelectHighestVersionCode": "自动选择版本号最高的 APK 文件",
|
"autoSelectHighestVersionCode": "自动选择内部版本号最高的 APK 文件",
|
||||||
"versionExtractionRegEx": "版本号提取规则(正则表达式)",
|
"versionExtractionRegEx": "版本号提取规则(正则表达式)",
|
||||||
"matchGroupToUse": "引用的捕获组",
|
"matchGroupToUse": "引用的捕获组",
|
||||||
"highlightTouchTargets": "突出展示不明显的触摸区域",
|
"highlightTouchTargets": "突出展示不明显的触摸区域",
|
||||||
@ -286,20 +288,22 @@
|
|||||||
"shizukuBinderNotFound": "未发现兼容的 Shizuku 服务",
|
"shizukuBinderNotFound": "未发现兼容的 Shizuku 服务",
|
||||||
"useSystemFont": "使用系统字体",
|
"useSystemFont": "使用系统字体",
|
||||||
"systemFontError": "加载系统字体出错:{}",
|
"systemFontError": "加载系统字体出错:{}",
|
||||||
"useVersionCodeAsOSVersion": "使用应用程序版本代码作为操作系统检测到的版本",
|
"useVersionCodeAsOSVersion": "使用内部版本号代替应用定义的版本号",
|
||||||
"requestHeader": "请求标头",
|
"requestHeader": "请求标头",
|
||||||
"useLatestAssetDateAsReleaseDate": "使用最新资产上传作为发布日期",
|
"useLatestAssetDateAsReleaseDate": "使用最近文件上传时间作为发行日期",
|
||||||
"defaultPseudoVersioningMethod": "默认伪版本控制方法",
|
"defaultPseudoVersioningMethod": "默认虚拟版本方案",
|
||||||
"partialAPKHash": "部分 APK 哈希值",
|
"partialAPKHash": "APK 文件散列值片段",
|
||||||
"APKLinkHash": "APK 链接哈希",
|
"APKLinkHash": "APK 文件链接散列值",
|
||||||
"directAPKLink": "直接 APK 链接",
|
"directAPKLink": "APK 文件直链",
|
||||||
"pseudoVersionInUse": "伪版本正在使用",
|
"pseudoVersionInUse": "正在使用虚拟版本号",
|
||||||
"installed": "已安装",
|
"installed": "当前版本",
|
||||||
"latest": "最新的",
|
"latest": "最新版本",
|
||||||
"invertRegEx": "反转正则表达式",
|
"invertRegEx": "反转匹配",
|
||||||
"note": "备注",
|
"note": "备注",
|
||||||
"selfHostedNote": "{}\"下拉菜单可用于访问任何来源的自托管/自定义实例。",
|
"selfHostedNote": "可以通过“{}”下拉菜单来指向任意来源的自托管/自定义实例。",
|
||||||
"badDownload": "无法解析 APK(不兼容或部分下载)",
|
"badDownload": "无法解析 APK 文件(不兼容或文件不完整)",
|
||||||
|
"beforeNewInstallsShareToAppVerifier": "与 AppVerifier 共享新应用程序(如有)",
|
||||||
|
"appVerifierInstructionToast": "分享到 AppVerifier,准备就绪后返回此处。",
|
||||||
"removeAppQuestion": {
|
"removeAppQuestion": {
|
||||||
"one": "是否删除应用?",
|
"one": "是否删除应用?",
|
||||||
"other": "是否删除应用?"
|
"other": "是否删除应用?"
|
||||||
|
@ -271,17 +271,14 @@ class GitHub extends AppSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MapEntry<String, String>> getReleaseAPKUrls(dynamic release) =>
|
List<MapEntry<String, String>> getReleaseAssetUrls(dynamic release) =>
|
||||||
(release['assets'] as List<dynamic>?)
|
(release['assets'] as List<dynamic>?)?.map((e) {
|
||||||
?.map((e) {
|
|
||||||
return (e['name'] != null) &&
|
return (e['name'] != null) &&
|
||||||
((e['url'] ?? e['browser_download_url']) != null)
|
((e['url'] ?? e['browser_download_url']) != null)
|
||||||
? MapEntry(e['name'] as String,
|
? MapEntry(e['name'] as String,
|
||||||
(e['url'] ?? e['browser_download_url']) as String)
|
(e['url'] ?? e['browser_download_url']) as String)
|
||||||
: const MapEntry('', '');
|
: const MapEntry('', '');
|
||||||
})
|
}).toList() ??
|
||||||
.where((element) => element.key.toLowerCase().endsWith('.apk'))
|
|
||||||
.toList() ??
|
|
||||||
[];
|
[];
|
||||||
|
|
||||||
DateTime? getPublishDateFromRelease(dynamic rel) =>
|
DateTime? getPublishDateFromRelease(dynamic rel) =>
|
||||||
@ -344,12 +341,14 @@ class GitHub extends AppSource {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (latestRelease != null &&
|
if (latestRelease != null &&
|
||||||
|
(latestRelease['tag_name'] ?? latestRelease['name']) != null &&
|
||||||
releases.isNotEmpty &&
|
releases.isNotEmpty &&
|
||||||
latestRelease !=
|
latestRelease !=
|
||||||
(releases[releases.length - 1]['tag_name'] ??
|
(releases[releases.length - 1]['tag_name'] ??
|
||||||
releases[0]['name'])) {
|
releases[0]['name'])) {
|
||||||
var ind = releases.indexWhere((element) =>
|
var ind = releases.indexWhere((element) =>
|
||||||
latestRelease == (element['tag_name'] ?? element['name']));
|
(latestRelease['tag_name'] ?? latestRelease['name']) ==
|
||||||
|
(element['tag_name'] ?? element['name']));
|
||||||
if (ind >= 0) {
|
if (ind >= 0) {
|
||||||
releases.add(releases.removeAt(ind));
|
releases.add(releases.removeAt(ind));
|
||||||
}
|
}
|
||||||
@ -381,7 +380,11 @@ class GitHub extends AppSource {
|
|||||||
.hasMatch(((releases[i]['body'] as String?) ?? '').trim())) {
|
.hasMatch(((releases[i]['body'] as String?) ?? '').trim())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var apkUrls = getReleaseAPKUrls(releases[i]);
|
var allAssetUrls = getReleaseAssetUrls(releases[i]);
|
||||||
|
List<MapEntry<String, String>> apkUrls = allAssetUrls
|
||||||
|
.where((element) => element.key.toLowerCase().endsWith('.apk'))
|
||||||
|
.toList();
|
||||||
|
|
||||||
apkUrls = filterApks(apkUrls, additionalSettings['apkFilterRegEx'],
|
apkUrls = filterApks(apkUrls, additionalSettings['apkFilterRegEx'],
|
||||||
additionalSettings['invertAPKFilter']);
|
additionalSettings['invertAPKFilter']);
|
||||||
if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) {
|
if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) {
|
||||||
@ -389,12 +392,25 @@ class GitHub extends AppSource {
|
|||||||
}
|
}
|
||||||
targetRelease = releases[i];
|
targetRelease = releases[i];
|
||||||
targetRelease['apkUrls'] = apkUrls;
|
targetRelease['apkUrls'] = apkUrls;
|
||||||
|
targetRelease['version'] =
|
||||||
|
targetRelease['tag_name'] ?? targetRelease['name'];
|
||||||
|
if (targetRelease['tarball_url'] != null) {
|
||||||
|
allAssetUrls.add(MapEntry(
|
||||||
|
(targetRelease['version'] ?? 'source') + '.tar.gz',
|
||||||
|
targetRelease['tarball_url']));
|
||||||
|
}
|
||||||
|
if (targetRelease['zipball_url'] != null) {
|
||||||
|
allAssetUrls.add(MapEntry(
|
||||||
|
(targetRelease['version'] ?? 'source') + '.zip',
|
||||||
|
targetRelease['zipball_url']));
|
||||||
|
}
|
||||||
|
targetRelease['allAssetUrls'] = allAssetUrls;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (targetRelease == null) {
|
if (targetRelease == null) {
|
||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
String? version = targetRelease['tag_name'] ?? targetRelease['name'];
|
String? version = targetRelease['version'];
|
||||||
DateTime? releaseDate = getReleaseDateFromRelease(
|
DateTime? releaseDate = getReleaseDateFromRelease(
|
||||||
targetRelease, useLatestAssetDateAsReleaseDate);
|
targetRelease, useLatestAssetDateAsReleaseDate);
|
||||||
if (version == null) {
|
if (version == null) {
|
||||||
@ -406,7 +422,9 @@ class GitHub extends AppSource {
|
|||||||
targetRelease['apkUrls'] as List<MapEntry<String, String>>,
|
targetRelease['apkUrls'] as List<MapEntry<String, String>>,
|
||||||
getAppNames(standardUrl),
|
getAppNames(standardUrl),
|
||||||
releaseDate: releaseDate,
|
releaseDate: releaseDate,
|
||||||
changeLog: changeLog.isEmpty ? null : changeLog);
|
changeLog: changeLog.isEmpty ? null : changeLog,
|
||||||
|
allAssetUrls:
|
||||||
|
targetRelease['allAssetUrls'] as List<MapEntry<String, String>>);
|
||||||
} else {
|
} else {
|
||||||
if (onHttpErrorCode != null) {
|
if (onHttpErrorCode != null) {
|
||||||
onHttpErrorCode(res);
|
onHttpErrorCode(res);
|
||||||
|
@ -2,7 +2,6 @@ import 'dart:convert';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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/github.dart';
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
@ -73,14 +72,6 @@ class GitLab extends AppSource {
|
|||||||
return creds != null && creds.isNotEmpty ? creds : null;
|
return creds != null && creds.isNotEmpty ? creds : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String?> getSourceNote() async {
|
|
||||||
if ((await getPATIfAny({})) == null) {
|
|
||||||
return '${tr('gitlabSourceNote')} ${hostChanged ? tr('addInfoBelow') : tr('addInfoInSettings')}';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, List<String>>> search(String query,
|
Future<Map<String, List<String>>> search(String query,
|
||||||
{Map<String, dynamic> querySettings = const {}}) async {
|
{Map<String, dynamic> querySettings = const {}}) async {
|
||||||
@ -125,18 +116,23 @@ class GitLab extends AppSource {
|
|||||||
String standardUrl,
|
String standardUrl,
|
||||||
Map<String, dynamic> additionalSettings,
|
Map<String, dynamic> additionalSettings,
|
||||||
) async {
|
) async {
|
||||||
bool fallbackToOlderReleases =
|
// Prepare request params
|
||||||
additionalSettings['fallbackToOlderReleases'] == true;
|
|
||||||
String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {});
|
|
||||||
Iterable<APKDetails> apkDetailsList = [];
|
|
||||||
if (PAT != null) {
|
|
||||||
var names = GitHub().getAppNames(standardUrl);
|
var names = GitHub().getAppNames(standardUrl);
|
||||||
|
String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {});
|
||||||
|
String optionalAuth = (PAT != null) ? 'private_token=$PAT' : '';
|
||||||
|
|
||||||
|
bool trackOnly = additionalSettings['trackOnly'] == true;
|
||||||
|
|
||||||
|
// Request data from REST API
|
||||||
Response res = await sourceRequest(
|
Response res = await sourceRequest(
|
||||||
'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/releases?private_token=$PAT',
|
'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/${trackOnly ? 'repository/tags' : 'releases'}?$optionalAuth',
|
||||||
additionalSettings);
|
additionalSettings);
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode != 200) {
|
||||||
throw getObtainiumHttpError(res);
|
throw getObtainiumHttpError(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract .apk details from received data
|
||||||
|
Iterable<APKDetails> apkDetailsList = [];
|
||||||
var json = jsonDecode(res.body) as List<dynamic>;
|
var json = jsonDecode(res.body) as List<dynamic>;
|
||||||
apkDetailsList = json.map((e) {
|
apkDetailsList = json.map((e) {
|
||||||
var apkUrlsFromAssets = (e['assets']?['links'] as List<dynamic>? ?? [])
|
var apkUrlsFromAssets = (e['assets']?['links'] as List<dynamic>? ?? [])
|
||||||
@ -158,67 +154,42 @@ class GitLab extends AppSource {
|
|||||||
var apkUrlsSet = apkUrlsFromAssets.toSet();
|
var apkUrlsSet = apkUrlsFromAssets.toSet();
|
||||||
apkUrlsSet.addAll(uploadedAPKsFromDescription);
|
apkUrlsSet.addAll(uploadedAPKsFromDescription);
|
||||||
var releaseDateString = e['released_at'] ?? e['created_at'];
|
var releaseDateString = e['released_at'] ?? e['created_at'];
|
||||||
DateTime? releaseDate = releaseDateString != null
|
DateTime? releaseDate =
|
||||||
? DateTime.parse(releaseDateString)
|
releaseDateString != null ? DateTime.parse(releaseDateString) : null;
|
||||||
: null;
|
|
||||||
return APKDetails(
|
return APKDetails(
|
||||||
e['tag_name'] ?? e['name'],
|
e['tag_name'] ?? e['name'],
|
||||||
getApkUrlsFromUrls(apkUrlsSet.toList()),
|
getApkUrlsFromUrls(apkUrlsSet.toList()),
|
||||||
GitHub().getAppNames(standardUrl),
|
GitHub().getAppNames(standardUrl),
|
||||||
releaseDate: releaseDate);
|
releaseDate: releaseDate);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
Response res = await sourceRequest(
|
|
||||||
'$standardUrl/-/tags?format=atom', additionalSettings);
|
|
||||||
if (res.statusCode != 200) {
|
|
||||||
throw getObtainiumHttpError(res);
|
|
||||||
}
|
|
||||||
var standardUri = Uri.parse(standardUrl);
|
|
||||||
var parsedHtml = parse(res.body);
|
|
||||||
apkDetailsList = parsedHtml.querySelectorAll('entry').map((entry) {
|
|
||||||
var entryContent = parse(
|
|
||||||
parseFragment(entry.querySelector('content')!.innerHtml).text);
|
|
||||||
var apkUrls = [
|
|
||||||
...getLinksFromParsedHTML(
|
|
||||||
entryContent,
|
|
||||||
RegExp(
|
|
||||||
'^${standardUri.path.replaceAllMapped(RegExp(r'[.*+?^${}()|[\]\\]'), (x) {
|
|
||||||
return '\\${x[0]}';
|
|
||||||
})}/uploads/[^/]+/[^/]+\\.apk\$',
|
|
||||||
caseSensitive: false),
|
|
||||||
standardUri.origin),
|
|
||||||
// GitLab releases may contain links to externally hosted APKs
|
|
||||||
...getLinksFromParsedHTML(entryContent,
|
|
||||||
RegExp('/[^/]+\\.apk\$', caseSensitive: false), '')
|
|
||||||
.where((element) => Uri.parse(element).host != '')
|
|
||||||
];
|
|
||||||
var entryId = entry.querySelector('id')?.innerHtml;
|
|
||||||
var version =
|
|
||||||
entryId == null ? null : Uri.parse(entryId).pathSegments.last;
|
|
||||||
var releaseDateString = entry.querySelector('updated')?.innerHtml;
|
|
||||||
DateTime? releaseDate = releaseDateString != null
|
|
||||||
? DateTime.parse(releaseDateString)
|
|
||||||
: null;
|
|
||||||
if (version == null) {
|
|
||||||
throw NoVersionError();
|
|
||||||
}
|
|
||||||
return APKDetails(version, getApkUrlsFromUrls(apkUrls),
|
|
||||||
GitHub().getAppNames(standardUrl),
|
|
||||||
releaseDate: releaseDate);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (apkDetailsList.isEmpty) {
|
if (apkDetailsList.isEmpty) {
|
||||||
throw NoReleasesError(note: tr('gitlabSourceNote'));
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
if (fallbackToOlderReleases) {
|
var finalResult = apkDetailsList.first;
|
||||||
if (additionalSettings['trackOnly'] != true) {
|
|
||||||
|
// Fallback procedure
|
||||||
|
bool fallbackToOlderReleases =
|
||||||
|
additionalSettings['fallbackToOlderReleases'] == true;
|
||||||
|
if (finalResult.apkUrls.isEmpty && fallbackToOlderReleases && !trackOnly) {
|
||||||
apkDetailsList =
|
apkDetailsList =
|
||||||
apkDetailsList.where((e) => e.apkUrls.isNotEmpty).toList();
|
apkDetailsList.where((e) => e.apkUrls.isNotEmpty).toList();
|
||||||
|
finalResult = apkDetailsList.first;
|
||||||
}
|
}
|
||||||
if (apkDetailsList.isEmpty) {
|
|
||||||
throw NoReleasesError(note: tr('gitlabSourceNote'));
|
if (finalResult.apkUrls.isEmpty && !trackOnly) {
|
||||||
|
throw NoAPKError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
finalResult.apkUrls = finalResult.apkUrls.map((apkUrl) {
|
||||||
|
if (RegExp('^$standardUrl/-/jobs/[0-9]+/artifacts/file/[^/]+\$')
|
||||||
|
.hasMatch(apkUrl.value)) {
|
||||||
|
return MapEntry(
|
||||||
|
apkUrl.key, apkUrl.value.replaceFirst('/file/', '/raw/'));
|
||||||
|
} else {
|
||||||
|
return apkUrl;
|
||||||
}
|
}
|
||||||
return apkDetailsList.first;
|
}).toList();
|
||||||
|
|
||||||
|
return finalResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,8 +245,8 @@ class _GeneratedFormState extends State<GeneratedForm> {
|
|||||||
void someValueChanged({bool isBuilding = false, bool forceInvalid = false}) {
|
void someValueChanged({bool isBuilding = false, bool forceInvalid = false}) {
|
||||||
Map<String, dynamic> returnValues = values;
|
Map<String, dynamic> returnValues = values;
|
||||||
var valid = true;
|
var valid = true;
|
||||||
for (int r = 0; r < widget.items.length; r++) {
|
for (int r = 0; r < formInputs.length; r++) {
|
||||||
for (int i = 0; i < widget.items[r].length; i++) {
|
for (int i = 0; i < formInputs[r].length; i++) {
|
||||||
if (formInputs[r][i] is TextFormField) {
|
if (formInputs[r][i] is TextFormField) {
|
||||||
valid = valid && validateTextField(formInputs[r][i] as TextFormField);
|
valid = valid && validateTextField(formInputs[r][i] as TextFormField);
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ List<MapEntry<Locale, String>> supportedLocales = const [
|
|||||||
MapEntry(Locale('nl'), 'Nederlands'),
|
MapEntry(Locale('nl'), 'Nederlands'),
|
||||||
MapEntry(Locale('vi'), 'Tiếng Việt'),
|
MapEntry(Locale('vi'), 'Tiếng Việt'),
|
||||||
MapEntry(Locale('tr'), 'Türkçe'),
|
MapEntry(Locale('tr'), 'Türkçe'),
|
||||||
|
MapEntry(Locale('uk'), 'Українська'),
|
||||||
];
|
];
|
||||||
const fallbackLocale = Locale('en');
|
const fallbackLocale = Locale('en');
|
||||||
const localeDir = 'assets/translations';
|
const localeDir = 'assets/translations';
|
||||||
|
@ -155,7 +155,8 @@ class AddAppPageState extends State<AddAppPage> {
|
|||||||
// 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) {
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
var apkUrl = await appsProvider.confirmApkUrl(app, context);
|
var apkUrl =
|
||||||
|
await appsProvider.confirmAppFileUrl(app, context, false);
|
||||||
if (apkUrl == null) {
|
if (apkUrl == null) {
|
||||||
throw ObtainiumError(tr('cancelled'));
|
throw ObtainiumError(tr('cancelled'));
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:obtainium/components/generated_form_modal.dart';
|
import 'package:obtainium/components/generated_form_modal.dart';
|
||||||
import 'package:obtainium/custom_errors.dart';
|
import 'package:obtainium/custom_errors.dart';
|
||||||
import 'package:obtainium/main.dart';
|
import 'package:obtainium/main.dart';
|
||||||
|
import 'package:obtainium/pages/apps.dart';
|
||||||
import 'package:obtainium/pages/settings.dart';
|
import 'package:obtainium/pages/settings.dart';
|
||||||
import 'package:obtainium/providers/apps_provider.dart';
|
import 'package:obtainium/providers/apps_provider.dart';
|
||||||
import 'package:obtainium/providers/settings_provider.dart';
|
import 'package:obtainium/providers/settings_provider.dart';
|
||||||
@ -108,6 +109,7 @@ class _AppPageState extends State<AppPage> {
|
|||||||
infoLines =
|
infoLines =
|
||||||
'$infoLines\n${app?.app.apkUrls.length == 1 ? app?.app.apkUrls[0].key : plural('apk', app?.app.apkUrls.length ?? 0)}';
|
'$infoLines\n${app?.app.apkUrls.length == 1 ? app?.app.apkUrls[0].key : plural('apk', app?.app.apkUrls.length ?? 0)}';
|
||||||
}
|
}
|
||||||
|
var changeLogFn = app != null ? getChangeLogFn(context, app.app) : null;
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
@ -125,13 +127,26 @@ class _AppPageState extends State<AppPage> {
|
|||||||
.textTheme
|
.textTheme
|
||||||
.bodyLarge!
|
.bodyLarge!
|
||||||
.copyWith(fontWeight: FontWeight.bold)),
|
.copyWith(fontWeight: FontWeight.bold)),
|
||||||
|
changeLogFn != null || app?.app.releaseDate != null
|
||||||
|
? GestureDetector(
|
||||||
|
onTap: changeLogFn,
|
||||||
|
child: Text(
|
||||||
app?.app.releaseDate == null
|
app?.app.releaseDate == null
|
||||||
? const SizedBox.shrink()
|
? tr('changes')
|
||||||
: Text(
|
: app!.app.releaseDate.toString(),
|
||||||
app!.app.releaseDate.toString(),
|
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: Theme.of(context).textTheme.labelSmall,
|
style:
|
||||||
|
Theme.of(context).textTheme.labelSmall!.copyWith(
|
||||||
|
decoration: changeLogFn != null
|
||||||
|
? TextDecoration.underline
|
||||||
|
: null,
|
||||||
|
fontStyle: changeLogFn != null
|
||||||
|
? FontStyle.italic
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
@ -143,6 +158,29 @@ class _AppPageState extends State<AppPage> {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 12),
|
style: const TextStyle(fontStyle: FontStyle.italic, fontSize: 12),
|
||||||
),
|
),
|
||||||
|
if (app?.app.apkUrls.isNotEmpty == true ||
|
||||||
|
app?.app.otherAssetUrls.isNotEmpty == true)
|
||||||
|
GestureDetector(
|
||||||
|
onTap: app?.app == null || updating
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
try {
|
||||||
|
await appsProvider
|
||||||
|
.downloadAppAssets([app!.app.id], context);
|
||||||
|
} catch (e) {
|
||||||
|
showError(e, context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
tr('downloadX', args: [tr('releaseAsset').toLowerCase()]),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: Theme.of(context).textTheme.labelSmall!.copyWith(
|
||||||
|
decoration:
|
||||||
|
changeLogFn != null ? TextDecoration.underline : null,
|
||||||
|
fontStyle: changeLogFn != null ? FontStyle.italic : null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 48,
|
height: 48,
|
||||||
),
|
),
|
||||||
@ -361,6 +399,9 @@ class _AppPageState extends State<AppPage> {
|
|||||||
!areDownloadsRunning
|
!areDownloadsRunning
|
||||||
? () async {
|
? () async {
|
||||||
try {
|
try {
|
||||||
|
var successMessage = app?.app.installedVersion == null
|
||||||
|
? tr('installed')
|
||||||
|
: tr('appsUpdated');
|
||||||
HapticFeedback.heavyImpact();
|
HapticFeedback.heavyImpact();
|
||||||
var res = await appsProvider.downloadAndInstallLatestApps(
|
var res = await appsProvider.downloadAndInstallLatestApps(
|
||||||
app?.app.id != null ? [app!.app.id] : [],
|
app?.app.id != null ? [app!.app.id] : [],
|
||||||
@ -368,7 +409,7 @@ class _AppPageState extends State<AppPage> {
|
|||||||
);
|
);
|
||||||
if (res.isNotEmpty && !trackOnly) {
|
if (res.isNotEmpty && !trackOnly) {
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
showMessage(tr('appsUpdated'), context);
|
showMessage(successMessage, context);
|
||||||
}
|
}
|
||||||
if (res.isNotEmpty && mounted) {
|
if (res.isNotEmpty && mounted) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
@ -26,6 +26,92 @@ class AppsPage extends StatefulWidget {
|
|||||||
State<AppsPage> createState() => AppsPageState();
|
State<AppsPage> createState() => AppsPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showChangeLogDialog(BuildContext context, App app, String? changesUrl,
|
||||||
|
AppSource appSource, String changeLog) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return GeneratedFormModal(
|
||||||
|
title: tr('changes'),
|
||||||
|
items: const [],
|
||||||
|
message: app.latestVersion,
|
||||||
|
additionalWidgets: [
|
||||||
|
changesUrl != null
|
||||||
|
? GestureDetector(
|
||||||
|
child: Text(
|
||||||
|
changesUrl,
|
||||||
|
style: const TextStyle(
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
fontStyle: FontStyle.italic),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
launchUrlString(changesUrl,
|
||||||
|
mode: LaunchMode.externalApplication);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
|
changesUrl != null
|
||||||
|
? const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
|
appSource.changeLogIfAnyIsMarkDown
|
||||||
|
? SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
height: MediaQuery.of(context).size.height - 350,
|
||||||
|
child: Markdown(
|
||||||
|
data: changeLog,
|
||||||
|
onTapLink: (text, href, title) {
|
||||||
|
if (href != null) {
|
||||||
|
launchUrlString(
|
||||||
|
href.startsWith('http://') ||
|
||||||
|
href.startsWith('https://')
|
||||||
|
? href
|
||||||
|
: '${Uri.parse(app.url).origin}/$href',
|
||||||
|
mode: LaunchMode.externalApplication);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
extensionSet: md.ExtensionSet(
|
||||||
|
md.ExtensionSet.gitHubFlavored.blockSyntaxes,
|
||||||
|
[
|
||||||
|
md.EmojiSyntax(),
|
||||||
|
...md.ExtensionSet.gitHubFlavored.inlineSyntaxes
|
||||||
|
],
|
||||||
|
),
|
||||||
|
))
|
||||||
|
: Text(changeLog),
|
||||||
|
],
|
||||||
|
singleNullReturnButton: tr('ok'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getChangeLogFn(BuildContext context, App app) {
|
||||||
|
AppSource appSource =
|
||||||
|
SourceProvider().getSource(app.url, overrideSource: app.overrideSource);
|
||||||
|
String? changesUrl = appSource.changeLogPageFromStandardUrl(app.url);
|
||||||
|
String? changeLog = 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)
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
if (changeLog != null) {
|
||||||
|
showChangeLogDialog(context, app, changesUrl, appSource, changeLog);
|
||||||
|
} else {
|
||||||
|
launchUrlString(changesUrl!, mode: LaunchMode.externalApplication);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
class AppsPageState extends State<AppsPage> {
|
class AppsPageState extends State<AppsPage> {
|
||||||
AppsFilter filter = AppsFilter();
|
AppsFilter filter = AppsFilter();
|
||||||
final AppsFilter neutralFilter = AppsFilter();
|
final AppsFilter neutralFilter = AppsFilter();
|
||||||
@ -262,66 +348,6 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
.where((a) => selectedAppIds.contains(a.id))
|
.where((a) => selectedAppIds.contains(a.id))
|
||||||
.toSet();
|
.toSet();
|
||||||
|
|
||||||
showChangeLogDialog(
|
|
||||||
String? changesUrl, AppSource appSource, String changeLog, int index) {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return GeneratedFormModal(
|
|
||||||
title: tr('changes'),
|
|
||||||
items: const [],
|
|
||||||
message: listedApps[index].app.latestVersion,
|
|
||||||
additionalWidgets: [
|
|
||||||
changesUrl != null
|
|
||||||
? GestureDetector(
|
|
||||||
child: Text(
|
|
||||||
changesUrl,
|
|
||||||
style: const TextStyle(
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
fontStyle: FontStyle.italic),
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
launchUrlString(changesUrl,
|
|
||||||
mode: LaunchMode.externalApplication);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
: const SizedBox.shrink(),
|
|
||||||
changesUrl != null
|
|
||||||
? const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
)
|
|
||||||
: const SizedBox.shrink(),
|
|
||||||
appSource.changeLogIfAnyIsMarkDown
|
|
||||||
? SizedBox(
|
|
||||||
width: MediaQuery.of(context).size.width,
|
|
||||||
height: MediaQuery.of(context).size.height - 350,
|
|
||||||
child: Markdown(
|
|
||||||
data: changeLog,
|
|
||||||
onTapLink: (text, href, title) {
|
|
||||||
if (href != null) {
|
|
||||||
launchUrlString(
|
|
||||||
href.startsWith('http://') ||
|
|
||||||
href.startsWith('https://')
|
|
||||||
? href
|
|
||||||
: '${Uri.parse(listedApps[index].app.url).origin}/$href',
|
|
||||||
mode: LaunchMode.externalApplication);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
extensionSet: md.ExtensionSet(
|
|
||||||
md.ExtensionSet.gitHubFlavored.blockSyntaxes,
|
|
||||||
[
|
|
||||||
md.EmojiSyntax(),
|
|
||||||
...md.ExtensionSet.gitHubFlavored.inlineSyntaxes
|
|
||||||
],
|
|
||||||
),
|
|
||||||
))
|
|
||||||
: Text(changeLog),
|
|
||||||
],
|
|
||||||
singleNullReturnButton: tr('ok'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getLoadingWidgets() {
|
getLoadingWidgets() {
|
||||||
return [
|
return [
|
||||||
if (listedApps.isEmpty)
|
if (listedApps.isEmpty)
|
||||||
@ -351,35 +377,6 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
getChangeLogFn(int appIndex) {
|
|
||||||
AppSource appSource = SourceProvider().getSource(
|
|
||||||
listedApps[appIndex].app.url,
|
|
||||||
overrideSource: listedApps[appIndex].app.overrideSource);
|
|
||||||
String? changesUrl =
|
|
||||||
appSource.changeLogPageFromStandardUrl(listedApps[appIndex].app.url);
|
|
||||||
String? changeLog = listedApps[appIndex].app.changeLog;
|
|
||||||
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)
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
if (changeLog != null) {
|
|
||||||
showChangeLogDialog(changesUrl, appSource, changeLog, appIndex);
|
|
||||||
} else {
|
|
||||||
launchUrlString(changesUrl!,
|
|
||||||
mode: LaunchMode.externalApplication);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
getUpdateButton(int appIndex) {
|
getUpdateButton(int appIndex) {
|
||||||
return IconButton(
|
return IconButton(
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
@ -444,7 +441,7 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSingleAppHorizTile(int index) {
|
getSingleAppHorizTile(int index) {
|
||||||
var showChangesFn = getChangeLogFn(index);
|
var showChangesFn = getChangeLogFn(context, listedApps[index].app);
|
||||||
var hasUpdate = listedApps[index].app.installedVersion != null &&
|
var hasUpdate = listedApps[index].app.installedVersion != null &&
|
||||||
listedApps[index].app.installedVersion !=
|
listedApps[index].app.installedVersion !=
|
||||||
listedApps[index].app.latestVersion;
|
listedApps[index].app.latestVersion;
|
||||||
@ -857,29 +854,18 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
scrollable: true,
|
scrollable: true,
|
||||||
content: Padding(
|
content: Padding(
|
||||||
padding: const EdgeInsets.only(top: 6),
|
padding: const EdgeInsets.only(top: 6),
|
||||||
child: Row(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
TextButton(
|
||||||
onPressed: appsProvider.areDownloadsRunning()
|
|
||||||
? null
|
|
||||||
: showMassMarkDialog,
|
|
||||||
tooltip: tr('markSelectedAppsUpdated'),
|
|
||||||
icon: const Icon(Icons.done)),
|
|
||||||
IconButton(
|
|
||||||
onPressed: pinSelectedApps,
|
onPressed: pinSelectedApps,
|
||||||
tooltip: selectedApps
|
child: Text(selectedApps
|
||||||
.where((element) => element.pinned)
|
.where((element) => element.pinned)
|
||||||
.isEmpty
|
.isEmpty
|
||||||
? tr('pinToTop')
|
? tr('pinToTop')
|
||||||
: tr('unpinFromTop'),
|
: tr('unpinFromTop'))),
|
||||||
icon: Icon(selectedApps
|
const Divider(),
|
||||||
.where((element) => element.pinned)
|
TextButton(
|
||||||
.isEmpty
|
|
||||||
? Icons.bookmark_outline_rounded
|
|
||||||
: Icons.bookmark_remove_outlined),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
String urls = '';
|
String urls = '';
|
||||||
for (var a in selectedApps) {
|
for (var a in selectedApps) {
|
||||||
@ -890,10 +876,9 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
subject: 'Obtainium - ${tr('appsString')}');
|
subject: 'Obtainium - ${tr('appsString')}');
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
tooltip: tr('shareSelectedAppURLs'),
|
child: Text(tr('shareSelectedAppURLs'))),
|
||||||
icon: const Icon(Icons.share_rounded),
|
const Divider(),
|
||||||
),
|
TextButton(
|
||||||
IconButton(
|
|
||||||
onPressed: selectedAppIds.isEmpty
|
onPressed: selectedAppIds.isEmpty
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
@ -915,11 +900,32 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
urls +=
|
urls +=
|
||||||
'</ul>\n\n<p><a href="$obtainiumUrl">${tr('about')}</a></p>';
|
'</ul>\n\n<p><a href="$obtainiumUrl">${tr('about')}</a></p>';
|
||||||
Share.share(urls,
|
Share.share(urls,
|
||||||
subject: 'Obtainium - ${tr('appsString')}');
|
subject:
|
||||||
|
'Obtainium - ${tr('appsString')}');
|
||||||
},
|
},
|
||||||
tooltip: tr('shareAppConfigLinks'),
|
child: Text(tr('shareAppConfigLinks'))),
|
||||||
icon: const Icon(Icons.ios_share),
|
const Divider(),
|
||||||
),
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
appsProvider
|
||||||
|
.downloadAppAssets(
|
||||||
|
selectedApps.map((e) => e.id).toList(),
|
||||||
|
globalNavigatorKey.currentContext ??
|
||||||
|
context)
|
||||||
|
.catchError((e) => showError(
|
||||||
|
e,
|
||||||
|
globalNavigatorKey.currentContext ??
|
||||||
|
context));
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Text(tr('downloadX',
|
||||||
|
args: [tr('releaseAsset').toLowerCase()]))),
|
||||||
|
const Divider(),
|
||||||
|
TextButton(
|
||||||
|
onPressed: appsProvider.areDownloadsRunning()
|
||||||
|
? null
|
||||||
|
: showMassMarkDialog,
|
||||||
|
child: Text(tr('markSelectedAppsUpdated'))),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -351,6 +351,22 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
height16,
|
height16,
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child:
|
||||||
|
Text(tr('removeOnExternalUninstall'))),
|
||||||
|
Switch(
|
||||||
|
value: settingsProvider
|
||||||
|
.removeOnExternalUninstall,
|
||||||
|
onChanged: (value) {
|
||||||
|
settingsProvider
|
||||||
|
.removeOnExternalUninstall = value;
|
||||||
|
})
|
||||||
|
],
|
||||||
|
),
|
||||||
|
height16,
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
@ -363,6 +379,43 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
})
|
})
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
height16,
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(tr(
|
||||||
|
'beforeNewInstallsShareToAppVerifier')),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
launchUrlString(
|
||||||
|
'https://github.com/soupslurpr/AppVerifier',
|
||||||
|
mode: LaunchMode
|
||||||
|
.externalApplication);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
tr('about'),
|
||||||
|
style: const TextStyle(
|
||||||
|
decoration:
|
||||||
|
TextDecoration.underline,
|
||||||
|
fontSize: 12),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
Switch(
|
||||||
|
value: settingsProvider
|
||||||
|
.beforeNewInstallsShareToAppVerifier,
|
||||||
|
onChanged: (value) {
|
||||||
|
settingsProvider
|
||||||
|
.beforeNewInstallsShareToAppVerifier =
|
||||||
|
value;
|
||||||
|
})
|
||||||
|
],
|
||||||
|
),
|
||||||
installMethodDropdown,
|
installMethodDropdown,
|
||||||
height32,
|
height32,
|
||||||
Text(
|
Text(
|
||||||
@ -474,22 +527,6 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
height16,
|
height16,
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
child:
|
|
||||||
Text(tr('removeOnExternalUninstall'))),
|
|
||||||
Switch(
|
|
||||||
value: settingsProvider
|
|
||||||
.removeOnExternalUninstall,
|
|
||||||
onChanged: (value) {
|
|
||||||
settingsProvider
|
|
||||||
.removeOnExternalUninstall = value;
|
|
||||||
})
|
|
||||||
],
|
|
||||||
),
|
|
||||||
height16,
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
@ -5,6 +5,7 @@ import 'dart:async';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
|
|
||||||
@ -31,6 +32,7 @@ import 'package:obtainium/providers/source_provider.dart';
|
|||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
import 'package:android_intent_plus/android_intent.dart';
|
import 'package:android_intent_plus/android_intent.dart';
|
||||||
import 'package:flutter_archive/flutter_archive.dart';
|
import 'package:flutter_archive/flutter_archive.dart';
|
||||||
|
import 'package:share_plus/share_plus.dart';
|
||||||
import 'package:shared_storage/shared_storage.dart' as saf;
|
import 'package:shared_storage/shared_storage.dart' as saf;
|
||||||
import 'native_provider.dart';
|
import 'native_provider.dart';
|
||||||
|
|
||||||
@ -202,14 +204,18 @@ Future<String> checkPartialDownloadHash(String url, int bytesToGrab,
|
|||||||
Future<File> downloadFile(
|
Future<File> downloadFile(
|
||||||
String url, String fileNameNoExt, Function? onProgress, String destDir,
|
String url, String fileNameNoExt, Function? onProgress, String destDir,
|
||||||
{bool useExisting = true, Map<String, String>? headers}) async {
|
{bool useExisting = true, Map<String, String>? headers}) async {
|
||||||
|
// Send the initial request but cancel it as soon as you have the headers
|
||||||
|
var reqHeaders = headers ?? {};
|
||||||
var req = Request('GET', Uri.parse(url));
|
var req = Request('GET', Uri.parse(url));
|
||||||
if (headers != null) {
|
req.headers.addAll(reqHeaders);
|
||||||
req.headers.addAll(headers);
|
|
||||||
}
|
|
||||||
var client = http.Client();
|
var client = http.Client();
|
||||||
StreamedResponse response = await client.send(req);
|
StreamedResponse response = await client.send(req);
|
||||||
String ext =
|
var resHeaders = response.headers;
|
||||||
response.headers['content-disposition']?.split('.').last ?? 'apk';
|
|
||||||
|
// Use the headers to decide what the file extension is, and
|
||||||
|
// whether it supports partial downloads (range request), and
|
||||||
|
// what the total size of the file is (if provided)
|
||||||
|
String ext = resHeaders['content-disposition']?.split('.').last ?? 'apk';
|
||||||
if (ext.endsWith('"') || ext.endsWith("other")) {
|
if (ext.endsWith('"') || ext.endsWith("other")) {
|
||||||
ext = ext.substring(0, ext.length - 1);
|
ext = ext.substring(0, ext.length - 1);
|
||||||
}
|
}
|
||||||
@ -217,41 +223,108 @@ Future<File> downloadFile(
|
|||||||
ext = 'apk';
|
ext = 'apk';
|
||||||
}
|
}
|
||||||
File downloadedFile = File('$destDir/$fileNameNoExt.$ext');
|
File downloadedFile = File('$destDir/$fileNameNoExt.$ext');
|
||||||
if (!(downloadedFile.existsSync() && useExisting)) {
|
|
||||||
|
bool rangeFeatureEnabled = false;
|
||||||
|
if (resHeaders['accept-ranges']?.isNotEmpty == true) {
|
||||||
|
rangeFeatureEnabled =
|
||||||
|
resHeaders['accept-ranges']?.trim().toLowerCase() == 'bytes';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If you have an existing file that is usable,
|
||||||
|
// decide whether you can use it (either return full or resume partial)
|
||||||
|
var fullContentLength = response.contentLength;
|
||||||
|
if (useExisting && downloadedFile.existsSync()) {
|
||||||
|
var length = downloadedFile.lengthSync();
|
||||||
|
if (fullContentLength == null) {
|
||||||
|
// Assume full
|
||||||
|
client.close();
|
||||||
|
return downloadedFile;
|
||||||
|
} else {
|
||||||
|
// Check if resume needed/possible
|
||||||
|
if (length == fullContentLength) {
|
||||||
|
client.close();
|
||||||
|
return downloadedFile;
|
||||||
|
}
|
||||||
|
if (length > fullContentLength) {
|
||||||
|
useExisting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download to a '.temp' file (to distinguish btn. complete/incomplete files)
|
||||||
File tempDownloadedFile = File('${downloadedFile.path}.part');
|
File tempDownloadedFile = File('${downloadedFile.path}.part');
|
||||||
if (tempDownloadedFile.existsSync()) {
|
|
||||||
|
// If the range feature is not available (or you need to start a ranged req from 0),
|
||||||
|
// complete the already-started request, else cancel it and start a ranged request,
|
||||||
|
// and open the file for writing in the appropriate mode
|
||||||
|
var targetFileLength = useExisting && tempDownloadedFile.existsSync()
|
||||||
|
? tempDownloadedFile.lengthSync()
|
||||||
|
: null;
|
||||||
|
int rangeStart = targetFileLength ?? 0;
|
||||||
|
IOSink? sink;
|
||||||
|
if (rangeFeatureEnabled && fullContentLength != null && rangeStart > 0) {
|
||||||
|
client.close();
|
||||||
|
client = http.Client();
|
||||||
|
req = Request('GET', Uri.parse(url));
|
||||||
|
req.headers.addAll(reqHeaders);
|
||||||
|
req.headers.addAll({'range': 'bytes=$rangeStart-${fullContentLength - 1}'});
|
||||||
|
response = await client.send(req);
|
||||||
|
sink = tempDownloadedFile.openWrite(mode: FileMode.writeOnlyAppend);
|
||||||
|
} else if (tempDownloadedFile.existsSync()) {
|
||||||
tempDownloadedFile.deleteSync(recursive: true);
|
tempDownloadedFile.deleteSync(recursive: true);
|
||||||
}
|
}
|
||||||
var length = response.contentLength;
|
sink ??= tempDownloadedFile.openWrite(mode: FileMode.writeOnly);
|
||||||
|
|
||||||
|
// Perform the download
|
||||||
var received = 0;
|
var received = 0;
|
||||||
double? progress;
|
double? progress;
|
||||||
var sink = tempDownloadedFile.openWrite();
|
if (rangeStart > 0 && fullContentLength != null) {
|
||||||
|
received = rangeStart;
|
||||||
|
}
|
||||||
await response.stream.map((s) {
|
await response.stream.map((s) {
|
||||||
received += s.length;
|
received += s.length;
|
||||||
progress = (length != null ? received / length * 100 : 30);
|
progress =
|
||||||
|
(fullContentLength != null ? (received / fullContentLength) * 100 : 30);
|
||||||
if (onProgress != null) {
|
if (onProgress != null) {
|
||||||
onProgress(progress);
|
onProgress(progress);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}).pipe(sink);
|
}).pipe(sink);
|
||||||
await sink.close();
|
await sink.close();
|
||||||
|
bool likelyCorruptFile = (progress ?? 0) > 101;
|
||||||
progress = null;
|
progress = null;
|
||||||
if (onProgress != null) {
|
if (onProgress != null) {
|
||||||
onProgress(progress);
|
onProgress(progress);
|
||||||
}
|
}
|
||||||
if (response.statusCode != 200) {
|
if (response.statusCode < 200 ||
|
||||||
|
response.statusCode > 299 ||
|
||||||
|
likelyCorruptFile) {
|
||||||
tempDownloadedFile.deleteSync(recursive: true);
|
tempDownloadedFile.deleteSync(recursive: true);
|
||||||
throw response.reasonPhrase ?? tr('unexpectedError');
|
throw response.reasonPhrase ?? tr('unexpectedError');
|
||||||
}
|
}
|
||||||
if (tempDownloadedFile.existsSync()) {
|
if (tempDownloadedFile.existsSync()) {
|
||||||
tempDownloadedFile.renameSync(downloadedFile.path);
|
tempDownloadedFile.renameSync(downloadedFile.path);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
client.close();
|
client.close();
|
||||||
}
|
|
||||||
return downloadedFile;
|
return downloadedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Map<String, String>> getHeaders(String url,
|
||||||
|
{Map<String, String>? headers}) async {
|
||||||
|
var req = http.Request('GET', Uri.parse(url));
|
||||||
|
if (headers != null) {
|
||||||
|
req.headers.addAll(headers);
|
||||||
|
}
|
||||||
|
var client = http.Client();
|
||||||
|
var response = await client.send(req);
|
||||||
|
if (response.statusCode < 200 || response.statusCode > 299) {
|
||||||
|
throw ObtainiumError(response.reasonPhrase ?? tr('unexpectedError'));
|
||||||
|
}
|
||||||
|
var returnHeaders = response.headers;
|
||||||
|
client.close();
|
||||||
|
return returnHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
Future<PackageInfo?> getInstalledInfo(String? packageName,
|
Future<PackageInfo?> getInstalledInfo(String? packageName,
|
||||||
{bool printErr = true}) async {
|
{bool printErr = true}) async {
|
||||||
if (packageName != null) {
|
if (packageName != null) {
|
||||||
@ -287,7 +360,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
foregroundStream = FGBGEvents.stream.asBroadcastStream();
|
foregroundStream = FGBGEvents.stream.asBroadcastStream();
|
||||||
foregroundSubscription = foregroundStream?.listen((event) async {
|
foregroundSubscription = foregroundStream?.listen((event) async {
|
||||||
isForeground = event == FGBGType.foreground;
|
isForeground = event == FGBGType.foreground;
|
||||||
if (isForeground) await loadApps();
|
if (isForeground) loadApps();
|
||||||
});
|
});
|
||||||
() async {
|
() async {
|
||||||
await settingsProvider.initializeSettings();
|
await settingsProvider.initializeSettings();
|
||||||
@ -493,13 +566,14 @@ class AppsProvider with ChangeNotifier {
|
|||||||
zipFile: File(filePath), destinationDir: Directory(destinationPath));
|
zipFile: File(filePath), destinationDir: Directory(destinationPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> installXApkDir(DownloadedXApkDir dir,
|
Future<bool> installXApkDir(
|
||||||
|
DownloadedXApkDir dir, BuildContext? firstTimeWithContext,
|
||||||
{bool needsBGWorkaround = false}) async {
|
{bool needsBGWorkaround = false}) async {
|
||||||
// We don't know which APKs in an XAPK are supported by the user's device
|
// We don't know which APKs in an XAPK are supported by the user's device
|
||||||
// So we try installing all of them and assume success if at least one installed
|
// So we try installing all of them and assume success if at least one installed
|
||||||
// If 0 APKs installed, throw the first install error encountered
|
// If 0 APKs installed, throw the first install error encountered
|
||||||
try {
|
|
||||||
var somethingInstalled = false;
|
var somethingInstalled = false;
|
||||||
|
try {
|
||||||
MultiAppMultiError errors = MultiAppMultiError();
|
MultiAppMultiError errors = MultiAppMultiError();
|
||||||
for (var file in dir.extracted
|
for (var file in dir.extracted
|
||||||
.listSync(recursive: true, followLinks: false)
|
.listSync(recursive: true, followLinks: false)
|
||||||
@ -507,7 +581,8 @@ class AppsProvider with ChangeNotifier {
|
|||||||
if (file.path.toLowerCase().endsWith('.apk')) {
|
if (file.path.toLowerCase().endsWith('.apk')) {
|
||||||
try {
|
try {
|
||||||
somethingInstalled = somethingInstalled ||
|
somethingInstalled = somethingInstalled ||
|
||||||
await installApk(DownloadedApk(dir.appId, file),
|
await installApk(
|
||||||
|
DownloadedApk(dir.appId, file), firstTimeWithContext,
|
||||||
needsBGWorkaround: needsBGWorkaround);
|
needsBGWorkaround: needsBGWorkaround);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logs.add(
|
logs.add(
|
||||||
@ -526,10 +601,22 @@ class AppsProvider with ChangeNotifier {
|
|||||||
} finally {
|
} finally {
|
||||||
dir.extracted.delete(recursive: true);
|
dir.extracted.delete(recursive: true);
|
||||||
}
|
}
|
||||||
|
return somethingInstalled;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> installApk(DownloadedApk file,
|
Future<bool> installApk(
|
||||||
|
DownloadedApk file, BuildContext? firstTimeWithContext,
|
||||||
{bool needsBGWorkaround = false}) async {
|
{bool needsBGWorkaround = false}) async {
|
||||||
|
if (firstTimeWithContext != null &&
|
||||||
|
settingsProvider.beforeNewInstallsShareToAppVerifier &&
|
||||||
|
(await getInstalledInfo('dev.soupslurpr.appverifier')) != null) {
|
||||||
|
XFile f = XFile.fromData(file.file.readAsBytesSync(),
|
||||||
|
mimeType: 'application/vnd.android.package-archive');
|
||||||
|
Fluttertoast.showToast(
|
||||||
|
msg: tr('appVerifierInstructionToast'),
|
||||||
|
toastLength: Toast.LENGTH_LONG);
|
||||||
|
await Share.shareXFiles([f]);
|
||||||
|
}
|
||||||
var newInfo =
|
var newInfo =
|
||||||
await pm.getPackageArchiveInfo(archiveFilePath: file.file.path);
|
await pm.getPackageArchiveInfo(archiveFilePath: file.file.path);
|
||||||
if (newInfo == null) {
|
if (newInfo == null) {
|
||||||
@ -577,7 +664,13 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
bool installed = false;
|
bool installed = false;
|
||||||
if (code != null && code != 0 && code != 3) {
|
if (code != null && code != 0 && code != 3) {
|
||||||
|
try {
|
||||||
|
file.file.deleteSync(recursive: true);
|
||||||
|
} catch (e) {
|
||||||
|
//
|
||||||
|
} finally {
|
||||||
throw InstallError(code);
|
throw InstallError(code);
|
||||||
|
}
|
||||||
} else if (code == 0) {
|
} else if (code == 0) {
|
||||||
installed = true;
|
installed = true;
|
||||||
apps[file.appId]!.app.installedVersion =
|
apps[file.appId]!.app.installedVersion =
|
||||||
@ -612,23 +705,28 @@ class AppsProvider with ChangeNotifier {
|
|||||||
await intent.launch();
|
await intent.launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<MapEntry<String, String>?> confirmApkUrl(
|
Future<MapEntry<String, String>?> confirmAppFileUrl(
|
||||||
App app, BuildContext? context) async {
|
App app, BuildContext? context, bool pickAnyAsset) async {
|
||||||
|
var urlsToSelectFrom = app.apkUrls;
|
||||||
|
if (pickAnyAsset) {
|
||||||
|
urlsToSelectFrom = [...urlsToSelectFrom, ...app.otherAssetUrls];
|
||||||
|
}
|
||||||
// If the App has more than one APK, the user should pick one (if context provided)
|
// If the App has more than one APK, the user should pick one (if context provided)
|
||||||
MapEntry<String, String>? apkUrl =
|
MapEntry<String, String>? appFileUrl = urlsToSelectFrom[
|
||||||
app.apkUrls[app.preferredApkIndex >= 0 ? app.preferredApkIndex : 0];
|
app.preferredApkIndex >= 0 ? app.preferredApkIndex : 0];
|
||||||
// get device supported architecture
|
// get device supported architecture
|
||||||
List<String> archs = (await DeviceInfoPlugin().androidInfo).supportedAbis;
|
List<String> archs = (await DeviceInfoPlugin().androidInfo).supportedAbis;
|
||||||
|
|
||||||
if (app.apkUrls.length > 1 && context != null) {
|
if (urlsToSelectFrom.length > 1 && context != null) {
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
apkUrl = await showDialog(
|
appFileUrl = await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext ctx) {
|
builder: (BuildContext ctx) {
|
||||||
return APKPicker(
|
return AppFilePicker(
|
||||||
app: app,
|
app: app,
|
||||||
initVal: apkUrl,
|
initVal: appFileUrl,
|
||||||
archs: archs,
|
archs: archs,
|
||||||
|
pickAnyAsset: pickAnyAsset,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -638,8 +736,8 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the picked APK comes from an origin different from the source, get user confirmation (if context provided)
|
// If the picked APK comes from an origin different from the source, get user confirmation (if context provided)
|
||||||
if (apkUrl != null &&
|
if (appFileUrl != null &&
|
||||||
getHost(apkUrl.value) != getHost(app.url) &&
|
getHost(appFileUrl.value) != getHost(app.url) &&
|
||||||
context != null) {
|
context != null) {
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
if (!(settingsProvider.hideAPKOriginWarning) &&
|
if (!(settingsProvider.hideAPKOriginWarning) &&
|
||||||
@ -648,13 +746,13 @@ class AppsProvider with ChangeNotifier {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext ctx) {
|
builder: (BuildContext ctx) {
|
||||||
return APKOriginWarningDialog(
|
return APKOriginWarningDialog(
|
||||||
sourceUrl: app.url, apkUrl: apkUrl!.value);
|
sourceUrl: app.url, apkUrl: appFileUrl!.value);
|
||||||
}) !=
|
}) !=
|
||||||
true) {
|
true) {
|
||||||
apkUrl = null;
|
appFileUrl = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return apkUrl;
|
return appFileUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given a list of AppIds, uses stored info about the apps to download APKs and install them
|
// Given a list of AppIds, uses stored info about the apps to download APKs and install them
|
||||||
@ -681,7 +779,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
var trackOnly = apps[id]!.app.additionalSettings['trackOnly'] == true;
|
var trackOnly = apps[id]!.app.additionalSettings['trackOnly'] == true;
|
||||||
if (!trackOnly) {
|
if (!trackOnly) {
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
apkUrl = await confirmApkUrl(apps[id]!.app, context);
|
apkUrl = await confirmAppFileUrl(apps[id]!.app, context, false);
|
||||||
}
|
}
|
||||||
if (apkUrl != null) {
|
if (apkUrl != null) {
|
||||||
int urlInd = apps[id]!
|
int urlInd = apps[id]!
|
||||||
@ -758,17 +856,24 @@ class AppsProvider with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
try {
|
try {
|
||||||
if (!skipInstalls) {
|
if (!skipInstalls) {
|
||||||
|
bool sayInstalled = true;
|
||||||
|
var contextIfNewInstall =
|
||||||
|
apps[id]?.installedInfo == null ? context : null;
|
||||||
if (downloadedFile != null) {
|
if (downloadedFile != null) {
|
||||||
if (willBeSilent && context == null) {
|
if (willBeSilent && context == null) {
|
||||||
installApk(downloadedFile, needsBGWorkaround: true);
|
installApk(downloadedFile, contextIfNewInstall,
|
||||||
|
needsBGWorkaround: true);
|
||||||
} else {
|
} else {
|
||||||
await installApk(downloadedFile);
|
sayInstalled =
|
||||||
|
await installApk(downloadedFile, contextIfNewInstall);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (willBeSilent && context == null) {
|
if (willBeSilent && context == null) {
|
||||||
installXApkDir(downloadedDir!, needsBGWorkaround: true);
|
installXApkDir(downloadedDir!, contextIfNewInstall,
|
||||||
|
needsBGWorkaround: true);
|
||||||
} else {
|
} else {
|
||||||
await installXApkDir(downloadedDir!);
|
sayInstalled =
|
||||||
|
await installXApkDir(downloadedDir!, contextIfNewInstall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (willBeSilent && context == null) {
|
if (willBeSilent && context == null) {
|
||||||
@ -776,8 +881,10 @@ class AppsProvider with ChangeNotifier {
|
|||||||
[apps[id]!.app],
|
[apps[id]!.app],
|
||||||
id: id.hashCode));
|
id: id.hashCode));
|
||||||
}
|
}
|
||||||
|
if (sayInstalled) {
|
||||||
installedIds.add(id);
|
installedIds.add(id);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
apps[id]?.downloadProgress = null;
|
apps[id]?.downloadProgress = null;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -809,6 +916,85 @@ class AppsProvider with ChangeNotifier {
|
|||||||
return installedIds;
|
return installedIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<String>> downloadAppAssets(
|
||||||
|
List<String> appIds, BuildContext context,
|
||||||
|
{bool forceParallelDownloads = false}) async {
|
||||||
|
NotificationsProvider notificationsProvider =
|
||||||
|
context.read<NotificationsProvider>();
|
||||||
|
List<MapEntry<MapEntry<String, String>, App>> filesToDownload = [];
|
||||||
|
for (var id in appIds) {
|
||||||
|
if (apps[id] == null) {
|
||||||
|
throw ObtainiumError(tr('appNotFound'));
|
||||||
|
}
|
||||||
|
MapEntry<String, String>? fileUrl;
|
||||||
|
if (apps[id]!.app.apkUrls.isNotEmpty ||
|
||||||
|
apps[id]!.app.otherAssetUrls.isNotEmpty) {
|
||||||
|
// ignore: use_build_context_synchronously
|
||||||
|
fileUrl = await confirmAppFileUrl(apps[id]!.app, context, true);
|
||||||
|
}
|
||||||
|
if (fileUrl != null) {
|
||||||
|
filesToDownload.add(MapEntry(fileUrl, apps[id]!.app));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to download+install Apps
|
||||||
|
MultiAppMultiError errors = MultiAppMultiError();
|
||||||
|
List<String> downloadedIds = [];
|
||||||
|
|
||||||
|
Future<void> downloadFn(MapEntry<String, String> fileUrl, App app) async {
|
||||||
|
try {
|
||||||
|
var exportDir = await settingsProvider.getExportDir();
|
||||||
|
String downloadPath = '/storage/emulated/0/Download';
|
||||||
|
bool downloadsAccessible = false;
|
||||||
|
try {
|
||||||
|
downloadsAccessible = Directory(downloadPath).existsSync();
|
||||||
|
} catch (e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
if (!downloadsAccessible && exportDir != null) {
|
||||||
|
downloadPath = exportDir.path;
|
||||||
|
}
|
||||||
|
await downloadFile(
|
||||||
|
fileUrl.value,
|
||||||
|
fileUrl.key
|
||||||
|
.split('.')
|
||||||
|
.reversed
|
||||||
|
.toList()
|
||||||
|
.sublist(1)
|
||||||
|
.reversed
|
||||||
|
.join('.'), (double? progress) {
|
||||||
|
notificationsProvider
|
||||||
|
.notify(DownloadNotification(fileUrl.key, progress?.ceil() ?? 0));
|
||||||
|
}, downloadPath,
|
||||||
|
headers: await SourceProvider()
|
||||||
|
.getSource(app.url, overrideSource: app.overrideSource)
|
||||||
|
.getRequestHeaders(app.additionalSettings,
|
||||||
|
forAPKDownload:
|
||||||
|
fileUrl.key.endsWith('.apk') ? true : false),
|
||||||
|
useExisting: false);
|
||||||
|
notificationsProvider
|
||||||
|
.notify(DownloadedNotification(fileUrl.key, fileUrl.value));
|
||||||
|
} catch (e) {
|
||||||
|
errors.add(fileUrl.key, e);
|
||||||
|
} finally {
|
||||||
|
notificationsProvider.cancel(DownloadNotification(fileUrl.key, 0).id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forceParallelDownloads || !settingsProvider.parallelDownloads) {
|
||||||
|
for (var urlWithApp in filesToDownload) {
|
||||||
|
await downloadFn(urlWithApp.key, urlWithApp.value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await Future.wait(filesToDownload
|
||||||
|
.map((urlWithApp) => downloadFn(urlWithApp.key, urlWithApp.value)));
|
||||||
|
}
|
||||||
|
if (errors.idsByErrorString.isNotEmpty) {
|
||||||
|
throw errors;
|
||||||
|
}
|
||||||
|
return downloadedIds;
|
||||||
|
}
|
||||||
|
|
||||||
Future<Directory> getAppsDir() async {
|
Future<Directory> getAppsDir() async {
|
||||||
Directory appsDir =
|
Directory appsDir =
|
||||||
Directory('${(await getExternalStorageDirectory())!.path}/app_data');
|
Directory('${(await getExternalStorageDirectory())!.path}/app_data');
|
||||||
@ -1380,38 +1566,49 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class APKPicker extends StatefulWidget {
|
class AppFilePicker extends StatefulWidget {
|
||||||
const APKPicker({super.key, required this.app, this.initVal, this.archs});
|
const AppFilePicker(
|
||||||
|
{super.key,
|
||||||
|
required this.app,
|
||||||
|
this.initVal,
|
||||||
|
this.archs,
|
||||||
|
this.pickAnyAsset = false});
|
||||||
|
|
||||||
final App app;
|
final App app;
|
||||||
final MapEntry<String, String>? initVal;
|
final MapEntry<String, String>? initVal;
|
||||||
final List<String>? archs;
|
final List<String>? archs;
|
||||||
|
final bool pickAnyAsset;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<APKPicker> createState() => _APKPickerState();
|
State<AppFilePicker> createState() => _AppFilePickerState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _APKPickerState extends State<APKPicker> {
|
class _AppFilePickerState extends State<AppFilePicker> {
|
||||||
MapEntry<String, String>? apkUrl;
|
MapEntry<String, String>? fileUrl;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
apkUrl ??= widget.initVal;
|
fileUrl ??= widget.initVal;
|
||||||
|
var urlsToSelectFrom = widget.app.apkUrls;
|
||||||
|
if (widget.pickAnyAsset) {
|
||||||
|
urlsToSelectFrom = [...urlsToSelectFrom, ...widget.app.otherAssetUrls];
|
||||||
|
}
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
scrollable: true,
|
scrollable: true,
|
||||||
title: Text(tr('pickAnAPK')),
|
title: Text(widget.pickAnyAsset
|
||||||
|
? tr('selectX', args: [tr('releaseAsset').toLowerCase()])
|
||||||
|
: tr('pickAnAPK')),
|
||||||
content: Column(children: [
|
content: Column(children: [
|
||||||
Text(tr('appHasMoreThanOnePackage', args: [widget.app.finalName])),
|
Text(tr('appHasMoreThanOnePackage', args: [widget.app.finalName])),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
...widget.app.apkUrls.map(
|
...urlsToSelectFrom.map(
|
||||||
(u) => RadioListTile<String>(
|
(u) => RadioListTile<String>(
|
||||||
title: Text(u.key),
|
title: Text(u.key),
|
||||||
value: u.value,
|
value: u.value,
|
||||||
groupValue: apkUrl!.value,
|
groupValue: fileUrl!.value,
|
||||||
onChanged: (String? val) {
|
onChanged: (String? val) {
|
||||||
setState(() {
|
setState(() {
|
||||||
apkUrl =
|
fileUrl = urlsToSelectFrom.where((e) => e.value == val).first;
|
||||||
widget.app.apkUrls.where((e) => e.value == val).first;
|
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
@ -1438,7 +1635,7 @@ class _APKPickerState extends State<APKPicker> {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
HapticFeedback.selectionClick();
|
HapticFeedback.selectionClick();
|
||||||
Navigator.of(context).pop(apkUrl);
|
Navigator.of(context).pop(fileUrl);
|
||||||
},
|
},
|
||||||
child: Text(tr('continue')))
|
child: Text(tr('continue')))
|
||||||
],
|
],
|
||||||
|
@ -120,6 +120,18 @@ class DownloadNotification extends ObtainiumNotification {
|
|||||||
progPercent: progPercent);
|
progPercent: progPercent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DownloadedNotification extends ObtainiumNotification {
|
||||||
|
DownloadedNotification(String fileName, String downloadUrl)
|
||||||
|
: super(
|
||||||
|
downloadUrl.hashCode,
|
||||||
|
tr('downloadedX', args: [fileName]),
|
||||||
|
'',
|
||||||
|
'FILE_DOWNLOADED',
|
||||||
|
tr('downloadedXNotifChannel', args: [tr('app')]),
|
||||||
|
tr('downloadedX', args: [tr('app')]),
|
||||||
|
Importance.defaultImportance);
|
||||||
|
}
|
||||||
|
|
||||||
final completeInstallationNotification = ObtainiumNotification(
|
final completeInstallationNotification = ObtainiumNotification(
|
||||||
1,
|
1,
|
||||||
tr('completeAppInstallation'),
|
tr('completeAppInstallation'),
|
||||||
|
@ -479,4 +479,13 @@ class SettingsProvider with ChangeNotifier {
|
|||||||
prefs?.setStringList('searchDeselected', list);
|
prefs?.setStringList('searchDeselected', list);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get beforeNewInstallsShareToAppVerifier {
|
||||||
|
return prefs?.getBool('beforeNewInstallsShareToAppVerifier') ?? true;
|
||||||
|
}
|
||||||
|
|
||||||
|
set beforeNewInstallsShareToAppVerifier(bool val) {
|
||||||
|
prefs?.setBool('beforeNewInstallsShareToAppVerifier', val);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,9 +47,10 @@ class APKDetails {
|
|||||||
late AppNames names;
|
late AppNames names;
|
||||||
late DateTime? releaseDate;
|
late DateTime? releaseDate;
|
||||||
late String? changeLog;
|
late String? changeLog;
|
||||||
|
late List<MapEntry<String, String>> allAssetUrls;
|
||||||
|
|
||||||
APKDetails(this.version, this.apkUrls, this.names,
|
APKDetails(this.version, this.apkUrls, this.names,
|
||||||
{this.releaseDate, this.changeLog});
|
{this.releaseDate, this.changeLog, this.allAssetUrls = const []});
|
||||||
}
|
}
|
||||||
|
|
||||||
stringMapListTo2DList(List<MapEntry<String, String>> mapList) =>
|
stringMapListTo2DList(List<MapEntry<String, String>> mapList) =>
|
||||||
@ -223,6 +224,7 @@ class App {
|
|||||||
String? installedVersion;
|
String? installedVersion;
|
||||||
late String latestVersion;
|
late String latestVersion;
|
||||||
List<MapEntry<String, String>> apkUrls = [];
|
List<MapEntry<String, String>> apkUrls = [];
|
||||||
|
List<MapEntry<String, String>> otherAssetUrls = [];
|
||||||
late int preferredApkIndex;
|
late int preferredApkIndex;
|
||||||
late Map<String, dynamic> additionalSettings;
|
late Map<String, dynamic> additionalSettings;
|
||||||
late DateTime? lastUpdateCheck;
|
late DateTime? lastUpdateCheck;
|
||||||
@ -248,7 +250,8 @@ class App {
|
|||||||
this.releaseDate,
|
this.releaseDate,
|
||||||
this.changeLog,
|
this.changeLog,
|
||||||
this.overrideSource,
|
this.overrideSource,
|
||||||
this.allowIdChange = false});
|
this.allowIdChange = false,
|
||||||
|
this.otherAssetUrls = const []});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@ -280,7 +283,8 @@ class App {
|
|||||||
changeLog: changeLog,
|
changeLog: changeLog,
|
||||||
releaseDate: releaseDate,
|
releaseDate: releaseDate,
|
||||||
overrideSource: overrideSource,
|
overrideSource: overrideSource,
|
||||||
allowIdChange: allowIdChange);
|
allowIdChange: allowIdChange,
|
||||||
|
otherAssetUrls: otherAssetUrls);
|
||||||
|
|
||||||
factory App.fromJson(Map<String, dynamic> json) {
|
factory App.fromJson(Map<String, dynamic> json) {
|
||||||
json = appJSONCompatibilityModifiers(json);
|
json = appJSONCompatibilityModifiers(json);
|
||||||
@ -293,8 +297,8 @@ class App {
|
|||||||
? null
|
? null
|
||||||
: json['installedVersion'] as String,
|
: json['installedVersion'] as String,
|
||||||
(json['latestVersion'] ?? tr('unknown')) as String,
|
(json['latestVersion'] ?? tr('unknown')) as String,
|
||||||
assumed2DlistToStringMapList(jsonDecode(
|
assumed2DlistToStringMapList(
|
||||||
(json['apkUrls'] ?? '[["placeholder", "placeholder"]]'))),
|
jsonDecode((json['apkUrls'] ?? '[["placeholder", "placeholder"]]'))),
|
||||||
(json['preferredApkIndex'] ?? -1) as int,
|
(json['preferredApkIndex'] ?? -1) as int,
|
||||||
jsonDecode(json['additionalSettings']) as Map<String, dynamic>,
|
jsonDecode(json['additionalSettings']) as Map<String, dynamic>,
|
||||||
json['lastUpdateCheck'] == null
|
json['lastUpdateCheck'] == null
|
||||||
@ -311,10 +315,12 @@ class App {
|
|||||||
releaseDate: json['releaseDate'] == null
|
releaseDate: json['releaseDate'] == null
|
||||||
? null
|
? null
|
||||||
: DateTime.fromMicrosecondsSinceEpoch(json['releaseDate']),
|
: DateTime.fromMicrosecondsSinceEpoch(json['releaseDate']),
|
||||||
changeLog:
|
changeLog: json['changeLog'] == null ? null : json['changeLog'] as String,
|
||||||
json['changeLog'] == null ? null : json['changeLog'] as String,
|
|
||||||
overrideSource: json['overrideSource'],
|
overrideSource: json['overrideSource'],
|
||||||
allowIdChange: json['allowIdChange'] ?? false);
|
allowIdChange: json['allowIdChange'] ?? false,
|
||||||
|
otherAssetUrls: assumed2DlistToStringMapList(
|
||||||
|
jsonDecode((json['otherAssetUrls'] ?? '[]'))),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
@ -325,6 +331,7 @@ class App {
|
|||||||
'installedVersion': installedVersion,
|
'installedVersion': installedVersion,
|
||||||
'latestVersion': latestVersion,
|
'latestVersion': latestVersion,
|
||||||
'apkUrls': jsonEncode(stringMapListTo2DList(apkUrls)),
|
'apkUrls': jsonEncode(stringMapListTo2DList(apkUrls)),
|
||||||
|
'otherAssetUrls': jsonEncode(stringMapListTo2DList(otherAssetUrls)),
|
||||||
'preferredApkIndex': preferredApkIndex,
|
'preferredApkIndex': preferredApkIndex,
|
||||||
'additionalSettings': jsonEncode(additionalSettings),
|
'additionalSettings': jsonEncode(additionalSettings),
|
||||||
'lastUpdateCheck': lastUpdateCheck?.microsecondsSinceEpoch,
|
'lastUpdateCheck': lastUpdateCheck?.microsecondsSinceEpoch,
|
||||||
@ -736,7 +743,6 @@ class SourceProvider {
|
|||||||
FDroid(),
|
FDroid(),
|
||||||
FDroidRepo(),
|
FDroidRepo(),
|
||||||
IzzyOnDroid(),
|
IzzyOnDroid(),
|
||||||
SourceForge(),
|
|
||||||
SourceHut(),
|
SourceHut(),
|
||||||
APKPure(),
|
APKPure(),
|
||||||
Aptoide(),
|
Aptoide(),
|
||||||
@ -893,8 +899,10 @@ class SourceProvider {
|
|||||||
allowIdChange: currentApp?.allowIdChange ??
|
allowIdChange: currentApp?.allowIdChange ??
|
||||||
trackOnly ||
|
trackOnly ||
|
||||||
(source.appIdInferIsOptional &&
|
(source.appIdInferIsOptional &&
|
||||||
inferAppIdIfOptional) // Optional ID inferring may be incorrect - allow correction on first install
|
inferAppIdIfOptional), // Optional ID inferring may be incorrect - allow correction on first install
|
||||||
);
|
otherAssetUrls: apk.allAssetUrls
|
||||||
|
.where((a) => apk.apkUrls.indexWhere((p) => a.key == p.key) < 0)
|
||||||
|
.toList());
|
||||||
return source.endOfGetAppChanges(finalApp);
|
return source.endOfGetAppChanges(finalApp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
132
pubspec.lock
132
pubspec.lock
@ -5,10 +5,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: android_intent_plus
|
name: android_intent_plus
|
||||||
sha256: e1c62bb41c90e15083b7fb84dc327fe90396cc9c1445b55ff1082144fabfb4d9
|
sha256: "2bfdbee8d65e7c26f88b66f0a91f2863da4d3596d8a658b4162c8de5cf04b074"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.3"
|
version: "5.0.2"
|
||||||
android_package_installer:
|
android_package_installer:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -38,10 +38,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: app_links
|
name: app_links
|
||||||
sha256: "4e392b5eba997df356ca6021f28431ce1cfeb16758699553a94b13add874a3bb"
|
sha256: "42dc15aecf2618ace4ffb74a2e58a50e45cd1b9f2c17c8f0cafe4c297f08c815"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.5.0"
|
version: "4.0.1"
|
||||||
archive:
|
archive:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -54,10 +54,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: args
|
name: args
|
||||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.2"
|
version: "2.5.0"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -70,10 +70,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: background_fetch
|
name: background_fetch
|
||||||
sha256: "1a7868d9bd165eb177f039ff8244cfa7952340b18f7caabf322b26e712b438a3"
|
sha256: dbffec0317ccdef6e2014cb543e147f52441e29c4fcb53dfd23558c4d92ddece
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.3"
|
version: "1.3.2"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -126,18 +126,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: connectivity_plus
|
name: connectivity_plus
|
||||||
sha256: "224a77051d52a11fbad53dd57827594d3bd24f945af28bd70bab376d68d437f0"
|
sha256: ebe15d94de9dd7c31dc2ac54e42780acdf3384b1497c69290c9f3c5b0279fc57
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.2"
|
version: "6.0.2"
|
||||||
connectivity_plus_platform_interface:
|
connectivity_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: connectivity_plus_platform_interface
|
name: connectivity_plus_platform_interface
|
||||||
sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a
|
sha256: b6a56efe1e6675be240de39107281d4034b64ac23438026355b4234042a35adb
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.4"
|
version: "2.0.0"
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -190,10 +190,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: device_info_plus
|
name: device_info_plus
|
||||||
sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110"
|
sha256: eead12d1a1ed83d8283ab4c2f3fca23ac4082f29f25f29dff0f758f57d06ec91
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.1.2"
|
version: "10.1.0"
|
||||||
device_info_plus_platform_interface:
|
device_info_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -254,10 +254,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: file_picker
|
name: file_picker
|
||||||
sha256: "4e42aacde3b993c5947467ab640882c56947d9d27342a5b6f2895b23956954a6"
|
sha256: d1d0ac3966b36dc3e66eeefb40280c17feb87fa2099c6e22e6a1fc959327bd03
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.1"
|
version: "8.0.0+1"
|
||||||
fixnum:
|
fixnum:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -299,18 +299,18 @@ packages:
|
|||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: flutter_lints
|
name: flutter_lints
|
||||||
sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
|
sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
flutter_local_notifications:
|
flutter_local_notifications:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_local_notifications
|
name: flutter_local_notifications
|
||||||
sha256: c18f1de98fe0bb9dd5ba91e1330d4febc8b6a7de6aae3ffe475ef423723e72f3
|
sha256: a701df4866f9a38bb8e4450a54c143bbeeb0ce2381e7df5a36e1006f3b43bb28
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "16.3.2"
|
version: "17.0.1"
|
||||||
flutter_local_notifications_linux:
|
flutter_local_notifications_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -336,18 +336,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_markdown
|
name: flutter_markdown
|
||||||
sha256: a64c5323ac83ed2b7940d2b6288d160aa1753ff271ba9d9b2a86770414aa3eab
|
sha256: "31c12de79262b5431c5492e9c89948aa789158435f707d3519a7fdef6af28af7"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.20+1"
|
version: "0.6.22+1"
|
||||||
flutter_plugin_android_lifecycle:
|
flutter_plugin_android_lifecycle:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_plugin_android_lifecycle
|
name: flutter_plugin_android_lifecycle
|
||||||
sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da
|
sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.17"
|
version: "2.0.19"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -426,10 +426,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: js
|
name: js
|
||||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.7"
|
version: "0.7.1"
|
||||||
json_annotation:
|
json_annotation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -474,10 +474,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: markdown
|
name: markdown
|
||||||
sha256: "1b134d9f8ff2da15cb298efe6cd8b7d2a78958c1b00384ebcbdf13fe340a6c90"
|
sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.2.1"
|
version: "7.2.2"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -538,18 +538,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
|
sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.3"
|
||||||
path_provider_android:
|
path_provider_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_android
|
name: path_provider_android
|
||||||
sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
|
sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.2"
|
version: "2.2.4"
|
||||||
path_provider_foundation:
|
path_provider_foundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -586,10 +586,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: permission_handler
|
name: permission_handler
|
||||||
sha256: "74e962b7fad7ff75959161bb2c0ad8fe7f2568ee82621c9c2660b751146bfe44"
|
sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "11.3.0"
|
version: "11.3.1"
|
||||||
permission_handler_android:
|
permission_handler_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -602,10 +602,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: permission_handler_apple
|
name: permission_handler_apple
|
||||||
sha256: bdafc6db74253abb63907f4e357302e6bb786ab41465e8635f362ee71fd8707b
|
sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "9.4.0"
|
version: "9.4.4"
|
||||||
permission_handler_html:
|
permission_handler_html:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -618,10 +618,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: permission_handler_platform_interface
|
name: permission_handler_platform_interface
|
||||||
sha256: "23dfba8447c076ab5be3dee9ceb66aad345c4a648f0cac292c77b1eb0e800b78"
|
sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2.0"
|
version: "4.2.1"
|
||||||
permission_handler_windows:
|
permission_handler_windows:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -658,10 +658,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: pointycastle
|
name: pointycastle
|
||||||
sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29"
|
sha256: "70fe966348fe08c34bf929582f1d8247d9d9408130723206472b4687227e4333"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.7.4"
|
version: "3.8.0"
|
||||||
provider:
|
provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -674,34 +674,34 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: share_plus
|
name: share_plus
|
||||||
sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900"
|
sha256: fb5319f3aab4c5dda5ebb92dca978179ba21f8c783ee4380910ef4c1c6824f51
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.2.2"
|
version: "8.0.3"
|
||||||
share_plus_platform_interface:
|
share_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: share_plus_platform_interface
|
name: share_plus_platform_interface
|
||||||
sha256: df08bc3a07d01f5ea47b45d03ffcba1fa9cd5370fb44b3f38c70e42cced0f956
|
sha256: "251eb156a8b5fa9ce033747d73535bf53911071f8d3b6f4f0b578505ce0d4496"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.3.1"
|
version: "3.4.0"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: shared_preferences
|
name: shared_preferences
|
||||||
sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
|
sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.2"
|
version: "2.2.3"
|
||||||
shared_preferences_android:
|
shared_preferences_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_android
|
name: shared_preferences_android
|
||||||
sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
|
sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.1"
|
version: "2.2.2"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -775,18 +775,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: sqflite
|
name: sqflite
|
||||||
sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6
|
sha256: "5ce2e1a15e822c3b4bfb5400455775e421da7098eed8adc8f26298ada7c9308c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.2"
|
version: "2.3.3"
|
||||||
sqflite_common:
|
sqflite_common:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqflite_common
|
name: sqflite_common
|
||||||
sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5"
|
sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.3"
|
version: "2.5.4"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -855,18 +855,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: url_launcher
|
name: url_launcher
|
||||||
sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e"
|
sha256: "6ce1e04375be4eed30548f10a315826fd933c1e493206eab82eed01f438c8d2e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.2.5"
|
version: "6.2.6"
|
||||||
url_launcher_android:
|
url_launcher_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_android
|
name: url_launcher_android
|
||||||
sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745
|
sha256: "360a6ed2027f18b73c8d98e159dda67a61b7f2e0f6ec26e86c3ada33b0621775"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.3.0"
|
version: "6.3.1"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -919,10 +919,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: uuid
|
name: uuid
|
||||||
sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8
|
sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.3.3"
|
version: "4.4.0"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -943,10 +943,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: web
|
name: web
|
||||||
sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad"
|
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0"
|
version: "0.5.1"
|
||||||
webview_flutter:
|
webview_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -959,10 +959,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_android
|
name: webview_flutter_android
|
||||||
sha256: "3e5f4e9d818086b0d01a66fb1ff9cc72ab0cc58c71980e3d3661c5685ea0efb0"
|
sha256: f038ee2fae73b509dde1bc9d2c5a50ca92054282de17631a9a3d515883740934
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.15.0"
|
version: "3.16.0"
|
||||||
webview_flutter_platform_interface:
|
webview_flutter_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -975,18 +975,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: webview_flutter_wkwebview
|
name: webview_flutter_wkwebview
|
||||||
sha256: "9bf168bccdf179ce90450b5f37e36fe263f591c9338828d6bf09b6f8d0f57f86"
|
sha256: f12f8d8a99784b863e8b85e4a9a5e3cf1839d6803d2c0c3e0533a8f3c5a992a7
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.12.0"
|
version: "3.13.0"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: win32
|
name: win32
|
||||||
sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
|
sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.2.0"
|
version: "5.4.0"
|
||||||
win32_registry:
|
win32_registry:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
16
pubspec.yaml
16
pubspec.yaml
@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# 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.4+2254 # When changing this, update the tag in main() accordingly
|
version: 1.1.3+2260
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0 <4.0.0'
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
@ -38,7 +38,7 @@ dependencies:
|
|||||||
cupertino_icons: ^1.0.5
|
cupertino_icons: ^1.0.5
|
||||||
path_provider: ^2.0.11
|
path_provider: ^2.0.11
|
||||||
flutter_fgbg: ^0.3.0 # Try removing reliance on this
|
flutter_fgbg: ^0.3.0 # Try removing reliance on this
|
||||||
flutter_local_notifications: ^16.1.0
|
flutter_local_notifications: ^17.0.0
|
||||||
provider: ^6.0.3
|
provider: ^6.0.3
|
||||||
http: ^1.0.0
|
http: ^1.0.0
|
||||||
webview_flutter: ^4.0.0
|
webview_flutter: ^4.0.0
|
||||||
@ -48,25 +48,25 @@ dependencies:
|
|||||||
url_launcher: ^6.1.5
|
url_launcher: ^6.1.5
|
||||||
permission_handler: ^11.0.0
|
permission_handler: ^11.0.0
|
||||||
fluttertoast: ^8.0.9
|
fluttertoast: ^8.0.9
|
||||||
device_info_plus: ^9.0.0
|
device_info_plus: ^10.0.1
|
||||||
file_picker: ^6.0.0
|
file_picker: ^8.0.0+1
|
||||||
animations: ^2.0.4
|
animations: ^2.0.4
|
||||||
android_package_installer:
|
android_package_installer:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/ImranR98/android_package_installer
|
url: https://github.com/ImranR98/android_package_installer
|
||||||
ref: main
|
ref: main
|
||||||
android_package_manager: ^0.7.0
|
android_package_manager: ^0.7.0
|
||||||
share_plus: ^7.0.0
|
share_plus: ^8.0.2
|
||||||
sqflite: ^2.2.0+3
|
sqflite: ^2.2.0+3
|
||||||
easy_localization: ^3.0.1
|
easy_localization: ^3.0.1
|
||||||
android_intent_plus: ^4.0.0
|
android_intent_plus: ^5.0.1
|
||||||
flutter_markdown: ^0.6.14
|
flutter_markdown: ^0.6.14
|
||||||
flutter_archive: ^6.0.0
|
flutter_archive: ^6.0.0
|
||||||
hsluv: ^1.1.3
|
hsluv: ^1.1.3
|
||||||
connectivity_plus: ^5.0.0
|
connectivity_plus: ^6.0.1
|
||||||
shared_storage: ^0.8.0
|
shared_storage: ^0.8.0
|
||||||
crypto: ^3.0.3
|
crypto: ^3.0.3
|
||||||
app_links: ^3.5.0
|
app_links: ^4.0.0
|
||||||
background_fetch: ^1.2.1
|
background_fetch: ^1.2.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
Reference in New Issue
Block a user