mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-11-02 22:33:28 +01:00 
			
		
		
		
	Compare commits
	
		
			194 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					dfac3af3f5 | ||
| 
						 | 
					5eceaeecde | ||
| 
						 | 
					62c23004f7 | ||
| 
						 | 
					cd153e7d11 | ||
| 
						 | 
					3b494511d7 | ||
| 
						 | 
					6c806a44d4 | ||
| 
						 | 
					c5bac43bfd | ||
| 
						 | 
					1636281d6d | ||
| 
						 | 
					0f4feb2da6 | ||
| 
						 | 
					c32f34c116 | ||
| 
						 | 
					d391c5cfc2 | ||
| 
						 | 
					bb45a157b3 | ||
| 
						 | 
					c90a571f89 | ||
| 
						 | 
					1278407c90 | ||
| 
						 | 
					dff1b4cf39 | ||
| 
						 | 
					105e70a814 | ||
| 
						 | 
					2938cea419 | ||
| 
						 | 
					9b6b7780d8 | ||
| 
						 | 
					f53a4f3827 | ||
| 
						 | 
					9b0d672553 | ||
| 
						 | 
					9d14145ac2 | ||
| 
						 | 
					9948797b25 | ||
| 
						 | 
					a80d9e3623 | ||
| 
						 | 
					37ecb057f9 | ||
| 
						 | 
					06cbe74c6c | ||
| 
						 | 
					f5769b85fe | ||
| 
						 | 
					875868af47 | ||
| 
						 | 
					24ea15d600 | ||
| 
						 | 
					87cdc3dcef | ||
| 
						 | 
					c2f976d7f4 | ||
| 
						 | 
					ebc46bfd3f | ||
| 
						 | 
					e674f7e89d | ||
| 
						 | 
					86d29b163c | ||
| 
						 | 
					a849919799 | ||
| 
						 | 
					d8c805a6b3 | ||
| 
						 | 
					8acbd3ef78 | ||
| 
						 | 
					b81088d767 | ||
| 
						 | 
					7071e34a74 | ||
| 
						 | 
					6a73ade359 | ||
| 
						 | 
					6c5e5043a4 | ||
| 
						 | 
					5edaf1306d | ||
| 
						 | 
					5bf7fdb94e | ||
| 
						 | 
					7808bc5ccb | ||
| 
						 | 
					06a079e452 | ||
| 
						 | 
					de509737e6 | ||
| 
						 | 
					08a3ba8d13 | ||
| 
						 | 
					2b27902d5f | ||
| 
						 | 
					62185127c2 | ||
| 
						 | 
					9c46e3f88c | ||
| 
						 | 
					daa4de921d | ||
| 
						 | 
					bc977e2a5a | ||
| 
						 | 
					1e3815ca20 | ||
| 
						 | 
					0e2fa96b9f | ||
| 
						 | 
					389aebe54e | ||
| 
						 | 
					fbfeaf2a91 | ||
| 
						 | 
					485812d076 | ||
| 
						 | 
					68e98ec719 | ||
| 
						 | 
					cbe41de734 | ||
| 
						 | 
					abb8641105 | ||
| 
						 | 
					dbcb4b3c09 | ||
| 
						 | 
					b231c756e6 | ||
| 
						 | 
					3cb3f7fdd4 | ||
| 
						 | 
					9837e8e325 | ||
| 
						 | 
					73d4814f18 | ||
| 
						 | 
					0a9219c314 | ||
| 
						 | 
					56c5a73d9a | ||
| 
						 | 
					a30e063246 | ||
| 
						 | 
					bd26b6514a | ||
| 
						 | 
					3ea8c7e888 | ||
| 
						 | 
					5f2ec5ce6f | ||
| 
						 | 
					783ce9d555 | ||
| 
						 | 
					a719b2475b | ||
| 
						 | 
					84df499ea6 | ||
| 
						 | 
					0d25b74050 | ||
| 
						 | 
					0effbc3841 | ||
| 
						 | 
					7478a7af22 | ||
| 
						 | 
					0838a6d30b | ||
| 
						 | 
					8cee268d13 | ||
| 
						 | 
					a3fddc5400 | ||
| 
						 | 
					c0a2e372e5 | ||
| 
						 | 
					c633963203 | ||
| 
						 | 
					299f457938 | ||
| 
						 | 
					37e62c922b | ||
| 
						 | 
					95722ce47b | ||
| 
						 | 
					8b806b3ef1 | ||
| 
						 | 
					09221b3526 | ||
| 
						 | 
					31b6250082 | ||
| 
						 | 
					07372da91b | ||
| 
						 | 
					5c36bcfb4b | ||
| 
						 | 
					e5012b1fcb | ||
| 
						 | 
					6f951175a4 | ||
| 
						 | 
					be52ec372f | ||
| 
						 | 
					eb7126afc3 | ||
| 
						 | 
					26fc63a02a | ||
| 
						 | 
					d33ca0948f | ||
| 
						 | 
					f76637a2e1 | ||
| 
						 | 
					b7de627c7b | ||
| 
						 | 
					27fc60d437 | ||
| 
						 | 
					ec240f946e | ||
| 
						 | 
					ecd80fc371 | ||
| 
						 | 
					68fa660e6d | ||
| 
						 | 
					70f9e33d17 | ||
| 
						 | 
					2e2dffd8e2 | ||
| 
						 | 
					0b1d5bf514 | ||
| 
						 | 
					2570c8e289 | ||
| 
						 | 
					43a8ba4de1 | ||
| 
						 | 
					3f2fb1c1ed | ||
| 
						 | 
					40d303fb57 | ||
| 
						 | 
					2c1687c33d | ||
| 
						 | 
					b688e7f160 | ||
| 
						 | 
					0c80d88583 | ||
| 
						 | 
					b293b1e9ff | ||
| 
						 | 
					61038a8969 | ||
| 
						 | 
					b92d1541bf | ||
| 
						 | 
					13f0ccb10d | ||
| 
						 | 
					ed732cfad2 | ||
| 
						 | 
					fb206aee84 | ||
| 
						 | 
					285530784d | ||
| 
						 | 
					0ddb5b5e81 | ||
| 
						 | 
					c16cda1962 | ||
| 
						 | 
					49022726d3 | ||
| 
						 | 
					a311894b9f | ||
| 
						 | 
					29e13efd66 | ||
| 
						 | 
					8c2a97e092 | ||
| 
						 | 
					34d571f586 | ||
| 
						 | 
					a20b87889b | ||
| 
						 | 
					c7319cd958 | ||
| 
						 | 
					d61fd800ef | ||
| 
						 | 
					12dda8bfa9 | ||
| 
						 | 
					0657f832e1 | ||
| 
						 | 
					6431357b15 | ||
| 
						 | 
					dcc42bdfe5 | ||
| 
						 | 
					85718dc3a3 | ||
| 
						 | 
					9dff352796 | ||
| 
						 | 
					c5477767a0 | ||
| 
						 | 
					3131ef8c4e | ||
| 
						 | 
					4d9f05aa87 | ||
| 
						 | 
					7b882d9bd8 | ||
| 
						 | 
					d1a2831922 | ||
| 
						 | 
					b042050ea3 | ||
| 
						 | 
					2d43dfe0a7 | ||
| 
						 | 
					b1a740223c | ||
| 
						 | 
					41c98d97b1 | ||
| 
						 | 
					fb06babb96 | ||
| 
						 | 
					ccc0e7696b | ||
| 
						 | 
					6d41ed8011 | ||
| 
						 | 
					c1476a7d58 | ||
| 
						 | 
					b1ee39be3b | ||
| 
						 | 
					c2ccdd3d05 | ||
| 
						 | 
					a621f1dfb4 | ||
| 
						 | 
					8527ad0007 | ||
| 
						 | 
					377ecef1b4 | ||
| 
						 | 
					1f9921e6ff | ||
| 
						 | 
					00988ed04d | ||
| 
						 | 
					3d1113c057 | ||
| 
						 | 
					1c81f0c1e1 | ||
| 
						 | 
					b26043ef5e | ||
| 
						 | 
					e3ad144c06 | ||
| 
						 | 
					fdb45c48ce | ||
| 
						 | 
					8619cfa819 | ||
| 
						 | 
					1fe4cdd648 | ||
| 
						 | 
					2289e58dda | ||
| 
						 | 
					049bcfbaf5 | ||
| 
						 | 
					5b5f922b54 | ||
| 
						 | 
					6545498c21 | ||
| 
						 | 
					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 | ||
| 
						 | 
					9717db0ca4 | 
							
								
								
									
										2
									
								
								.flutter
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								.flutter
									
									
									
									
									
								
							 Submodule .flutter updated: ba39319843...761747bfc5
									
								
							
							
								
								
									
										10
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							@@ -15,7 +15,16 @@ jobs:
 | 
			
		||||
      
 | 
			
		||||
      - uses: actions/checkout@v3
 | 
			
		||||
      - 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
 | 
			
		||||
        id: import_pgp_key
 | 
			
		||||
        uses: crazy-max/ghaction-import-gpg@v6
 | 
			
		||||
@@ -42,7 +51,6 @@ jobs:
 | 
			
		||||
          if [ ${{ inputs.beta }} == true ]; then BETA=true; else BETA=false; fi
 | 
			
		||||
          echo "beta=$BETA" >> $GITHUB_OUTPUT
 | 
			
		||||
          TAG="v$VERSION"
 | 
			
		||||
          if [ $BETA == true ]; then TAG="$TAG"-beta; fi
 | 
			
		||||
          echo "tag=$TAG" >> $GITHUB_OUTPUT
 | 
			
		||||
 | 
			
		||||
      - name: Build APKs
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								README.md
									
									
									
									
									
								
							@@ -4,11 +4,13 @@
 | 
			
		||||
 | 
			
		||||
Get Android App Updates Directly From the Source.
 | 
			
		||||
 | 
			
		||||
Obtainium allows you to install and update Apps directly from their releases pages, and receive notifications when new releases are made available.
 | 
			
		||||
Obtainium allows you to install and update apps directly from their releases pages, and receive notifications when new releases are made available.
 | 
			
		||||
 | 
			
		||||
Motivation: [Side Of Burritos - You should use this instead of F-Droid | How to use app RSS feed](https://youtu.be/FFz57zNR_M0)
 | 
			
		||||
 | 
			
		||||
Read the Wiki: [https://github.com/ImranR98/Obtainium/wiki](https://github.com/ImranR98/Obtainium/wiki)
 | 
			
		||||
More info:
 | 
			
		||||
- [Obtainium/wiki](https://github.com/ImranR98/Obtainium/wiki)
 | 
			
		||||
- [AppVerifier](https://github.com/soupslurpr/AppVerifier) - App verification tool (recommended, integrates with Obtainium)
 | 
			
		||||
- [apps.obtainium.imranr.dev](https://apps.obtainium.imranr.dev/) - Crowdsourced app configurations
 | 
			
		||||
- [Side Of Burritos - You should use this instead of F-Droid | How to use app RSS feed](https://youtu.be/FFz57zNR_M0) - Original motivation for this app
 | 
			
		||||
 | 
			
		||||
Currently supported App sources:
 | 
			
		||||
- Open Source - General:
 | 
			
		||||
@@ -18,7 +20,6 @@ Currently supported App sources:
 | 
			
		||||
  - [F-Droid](https://f-droid.org/)
 | 
			
		||||
  - Third Party F-Droid Repos
 | 
			
		||||
  - [IzzyOnDroid](https://android.izzysoft.de/)
 | 
			
		||||
  - [SourceForge](https://sourceforge.net/)
 | 
			
		||||
  - [SourceHut](https://git.sr.ht/)
 | 
			
		||||
- Other - General:
 | 
			
		||||
  - [APKPure](https://apkpure.net/)
 | 
			
		||||
@@ -28,15 +29,23 @@ Currently supported App sources:
 | 
			
		||||
  - [Huawei AppGallery](https://appgallery.huawei.com/)
 | 
			
		||||
  - Jenkins Jobs
 | 
			
		||||
- Open Source - App-Specific:
 | 
			
		||||
  - [Mullvad](https://mullvad.net/en/)
 | 
			
		||||
  - [Signal](https://signal.org/)
 | 
			
		||||
  - [VLC](https://videolan.org/)
 | 
			
		||||
- Other - App-Specific:
 | 
			
		||||
  - [WhatsApp](https://whatsapp.com)
 | 
			
		||||
  - [Telegram App](https://telegram.org)
 | 
			
		||||
  - [Neutron Code](https://neutroncode.com)
 | 
			
		||||
- Direct APK Link
 | 
			
		||||
- "HTML" (Fallback): Any other URL that returns an HTML page with links to APK files
 | 
			
		||||
 | 
			
		||||
## Finding App Configurations
 | 
			
		||||
 | 
			
		||||
You can find crowdsourced app configurations at [apps.obtainium.imranr.dev](https://apps.obtainium.imranr.dev).
 | 
			
		||||
 | 
			
		||||
If you can't find the configuration for an app you want, feel free to leave a request on the [discussions page](https://github.com/ImranR98/apps.obtainium.imranr.dev/discussions/new?category=app-requests).
 | 
			
		||||
 | 
			
		||||
Or, contribute some configurations to the website by creating a PR at [this repo](https://github.com/ImranR98/apps.obtainium.imranr.dev).
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
[<img src="https://github.com/machiav3lli/oandbackupx/blob/034b226cea5c1b30eb4f6a6f313e4dadcbb0ece4/badge_github.png"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,9 @@
 | 
			
		||||
plugins {
 | 
			
		||||
    id "com.android.application"
 | 
			
		||||
    id "kotlin-android"
 | 
			
		||||
    id "dev.flutter.flutter-gradle-plugin"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def localProperties = new Properties()
 | 
			
		||||
def localPropertiesFile = rootProject.file('local.properties')
 | 
			
		||||
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')
 | 
			
		||||
if (flutterVersionCode == null) {
 | 
			
		||||
    flutterVersionCode = '1'
 | 
			
		||||
@@ -21,11 +22,6 @@ if (flutterVersionName == null) {
 | 
			
		||||
    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 keystorePropertiesFile = rootProject.file('key.properties')
 | 
			
		||||
if (keystorePropertiesFile.exists()) {
 | 
			
		||||
@@ -33,7 +29,8 @@ if (keystorePropertiesFile.exists()) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
android {
 | 
			
		||||
    compileSdkVersion rootProject.ext.compileSdkVersion
 | 
			
		||||
    namespace "dev.imranr.obtainium"
 | 
			
		||||
    compileSdk flutter.compileSdkVersion
 | 
			
		||||
    ndkVersion flutter.ndkVersion
 | 
			
		||||
 | 
			
		||||
    compileOptions {
 | 
			
		||||
@@ -54,7 +51,7 @@ android {
 | 
			
		||||
        // 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.
 | 
			
		||||
        minSdkVersion 24
 | 
			
		||||
        targetSdkVersion rootProject.ext.targetSdkVersion
 | 
			
		||||
        targetSdkVersion flutter.targetSdkVersion
 | 
			
		||||
        versionCode flutterVersionCode.toInteger()
 | 
			
		||||
        versionName flutterVersionName
 | 
			
		||||
    }
 | 
			
		||||
@@ -95,20 +92,6 @@ repositories {
 | 
			
		||||
    maven { url 'https://jitpack.io' }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
    def shizuku_version = '13.1.5'
 | 
			
		||||
    implementation "dev.rikka.shizuku:api:$shizuku_version"
 | 
			
		||||
    implementation "dev.rikka.shizuku:provider:$shizuku_version"
 | 
			
		||||
 | 
			
		||||
    def hidden_api_version = '4.3.1'
 | 
			
		||||
    implementation "dev.rikka.tools.refine:runtime:$hidden_api_version"
 | 
			
		||||
    implementation "dev.rikka.hidden:compat:$hidden_api_version"
 | 
			
		||||
    compileOnly "dev.rikka.hidden:stub:$hidden_api_version"
 | 
			
		||||
    implementation "org.lsposed.hiddenapibypass:hiddenapibypass:4.3"
 | 
			
		||||
 | 
			
		||||
    implementation "com.github.topjohnwu.libsu:core:5.2.2"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ext.abiCodes = ["x86_64": 1, "armeabi-v7a": 2, "arm64-v8a": 3]
 | 
			
		||||
import com.android.build.OutputFile
 | 
			
		||||
android.applicationVariants.all { variant ->
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,8 @@
 | 
			
		||||
        android:name="${applicationName}"
 | 
			
		||||
        android:icon="@mipmap/ic_launcher"
 | 
			
		||||
        android:requestLegacyExternalStorage="true"
 | 
			
		||||
        android:usesCleartextTraffic="true">
 | 
			
		||||
        android:usesCleartextTraffic="true"
 | 
			
		||||
        android:localeConfig="@xml/locales_config">
 | 
			
		||||
        <activity
 | 
			
		||||
            android:name=".MainActivity"
 | 
			
		||||
            android:exported="true"
 | 
			
		||||
@@ -47,7 +48,7 @@
 | 
			
		||||
            android:value="2" />
 | 
			
		||||
        <provider
 | 
			
		||||
            android:name="androidx.core.content.FileProvider"
 | 
			
		||||
            android:authorities="dev.imranr.obtainium"
 | 
			
		||||
            android:authorities="${applicationId}"
 | 
			
		||||
            android:grantUriPermissions="true">
 | 
			
		||||
            <meta-data
 | 
			
		||||
                android:name="android.support.FILE_PROVIDER_PATHS"
 | 
			
		||||
@@ -72,4 +73,4 @@
 | 
			
		||||
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
 | 
			
		||||
        android:maxSdkVersion="29" />\
 | 
			
		||||
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
 | 
			
		||||
</manifest>
 | 
			
		||||
</manifest>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,44 +0,0 @@
 | 
			
		||||
package dev.imranr.obtainium
 | 
			
		||||
 | 
			
		||||
import android.util.Xml
 | 
			
		||||
import org.xmlpull.v1.XmlPullParser
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.io.FileInputStream
 | 
			
		||||
 | 
			
		||||
class DefaultSystemFont {
 | 
			
		||||
    fun get(): String {
 | 
			
		||||
        return try {
 | 
			
		||||
            val file = File("/system/etc/fonts.xml")
 | 
			
		||||
            val fileStream = FileInputStream(file)
 | 
			
		||||
            parseFontsFileStream(fileStream)
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            e.message ?: "Unknown fonts.xml parsing exception"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun parseFontsFileStream(fileStream: FileInputStream): String {
 | 
			
		||||
        fileStream.use { stream ->
 | 
			
		||||
            val parser = Xml.newPullParser()
 | 
			
		||||
            parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false)
 | 
			
		||||
            parser.setInput(stream, null)
 | 
			
		||||
            parser.nextTag()
 | 
			
		||||
            return parseFonts(parser)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun parseFonts(parser: XmlPullParser): String {
 | 
			
		||||
        while (!((parser.next() == XmlPullParser.END_TAG) && (parser.name == "family"))) {
 | 
			
		||||
            if ((parser.eventType == XmlPullParser.START_TAG) && (parser.name == "font")
 | 
			
		||||
                && (parser.getAttributeValue(null, "style") == "normal")
 | 
			
		||||
                && (parser.getAttributeValue(null, "weight") == "400")) {
 | 
			
		||||
                break
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        parser.next()
 | 
			
		||||
        val fontFile = parser.text.trim()
 | 
			
		||||
        if (fontFile == "") {
 | 
			
		||||
            throw NoSuchFieldException("The font filename couldn't be found in fonts.xml")
 | 
			
		||||
        }
 | 
			
		||||
        return "/system/fonts/$fontFile"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,179 +1,5 @@
 | 
			
		||||
package dev.imranr.obtainium
 | 
			
		||||
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.content.IntentSender
 | 
			
		||||
import android.content.pm.IPackageInstaller
 | 
			
		||||
import android.content.pm.IPackageInstallerSession
 | 
			
		||||
import android.content.pm.PackageInstaller
 | 
			
		||||
import android.content.pm.PackageManager
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.os.Process
 | 
			
		||||
import androidx.annotation.NonNull
 | 
			
		||||
import com.topjohnwu.superuser.Shell
 | 
			
		||||
import dev.imranr.obtainium.util.IIntentSenderAdaptor
 | 
			
		||||
import dev.imranr.obtainium.util.IntentSenderUtils
 | 
			
		||||
import dev.imranr.obtainium.util.PackageInstallerUtils
 | 
			
		||||
import dev.imranr.obtainium.util.ShizukuSystemServerApi
 | 
			
		||||
import io.flutter.embedding.android.FlutterActivity
 | 
			
		||||
import io.flutter.embedding.engine.FlutterEngine
 | 
			
		||||
import io.flutter.plugin.common.MethodChannel
 | 
			
		||||
import io.flutter.plugin.common.MethodChannel.Result
 | 
			
		||||
import java.io.IOException
 | 
			
		||||
import java.util.concurrent.CountDownLatch
 | 
			
		||||
import org.lsposed.hiddenapibypass.HiddenApiBypass
 | 
			
		||||
import rikka.shizuku.Shizuku
 | 
			
		||||
import rikka.shizuku.Shizuku.OnRequestPermissionResultListener
 | 
			
		||||
import rikka.shizuku.ShizukuBinderWrapper
 | 
			
		||||
 | 
			
		||||
class MainActivity: FlutterActivity() {
 | 
			
		||||
    private var nativeChannel: MethodChannel? = null
 | 
			
		||||
    private val SHIZUKU_PERMISSION_REQUEST_CODE = (10..200).random()
 | 
			
		||||
 | 
			
		||||
    private fun shizukuCheckPermission(result: Result) {
 | 
			
		||||
        try {
 | 
			
		||||
            if (Shizuku.isPreV11()) {  // Unsupported
 | 
			
		||||
                result.success(-1)
 | 
			
		||||
            } else if (Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED) {
 | 
			
		||||
                result.success(1)
 | 
			
		||||
            } else if (Shizuku.shouldShowRequestPermissionRationale()) {  // Deny and don't ask again
 | 
			
		||||
                result.success(0)
 | 
			
		||||
            } else {
 | 
			
		||||
                Shizuku.requestPermission(SHIZUKU_PERMISSION_REQUEST_CODE)
 | 
			
		||||
                result.success(-2)
 | 
			
		||||
            }
 | 
			
		||||
        } catch (_: Exception) {  // If shizuku not running
 | 
			
		||||
            result.success(-1)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private val shizukuRequestPermissionResultListener = OnRequestPermissionResultListener {
 | 
			
		||||
            requestCode: Int, grantResult: Int ->
 | 
			
		||||
        if (requestCode == SHIZUKU_PERMISSION_REQUEST_CODE) {
 | 
			
		||||
            val res = if (grantResult == PackageManager.PERMISSION_GRANTED) 1 else 0
 | 
			
		||||
            nativeChannel!!.invokeMethod("resPermShizuku", mapOf("res" to res))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun shizukuInstallApk(apkFileUri: String, result: Result) {
 | 
			
		||||
        val uri = Uri.parse(apkFileUri)
 | 
			
		||||
        var res = false
 | 
			
		||||
        var session: PackageInstaller.Session? = null
 | 
			
		||||
        try {
 | 
			
		||||
            val iPackageInstaller: IPackageInstaller =
 | 
			
		||||
                ShizukuSystemServerApi.PackageManager_getPackageInstaller()
 | 
			
		||||
            val isRoot = Shizuku.getUid() == 0
 | 
			
		||||
            // The reason for use "com.android.shell" as installer package under adb
 | 
			
		||||
            // is that getMySessions will check installer package's owner
 | 
			
		||||
            val installerPackageName = if (isRoot) packageName else "com.android.shell"
 | 
			
		||||
            var installerAttributionTag: String? = null
 | 
			
		||||
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
 | 
			
		||||
                installerAttributionTag = attributionTag
 | 
			
		||||
            }
 | 
			
		||||
            val userId = if (isRoot) Process.myUserHandle().hashCode() else 0
 | 
			
		||||
            val packageInstaller = PackageInstallerUtils.createPackageInstaller(
 | 
			
		||||
                iPackageInstaller, installerPackageName, installerAttributionTag, userId)
 | 
			
		||||
            val params =
 | 
			
		||||
                PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
 | 
			
		||||
            var installFlags: Int = PackageInstallerUtils.getInstallFlags(params)
 | 
			
		||||
            installFlags = installFlags or (0x00000002/*PackageManager.INSTALL_REPLACE_EXISTING*/
 | 
			
		||||
                    or 0x00000004 /*PackageManager.INSTALL_ALLOW_TEST*/)
 | 
			
		||||
            PackageInstallerUtils.setInstallFlags(params, installFlags)
 | 
			
		||||
            val sessionId = packageInstaller.createSession(params)
 | 
			
		||||
            val iSession = IPackageInstallerSession.Stub.asInterface(
 | 
			
		||||
                ShizukuBinderWrapper(iPackageInstaller.openSession(sessionId).asBinder()))
 | 
			
		||||
            session = PackageInstallerUtils.createSession(iSession)
 | 
			
		||||
            val inputStream = contentResolver.openInputStream(uri)
 | 
			
		||||
            val openedSession = session.openWrite("apk.apk", 0, -1)
 | 
			
		||||
            val buffer = ByteArray(8192)
 | 
			
		||||
            var length: Int
 | 
			
		||||
            try {
 | 
			
		||||
                while (inputStream!!.read(buffer).also { length = it } > 0) {
 | 
			
		||||
                    openedSession.write(buffer, 0, length)
 | 
			
		||||
                    openedSession.flush()
 | 
			
		||||
                    session.fsync(openedSession)
 | 
			
		||||
                }
 | 
			
		||||
            } finally {
 | 
			
		||||
                try {
 | 
			
		||||
                    inputStream!!.close()
 | 
			
		||||
                    openedSession.close()
 | 
			
		||||
                } catch (e: IOException) {
 | 
			
		||||
                    e.printStackTrace()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            val results = arrayOf<Intent?>(null)
 | 
			
		||||
            val countDownLatch = CountDownLatch(1)
 | 
			
		||||
            val intentSender: IntentSender =
 | 
			
		||||
                IntentSenderUtils.newInstance(object : IIntentSenderAdaptor() {
 | 
			
		||||
                    override fun send(intent: Intent?) {
 | 
			
		||||
                        results[0] = intent
 | 
			
		||||
                        countDownLatch.countDown()
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
            session.commit(intentSender)
 | 
			
		||||
            countDownLatch.await()
 | 
			
		||||
            res = results[0]!!.getIntExtra(
 | 
			
		||||
                PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE) == 0
 | 
			
		||||
        } catch (_: Exception) {
 | 
			
		||||
            res = false
 | 
			
		||||
        } finally {
 | 
			
		||||
            if (session != null) {
 | 
			
		||||
                try {
 | 
			
		||||
                    session.close()
 | 
			
		||||
                } catch (_: Exception) {
 | 
			
		||||
                    res = false
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        result.success(res)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun rootCheckPermission(result: Result) {
 | 
			
		||||
        Shell.getShell(Shell.GetShellCallback(
 | 
			
		||||
            fun(shell: Shell) {
 | 
			
		||||
                result.success(shell.isRoot)
 | 
			
		||||
            }
 | 
			
		||||
        ))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun rootInstallApk(apkFilePath: String, result: Result) {
 | 
			
		||||
        Shell.sh("pm install -r -t " + apkFilePath).submit { out ->
 | 
			
		||||
            val builder = StringBuilder()
 | 
			
		||||
            for (data in out.getOut()) { builder.append(data) }
 | 
			
		||||
            result.success(builder.toString().endsWith("Success"))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
 | 
			
		||||
        super.configureFlutterEngine(flutterEngine)
 | 
			
		||||
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
 | 
			
		||||
            HiddenApiBypass.addHiddenApiExemptions("")
 | 
			
		||||
        }
 | 
			
		||||
        Shizuku.addRequestPermissionResultListener(shizukuRequestPermissionResultListener)
 | 
			
		||||
        nativeChannel = MethodChannel(
 | 
			
		||||
            flutterEngine.dartExecutor.binaryMessenger, "native")
 | 
			
		||||
        nativeChannel!!.setMethodCallHandler {
 | 
			
		||||
            call, result ->
 | 
			
		||||
            if (call.method == "getSystemFont") {
 | 
			
		||||
                val res = DefaultSystemFont().get()
 | 
			
		||||
                result.success(res)
 | 
			
		||||
            } else if (call.method == "checkPermissionShizuku") {
 | 
			
		||||
                shizukuCheckPermission(result)
 | 
			
		||||
            } else if (call.method == "checkPermissionRoot") {
 | 
			
		||||
                rootCheckPermission(result)
 | 
			
		||||
            } else if (call.method == "installWithShizuku") {
 | 
			
		||||
                val apkFileUri: String? = call.argument("apkFileUri")
 | 
			
		||||
                shizukuInstallApk(apkFileUri!!, result)
 | 
			
		||||
            } else if (call.method == "installWithRoot") {
 | 
			
		||||
                val apkFilePath: String? = call.argument("apkFilePath")
 | 
			
		||||
                rootInstallApk(apkFilePath!!, result)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onDestroy() {
 | 
			
		||||
        super.onDestroy()
 | 
			
		||||
        Shizuku.removeRequestPermissionResultListener(shizukuRequestPermissionResultListener)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
class MainActivity: FlutterActivity()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,37 +0,0 @@
 | 
			
		||||
package dev.imranr.obtainium.util;
 | 
			
		||||
 | 
			
		||||
import android.annotation.SuppressLint;
 | 
			
		||||
import android.app.Application;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.InvocationTargetException;
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
 | 
			
		||||
public class ApplicationUtils {
 | 
			
		||||
 | 
			
		||||
    private static Application application;
 | 
			
		||||
 | 
			
		||||
    public static Application getApplication() {
 | 
			
		||||
        return application;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void setApplication(Application application) {
 | 
			
		||||
        ApplicationUtils.application = application;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String getProcessName() {
 | 
			
		||||
        if (Build.VERSION.SDK_INT >= 28)
 | 
			
		||||
            return Application.getProcessName();
 | 
			
		||||
        else {
 | 
			
		||||
            try {
 | 
			
		||||
                @SuppressLint("PrivateApi")
 | 
			
		||||
                Class<?> activityThread = Class.forName("android.app.ActivityThread");
 | 
			
		||||
                @SuppressLint("DiscouragedPrivateApi")
 | 
			
		||||
                Method method = activityThread.getDeclaredMethod("currentProcessName");
 | 
			
		||||
                return (String) method.invoke(null);
 | 
			
		||||
            } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
 | 
			
		||||
                throw new RuntimeException(e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
package dev.imranr.obtainium.util;
 | 
			
		||||
 | 
			
		||||
import android.content.IIntentReceiver;
 | 
			
		||||
import android.content.IIntentSender;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.os.IBinder;
 | 
			
		||||
 | 
			
		||||
public abstract class IIntentSenderAdaptor extends IIntentSender.Stub {
 | 
			
		||||
 | 
			
		||||
    public abstract void send(Intent intent);
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int send(int code, Intent intent, String resolvedType, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
 | 
			
		||||
        send(intent);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken, IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
 | 
			
		||||
        send(intent);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
package dev.imranr.obtainium.util;
 | 
			
		||||
 | 
			
		||||
import android.content.IIntentSender;
 | 
			
		||||
import android.content.IntentSender;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.InvocationTargetException;
 | 
			
		||||
 | 
			
		||||
public class IntentSenderUtils {
 | 
			
		||||
 | 
			
		||||
    public static IntentSender newInstance(IIntentSender binder) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
 | 
			
		||||
        //noinspection JavaReflectionMemberAccess
 | 
			
		||||
        return IntentSender.class.getConstructor(IIntentSender.class).newInstance(binder);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,41 +0,0 @@
 | 
			
		||||
package dev.imranr.obtainium.util;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.pm.IPackageInstaller;
 | 
			
		||||
import android.content.pm.IPackageInstallerSession;
 | 
			
		||||
import android.content.pm.PackageInstaller;
 | 
			
		||||
import android.content.pm.PackageManager;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.InvocationTargetException;
 | 
			
		||||
 | 
			
		||||
@SuppressWarnings({"JavaReflectionMemberAccess"})
 | 
			
		||||
public class PackageInstallerUtils {
 | 
			
		||||
 | 
			
		||||
    public static PackageInstaller createPackageInstaller(IPackageInstaller installer, String installerPackageName, String installerAttributionTag, int userId) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
 | 
			
		||||
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
 | 
			
		||||
            return PackageInstaller.class.getConstructor(IPackageInstaller.class, String.class, String.class, int.class)
 | 
			
		||||
                    .newInstance(installer, installerPackageName, installerAttributionTag, userId);
 | 
			
		||||
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 | 
			
		||||
            return PackageInstaller.class.getConstructor(IPackageInstaller.class, String.class, int.class)
 | 
			
		||||
                    .newInstance(installer, installerPackageName, userId);
 | 
			
		||||
        } else {
 | 
			
		||||
            return PackageInstaller.class.getConstructor(Context.class, PackageManager.class, IPackageInstaller.class, String.class, int.class)
 | 
			
		||||
                    .newInstance(ApplicationUtils.getApplication(), ApplicationUtils.getApplication().getPackageManager(), installer, installerPackageName, userId);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static PackageInstaller.Session createSession(IPackageInstallerSession session) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
 | 
			
		||||
        return PackageInstaller.Session.class.getConstructor(IPackageInstallerSession.class)
 | 
			
		||||
                .newInstance(session);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int getInstallFlags(PackageInstaller.SessionParams params) throws NoSuchFieldException, IllegalAccessException {
 | 
			
		||||
        return (int) PackageInstaller.SessionParams.class.getDeclaredField("installFlags").get(params);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void setInstallFlags(PackageInstaller.SessionParams params, int newValue) throws NoSuchFieldException, IllegalAccessException {
 | 
			
		||||
        PackageInstaller.SessionParams.class.getDeclaredField("installFlags").set(params, newValue);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,68 +0,0 @@
 | 
			
		||||
package dev.imranr.obtainium.util;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.pm.IPackageInstaller;
 | 
			
		||||
import android.content.pm.IPackageManager;
 | 
			
		||||
import android.content.pm.UserInfo;
 | 
			
		||||
import android.os.Build;
 | 
			
		||||
import android.os.IUserManager;
 | 
			
		||||
import android.os.RemoteException;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import rikka.shizuku.ShizukuBinderWrapper;
 | 
			
		||||
import rikka.shizuku.SystemServiceHelper;
 | 
			
		||||
 | 
			
		||||
public class ShizukuSystemServerApi {
 | 
			
		||||
 | 
			
		||||
    private static final Singleton<IPackageManager> PACKAGE_MANAGER = new Singleton<IPackageManager>() {
 | 
			
		||||
        @Override
 | 
			
		||||
        protected IPackageManager create() {
 | 
			
		||||
            return IPackageManager.Stub.asInterface(new ShizukuBinderWrapper(SystemServiceHelper.getSystemService("package")));
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    private static final Singleton<IUserManager> USER_MANAGER = new Singleton<IUserManager>() {
 | 
			
		||||
        @Override
 | 
			
		||||
        protected IUserManager create() {
 | 
			
		||||
            return IUserManager.Stub.asInterface(new ShizukuBinderWrapper(SystemServiceHelper.getSystemService(Context.USER_SERVICE)));
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    public static IPackageInstaller PackageManager_getPackageInstaller() throws RemoteException {
 | 
			
		||||
        IPackageInstaller packageInstaller = PACKAGE_MANAGER.get().getPackageInstaller();
 | 
			
		||||
        return IPackageInstaller.Stub.asInterface(new ShizukuBinderWrapper(packageInstaller.asBinder()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List<UserInfo> UserManager_getUsers(boolean excludePartial, boolean excludeDying, boolean excludePreCreated) throws RemoteException {
 | 
			
		||||
        if (Build.VERSION.SDK_INT >= 30) {
 | 
			
		||||
            return USER_MANAGER.get().getUsers(excludePartial, excludeDying, excludePreCreated);
 | 
			
		||||
        } else {
 | 
			
		||||
            try {
 | 
			
		||||
                return USER_MANAGER.get().getUsers(excludeDying);
 | 
			
		||||
            } catch (NoSuchFieldError e) {
 | 
			
		||||
                return USER_MANAGER.get().getUsers(excludePartial, excludeDying, excludePreCreated);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // method 2: use transactRemote directly
 | 
			
		||||
    /*public static List<UserInfo> UserManager_getUsers(boolean excludeDying) {
 | 
			
		||||
        Parcel data = SystemServiceHelper.obtainParcel(Context.USER_SERVICE, "android.os.IUserManager", "getUsers");
 | 
			
		||||
        Parcel reply = Parcel.obtain();
 | 
			
		||||
        data.writeInt(excludeDying ? 1 : 0);
 | 
			
		||||
 | 
			
		||||
        List<UserInfo> res = null;
 | 
			
		||||
        try {
 | 
			
		||||
            ShizukuService.transactRemote(data, reply, 0);
 | 
			
		||||
            reply.readException();
 | 
			
		||||
            res = reply.createTypedArrayList(UserInfo.CREATOR);
 | 
			
		||||
        } catch (RemoteException e) {
 | 
			
		||||
            Log.e("ShizukuSample", "UserManager#getUsers", e);
 | 
			
		||||
        } finally {
 | 
			
		||||
            data.recycle();
 | 
			
		||||
            reply.recycle();
 | 
			
		||||
        }
 | 
			
		||||
        return res;
 | 
			
		||||
    }*/
 | 
			
		||||
}
 | 
			
		||||
@@ -1,17 +0,0 @@
 | 
			
		||||
package dev.imranr.obtainium.util;
 | 
			
		||||
 | 
			
		||||
public abstract class Singleton<T> {
 | 
			
		||||
 | 
			
		||||
    private T mInstance;
 | 
			
		||||
 | 
			
		||||
    protected abstract T create();
 | 
			
		||||
 | 
			
		||||
    public final T get() {
 | 
			
		||||
        synchronized (this) {
 | 
			
		||||
            if (mInstance == null) {
 | 
			
		||||
                mInstance = create();
 | 
			
		||||
            }
 | 
			
		||||
            return mInstance;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								android/app/src/main/res/xml/locales_config.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								android/app/src/main/res/xml/locales_config.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
 | 
			
		||||
    <locale android:name="bs"/>
 | 
			
		||||
    <locale android:name="cs"/>
 | 
			
		||||
    <locale android:name="de"/>
 | 
			
		||||
    <locale android:name="en"/>
 | 
			
		||||
    <locale android:name="es"/>
 | 
			
		||||
    <locale android:name="fa"/>
 | 
			
		||||
    <locale android:name="fr"/>
 | 
			
		||||
    <locale android:name="hu"/>
 | 
			
		||||
    <locale android:name="it"/>
 | 
			
		||||
    <locale android:name="ja"/>
 | 
			
		||||
    <locale android:name="nl"/>
 | 
			
		||||
    <locale android:name="pl"/>
 | 
			
		||||
    <locale android:name="pt"/>
 | 
			
		||||
    <locale android:name="ru"/>
 | 
			
		||||
    <locale android:name="sv"/>
 | 
			
		||||
    <locale android:name="tr"/>
 | 
			
		||||
    <locale android:name="uk"/>
 | 
			
		||||
    <locale android:name="vi"/>
 | 
			
		||||
    <locale android:name="zh"/>
 | 
			
		||||
</locale-config>
 | 
			
		||||
@@ -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 {
 | 
			
		||||
    repositories {
 | 
			
		||||
        google()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
org.gradle.jvmargs=-Xmx1536M
 | 
			
		||||
org.gradle.jvmargs=-Xmx2048M
 | 
			
		||||
android.useAndroidX=true
 | 
			
		||||
android.enableJetifier=true
 | 
			
		||||
 
 | 
			
		||||
@@ -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")
 | 
			
		||||
def properties = new Properties()
 | 
			
		||||
    includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
 | 
			
		||||
 | 
			
		||||
assert localPropertiesFile.exists()
 | 
			
		||||
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
 | 
			
		||||
    repositories {
 | 
			
		||||
        google()
 | 
			
		||||
        mavenCentral()
 | 
			
		||||
        gradlePluginPortal()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
 | 
			
		||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
 | 
			
		||||
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
 | 
			
		||||
plugins {
 | 
			
		||||
    id "dev.flutter.flutter-plugin-loader" version "1.0.0"
 | 
			
		||||
    id "com.android.application" version "7.4.2" apply false
 | 
			
		||||
    id "org.jetbrains.kotlin.android" version "1.8.10" apply false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
include ":app"
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(obavezno)",
 | 
			
		||||
    "dropdownNoOptsError": "GREŠKA: PADAJUĆI MENI MORA IMATI NAJMANJE JEDNU OPCIJU",
 | 
			
		||||
    "colour": "Boja",
 | 
			
		||||
    "standard": "Standard",
 | 
			
		||||
    "custom": "Custom",
 | 
			
		||||
    "useMaterialYou": "Use Material You",
 | 
			
		||||
    "githubStarredRepos": "GitHub repo-i sa zvjezdicom",
 | 
			
		||||
    "uname": "Korisničko ime",
 | 
			
		||||
    "wrongArgNum": "Naveden je pogrešan broj argumenata",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Tamna",
 | 
			
		||||
    "light": "Svijetla",
 | 
			
		||||
    "followSystem": "Pratite sistem",
 | 
			
		||||
    "followSystemThemeExplanation": "Following system theme is possible only by using third-party applications",
 | 
			
		||||
    "useBlackTheme": "Koristite čisto crnu tamnu temu",
 | 
			
		||||
    "appSortBy": "Aplikacije sortirane po",
 | 
			
		||||
    "authorName": "Autor/Ime",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "Nema novih ažuriranja.",
 | 
			
		||||
    "xHasAnUpdate": "{} ima ažuriranje.",
 | 
			
		||||
    "appsUpdated": "Aplikacije su ažurirane",
 | 
			
		||||
    "appsNotUpdated": "Failed to update applications",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Obavještava korisnika da su u pozadini primijenjena ažuriranja na jednu ili više aplikacija",
 | 
			
		||||
    "xWasUpdatedToY": "{} je ažuriran na {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Failed to update {} to {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Greška pri provjeri ažuriranja",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Obavijest koja se prikazuje kada provjera sigurnosnog ažuriranja ne uspije",
 | 
			
		||||
    "appsRemoved": "Aplikacije su uklonjene",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "Onemogući detekciju verzije",
 | 
			
		||||
    "noVersionDetectionExplanation": "Ova opcija bi se trebala koristiti samo za aplikacije gdje detekcija verzije ne radi ispravno.",
 | 
			
		||||
    "downloadingX": "Preuzimanje {}",
 | 
			
		||||
    "downloadX": "Download {}",
 | 
			
		||||
    "downloadedX": "Downloaded {}",
 | 
			
		||||
    "releaseAsset": "Release Asset",
 | 
			
		||||
    "downloadNotifDescription": "Obavještava korisnika o napretku u preuzimanju aplikacije",
 | 
			
		||||
    "noAPKFound": "APK nije pronađen",
 | 
			
		||||
    "noVersionDetection": "Nema detekcije verzije",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "Podržite fiksne APK URL-ove",
 | 
			
		||||
    "selectX": "Izaberite {}",
 | 
			
		||||
    "parallelDownloads": "Dozvoli paralelna preuzimanja",
 | 
			
		||||
    "installMethod": "Način instalacije",
 | 
			
		||||
    "normal": "normalno",
 | 
			
		||||
    "root": "korijen",
 | 
			
		||||
    "useShizuku": "Use Shizuku or Sui to install",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku is not running",
 | 
			
		||||
    "shizukuOld": "Old Shizuku version (<11) - update it",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku running on Android < 8.1 with ADB - update Android or use Sui instead",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Set Google Play as the installation source (if Shizuku is used)",
 | 
			
		||||
    "useSystemFont": "Koristite sistemski font",
 | 
			
		||||
    "systemFontError": "Greška pri učitavanju sistemskog fonta: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Koristite kod verzije aplikacije kao verziju koju je otkrio OS",
 | 
			
		||||
    "requestHeader": "Zaglavlje zahtjeva",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Koristite najnovije otpremanje materijala kao datum izdavanja",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Note",
 | 
			
		||||
    "selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
 | 
			
		||||
    "badDownload": "The APK could not be parsed (incompatible or partial download)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)",
 | 
			
		||||
    "appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.",
 | 
			
		||||
    "wiki": "Help/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Želite li ukloniti aplikaciju?",
 | 
			
		||||
        "other": "Želite li ukloniti aplikacije?"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} i još 1 aplikacija je ažurirana.",
 | 
			
		||||
        "other": "{} i još {} aplikacija je ažurirano."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Failed to update {} and 1 more app.",
 | 
			
		||||
        "other": "Failed to update {} and {} more apps."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} i još jedna aplikacija je vjerovatno ažurirana.",
 | 
			
		||||
        "other": "{} i još {} aplikacija su vjerovatno ažurirane."
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(Požadované)",
 | 
			
		||||
    "dropdownNoOptsError": "ERROR: DROPDOWN MUSÍ MÍT AŽ JEDNU MOŽNOST",
 | 
			
		||||
    "colour": "Barva",
 | 
			
		||||
    "standard": "Standardní",
 | 
			
		||||
    "custom": "Vlastní",
 | 
			
		||||
    "useMaterialYou": "Použijte materiál, který jste",
 | 
			
		||||
    "githubStarredRepos": "GitHub označená hvězdičkou",
 | 
			
		||||
    "uname": "Uživatelské jméno",
 | 
			
		||||
    "wrongArgNum": "Nesprávný počet zadaných argumentů",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Tmavé",
 | 
			
		||||
    "light": "Světlé",
 | 
			
		||||
    "followSystem": "Jako systém",
 | 
			
		||||
    "followSystemThemeExplanation": "Sledování motivu systému je možné pouze pomocí aplikací třetích stran.",
 | 
			
		||||
    "useBlackTheme": "Použít čistě černé tmavé téma",
 | 
			
		||||
    "appSortBy": "Seřadit podle",
 | 
			
		||||
    "authorName": "Autor/Jméno",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "Žádné nové aktualizace.",
 | 
			
		||||
    "xHasAnUpdate": "{} má aktualizaci.",
 | 
			
		||||
    "appsUpdated": "Aplikace aktualizovány",
 | 
			
		||||
    "appsNotUpdated": "Nepodařilo se aktualizovat aplikace",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Upozornit, že byly provedeny aktualizace jedné nebo více aplikací na pozadí",
 | 
			
		||||
    "xWasUpdatedToY": "{} byla aktualizována na {}",
 | 
			
		||||
    "xWasNotUpdatedToY": "Nepodařilo se aktualizovat {} na {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Chyba kontroly aktualizací",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Zobrazit oznámení při neúspěšné kontrole aktualizací na pozadí",
 | 
			
		||||
    "appsRemoved": "Odstraněné aplikace",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "Deaktivovat detekci verze",
 | 
			
		||||
    "noVersionDetectionExplanation": "Tato možnost by měla být použita pouze u aplikace, kde detekce verzí nefunguje správně.",
 | 
			
		||||
    "downloadingX": "Stáhnout {}",
 | 
			
		||||
    "downloadX": "Stáhnout {}",
 | 
			
		||||
    "downloadedX": "Staženo {}",
 | 
			
		||||
    "releaseAsset": "Vydání aktiva",
 | 
			
		||||
    "downloadNotifDescription": "Informuje uživatele o průběhu stahování aplikace",
 | 
			
		||||
    "noAPKFound": "Žádná APK nebyla nalezena",
 | 
			
		||||
    "noVersionDetection": "Žádná detekce verze",
 | 
			
		||||
@@ -218,7 +227,7 @@
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Nezobrazovat varování pro 'Jen sledované'",
 | 
			
		||||
    "dontShowAPKOriginWarnings": "Nezobrazovat varování pro původ APK",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Přesunout nenainstalované aplikace na konec zobrazení Aplikace",
 | 
			
		||||
    "gitlabPATLabel": "GitLab Personal Access Token",
 | 
			
		||||
    "gitlabPATLabel": "Osobní přístupový token GitLab",
 | 
			
		||||
    "about": "O",
 | 
			
		||||
    "requiresCredentialsInSettings": "{}: Vyžaduje další pověření (v nastavení)",
 | 
			
		||||
    "checkOnStart": "Zkontrolovat jednou při spuštění",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "Odhadnout novější verzi na základě prvních třiceti číslic kontrolního součtu adresy URL APK, pokud není podporována jinak",
 | 
			
		||||
    "selectX": "Vybrat {}",
 | 
			
		||||
    "parallelDownloads": "Povolit souběžné stahování",
 | 
			
		||||
    "installMethod": "Metoda instalace",
 | 
			
		||||
    "normal": "Normální",
 | 
			
		||||
    "root": "Správce",
 | 
			
		||||
    "useShizuku": "K instalaci použijte Shizuku nebo Sui",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku neběží",
 | 
			
		||||
    "shizukuOld": "Stará verze Shizuku (<11) - aktualizujte ji",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku běží na Androidu < 8.1 s ADB - aktualizujte Android nebo místo toho použijte Sui",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Nastavení Google Play jako zdroje instalace (pokud se používá Shizuku)",
 | 
			
		||||
    "useSystemFont": "Použít systémové písmo",
 | 
			
		||||
    "systemFontError": "Chyba při načítání systémového písma: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Použít kód verze aplikace jako verzi zjištěnou OS",
 | 
			
		||||
    "requestHeader": "Hlavička požadavku",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Použít poslední nahrané dílo jako datum vydání",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Poznámka",
 | 
			
		||||
    "selfHostedNote": "Rozbalovací seznam \"{}\" lze použít k dosažení vlastních/obvyklých instancí libovolného zdroje.",
 | 
			
		||||
    "badDownload": "APK nelze analyzovat (nekompatibilní nebo částečné stažení)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Sdílení nových aplikací s aplikací AppVerifier (pokud je k dispozici)",
 | 
			
		||||
    "appVerifierInstructionToast": "Sdílejte do aplikace AppVerifier a po dokončení se sem vraťte.",
 | 
			
		||||
    "wiki": "Nápověda/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Konfigurace aplikací s využitím crowdsourcingu (použití na vlastní nebezpečí)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Odstranit Apku?",
 | 
			
		||||
        "other": "Odstranit Apky?"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} a 1 další aplikace mají aktualizace.",
 | 
			
		||||
        "other": "{} a {} další aplikace byly aktualizovány."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Nepodařilo se aktualizovat {} a 1 další aplikaci.",
 | 
			
		||||
        "other": "Nepodařilo se aktualizovat {} a {} další aplikace."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} a 1 další aplikace možno aktualizovat",
 | 
			
		||||
        "other": "{} a {} další aplikace mohou být aktualizovány."
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										375
									
								
								assets/translations/da.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										375
									
								
								assets/translations/da.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,375 @@
 | 
			
		||||
{
 | 
			
		||||
    "invalidURLForSource": "Ikke et gyldigt {} App-URL",
 | 
			
		||||
    "noReleaseFound": "Kunne ikke finde en passende udgivelse",
 | 
			
		||||
    "noVersionFound": "Kunne ikke afgøre udgivelsesversion",
 | 
			
		||||
    "urlMatchesNoSource": "URL'en matcher ikke en kendt kilde",
 | 
			
		||||
    "cantInstallOlderVersion": "Kan ikke installere en ældre version af en app",
 | 
			
		||||
    "appIdMismatch": "Hentet pakke-ID matcher ikke eksisterende app-ID",
 | 
			
		||||
    "functionNotImplemented": "Denne klasse har ikke implementeret denne funktion",
 | 
			
		||||
    "placeholder": "Pladsholder",
 | 
			
		||||
    "someErrors": "Nogle fejl opstod",
 | 
			
		||||
    "unexpectedError": "Uventet fejl",
 | 
			
		||||
    "ok": "Okay",
 | 
			
		||||
    "and": "og",
 | 
			
		||||
    "githubPATLabel": "GitHub Personlig Adgangstoken (øger hastighedsgrænse)",
 | 
			
		||||
    "includePrereleases": "Inkluder forudgivelser",
 | 
			
		||||
    "fallbackToOlderReleases": "Fallback til ældre udgivelser",
 | 
			
		||||
    "filterReleaseTitlesByRegEx": "Filtrer udgivelsestitler efter regulært udtryk",
 | 
			
		||||
    "invalidRegEx": "Ugyldigt regulært udtryk",
 | 
			
		||||
    "noDescription": "Ingen beskrivelse",
 | 
			
		||||
    "cancel": "Annuller",
 | 
			
		||||
    "continue": "Fortsæt",
 | 
			
		||||
    "requiredInBrackets": "(Påkrævet)",
 | 
			
		||||
    "dropdownNoOptsError": "FEJL: RULLEMENU SKAL HAVE MINDST ÉT TILVALG",
 | 
			
		||||
    "colour": "Farve",
 | 
			
		||||
    "standard": "Standard",
 | 
			
		||||
    "custom": "Brugerdefineret",
 | 
			
		||||
    "useMaterialYou": "Brug Material You",
 | 
			
		||||
    "githubStarredRepos": "Stjernemarkeret GitHub-repos",
 | 
			
		||||
    "uname": "Brugernavn",
 | 
			
		||||
    "wrongArgNum": "Forkert antal argumenter angivet",
 | 
			
		||||
    "xIsTrackOnly": "{} kan kun følges",
 | 
			
		||||
    "source": "Kilde",
 | 
			
		||||
    "app": "App",
 | 
			
		||||
    "appsFromSourceAreTrackOnly": "Apps fra denne kilde er 'Følg Kun'.",
 | 
			
		||||
    "youPickedTrackOnly": "Du har valgt 'Følg Kun'-indstillingen.",
 | 
			
		||||
    "trackOnlyAppDescription": "Appen tjekkes for opdateringer, men Obtainium kan ikke hente eller installere den.",
 | 
			
		||||
    "cancelled": "Annulleret",
 | 
			
		||||
    "appAlreadyAdded": "Appen er allerede tilføjet",
 | 
			
		||||
    "alreadyUpToDateQuestion": "Appen er allerede opdateret?",
 | 
			
		||||
    "addApp": "Tilføj app",
 | 
			
		||||
    "appSourceURL": "URL til app-kilde",
 | 
			
		||||
    "error": "Fejl",
 | 
			
		||||
    "add": "Tilføj",
 | 
			
		||||
    "searchSomeSourcesLabel": "Søg (kun visse kilder)",
 | 
			
		||||
    "search": "Søg",
 | 
			
		||||
    "additionalOptsFor": "Yderligere indstillinger for {}",
 | 
			
		||||
    "supportedSources": "Understøttede kilder",
 | 
			
		||||
    "trackOnlyInBrackets": "(Følg Kun)",
 | 
			
		||||
    "searchableInBrackets": "(Kan Søges)",
 | 
			
		||||
    "appsString": "Apps",
 | 
			
		||||
    "noApps": "Ingen apps",
 | 
			
		||||
    "noAppsForFilter": "Ingen apps til filter",
 | 
			
		||||
    "byX": "Af {}",
 | 
			
		||||
    "percentProgress": "Fremskridt: {}%",
 | 
			
		||||
    "pleaseWait": "Vent venligst",
 | 
			
		||||
    "updateAvailable": "Opdatering tilgængelig",
 | 
			
		||||
    "notInstalled": "Ikke installeret",
 | 
			
		||||
    "pseudoVersion": "pseudo-version",
 | 
			
		||||
    "selectAll": "Vælg alle",
 | 
			
		||||
    "deselectX": "Fravælg {}",
 | 
			
		||||
    "xWillBeRemovedButRemainInstalled": "{} fjernes fra Obtainium, men forbliver installeret på enheden.",
 | 
			
		||||
    "removeSelectedAppsQuestion": "Fjern valgte apps?",
 | 
			
		||||
    "removeSelectedApps": "Fjern valgte apps",
 | 
			
		||||
    "updateX": "Opdater {}",
 | 
			
		||||
    "installX": "Installer {}",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "Markér {}\n(Følg Kun)\nsom opdateret",
 | 
			
		||||
    "changeX": "Skift {}",
 | 
			
		||||
    "installUpdateApps": "Installer/Opdater apps",
 | 
			
		||||
    "installUpdateSelectedApps": "Installer/Opdater valgte apps",
 | 
			
		||||
    "markXSelectedAppsAsUpdated": "Markér {} valgte apps som opdateret?",
 | 
			
		||||
    "no": "Nej",
 | 
			
		||||
    "yes": "Ja",
 | 
			
		||||
    "markSelectedAppsUpdated": "Markér valgte apps som opdateret",
 | 
			
		||||
    "pinToTop": "Fastgør til toppen",
 | 
			
		||||
    "unpinFromTop": "Frigør fra toppen",
 | 
			
		||||
    "resetInstallStatusForSelectedAppsQuestion": "Nulstil installationsstatus for valgte apps?",
 | 
			
		||||
    "installStatusOfXWillBeResetExplanation": "Installationsstatus for alle valgte apps nulstilles.\n\nDette kan hjælpe, når den app-version, der vises i Obtainium, er forkert grundet mislykkede opdateringer eller andre problemer.",
 | 
			
		||||
    "customLinkMessage": "Disse links virker på enheder med Obtainium installeret",
 | 
			
		||||
    "shareAppConfigLinks": "Del app-konfiguration som HTML-link",
 | 
			
		||||
    "shareSelectedAppURLs": "Del valgte app-URL'er",
 | 
			
		||||
    "resetInstallStatus": "Nulstil installationsstatus",
 | 
			
		||||
    "more": "Mere",
 | 
			
		||||
    "removeOutdatedFilter": "Fjern forældet app-filter",
 | 
			
		||||
    "showOutdatedOnly": "Vis kun forældet apps",
 | 
			
		||||
    "filter": "Filtrer",
 | 
			
		||||
    "filterApps": "Filtrer Apps",
 | 
			
		||||
    "appName": "Appnavn",
 | 
			
		||||
    "author": "Udvikler",
 | 
			
		||||
    "upToDateApps": "Opdaterede apps",
 | 
			
		||||
    "nonInstalledApps": "Ikke-installerede apps",
 | 
			
		||||
    "importExport": "Import/Eksport",
 | 
			
		||||
    "settings": "Indstillinger",
 | 
			
		||||
    "exportedTo": "Eksportér til {}",
 | 
			
		||||
    "obtainiumExport": "Obtainium-eksport",
 | 
			
		||||
    "invalidInput": "Ugyldigt input",
 | 
			
		||||
    "importedX": "Importerede {}",
 | 
			
		||||
    "obtainiumImport": "Obtainium-import",
 | 
			
		||||
    "importFromURLList": "Importér fra URL-liste",
 | 
			
		||||
    "searchQuery": "Søgning",
 | 
			
		||||
    "appURLList": "Liste over app-URL'er",
 | 
			
		||||
    "line": "Linje",
 | 
			
		||||
    "searchX": "Søg {}",
 | 
			
		||||
    "noResults": "Ingen resultater fundet",
 | 
			
		||||
    "importX": "Importér {}",
 | 
			
		||||
    "importedAppsIdDisclaimer": "Importerede apps vises muligvis forkert som \"Ikke installeret\".\nFor at løse dette, geninstaller dem via Obtainium.\nDette bør ikke påvirke app-data.\n\nPåvirker kun URL- og tredjepartsimportmetoder.",
 | 
			
		||||
    "importErrors": "Importfejl",
 | 
			
		||||
    "importedXOfYApps": "{} af {} app importeret.",
 | 
			
		||||
    "followingURLsHadErrors": "Følgende URL'er havde fejl:",
 | 
			
		||||
    "selectURL": "Vælg URL",
 | 
			
		||||
    "selectURLs": "Vælg URL'er",
 | 
			
		||||
    "pick": "Vælg",
 | 
			
		||||
    "theme": "Tema",
 | 
			
		||||
    "dark": "Mørk",
 | 
			
		||||
    "light": "Lys",
 | 
			
		||||
    "followSystem": "Følg system",
 | 
			
		||||
    "followSystemThemeExplanation": "Det er kun muligt at følge systemtemaet ved brug af tredjepartsapplikationer",
 | 
			
		||||
    "useBlackTheme": "Brug rent sort, mørkt tema",
 | 
			
		||||
    "appSortBy": "Sortér apps efter:",
 | 
			
		||||
    "authorName": "Udvikler/Navn",
 | 
			
		||||
    "nameAuthor": "Navn/Udvikler",
 | 
			
		||||
    "asAdded": "Som tilføjet",
 | 
			
		||||
    "appSortOrder": "Sorteringsrækkefølge for apps",
 | 
			
		||||
    "ascending": "Stigende",
 | 
			
		||||
    "descending": "Faldende",
 | 
			
		||||
    "bgUpdateCheckInterval": "Kontrolinterval for baggrundsopdatering",
 | 
			
		||||
    "neverManualOnly": "Aldrig - Kun manuelt",
 | 
			
		||||
    "appearance": "Udseende",
 | 
			
		||||
    "showWebInAppView": "Vis kildewebsiden i appvisning",
 | 
			
		||||
    "pinUpdates": "Fastgør opdateringer til toppen af appvisning",
 | 
			
		||||
    "updates": "Opdateringer",
 | 
			
		||||
    "sourceSpecific": "Kildespecifik",
 | 
			
		||||
    "appSource": "App-kilde",
 | 
			
		||||
    "noLogs": "Ingen logs",
 | 
			
		||||
    "appLogs": "App-logs",
 | 
			
		||||
    "close": "Luk",
 | 
			
		||||
    "share": "Del",
 | 
			
		||||
    "appNotFound": "App ikke fundet",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "obtainium-eksport",
 | 
			
		||||
    "pickAnAPK": "Vælg en APK",
 | 
			
		||||
    "appHasMoreThanOnePackage": "{} har mere end én pakke:",
 | 
			
		||||
    "deviceSupportsXArch": "Din enhed understøtter {} CPU-arkitekturen.",
 | 
			
		||||
    "deviceSupportsFollowingArchs": "Din enhed understøtter følgende CPU-arkitekturer:",
 | 
			
		||||
    "warning": "Advarsel",
 | 
			
		||||
    "sourceIsXButPackageFromYPrompt": "App-kilden er '{}', men udgivelsespakken kommer fra '{}'. Fortsæt?",
 | 
			
		||||
    "updatesAvailable": "Opdateringer tilgængelige",
 | 
			
		||||
    "updatesAvailableNotifDescription": "Underretter brugeren om, at opdateringer er tilgængelige for en eller flere apps, der spores af Obtainium",
 | 
			
		||||
    "noNewUpdates": "Ingen nye opdateringer.",
 | 
			
		||||
    "xHasAnUpdate": "{} har en opdatering.",
 | 
			
		||||
    "appsUpdated": "Apps opdateret",
 | 
			
		||||
    "appsNotUpdated": "Kunne ikke opdatere applikationerne",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Underretter brugeren om, at opdateringer til en eller flere apps blev udført i baggrunden",
 | 
			
		||||
    "xWasUpdatedToY": "{} blev opdateret til {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Kunne ikke opdatere {} til {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Fejl ved tjek for opdateringer",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "En meddelelse, der vises, når opdateringstjek i baggrunden mislykkes",
 | 
			
		||||
    "appsRemoved": "Apps fjernet",
 | 
			
		||||
    "appsRemovedNotifDescription": "Underretter brugeren om, at en eller flere apps blev fjernet grundet fejl under indlæsning af dem",
 | 
			
		||||
    "xWasRemovedDueToErrorY": "{} blev fjernet grundet denne fejl: {}",
 | 
			
		||||
    "completeAppInstallation": "Færdiggør app-installation",
 | 
			
		||||
    "obtainiumMustBeOpenToInstallApps": "Obtainium skal være åben for at installere apps",
 | 
			
		||||
    "completeAppInstallationNotifDescription": "Beder brugeren om at vende tilbage til Obtainium for at afslutte installationen af en app",
 | 
			
		||||
    "checkingForUpdates": "Tjekker for opdateringer",
 | 
			
		||||
    "checkingForUpdatesNotifDescription": "Kortvarig meddelelse, der vises ved tjek for opdateringer",
 | 
			
		||||
    "pleaseAllowInstallPerm": "Tillad venligst Obtainium at installere apps",
 | 
			
		||||
    "trackOnly": "Følg Kun",
 | 
			
		||||
    "errorWithHttpStatusCode": "Fejl {}",
 | 
			
		||||
    "versionCorrectionDisabled": "Versionskorrigering deaktiveret (plugin ser ikke ud til at virke)",
 | 
			
		||||
    "unknown": "Ukendt",
 | 
			
		||||
    "none": "Ingen",
 | 
			
		||||
    "never": "Aldrig",
 | 
			
		||||
    "latestVersionX": "Seneste: {}",
 | 
			
		||||
    "installedVersionX": "Installeret: {}",
 | 
			
		||||
    "lastUpdateCheckX": "Sidste opdateringstjek: {}",
 | 
			
		||||
    "remove": "Fjern",
 | 
			
		||||
    "yesMarkUpdated": "Ja, markér som opdateret",
 | 
			
		||||
    "fdroid": "F-Droid Officiel",
 | 
			
		||||
    "appIdOrName": "App-ID eller navn",
 | 
			
		||||
    "appId": "App-ID",
 | 
			
		||||
    "appWithIdOrNameNotFound": "Ingen app med det ID eller navn blev fundet",
 | 
			
		||||
    "reposHaveMultipleApps": "Repos kan indeholde flere apps",
 | 
			
		||||
    "fdroidThirdPartyRepo": "F-Droid Tredjeparts-repo",
 | 
			
		||||
    "steamMobile": "Steam Mobil",
 | 
			
		||||
    "steamChat": "Steam Chat",
 | 
			
		||||
    "install": "Installer",
 | 
			
		||||
    "markInstalled": "Markér som installeret",
 | 
			
		||||
    "update": "Opdater",
 | 
			
		||||
    "markUpdated": "Markér som opdateret",
 | 
			
		||||
    "additionalOptions": "Yderligere indstillinger",
 | 
			
		||||
    "disableVersionDetection": "Deaktivér versionsregistrering",
 | 
			
		||||
    "noVersionDetectionExplanation": "Denne indstilling bør kun bruges til apps, hvor versionsregistrering ikke virker korrekt.",
 | 
			
		||||
    "downloadingX": "Henter {}",
 | 
			
		||||
    "downloadX": "Hent {}",
 | 
			
		||||
    "downloadedX": "Hentede {}",
 | 
			
		||||
    "releaseAsset": "Udgivelsesressource",
 | 
			
		||||
    "downloadNotifDescription": "Underretter brugeren om fremskridt i hentning af en app",
 | 
			
		||||
    "noAPKFound": "Ingen APK fundet",
 | 
			
		||||
    "noVersionDetection": "Ingen versionsregistrering",
 | 
			
		||||
    "categorize": "Kategoriser",
 | 
			
		||||
    "categories": "Kategorier",
 | 
			
		||||
    "category": "Kategori",
 | 
			
		||||
    "noCategory": "Ingen kategori",
 | 
			
		||||
    "noCategories": "Ingen kategorier",
 | 
			
		||||
    "deleteCategoriesQuestion": "Slet kategorier?",
 | 
			
		||||
    "categoryDeleteWarning": "Alle apps i slettede kategorier indstilles til ukategoriseret.",
 | 
			
		||||
    "addCategory": "Tilføj kategori",
 | 
			
		||||
    "label": "Etiket",
 | 
			
		||||
    "language": "Sprog",
 | 
			
		||||
    "copiedToClipboard": "Kopieret til udklipsholder",
 | 
			
		||||
    "storagePermissionDenied": "Lagringstilladelse nægtet",
 | 
			
		||||
    "selectedCategorizeWarning": "Dette erstatter alle eksisterende kategoriindstillinger for de valgte apps.",
 | 
			
		||||
    "filterAPKsByRegEx": "Filtrer APK'er efter regulært udtryk",
 | 
			
		||||
    "removeFromObtainium": "Fjern fra Obtainium",
 | 
			
		||||
    "uninstallFromDevice": "Afinstaller fra enhed",
 | 
			
		||||
    "onlyWorksWithNonVersionDetectApps": "Virker kun for apps med versionsregistrering deaktiveret.",
 | 
			
		||||
    "releaseDateAsVersion": "Brug udgivelsesdato som versionsstreng",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "Denne indstilling bør kun bruges til apps, hvor versionsregistrering ikke virker korrekt, men hvor en udgivelsesdato er tilgængelig.",
 | 
			
		||||
    "changes": "Ændringer",
 | 
			
		||||
    "releaseDate": "Udgivelsesdato",
 | 
			
		||||
    "importFromURLsInFile": "Importér fra URL'er i fil (som OPML)",
 | 
			
		||||
    "versionDetectionExplanation": "Afstem versionsstreng med versionen registreret fra OS",
 | 
			
		||||
    "versionDetection": "Versionsregistrering",
 | 
			
		||||
    "standardVersionDetection": "Standard versionsregistrering",
 | 
			
		||||
    "groupByCategory": "Gruppér efter kategori",
 | 
			
		||||
    "autoApkFilterByArch": "Forsøg at filtrere APK'er efter CPU-arkitektur, hvis muligt",
 | 
			
		||||
    "overrideSource": "Tilsidesæt kilde",
 | 
			
		||||
    "dontShowAgain": "Vis ikke denne igen",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Vis ikke 'Følg Kun'-advarsler",
 | 
			
		||||
    "dontShowAPKOriginWarnings": "Vis ikke advarsler om APK-oprindelse",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Flyt ikke-installerede apps til bunden af appvisning",
 | 
			
		||||
    "gitlabPATLabel": "GitLab Personlig Adgangstoken",
 | 
			
		||||
    "about": "Om",
 | 
			
		||||
    "requiresCredentialsInSettings": "{} kræver yderligere legitimation (i Indstillinger)",
 | 
			
		||||
    "checkOnStart": "Tjek for opdateringer ved opstart",
 | 
			
		||||
    "tryInferAppIdFromCode": "Forsøg at udlede app-ID fra kildekode",
 | 
			
		||||
    "removeOnExternalUninstall": "Fjern automatisk eksternt afinstallerede apps",
 | 
			
		||||
    "pickHighestVersionCode": "Auto-vælg højeste versionKode af APK",
 | 
			
		||||
    "checkUpdateOnDetailPage": "Tjek for opdateringer ved åbning af appens detaljeside",
 | 
			
		||||
    "disablePageTransitions": "Deaktivér sideovergangsanimationer",
 | 
			
		||||
    "reversePageTransitions": "Omvendte sideovergangsanimationer",
 | 
			
		||||
    "minStarCount": "Minimum antal stjerner",
 | 
			
		||||
    "addInfoBelow": "Tilføj denne info nedenfor.",
 | 
			
		||||
    "addInfoInSettings": "Tilføj denne info i indstillingerne.",
 | 
			
		||||
    "githubSourceNote": "GitHubs hastighedsbegrænsning kan undgås med en API-nøgle.",
 | 
			
		||||
    "sortByLastLinkSegment": "Sortér kun efter det sidste segment af linket",
 | 
			
		||||
    "filterReleaseNotesByRegEx": "Filtrer udgivelsesnoter efter regulært udtryk",
 | 
			
		||||
    "customLinkFilterRegex": "Brugerdefineret APK-linkfilter efter regulært udtryk (standard '.apk$')",
 | 
			
		||||
    "appsPossiblyUpdated": "App-opdateringer forsøgt",
 | 
			
		||||
    "appsPossiblyUpdatedNotifDescription": "Underretter brugeren om, at opdateringer til en eller flere apps potentielt blev udført i baggrunden",
 | 
			
		||||
    "xWasPossiblyUpdatedToY": "{} er muligvis blevet opdateret til {}.",
 | 
			
		||||
    "enableBackgroundUpdates": "Aktivér baggrundsopdateringer",
 | 
			
		||||
    "backgroundUpdateReqsExplanation": "Baggrundsopdateringer er muligvis ikke mulige for alle apps.",
 | 
			
		||||
    "backgroundUpdateLimitsExplanation": "Om en baggrundsinstallation er vellykket, kan kun afgøres, når Obtainium åbnes.",
 | 
			
		||||
    "verifyLatestTag": "Verificer 'seneste'-tagget",
 | 
			
		||||
    "intermediateLinkRegex": "Filtrer efter et 'mellemliggende' link at besøge",
 | 
			
		||||
    "filterByLinkText": "Filtrer links efter linktekst",
 | 
			
		||||
    "intermediateLinkNotFound": "Mellemliggende link ikke fundet",
 | 
			
		||||
    "intermediateLink": "Mellemliggende link",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "Undtag fra baggrundsopdateringer (hvis aktiveret)",
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "Deaktivér baggrundsopdateringer, når du ikke er på WiFi",
 | 
			
		||||
    "autoSelectHighestVersionCode": "Auto-vælg højeste versionKode af APK",
 | 
			
		||||
    "versionExtractionRegEx": "RegEx for versionsstrengsudtrækning",
 | 
			
		||||
    "matchGroupToUse": "Match gruppe til brug til RegEx for versionsstrengsudtrækning",
 | 
			
		||||
    "highlightTouchTargets": "Fremhæv mindre åbenlyse berøringsmål",
 | 
			
		||||
    "pickExportDir": "Vælg eksportmappe",
 | 
			
		||||
    "autoExportOnChanges": "Auto-eksport ved ændringer",
 | 
			
		||||
    "includeSettings": "Inkluder indstillinger",
 | 
			
		||||
    "filterVersionsByRegEx": "Filtrer versioner efter regulært udtryk",
 | 
			
		||||
    "trySelectingSuggestedVersionCode": "Forsøg at vælge den foreslåede versionKode af APK",
 | 
			
		||||
    "dontSortReleasesList": "Behold udgivelsesordre fra API",
 | 
			
		||||
    "reverseSort": "Omvendt sortering",
 | 
			
		||||
    "takeFirstLink": "Tag første link",
 | 
			
		||||
    "skipSort": "Spring sortering over",
 | 
			
		||||
    "debugMenu": "Fejlfindingsmenu",
 | 
			
		||||
    "bgTaskStarted": "Baggrundsopgave startet - tjek logfiler.",
 | 
			
		||||
    "runBgCheckNow": "Kør baggrundsopdateringstjek nu",
 | 
			
		||||
    "versionExtractWholePage": "Anvend RegEx for versionsstrengsudtrækning for hele siden",
 | 
			
		||||
    "installing": "Installerer",
 | 
			
		||||
    "skipUpdateNotifications": "Spring opdateringsmeddelelser over",
 | 
			
		||||
    "updatesAvailableNotifChannel": "Opdateringer tilgængelige",
 | 
			
		||||
    "appsUpdatedNotifChannel": "Apps opdateret",
 | 
			
		||||
    "appsPossiblyUpdatedNotifChannel": "App-opdateringer forsøgt",
 | 
			
		||||
    "errorCheckingUpdatesNotifChannel": "Fejl ved opdateringstjek",
 | 
			
		||||
    "appsRemovedNotifChannel": "Apps fjernet",
 | 
			
		||||
    "downloadingXNotifChannel": "Henter {}",
 | 
			
		||||
    "completeAppInstallationNotifChannel": "Færdiggør app-installation",
 | 
			
		||||
    "checkingForUpdatesNotifChannel": "Tjekker for opdateringer",
 | 
			
		||||
    "onlyCheckInstalledOrTrackOnlyApps": "Tjek kun installeret og 'Følg Kun'-apps for opdateringer",
 | 
			
		||||
    "supportFixedAPKURL": "Understøt fikserede APK-URL'er",
 | 
			
		||||
    "selectX": "Vælg {}",
 | 
			
		||||
    "parallelDownloads": "Tillad samtidige overførsler",
 | 
			
		||||
    "useShizuku": "Brug Shizuku eller Sui til at installere",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku-tjeneste kører ikke",
 | 
			
		||||
    "shizukuOld": "Forældet Shizuku-version (<11). Opdater den",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku kører på Android <8.1 med ADB. Opdater Android eller brug Sui i stedet",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Indstil Google Play som installationskilde (hvis Shizuku bruges)",
 | 
			
		||||
    "useSystemFont": "Brug systemskrifttype",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Brug app versionKode som OS-registreret version",
 | 
			
		||||
    "requestHeader": "Anmod overskrift",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Brug seneste ressourceupload som udgivelsesdato",
 | 
			
		||||
    "defaultPseudoVersioningMethod": "Standard pseudo-versioneringsmetode",
 | 
			
		||||
    "partialAPKHash": "Delvis APK-hash",
 | 
			
		||||
    "APKLinkHash": "Hash for APK-link",
 | 
			
		||||
    "directAPKLink": "Direkte APK-link",
 | 
			
		||||
    "pseudoVersionInUse": "En pseudo-version er i brug",
 | 
			
		||||
    "installed": "Installeret",
 | 
			
		||||
    "latest": "Seneste",
 | 
			
		||||
    "invertRegEx": "Inverter regulært udtryk",
 | 
			
		||||
    "note": "Note",
 | 
			
		||||
    "selfHostedNote": "Rullemenuen \"{}\" kan bruges til at nå selvhostede/brugerdefinerede instanser af enhver kilde.",
 | 
			
		||||
    "badDownload": "APK'en kunne ikke analyseres (inkompatibel eller delvis hentning)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Del nye apps med AppVerifier (hvis tilgængelig)",
 | 
			
		||||
    "appVerifierInstructionToast": "Del til AppVerifier, og vend tilbage hertil, når du er klar.",
 | 
			
		||||
    "wiki": "Hjælp/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourcede app-konfigurationer (brug på egen risiko)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Fjern app?",
 | 
			
		||||
        "other": "Fjern apps?"
 | 
			
		||||
    },
 | 
			
		||||
    "tooManyRequestsTryAgainInMinutes": {
 | 
			
		||||
        "one": "For mange anmodninger (begrænset hastighed). Prøv igen om {} minut",
 | 
			
		||||
        "other": "For mange anmodninger (begrænset hastighed). Prøv igen om {} minutter"
 | 
			
		||||
    },
 | 
			
		||||
    "bgUpdateGotErrorRetryInMinutes": {
 | 
			
		||||
        "one": "Baggrundsopdateringstjek stødte på en {}. Planlægger et nyt tjek om {} minut",
 | 
			
		||||
        "other": "Baggrundsopdateringstjek stødte på en {}. Planlægger et nyt tjek om {} minutter"
 | 
			
		||||
    },
 | 
			
		||||
    "bgCheckFoundUpdatesWillNotifyIfNeeded": {
 | 
			
		||||
        "one": "Baggrundsopdateringstjek fandt {} opdatering. Underretter brugeren, hvis nødvendigt",
 | 
			
		||||
        "other": "Baggrundsopdateringstjek fandt {} opdateringer. Underretter brugeren, hvis nødvendigt"
 | 
			
		||||
    },
 | 
			
		||||
    "apps": {
 | 
			
		||||
        "one": "{} App",
 | 
			
		||||
        "other": "{} Apps"
 | 
			
		||||
    },
 | 
			
		||||
    "url": {
 | 
			
		||||
        "one": "{} URL",
 | 
			
		||||
        "other": "{} URL'er"
 | 
			
		||||
    },
 | 
			
		||||
    "minute": {
 | 
			
		||||
        "one": "{} Minut",
 | 
			
		||||
        "other": "{} Minutter"
 | 
			
		||||
    },
 | 
			
		||||
    "hour": {
 | 
			
		||||
        "one": "{} Time",
 | 
			
		||||
        "other": "{} Timer"
 | 
			
		||||
    },
 | 
			
		||||
    "day": {
 | 
			
		||||
        "one": "{} Dag",
 | 
			
		||||
        "other": "{} Dage"
 | 
			
		||||
    },
 | 
			
		||||
    "clearedNLogsBeforeXAfterY": {
 | 
			
		||||
        "one": "Ryddet {n} log (før = {before}, efter = {after})",
 | 
			
		||||
        "other": "Ryddet {n} logs (før = {before}, efter = {after})"
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesAvailable": {
 | 
			
		||||
        "one": "{} og 1 anden app har opdateringer.",
 | 
			
		||||
        "other": "{} og {} andre apps har opdateringer."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesInstalled": {
 | 
			
		||||
        "one": "{} og 1 anden app blev opdateret.",
 | 
			
		||||
        "other": "{} og {} andre apps blev opdateret."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Kunne ikke opdatere {} og 1 anden app.",
 | 
			
		||||
        "other": "Kunne ikke opdatere {} og {} andre apps."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} og 1 anden app blev muligvis opdateret.",
 | 
			
		||||
        "other": "{} og {} andre apps blev muligvis opdateret."
 | 
			
		||||
    },
 | 
			
		||||
    "apk": {
 | 
			
		||||
        "one": "{} APK",
 | 
			
		||||
        "other": "{} APK'er"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -19,9 +19,12 @@
 | 
			
		||||
    "noDescription": "Keine Beschreibung",
 | 
			
		||||
    "cancel": "Abbrechen",
 | 
			
		||||
    "continue": "Weiter",
 | 
			
		||||
    "requiredInBrackets": "(Benötigt)",
 | 
			
		||||
    "requiredInBrackets": "(wird benötigt)",
 | 
			
		||||
    "dropdownNoOptsError": "FEHLER: DROPDOWN MUSS MINDESTENS EINE OPTION HABEN",
 | 
			
		||||
    "colour": "Farbe",
 | 
			
		||||
    "standard": "Standard",
 | 
			
		||||
    "custom": "Benutzerdefiniert",
 | 
			
		||||
    "useMaterialYou": "Verwende Material You",
 | 
			
		||||
    "githubStarredRepos": "GitHub Starred Repos",
 | 
			
		||||
    "uname": "Benutzername",
 | 
			
		||||
    "wrongArgNum": "Falsche Anzahl von Argumenten (Parametern) übermittelt",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Dunkel",
 | 
			
		||||
    "light": "Hell",
 | 
			
		||||
    "followSystem": "System folgen",
 | 
			
		||||
    "followSystemThemeExplanation": "Das Folgen des Systemthemes ist unter Android <10 nur mit Hilfe von Drittanbieteranwendungen möglich",
 | 
			
		||||
    "useBlackTheme": "Verwende Pure Black Dark Theme",
 | 
			
		||||
    "appSortBy": "App sortieren nach",
 | 
			
		||||
    "authorName": "Autor/Name",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "Keine neuen Aktualisierungen.",
 | 
			
		||||
    "xHasAnUpdate": "{} hat eine Aktualisierung.",
 | 
			
		||||
    "appsUpdated": "Apps aktualisiert",
 | 
			
		||||
    "appsNotUpdated": "Aktualisierung der Anwendungen fehlgeschlagen",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Benachrichtigt den Benutzer, dass Aktualisierungen für eine oder mehrere Apps im Hintergrund durchgeführt wurden",
 | 
			
		||||
    "xWasUpdatedToY": "{} wurde auf {} aktualisiert.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Die Aktualisierung von {} auf {} ist fehlgeschlagen.",
 | 
			
		||||
    "errorCheckingUpdates": "Fehler beim Prüfen auf Aktualisierungen",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Eine Benachrichtigung, die angezeigt wird, wenn die Prüfung der Hintergrundaktualisierung fehlschlägt",
 | 
			
		||||
    "appsRemoved": "Apps entfernt",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "Versionsermittlung deaktivieren",
 | 
			
		||||
    "noVersionDetectionExplanation": "Diese Option sollte nur für Apps verwendet werden, bei denen die Versionserkennung nicht korrekt funktioniert.",
 | 
			
		||||
    "downloadingX": "Lade {} herunter",
 | 
			
		||||
    "downloadX": "{} herunterladen",
 | 
			
		||||
    "downloadedX": "{} heruntergeladen",
 | 
			
		||||
    "releaseAsset": "release Asset",
 | 
			
		||||
    "downloadNotifDescription": "Benachrichtigt den Nutzer über den Fortschritt beim Herunterladen einer App",
 | 
			
		||||
    "noAPKFound": "Keine APK gefunden",
 | 
			
		||||
    "noVersionDetection": "Keine Versionserkennung",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "neuere Version anhand der ersten dreißig Zahlen der Checksumme der APK URL erraten, wenn anderweitig nicht unterstützt",
 | 
			
		||||
    "selectX": "Wähle {}",
 | 
			
		||||
    "parallelDownloads": "Erlaube parallele Downloads",
 | 
			
		||||
    "installMethod": "Installationsmethode",
 | 
			
		||||
    "normal": "Normal",
 | 
			
		||||
    "root": "Root",
 | 
			
		||||
    "useShizuku": "Verwenden Sie Shizuku oder Sui zur Installation",
 | 
			
		||||
    "shizukuBinderNotFound": "Kompatibler Shizukudienst wurde nicht gefunden",
 | 
			
		||||
    "shizukuOld": "Alte Shizuku-Version (<11) - aktualisieren Sie sie",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku läuft auf Android < 8.1 mit ADB - aktualisieren Sie Android oder verwenden Sie stattdessen Sui",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Google Play als Installationsquelle festlegen (wenn Shizuku verwendet wird)",
 | 
			
		||||
    "useSystemFont": "Verwende die Systemschriftart",
 | 
			
		||||
    "systemFontError": "Fehler beim Laden der Systemschriftart: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Verwende die Appversion als erkannte Version vom Betriebssystem",
 | 
			
		||||
    "requestHeader": "Request Header",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Den letzten Asset-Upload als Veröffentlichungsdatum verwenden",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Hinweis",
 | 
			
		||||
    "selfHostedNote": "Das „{}“-Dropdown-Menü kann verwendet werden, um selbst gehostete/angepasste Instanzen einer beliebigen Quelle zu erreichen.",
 | 
			
		||||
    "badDownload": "Die APK konnte nicht geparst werden (inkompatibler oder teilweiser Download)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Neue Apps mit AppVerifier teilen (falls verfügbar)",
 | 
			
		||||
    "appVerifierInstructionToast": "Geben Sie die Daten an AppVerifier weiter und kehren Sie dann hierher zurück, wenn Sie fertig sind.",
 | 
			
		||||
    "wiki": "Hilfe/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (Verwendung auf eigene Gefahr)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "App entfernen?",
 | 
			
		||||
        "other": "Apps entfernen?"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} und 1 weitere Anwendung wurden aktualisiert.",
 | 
			
		||||
        "other": "{} und {} weitere Anwendungen wurden aktualisiert."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Aktualisierung fehlgeschlagen {} und 1 weitere Anwendung.",
 | 
			
		||||
        "other": "Die Aktualisierung von {} und {} weiteren Anwendungen ist fehlgeschlagen."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} und 1 weitere Anwendung wurden möglicherweise aktualisiert.",
 | 
			
		||||
        "other": "{} und {} weitere Anwendungen wurden möglicherweise aktualisiert."
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(Required)",
 | 
			
		||||
    "dropdownNoOptsError": "ERROR: DROPDOWN MUST HAVE AT LEAST ONE OPT",
 | 
			
		||||
    "colour": "Colour",
 | 
			
		||||
    "standard": "Standard",
 | 
			
		||||
    "custom": "Custom",
 | 
			
		||||
    "useMaterialYou": "Use Material You",
 | 
			
		||||
    "githubStarredRepos": "GitHub Starred Repos",
 | 
			
		||||
    "uname": "Username",
 | 
			
		||||
    "wrongArgNum": "Wrong number of arguments provided",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Dark",
 | 
			
		||||
    "light": "Light",
 | 
			
		||||
    "followSystem": "Follow System",
 | 
			
		||||
    "followSystemThemeExplanation": "Following system theme is possible only by using third-party applications",
 | 
			
		||||
    "useBlackTheme": "Use pure black dark theme",
 | 
			
		||||
    "appSortBy": "App Sort By",
 | 
			
		||||
    "authorName": "Author/Name",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "No new updates.",
 | 
			
		||||
    "xHasAnUpdate": "{} has an update.",
 | 
			
		||||
    "appsUpdated": "Apps Updated",
 | 
			
		||||
    "appsNotUpdated": "Failed to update applications",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Notifies the user that updates to one or more Apps were applied in the background",
 | 
			
		||||
    "xWasUpdatedToY": "{} was updated to {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Failed to update {} to {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Error Checking for Updates",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "A notification that shows when background update checking fails",
 | 
			
		||||
    "appsRemoved": "Apps Removed",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "Disable Version Detection",
 | 
			
		||||
    "noVersionDetectionExplanation": "This option should only be used for Apps where version detection does not work correctly.",
 | 
			
		||||
    "downloadingX": "Downloading {}",
 | 
			
		||||
    "downloadX": "Download {}",
 | 
			
		||||
    "downloadedX": "Downloaded {}",
 | 
			
		||||
    "releaseAsset": "Release Asset",
 | 
			
		||||
    "downloadNotifDescription": "Notifies the user of the progress in downloading an App",
 | 
			
		||||
    "noAPKFound": "No APK found",
 | 
			
		||||
    "noVersionDetection": "No version detection",
 | 
			
		||||
@@ -250,7 +259,7 @@
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi",
 | 
			
		||||
    "autoSelectHighestVersionCode": "Auto-select highest versionCode APK",
 | 
			
		||||
    "versionExtractionRegEx": "Version String Extraction RegEx",
 | 
			
		||||
    "matchGroupToUse": "Match Group to Use for Version String Extraction Regex",
 | 
			
		||||
    "matchGroupToUse": "Match Group to Use for Version String Extraction RegEx",
 | 
			
		||||
    "highlightTouchTargets": "Highlight less obvious touch targets",
 | 
			
		||||
    "pickExportDir": "Pick Export Directory",
 | 
			
		||||
    "autoExportOnChanges": "Auto-export on changes",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "Support fixed APK URLs",
 | 
			
		||||
    "selectX": "Select {}",
 | 
			
		||||
    "parallelDownloads": "Allow parallel downloads",
 | 
			
		||||
    "installMethod": "Installation method",
 | 
			
		||||
    "normal": "Normal",
 | 
			
		||||
    "root": "Root",
 | 
			
		||||
    "shizukuBinderNotFound": "Сompatible Shizuku service wasn't found",
 | 
			
		||||
    "useShizuku": "Use Shizuku or Sui to install",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku service not running",
 | 
			
		||||
    "shizukuOld": "Old Shizuku version (<11) - update it",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku running on Android < 8.1 with ADB - update Android or use Sui instead",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Set Google Play as the installation source (if Shizuku is used)",
 | 
			
		||||
    "useSystemFont": "Use the system font",
 | 
			
		||||
    "systemFontError": "Error loading the system font: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Use app versionCode as OS-detected version",
 | 
			
		||||
    "requestHeader": "Request header",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Use latest asset upload as release date",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Note",
 | 
			
		||||
    "selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
 | 
			
		||||
    "badDownload": "The APK could not be parsed (incompatible or partial download)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)",
 | 
			
		||||
    "appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.",
 | 
			
		||||
    "wiki": "Help/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Remove App?",
 | 
			
		||||
        "other": "Remove Apps?"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} and 1 more app was updated.",
 | 
			
		||||
        "other": "{} and {} more apps were updated."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Failed to update {} and 1 more app.",
 | 
			
		||||
        "other": "Failed to update {} and {} more apps."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} and 1 more app may have been updated.",
 | 
			
		||||
        "other": "{} and {} more apps may have been updated."
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,15 @@
 | 
			
		||||
{
 | 
			
		||||
    "invalidURLForSource": "URL de la aplicación {} no es válida",
 | 
			
		||||
    "noReleaseFound": "No se ha podido encontrar una versión válida",
 | 
			
		||||
    "invalidURLForSource": "El URL de la aplicación {} no es válido",
 | 
			
		||||
    "noReleaseFound": "No se ha encontrado una versión válida",
 | 
			
		||||
    "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",
 | 
			
		||||
    "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 el ID de la aplicación instalada",
 | 
			
		||||
    "functionNotImplemented": "Esta clase no ha implementado esta función",
 | 
			
		||||
    "placeholder": "Espacio reservado",
 | 
			
		||||
    "someErrors": "Han ocurrido algunos errores",
 | 
			
		||||
    "unexpectedError": "Error inesperado",
 | 
			
		||||
    "ok": "OK",
 | 
			
		||||
    "ok": "Aceptar",
 | 
			
		||||
    "and": "y",
 | 
			
		||||
    "githubPATLabel": "Token de acceso personal a GitHub\n(reduce tiempos de espera)",
 | 
			
		||||
    "includePrereleases": "Incluir versiones preliminares",
 | 
			
		||||
@@ -21,88 +21,91 @@
 | 
			
		||||
    "continue": "Continuar",
 | 
			
		||||
    "requiredInBrackets": "(Requerido)",
 | 
			
		||||
    "dropdownNoOptsError": "ERROR: EL DESPLEGABLE DEBE TENER AL MENOS UNA OPCIÓN",
 | 
			
		||||
    "colour": "Color",
 | 
			
		||||
    "githubStarredRepos": "Repositorios favoritos en GitHub",
 | 
			
		||||
    "colour": "color",
 | 
			
		||||
    "standard": "Estándar",
 | 
			
		||||
    "custom": "A medida",
 | 
			
		||||
    "useMaterialYou": "Aplicar 'Material You'",
 | 
			
		||||
    "githubStarredRepos": "repositorios favoritos en GitHub",
 | 
			
		||||
    "uname": "Nombre de usuario",
 | 
			
		||||
    "wrongArgNum": "Número de argumentos provistos inválido",
 | 
			
		||||
    "xIsTrackOnly": "{} es de 'sólo seguimiento'",
 | 
			
		||||
    "source": "Origen",
 | 
			
		||||
    "source": "origen",
 | 
			
		||||
    "app": "Aplicación",
 | 
			
		||||
    "appsFromSourceAreTrackOnly": "Las aplicaciones de este origen son de 'solo seguimiento'.",
 | 
			
		||||
    "youPickedTrackOnly": "Debe seleccionar la opción de 'solo seguimiento'.",
 | 
			
		||||
    "appsFromSourceAreTrackOnly": "Las aplicaciones de este origen son solo para seguimiento.",
 | 
			
		||||
    "youPickedTrackOnly": "Debe seleccionar la opción de 'solo para seguimiento'.",
 | 
			
		||||
    "trackOnlyAppDescription": "Se hará el seguimiento de actualizaciones para la aplicación, pero Obtainium no será capaz de descargar o actualizarla.",
 | 
			
		||||
    "cancelled": "Cancelado",
 | 
			
		||||
    "appAlreadyAdded": "Aplicación añadida anteriormente",
 | 
			
		||||
    "alreadyUpToDateQuestion": "¿Aplicación actualizada previamente?",
 | 
			
		||||
    "addApp": "Añadir Aplicación",
 | 
			
		||||
    "addApp": "Añadir aplicación",
 | 
			
		||||
    "appSourceURL": "URL de origen de la aplicación",
 | 
			
		||||
    "error": "Error",
 | 
			
		||||
    "add": "Añadir",
 | 
			
		||||
    "searchSomeSourcesLabel": "Buscar (solo algunas fuentes)",
 | 
			
		||||
    "search": "Buscar",
 | 
			
		||||
    "additionalOptsFor": "Opciones Adicionales para {}",
 | 
			
		||||
    "supportedSources": "Fuentes Soportadas",
 | 
			
		||||
    "trackOnlyInBrackets": "(Solo seguimiento)",
 | 
			
		||||
    "searchableInBrackets": "(soporta búsqueda)",
 | 
			
		||||
    "additionalOptsFor": "Opciones adicionales para {}",
 | 
			
		||||
    "supportedSources": "Fuentes admitidas",
 | 
			
		||||
    "trackOnlyInBrackets": "(Solo para seguimiento)",
 | 
			
		||||
    "searchableInBrackets": "(permite búsqueda)",
 | 
			
		||||
    "appsString": "Aplicaciones",
 | 
			
		||||
    "noApps": "Sin Aplicaciones",
 | 
			
		||||
    "noAppsForFilter": "Sin aplicaciones para filtrar",
 | 
			
		||||
    "byX": "por: {}",
 | 
			
		||||
    "percentProgress": "Progreso: {}%",
 | 
			
		||||
    "pleaseWait": "Por favor, espere",
 | 
			
		||||
    "updateAvailable": "Actualización Disponible",
 | 
			
		||||
    "notInstalled": "No Instalado",
 | 
			
		||||
    "percentProgress": "Progreso: {} %",
 | 
			
		||||
    "pleaseWait": "Espere...",
 | 
			
		||||
    "updateAvailable": "Actualización disponible",
 | 
			
		||||
    "notInstalled": "No instalado",
 | 
			
		||||
    "pseudoVersion": "pseudoversión",
 | 
			
		||||
    "selectAll": "Seleccionar Todo",
 | 
			
		||||
    "selectAll": "Seleccionar todo",
 | 
			
		||||
    "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?",
 | 
			
		||||
    "removeSelectedApps": "Eliminar Aplicaciones Seleccionadas",
 | 
			
		||||
    "removeSelectedApps": "Eliminar aplicaciones seleccionadas",
 | 
			
		||||
    "updateX": "Actualizar {}",
 | 
			
		||||
    "installX": "Instalar {}",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "Marcar {}\n(Solo seguimiento)\ncomo actualizada",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "Marcar {}\n(solo para seguimiento)\ncomo actualizada",
 | 
			
		||||
    "changeX": "Cambiar {}",
 | 
			
		||||
    "installUpdateApps": "Instalar/Actualizar aplicaciones",
 | 
			
		||||
    "installUpdateSelectedApps": "Instalar/Actualizar aplicaciones seleccionadas",
 | 
			
		||||
    "installUpdateApps": "Instalar/actualizar aplicaciones",
 | 
			
		||||
    "installUpdateSelectedApps": "Instalar/actualizar aplicaciones seleccionadas",
 | 
			
		||||
    "markXSelectedAppsAsUpdated": "¿Marcar {} aplicaciones seleccionadas como actualizadas?",
 | 
			
		||||
    "no": "No",
 | 
			
		||||
    "yes": "Sí",
 | 
			
		||||
    "markSelectedAppsUpdated": "Marcar aplicaciones seleccionadas como actualizadas",
 | 
			
		||||
    "pinToTop": "Fijar arriba",
 | 
			
		||||
    "unpinFromTop": "Desfijar de arriba",
 | 
			
		||||
    "pinToTop": "Anclar al principio",
 | 
			
		||||
    "unpinFromTop": "Desanclar del principio",
 | 
			
		||||
    "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.",
 | 
			
		||||
    "customLinkMessage": "Estos enlaces funcionan en dispositivos con Obtainium instalado",
 | 
			
		||||
    "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",
 | 
			
		||||
    "more": "Más",
 | 
			
		||||
    "removeOutdatedFilter": "Elimiar filtro de aplicaciones desactualizado",
 | 
			
		||||
    "removeOutdatedFilter": "Eliminar filtro de aplicaciones desactualizado",
 | 
			
		||||
    "showOutdatedOnly": "Mostrar solo aplicaciones desactualizadas",
 | 
			
		||||
    "filter": "Filtrar",
 | 
			
		||||
    "filterApps": "Filtrar Actualizaciones",
 | 
			
		||||
    "filterApps": "Filtrar actualizaciones",
 | 
			
		||||
    "appName": "Nombre de la aplicación",
 | 
			
		||||
    "author": "Autor",
 | 
			
		||||
    "upToDateApps": "Aplicaciones Actualizadas",
 | 
			
		||||
    "nonInstalledApps": "Aplicaciones No Instaladas",
 | 
			
		||||
    "importExport": "Importar/Exportar",
 | 
			
		||||
    "upToDateApps": "Aplicaciones actualizadas",
 | 
			
		||||
    "nonInstalledApps": "Aplicaciones no instaladas",
 | 
			
		||||
    "importExport": "Importar/exportar",
 | 
			
		||||
    "settings": "Ajustes",
 | 
			
		||||
    "exportedTo": "Exportado a {}",
 | 
			
		||||
    "obtainiumExport": "Exportar Obtainium",
 | 
			
		||||
    "invalidInput": "Input incorrecto",
 | 
			
		||||
    "invalidInput": "Entrada no válida",
 | 
			
		||||
    "importedX": "Importado {}",
 | 
			
		||||
    "obtainiumImport": "Importar Obtainium",
 | 
			
		||||
    "importFromURLList": "Importar desde lista de URLs",
 | 
			
		||||
    "searchQuery": "Consulta de Búsqueda",
 | 
			
		||||
    "appURLList": "Lista de URLs de Aplicaciones",
 | 
			
		||||
    "importFromURLList": "Importar desde lista de URL",
 | 
			
		||||
    "searchQuery": "Término de búsqueda",
 | 
			
		||||
    "appURLList": "Lista de URL de aplicaciones",
 | 
			
		||||
    "line": "Línea",
 | 
			
		||||
    "searchX": "Buscar {}",
 | 
			
		||||
    "noResults": "Resultados no encontrados",
 | 
			
		||||
    "noResults": "No se ha encontrado ningún resultado",
 | 
			
		||||
    "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",
 | 
			
		||||
    "importedXOfYApps": "{} de {} Aplicaciones importadas.",
 | 
			
		||||
    "followingURLsHadErrors": "Las siguientes URLs han tenido problemas:",
 | 
			
		||||
    "importedXOfYApps": "{} de {} aplicaciones importadas.",
 | 
			
		||||
    "followingURLsHadErrors": "Los URL siguientes han tenido problemas:",
 | 
			
		||||
    "selectURL": "Seleccionar URL",
 | 
			
		||||
    "selectURLs": "Seleccionar URLs",
 | 
			
		||||
    "pick": "Escoger",
 | 
			
		||||
@@ -110,52 +113,55 @@
 | 
			
		||||
    "dark": "Oscuro",
 | 
			
		||||
    "light": "Claro",
 | 
			
		||||
    "followSystem": "Seguir al sistema",
 | 
			
		||||
    "useBlackTheme": "Negro puro en tema Oscuro",
 | 
			
		||||
    "appSortBy": "Ordenar Apps Por",
 | 
			
		||||
    "authorName": "Autor/Nombre",
 | 
			
		||||
    "followSystemThemeExplanation": "Seguir el tema del sistema sólo es posible utilizando aplicaciones de terceros",
 | 
			
		||||
    "useBlackTheme": "Negro puro en tema oscuro",
 | 
			
		||||
    "appSortBy": "Ordenar aplicaciones por",
 | 
			
		||||
    "authorName": "Autor/nombre",
 | 
			
		||||
    "nameAuthor": "Nombre/Autor",
 | 
			
		||||
    "asAdded": "Según se Añadieron",
 | 
			
		||||
    "appSortOrder": "Orden de Clasificación",
 | 
			
		||||
    "ascending": "Ascendente",
 | 
			
		||||
    "descending": "Descendente",
 | 
			
		||||
    "bgUpdateCheckInterval": "Comprobación actualizaciones en segundo plano",
 | 
			
		||||
    "bgUpdateCheckInterval": "Comprobar actualizaciones en segundo plano",
 | 
			
		||||
    "neverManualOnly": "Nunca, solo manual",
 | 
			
		||||
    "appearance": "Apariencia",
 | 
			
		||||
    "showWebInAppView": "Mostrar vista de la web de origen",
 | 
			
		||||
    "pinUpdates": "Fijar actualizaciones al principio",
 | 
			
		||||
    "pinUpdates": "Anclar actualizaciones al principio",
 | 
			
		||||
    "updates": "Actualizaciones",
 | 
			
		||||
    "sourceSpecific": "Fuente Específica",
 | 
			
		||||
    "appSource": "Obtainium en GitHub",
 | 
			
		||||
    "noLogs": "Sin Logs",
 | 
			
		||||
    "appLogs": "Logs",
 | 
			
		||||
    "sourceSpecific": "Fuente específica",
 | 
			
		||||
    "appSource": "Filtrar por fuente",
 | 
			
		||||
    "noLogs": "Ningún registro",
 | 
			
		||||
    "appLogs": "Registros",
 | 
			
		||||
    "close": "Cerrar",
 | 
			
		||||
    "share": "Compartir",
 | 
			
		||||
    "appNotFound": "Aplicación no encontrada",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "obtainium-exportación",
 | 
			
		||||
    "pickAnAPK": "Seleccione una APK",
 | 
			
		||||
    "appHasMoreThanOnePackage": "{} tiene más de un paquete:",
 | 
			
		||||
    "deviceSupportsXArch": "Su dispositivo soporta las siguientes arquitecturas de procesador: {}.",
 | 
			
		||||
    "deviceSupportsFollowingArchs": "Su dispositivo soporta las siguientes arquitecturas de procesador:",
 | 
			
		||||
    "deviceSupportsXArch": "Su dispositivo admite las siguientes arquitecturas de procesador: {}.",
 | 
			
		||||
    "deviceSupportsFollowingArchs": "Su dispositivo admite las siguientes arquitecturas de procesador:",
 | 
			
		||||
    "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",
 | 
			
		||||
    "updatesAvailableNotifDescription": "Notifica al usuario de que hay actualizaciones para una o más aplicaciones monitoreadas por Obtainium",
 | 
			
		||||
    "noNewUpdates": "No hay nuevas actualizaciones.",
 | 
			
		||||
    "xHasAnUpdate": "{} tiene una actualización.",
 | 
			
		||||
    "appsUpdated": "Aplicaciones actualizadas",
 | 
			
		||||
    "appsNotUpdated": "Error al actualizar las aplicaciones",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Notifica al usuario de que una o más aplicaciones han sido actualizadas en segundo plano",
 | 
			
		||||
    "xWasUpdatedToY": "{} ha sido actualizada a {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Error buscando ectualizaciones",
 | 
			
		||||
    "xWasNotUpdatedToY": "Error al actualizar {} a {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Error al buscar actualizaciones",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Una notificación que muestra cuándo la comprobación de actualizaciones en segundo plano falla",
 | 
			
		||||
    "appsRemoved": "Aplicaciones eliminadas",
 | 
			
		||||
    "appsRemovedNotifDescription": "Notifica al usuario que una o más aplicaciones fueron eliminadas por problemas al cargarlas",
 | 
			
		||||
    "xWasRemovedDueToErrorY": "{} ha sido eliminada por: {}",
 | 
			
		||||
    "completeAppInstallation": "Instalación completa de la aplicación",
 | 
			
		||||
    "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...",
 | 
			
		||||
    "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",
 | 
			
		||||
    "errorWithHttpStatusCode": "Error {}",
 | 
			
		||||
    "versionCorrectionDisabled": "Corrección de versiones desactivada (el plugin parece no funcionar)",
 | 
			
		||||
@@ -170,11 +176,11 @@
 | 
			
		||||
    "fdroid": "Repositorio oficial F-Droid",
 | 
			
		||||
    "appIdOrName": "ID o Nombre de la Aplicación",
 | 
			
		||||
    "appId": "ID de la Aplicación",
 | 
			
		||||
    "appWithIdOrNameNotFound": "No se han encontrado aplicaciones con esa ID o nombre",
 | 
			
		||||
    "appWithIdOrNameNotFound": "No se han encontrado aplicaciones con ese ID o nombre",
 | 
			
		||||
    "reposHaveMultipleApps": "Los repositorios pueden contener varias aplicaciones",
 | 
			
		||||
    "fdroidThirdPartyRepo": "Repositorio de tercera parte F-Droid",
 | 
			
		||||
    "steamMobile": "Móvil de vapor",
 | 
			
		||||
    "steamChat": "Chat de vapor",
 | 
			
		||||
    "fdroidThirdPartyRepo": "Repositorio de terceros F-Droid",
 | 
			
		||||
    "steamMobile": "Steam para móviles",
 | 
			
		||||
    "steamChat": "Chat de Steam",
 | 
			
		||||
    "install": "Instalar",
 | 
			
		||||
    "markInstalled": "Marcar como instalada",
 | 
			
		||||
    "update": "Actualizar",
 | 
			
		||||
@@ -183,8 +189,11 @@
 | 
			
		||||
    "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.",
 | 
			
		||||
    "downloadingX": "Descargando {}",
 | 
			
		||||
    "downloadX": "Descargar {}",
 | 
			
		||||
    "downloadedX": "Descargado {}",
 | 
			
		||||
    "releaseAsset": "Recurso publicado",
 | 
			
		||||
    "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 ha encontrado el paquete de instalación APK",
 | 
			
		||||
    "noVersionDetection": "Sin detección de versiones",
 | 
			
		||||
    "categorize": "Catogorizar",
 | 
			
		||||
    "categories": "Categorías",
 | 
			
		||||
@@ -192,14 +201,14 @@
 | 
			
		||||
    "noCategory": "Sin categoría",
 | 
			
		||||
    "noCategories": "Sin 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",
 | 
			
		||||
    "label": "Nombre",
 | 
			
		||||
    "language": "Idioma",
 | 
			
		||||
    "copiedToClipboard": "Copiado al portapapeles",
 | 
			
		||||
    "copiedToClipboard": "Copiado en el portapapeles",
 | 
			
		||||
    "storagePermissionDenied": "Permiso de almacenamiento rechazado",
 | 
			
		||||
    "selectedCategorizeWarning": "Esto reemplazará cualquier ajuste de categoría para las aplicaciones seleccionadas.",
 | 
			
		||||
    "filterAPKsByRegEx": "Filtrar por APKs",
 | 
			
		||||
    "filterAPKsByRegEx": "Filtrar por APK",
 | 
			
		||||
    "removeFromObtainium": "Eliminar de Obtainium",
 | 
			
		||||
    "uninstallFromDevice": "Desinstalar del dispositivo",
 | 
			
		||||
    "onlyWorksWithNonVersionDetectApps": "Solo funciona para aplicaciones con la detección de versiones desactivada.",
 | 
			
		||||
@@ -211,18 +220,18 @@
 | 
			
		||||
    "versionDetectionExplanation": "Conciliar la cadena de versión con la versión detectada desde el sistema operativo",
 | 
			
		||||
    "versionDetection": "Detección de versiones",
 | 
			
		||||
    "standardVersionDetection": "Por versión",
 | 
			
		||||
    "groupByCategory": "Agrupar por categoría",
 | 
			
		||||
    "autoApkFilterByArch": "Filtrar APKs por arquitectura del procesador (si es posible)",
 | 
			
		||||
    "overrideSource": "Sobrescribir Fuente",
 | 
			
		||||
    "groupByCategory": "Agrupar por categorías",
 | 
			
		||||
    "autoApkFilterByArch": "Filtrar APK por arquitectura del procesador (si es posible)",
 | 
			
		||||
    "overrideSource": "Forzar desde la fuente",
 | 
			
		||||
    "dontShowAgain": "No mostrar de nuevo",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "No mostrar avisos sobre apps en 'solo seguimiento'",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "No mostrar avisos sobre apps 'solo para seguimiento'",
 | 
			
		||||
    "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",
 | 
			
		||||
    "about": "Acerca",
 | 
			
		||||
    "requiresCredentialsInSettings": "{}: Esto requiere credenciales adicionales (en ajustes)",
 | 
			
		||||
    "checkOnStart": "Comprobar actualizaciones al inicio",
 | 
			
		||||
    "tryInferAppIdFromCode": "Intentar deducir la ID de la app por el código fuente",
 | 
			
		||||
    "tryInferAppIdFromCode": "Intentar deducir el ID de la app por el código fuente",
 | 
			
		||||
    "removeOnExternalUninstall": "Auto eliminar apps desinstaladas externamente",
 | 
			
		||||
    "pickHighestVersionCode": "Auto selección de versión superior del paquete APK",
 | 
			
		||||
    "checkUpdateOnDetailPage": "Comprobar actualizaciones al abrir detalles de la app",
 | 
			
		||||
@@ -262,7 +271,7 @@
 | 
			
		||||
    "takeFirstLink": "Usar primer enlace",
 | 
			
		||||
    "skipSort": "Omitir orden",
 | 
			
		||||
    "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",
 | 
			
		||||
    "versionExtractWholePage": "Aplicar la versión de extracción regex a la página entera",
 | 
			
		||||
    "installing": "Instalando",
 | 
			
		||||
@@ -277,43 +286,47 @@
 | 
			
		||||
    "checkingForUpdatesNotifChannel": "Buscando actualizaciones",
 | 
			
		||||
    "onlyCheckInstalledOrTrackOnlyApps": "Comprobar actualizaciones solo para apps instaladas o en seguimiento",
 | 
			
		||||
    "supportFixedAPKURL": "Soporte para URLs fijas de APK",
 | 
			
		||||
    "selectX": "Selecciona {}",
 | 
			
		||||
    "selectX": "Elija {}",
 | 
			
		||||
    "parallelDownloads": "Permitir descargas paralelas",
 | 
			
		||||
    "installMethod": "Método de instalación",
 | 
			
		||||
    "normal": "Normal",
 | 
			
		||||
    "root": "Raíz",
 | 
			
		||||
    "useShizuku": "Usar Shizuku o Sui para instalar",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku no funciona",
 | 
			
		||||
    "useSystemFont": "Usar la fuente de impresión del sistema",
 | 
			
		||||
    "systemFontError": "Error al cargar la fuente de impresión del sistema: {}",
 | 
			
		||||
    "shizukuOld": "Versión antigua de Shizuku (<11) - actualícela",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku corriendo en Android < 8.1 con ADB - actualiza Android o usa Sui en su lugar",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Establecer Google Play como fuente de instalación (si se usa Shizuku)",
 | 
			
		||||
    "useSystemFont": "Usar fuente del sistema",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Usar la versión de la aplicación como versión detectada por el sistema operativo",
 | 
			
		||||
    "requestHeader": "Encabezado de solicitud",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Usar la última carga de recursos como fecha de lanzamiento",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Usar la última carga del recurso como fecha de lanzamiento",
 | 
			
		||||
    "defaultPseudoVersioningMethod": "Método de pseudoversionado predeterminado",
 | 
			
		||||
    "partialAPKHash": "Hash de APK parcial",
 | 
			
		||||
    "APKLinkHash": "Hash de enlace APK",
 | 
			
		||||
    "directAPKLink": "Enlace APK directo",
 | 
			
		||||
    "pseudoVersionInUse": "Se está utilizando una pseudoversión",
 | 
			
		||||
    "pseudoVersionInUse": "Se está usando una pseudoversión",
 | 
			
		||||
    "installed": "Instalado",
 | 
			
		||||
    "latest": "Versión más reciente",
 | 
			
		||||
    "invertRegEx": "Invertir expresión regular",
 | 
			
		||||
    "note": "Nota",
 | 
			
		||||
    "selfHostedNote": "El desplegable \"{}\" puede utilizarse para acceder a instancias autoalojadas/personalizadas de cualquier fuente.",
 | 
			
		||||
    "selfHostedNote": "El desplegable «{}» puede usarse para acceder a instancias autoalojadas/personalizadas de cualquier fuente.",
 | 
			
		||||
    "badDownload": "No se ha podido analizar el APK (incompatible o descarga parcial)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Compartir aplicaciones nuevas con AppVerifier (si está disponible)",
 | 
			
		||||
    "appVerifierInstructionToast": "Comparta con AppVerifier y vuelva aquí cuando esté listo.",
 | 
			
		||||
    "wiki": "Ayuda/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (uso bajo su propia responsabilidad)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "¿Eliminar Aplicación?",
 | 
			
		||||
        "other": "¿Eliminar Aplicaciones?"
 | 
			
		||||
        "one": "¿Eliminar aplicación?",
 | 
			
		||||
        "other": "¿Eliminar aplicaciones?"
 | 
			
		||||
    },
 | 
			
		||||
    "tooManyRequestsTryAgainInMinutes": {
 | 
			
		||||
        "one": "Muchas peticiones (limitado) - prueba de nuevo en {} minuto",
 | 
			
		||||
        "other": "Muchas peticiones (limitado) - prueba de nuevo en {} minutos"
 | 
			
		||||
        "one": "Muchas peticiones (limitado); pruebe de nuevo en {} minuto",
 | 
			
		||||
        "other": "Muchas peticiones (limitado); pruebe de nuevo en {} minutos"
 | 
			
		||||
    },
 | 
			
		||||
    "bgUpdateGotErrorRetryInMinutes": {
 | 
			
		||||
        "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"
 | 
			
		||||
        "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"
 | 
			
		||||
    },
 | 
			
		||||
    "bgCheckFoundUpdatesWillNotifyIfNeeded": {
 | 
			
		||||
        "one": "La comprobación de actualizaciones en segundo plano ha encontrado {} actualización - se notificará al usuario si es necesario",
 | 
			
		||||
        "other": "La comprobación de actualizaciones en segundo plano ha encontrado {} actualizaciones - 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 le notificará si es necesario"
 | 
			
		||||
    },
 | 
			
		||||
    "apps": {
 | 
			
		||||
        "one": "{} Aplicación",
 | 
			
		||||
@@ -336,16 +349,20 @@
 | 
			
		||||
        "other": "{} días"
 | 
			
		||||
    },
 | 
			
		||||
    "clearedNLogsBeforeXAfterY": {
 | 
			
		||||
        "one": "Eliminado {n} log (previo a = {before}, posterior a = {after})",
 | 
			
		||||
        "other": "Eliminados {n} logs (previos a = {before}, posteriores a = {after})"
 | 
			
		||||
        "one": "Eliminado {n} registro (previo a = {before}, posterior a = {after})",
 | 
			
		||||
        "other": "Eliminados {n} registros (previos a = {before}, posteriores a = {after})"
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesAvailable": {
 | 
			
		||||
        "one": "{} y 1 aplicación más tiene actualizaciones.",
 | 
			
		||||
        "other": "{} y {} aplicaciones más tienen actualizaciones."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesInstalled": {
 | 
			
		||||
        "one": "{} y 1 aplicación más han sido actualizadas.",
 | 
			
		||||
        "other": "{} y {} aplicaciones más han sido actualizadas."
 | 
			
		||||
        "one": "{} y 1 aplicación más se han actualizado.",
 | 
			
		||||
        "other": "{} y {} aplicaciones más se han actualizado."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Error al actualizar {} y 1 aplicación más.",
 | 
			
		||||
        "other": "No se han podido actualizar {} y {} aplicaciones más."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} y 1 aplicación más podría haber sido actualizada.",
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(ضروری)",
 | 
			
		||||
    "dropdownNoOptsError": "خطا: کشویی باید حداقل یک گزینه داشته باشد",
 | 
			
		||||
    "colour": "رنگ",
 | 
			
		||||
    "standard": "Standard",
 | 
			
		||||
    "custom": "Custom",
 | 
			
		||||
    "useMaterialYou": "Use Material You",
 | 
			
		||||
    "githubStarredRepos": "مخازن ستاره دار گیتهاب",
 | 
			
		||||
    "uname": "نام کاربری",
 | 
			
		||||
    "wrongArgNum": "تعداد آرگومان های ارائه شده اشتباه است",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "تاریک",
 | 
			
		||||
    "light": "روشن",
 | 
			
		||||
    "followSystem": "هماهنگ با سیستم",
 | 
			
		||||
    "followSystemThemeExplanation": "دنبال کردن تم سیستم فقط با استفاده از برنامه های شخص ثالث امکان پذیر است",
 | 
			
		||||
    "useBlackTheme": "استفاده از تم تیره سیاه خالص",
 | 
			
		||||
    "appSortBy": "مرتب سازی برنامه بر اساس",
 | 
			
		||||
    "authorName": "سازنده/اسم",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "به روز رسانی جدیدی وجود ندارد.",
 | 
			
		||||
    "xHasAnUpdate": "{} یک به روز رسانی دارد.",
 | 
			
		||||
    "appsUpdated": "برنامه ها به روز شدند",
 | 
			
		||||
    "appsNotUpdated": "به روز رسانی برنامه ها ناموفق بود",
 | 
			
		||||
    "appsUpdatedNotifDescription": "به کاربر اطلاع می دهد که به روز رسانی یک یا چند برنامه در پس زمینه اعمال شده است",
 | 
			
		||||
    "xWasUpdatedToY": "{} به {} به روز شد.",
 | 
			
		||||
    "xWasNotUpdatedToY": "به روز رسانی {} به {} انجام نشد.",
 | 
			
		||||
    "errorCheckingUpdates": "خطا در بررسی بهروزرسانیها",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "اعلانی که وقتی بررسی بهروزرسانی پسزمینه ناموفق است نشان میدهد",
 | 
			
		||||
    "appsRemoved": "برنامه ها حذف شدند",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "غیرفعال کردن تشخیص نسخه",
 | 
			
		||||
    "noVersionDetectionExplanation": "این گزینه فقط باید برای برنامه هایی استفاده شود که تشخیص نسخه به درستی کار نمی کند.",
 | 
			
		||||
    "downloadingX": "در حال دانلود {}",
 | 
			
		||||
    "downloadX": "دانلود {}",
 | 
			
		||||
    "downloadedX": "دانلود شده {}",
 | 
			
		||||
    "releaseAsset": "انتشار دارایی",
 | 
			
		||||
    "downloadNotifDescription": "کاربر را از پیشرفت دانلود یک برنامه مطلع می کند",
 | 
			
		||||
    "noAPKFound": "APK پیدا نشد فایل",
 | 
			
		||||
    "noVersionDetection": "بدون تشخیص نسخه",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "پشتیبانی از URL های APK ثابت",
 | 
			
		||||
    "selectX": "انتخاب کنید {}",
 | 
			
		||||
    "parallelDownloads": "اجازه دانلود موازی",
 | 
			
		||||
    "installMethod": "روش نصب",
 | 
			
		||||
    "normal": "طبیعی",
 | 
			
		||||
    "root": "ریشه",
 | 
			
		||||
    "useShizuku": "Use Shizuku or Sui to install",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku در حال اجرا نیست",
 | 
			
		||||
    "shizukuOld": "Old Shizuku version (<11) - update it",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku running on Android < 8.1 with ADB - update Android or use Sui instead",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Set Google Play as the installation source (if Shizuku is used)",
 | 
			
		||||
    "useSystemFont": "استفاده از فونت سیستم",
 | 
			
		||||
    "systemFontError": "خطا در بارگیری فونت سیستم: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "استفاده کد نسخه برنامه به جای نسخه شناسایی شده توسط سیستم عامل استفاده کنید",
 | 
			
		||||
    "requestHeader": "درخواست سطر بالایی",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "استفاده از آخرین بارگذاری دارایی به عنوان تاریخ انتشار",
 | 
			
		||||
@@ -296,9 +305,13 @@
 | 
			
		||||
    "installed": "نصب شده است",
 | 
			
		||||
    "latest": "آخرین",
 | 
			
		||||
    "invertRegEx": "معکوس کردن عبارت منظم",
 | 
			
		||||
    "note": "Note",
 | 
			
		||||
    "selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
 | 
			
		||||
    "badDownload": "The APK could not be parsed (incompatible or partial download)",
 | 
			
		||||
    "note": "یادداشت",
 | 
			
		||||
    "selfHostedNote": "از منوی کرکره ای \"{}\" می توان برای دسترسی به نمونه های خود میزبانی/سفارشی از هر منبعی استفاده کرد.",
 | 
			
		||||
    "badDownload": "APK قابل تجزیه نیست (دانلود ناسازگار یا جزئی)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "اشتراکگذاری برنامههای جدید با AppVerifier (در صورت وجود)",
 | 
			
		||||
    "appVerifierInstructionToast": "در AppVerifier به اشتراک بگذارید، سپس پس از آماده شدن به اینجا برگردید.",
 | 
			
		||||
    "wiki": "راهنما/ویکی",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "تنظیمات برنامه Crowdsourced (با مسئولیت خود استفاده کنید)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "برنامه حذف شود؟",
 | 
			
		||||
        "other": "برنامه ها حذف شوند؟"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} و 1 برنامه دیگر به روز شدند.",
 | 
			
		||||
        "other": "{} و {} برنامه دیگر به روز شدند."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "{} و 1 برنامه دیگر به روز نشد.",
 | 
			
		||||
        "other": "{} و {} برنامه دیگر به روز نشد."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} و 1 برنامه دیگر ممکن است به روز شده باشند.",
 | 
			
		||||
        "other": "ممکن است {} و {} برنامه های دیگر به روز شده باشند."
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
    "invalidURLForSource": "URL d'application {} invalide",
 | 
			
		||||
    "noReleaseFound": "Impossible de trouver une version appropriée",
 | 
			
		||||
    "noVersionFound": "Impossible de déterminer la version de la version",
 | 
			
		||||
    "noReleaseFound": "Impossible de trouver une version adaptée",
 | 
			
		||||
    "noVersionFound": "Impossible de déterminer la variante de la version",
 | 
			
		||||
    "urlMatchesNoSource": "L'URL ne correspond pas à une source connue",
 | 
			
		||||
    "cantInstallOlderVersion": "Impossible d'installer une ancienne version d'une application",
 | 
			
		||||
    "appIdMismatch": "L'ID de paquet téléchargé ne correspond pas à l'ID de l'application existante",
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
    "unexpectedError": "Erreur inattendue",
 | 
			
		||||
    "ok": "D'accord",
 | 
			
		||||
    "and": "et",
 | 
			
		||||
    "githubPATLabel": "Jeton d'Accès Personnel GitHub (Augmente la limite de débit)",
 | 
			
		||||
    "githubPATLabel": "Jeton d'Accès Personnel GitHub (augmente la limite de débit)",
 | 
			
		||||
    "includePrereleases": "Inclure les avant-premières",
 | 
			
		||||
    "fallbackToOlderReleases": "Retour aux anciennes versions",
 | 
			
		||||
    "filterReleaseTitlesByRegEx": "Filtrer les titres de version par expression régulière",
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(Requis)",
 | 
			
		||||
    "dropdownNoOptsError": "ERREUR : LE DÉROULEMENT DOIT AVOIR AU MOINS UNE OPT",
 | 
			
		||||
    "colour": "Couleur",
 | 
			
		||||
    "standard": "Standard",
 | 
			
		||||
    "custom": "Sur mesure",
 | 
			
		||||
    "useMaterialYou": "Utiliser Material You",
 | 
			
		||||
    "githubStarredRepos": "Dépôts étoilés GitHub",
 | 
			
		||||
    "uname": "Nom d'utilisateur",
 | 
			
		||||
    "wrongArgNum": "Mauvais nombre d'arguments fournis",
 | 
			
		||||
@@ -43,15 +46,15 @@
 | 
			
		||||
    "additionalOptsFor": "Options supplémentaires pour {}",
 | 
			
		||||
    "supportedSources": "Sources prises en charge ",
 | 
			
		||||
    "trackOnlyInBrackets": "(Suivi uniquement)",
 | 
			
		||||
    "searchableInBrackets": "(Recherchable)",
 | 
			
		||||
    "searchableInBrackets": "(Interrogeable)",
 | 
			
		||||
    "appsString": "Applications",
 | 
			
		||||
    "noApps": "Aucune application",
 | 
			
		||||
    "noAppsForFilter": "Aucune application pour le filtre",
 | 
			
		||||
    "byX": "Par {}",
 | 
			
		||||
    "percentProgress": "Progrès: {}%",
 | 
			
		||||
    "percentProgress": "Progrès : {}%",
 | 
			
		||||
    "pleaseWait": "Veuillez patienter",
 | 
			
		||||
    "updateAvailable": "Mise à jour disponible",
 | 
			
		||||
    "notInstalled": "Pas installé",
 | 
			
		||||
    "notInstalled": "Non installé",
 | 
			
		||||
    "pseudoVersion": "pseudo-version",
 | 
			
		||||
    "selectAll": "Tout sélectionner",
 | 
			
		||||
    "deselectX": "Déselectionner {}",
 | 
			
		||||
@@ -60,21 +63,21 @@
 | 
			
		||||
    "removeSelectedApps": "Supprimer les applications sélectionnées",
 | 
			
		||||
    "updateX": "Mise à jour {}",
 | 
			
		||||
    "installX": "Installer {}",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "Marquer {}\n(Suivi uniquement)\nas mis à jour",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "Marquer {}\n(Suivi uniquement)\n comme mis à jour",
 | 
			
		||||
    "changeX": "Changer {}",
 | 
			
		||||
    "installUpdateApps": "Installer/Mettre à jour les applications",
 | 
			
		||||
    "installUpdateSelectedApps": "Installer/Mettre à jour les applications sélectionnées",
 | 
			
		||||
    "markXSelectedAppsAsUpdated": "Marquer {} les applications sélectionnées comme mises à jour ?",
 | 
			
		||||
    "markXSelectedAppsAsUpdated": "Marquer {} les applications sélectionnées comme étant à jour ?",
 | 
			
		||||
    "no": "Non",
 | 
			
		||||
    "yes": "Oui",
 | 
			
		||||
    "markSelectedAppsUpdated": "Marquer les applications sélectionnées comme mises à jour",
 | 
			
		||||
    "markSelectedAppsUpdated": "Marquer les applications sélectionnées comme étant à jour",
 | 
			
		||||
    "pinToTop": "Épingler en haut",
 | 
			
		||||
    "unpinFromTop": "Détacher du haut",
 | 
			
		||||
    "resetInstallStatusForSelectedAppsQuestion": "Réinitialiser l'état d'installation des applications sélectionnées ?",
 | 
			
		||||
    "installStatusOfXWillBeResetExplanation": "L'état d'installation de toutes les applications sélectionnées sera réinitialisé.\n\nCela peut aider lorsque la version de l'application affichée dans Obtainium est incorrecte en raison d'échecs de mises à jour ou d'autres problèmes.",
 | 
			
		||||
    "customLinkMessage": "Ces liens fonctionnent sur les appareils sur lesquels Obtenirium est installé",
 | 
			
		||||
    "unpinFromTop": "Désépingler du haut",
 | 
			
		||||
    "resetInstallStatusForSelectedAppsQuestion": "Réinitialiser le statut d'installation des applications sélectionnées ?",
 | 
			
		||||
    "installStatusOfXWillBeResetExplanation": "Le statut d'installation de toutes les applications sélectionnées sera réinitialisé.\n\nCela peut aider lorsque la version de l'application affichée dans Obtainium est incorrecte en raison d'échecs de mises à jour ou d'autres problèmes.",
 | 
			
		||||
    "customLinkMessage": "Ces liens fonctionnent sur les appareils sur lesquels Obtainium est installé",
 | 
			
		||||
    "shareAppConfigLinks": "Partager la configuration de l'application sous forme de lien HTML",
 | 
			
		||||
    "shareSelectedAppURLs": "Partager les URL d'application sélectionnées",
 | 
			
		||||
    "shareSelectedAppURLs": "Partager les URL d'applications sélectionnées",
 | 
			
		||||
    "resetInstallStatus": "Réinitialiser le statut d'installation",
 | 
			
		||||
    "more": "Plus",
 | 
			
		||||
    "removeOutdatedFilter": "Supprimer le filtre d'application obsolète",
 | 
			
		||||
@@ -88,14 +91,14 @@
 | 
			
		||||
    "importExport": "Importer/Exporter",
 | 
			
		||||
    "settings": "Paramètres",
 | 
			
		||||
    "exportedTo": "Exporté vers {}",
 | 
			
		||||
    "obtainiumExport": "Exportation d'Obtainium",
 | 
			
		||||
    "obtainiumExport": "Exporter d'Obtainium",
 | 
			
		||||
    "invalidInput": "Entrée invalide",
 | 
			
		||||
    "importedX": "Importé {}",
 | 
			
		||||
    "obtainiumImport": "Importation d'Obtainium",
 | 
			
		||||
    "obtainiumImport": "Importer d'Obtainium",
 | 
			
		||||
    "importFromURLList": "Importer à partir de la liste d'URL",
 | 
			
		||||
    "searchQuery": "Requête de recherche",
 | 
			
		||||
    "searchQuery": "Requête",
 | 
			
		||||
    "appURLList": "Liste d'URL d'application",
 | 
			
		||||
    "line": "Queue",
 | 
			
		||||
    "line": "File d'attente",
 | 
			
		||||
    "searchX": "Rechercher {}",
 | 
			
		||||
    "noResults": "Aucun résultat trouvé",
 | 
			
		||||
    "importX": "Importer {}",
 | 
			
		||||
@@ -104,25 +107,26 @@
 | 
			
		||||
    "importedXOfYApps": "{} sur {} applications importées.",
 | 
			
		||||
    "followingURLsHadErrors": "Les URL suivantes comportaient des erreurs :",
 | 
			
		||||
    "selectURL": "Sélectionnez l'URL",
 | 
			
		||||
    "selectURLs": "Sélectionnez les URLs",
 | 
			
		||||
    "selectURLs": "Sélectionnez les URL",
 | 
			
		||||
    "pick": "Prendre",
 | 
			
		||||
    "theme": "Thème",
 | 
			
		||||
    "dark": "Sombre",
 | 
			
		||||
    "light": "Clair",
 | 
			
		||||
    "followSystem": "Suivre le système",
 | 
			
		||||
    "useBlackTheme": "Utilisez le thème noir pur et sombre",
 | 
			
		||||
    "followSystemThemeExplanation": "Il n'est possible de suivre le thème du système qu'en utilisant des applications tierces.",
 | 
			
		||||
    "useBlackTheme": "Utiliser le thème noir pur",
 | 
			
		||||
    "appSortBy": "Applications triées par",
 | 
			
		||||
    "authorName": "Auteur/Nom",
 | 
			
		||||
    "nameAuthor": "Nom/Auteur",
 | 
			
		||||
    "asAdded": "Comme ajouté",
 | 
			
		||||
    "appSortOrder": "Ordre de tri des applications",
 | 
			
		||||
    "ascending": "Ascendant",
 | 
			
		||||
    "descending": "Descendanr",
 | 
			
		||||
    "descending": "Descendant",
 | 
			
		||||
    "bgUpdateCheckInterval": "Intervalle de vérification des mises à jour en arrière-plan",
 | 
			
		||||
    "neverManualOnly": "Jamais - Manuel uniquement",
 | 
			
		||||
    "neverManualOnly": "Jamais — Manuel uniquement",
 | 
			
		||||
    "appearance": "Apparence",
 | 
			
		||||
    "showWebInAppView": "Afficher la page Web source dans la vue de l'application",
 | 
			
		||||
    "pinUpdates": "Épingler les mises à jour dans la vue Top des applications",
 | 
			
		||||
    "pinUpdates": "Épingler les mises à jour en tête de la vue Applications",
 | 
			
		||||
    "updates": "Mises à jour",
 | 
			
		||||
    "sourceSpecific": "Spécifique à la source",
 | 
			
		||||
    "appSource": "Source de l'application",
 | 
			
		||||
@@ -131,20 +135,22 @@
 | 
			
		||||
    "close": "Fermer",
 | 
			
		||||
    "share": "Partager",
 | 
			
		||||
    "appNotFound": "Application introuvable",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "exportation d'obtainium",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "Exportation-Obtainium",
 | 
			
		||||
    "pickAnAPK": "Choisissez un APK",
 | 
			
		||||
    "appHasMoreThanOnePackage": "{} a plus d'un paquet :",
 | 
			
		||||
    "deviceSupportsXArch": "Votre appareil prend en charge l'architecture de processeur {}.",
 | 
			
		||||
    "deviceSupportsXArch": "Votre appareil prend en charge l'architecture CPU {}.",
 | 
			
		||||
    "deviceSupportsFollowingArchs": "Votre appareil prend en charge les architectures CPU suivantes :",
 | 
			
		||||
    "warning": "Avertissement",
 | 
			
		||||
    "sourceIsXButPackageFromYPrompt": "La source de l'application est '{}' mais le paquet de version provient de '{}'. Continuer?",
 | 
			
		||||
    "sourceIsXButPackageFromYPrompt": "La source de l'application est '{}' mais la version du paquet provient de '{}'. Continuer ?",
 | 
			
		||||
    "updatesAvailable": "Mises à jour disponibles",
 | 
			
		||||
    "updatesAvailableNotifDescription": "Avertit l'utilisateur que des mises à jour sont disponibles pour une ou plusieurs applications suivies par Obtainium",
 | 
			
		||||
    "noNewUpdates": "Aucune nouvelle mise à jour.",
 | 
			
		||||
    "xHasAnUpdate": "{} a une mise à jour.",
 | 
			
		||||
    "appsUpdated": "Applications mises à jour",
 | 
			
		||||
    "appsNotUpdated": "Échec de la mise à jour des applications",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Avertit l'utilisateur que les mises à jour d'une ou plusieurs applications ont été appliquées en arrière-plan",
 | 
			
		||||
    "xWasUpdatedToY": "{} a été mis à jour pour {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Échec de la mise à jour de {} vers {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Erreur lors de la vérification des mises à jour",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Une notification qui s'affiche lorsque la vérification de la mise à jour en arrière-plan échoue",
 | 
			
		||||
    "appsRemoved": "Applications supprimées",
 | 
			
		||||
@@ -162,7 +168,7 @@
 | 
			
		||||
    "unknown": "Inconnu",
 | 
			
		||||
    "none": "Aucun",
 | 
			
		||||
    "never": "Jamais",
 | 
			
		||||
    "latestVersionX": "Dernière version: {}",
 | 
			
		||||
    "latestVersionX": "Dernière version : {}",
 | 
			
		||||
    "installedVersionX": "Version installée : {}",
 | 
			
		||||
    "lastUpdateCheckX": "Vérification de la dernière mise à jour : {}",
 | 
			
		||||
    "remove": "Retirer",
 | 
			
		||||
@@ -173,38 +179,41 @@
 | 
			
		||||
    "appWithIdOrNameNotFound": "Aucune application n'a été trouvée avec cet identifiant ou ce nom",
 | 
			
		||||
    "reposHaveMultipleApps": "Les dépôts peuvent contenir plusieurs applications",
 | 
			
		||||
    "fdroidThirdPartyRepo": "Dépôt tiers F-Droid",
 | 
			
		||||
    "steamMobile": "Vapeur Mobile",
 | 
			
		||||
    "steamChat": "Chat sur Steam",
 | 
			
		||||
    "steamMobile": "Application mobile Steam",
 | 
			
		||||
    "steamChat": "Steam Chat",
 | 
			
		||||
    "install": "Installer",
 | 
			
		||||
    "markInstalled": "Marquer installée",
 | 
			
		||||
    "markInstalled": "Marquer comme installée",
 | 
			
		||||
    "update": "Mettre à jour",
 | 
			
		||||
    "markUpdated": "Marquer à jour",
 | 
			
		||||
    "additionalOptions": "Options additionelles",
 | 
			
		||||
    "markUpdated": "Marquer comme étant à jour",
 | 
			
		||||
    "additionalOptions": "Options additionnelles",
 | 
			
		||||
    "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 être utilisée uniquement pour les applications où la détection de version ne fonctionne pas correctement.",
 | 
			
		||||
    "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",
 | 
			
		||||
    "noAPKFound": "Aucun APK trouvé",
 | 
			
		||||
    "noVersionDetection": "Pas de détection de version",
 | 
			
		||||
    "noVersionDetection": "Aucune de détection de version",
 | 
			
		||||
    "categorize": "Catégoriser",
 | 
			
		||||
    "categories": "Catégories",
 | 
			
		||||
    "category": "Catégorie",
 | 
			
		||||
    "noCategory": "Aucune catégorie",
 | 
			
		||||
    "noCategories": "Aucune catégorie",
 | 
			
		||||
    "deleteCategoriesQuestion": "Supprimer les catégories ?",
 | 
			
		||||
    "categoryDeleteWarning": "Toutes les applications dans les catégories supprimées seront définies sur non catégorisées.",
 | 
			
		||||
    "noCategories": "Aucune catégories",
 | 
			
		||||
    "deleteCategoriesQuestion": "Supprimer les catégories ?",
 | 
			
		||||
    "categoryDeleteWarning": "Toutes les applications dans les catégories supprimées ne seront plus catégorisées.",
 | 
			
		||||
    "addCategory": "Ajouter une catégorie",
 | 
			
		||||
    "label": "Étiquette",
 | 
			
		||||
    "language": "Langue",
 | 
			
		||||
    "copiedToClipboard": "Copié dans le presse-papier",
 | 
			
		||||
    "storagePermissionDenied": "Autorisation de stockage refusée",
 | 
			
		||||
    "selectedCategorizeWarning": "Cela remplacera tous les paramètres de catégorie existants pour les applications sélectionnées.",
 | 
			
		||||
    "selectedCategorizeWarning": "Cela remplacera toutes les catégorie définies pour les applications sélectionnées.",
 | 
			
		||||
    "filterAPKsByRegEx": "Filtrer les APK par expression régulière",
 | 
			
		||||
    "removeFromObtainium": "Supprimer d'Obtainium",
 | 
			
		||||
    "uninstallFromDevice": "Désinstaller de l'appareil",
 | 
			
		||||
    "onlyWorksWithNonVersionDetectApps": "Fonctionne uniquement pour les applications avec la détection de version désactivée.",
 | 
			
		||||
    "releaseDateAsVersion": "Utiliser la date de sortie comme version",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "Cette option ne doit être utilisée que pour les applications où la détection de version ne fonctionne pas correctement, mais une date de sortie est disponible.",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "Cette option ne doit être utilisée que pour les applications où la détection de version ne fonctionne pas correctement, mais dont une date de sortie est disponible.",
 | 
			
		||||
    "changes": "Changements",
 | 
			
		||||
    "releaseDate": "Date de sortie",
 | 
			
		||||
    "importFromURLsInFile": "Importer à partir d'URL dans un fichier (comme OPML)",
 | 
			
		||||
@@ -212,59 +221,59 @@
 | 
			
		||||
    "versionDetection": "Détection des versions",
 | 
			
		||||
    "standardVersionDetection": "Détection de version standard",
 | 
			
		||||
    "groupByCategory": "Regrouper par catégorie",
 | 
			
		||||
    "autoApkFilterByArch": "Essayez de filtrer les APK par architecture CPU si possible",
 | 
			
		||||
    "autoApkFilterByArch": "Si possible, essayer de filtrer les APK par architecture CPU",
 | 
			
		||||
    "overrideSource": "Remplacer la source",
 | 
			
		||||
    "dontShowAgain": "Ne montre plus ça",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Don't Show the 'Track-Only' Warning",
 | 
			
		||||
    "dontShowAgain": "Ne plus montrer",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Ne pas afficher l'avertissement 'Suivi uniquement'",
 | 
			
		||||
    "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",
 | 
			
		||||
    "gitlabPATLabel": "Jeton d'accès personnel GitLab",
 | 
			
		||||
    "about": "À propos de",
 | 
			
		||||
    "requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
 | 
			
		||||
    "requiresCredentialsInSettings": "{} : Cela nécessite des identifiants supplémentaires (dans Paramètres)",
 | 
			
		||||
    "checkOnStart": "Vérifier les mises à jour au démarrage",
 | 
			
		||||
    "tryInferAppIdFromCode": "Essayez de déduire l'ID de l'application à partir du code source",
 | 
			
		||||
    "removeOnExternalUninstall": "Supprimer automatiquement les applications désinstallées en externe",
 | 
			
		||||
    "pickHighestVersionCode": "Sélectionner automatiquement le code APK de la version la plus élevée",
 | 
			
		||||
    "checkUpdateOnDetailPage": "Vérifier les mises à jour lors de l'ouverture d'une page de détails d'application",
 | 
			
		||||
    "tryInferAppIdFromCode": "Essayer de déduire l'ID de l'application à partir du code source",
 | 
			
		||||
    "removeOnExternalUninstall": "Supprimer automatiquement les applications désinstallées depuis l'extérieur",
 | 
			
		||||
    "pickHighestVersionCode": "Sélectionner automatiquement le code de version de l'APK la plus élevée",
 | 
			
		||||
    "checkUpdateOnDetailPage": "Vérifier les mises à jour lors de l'ouverture de la page détaillée d'une application",
 | 
			
		||||
    "disablePageTransitions": "Désactiver les animations de transition de page",
 | 
			
		||||
    "reversePageTransitions": "Animations de transition de page inversée",
 | 
			
		||||
    "reversePageTransitions": "Inverser les animations de transition de page",
 | 
			
		||||
    "minStarCount": "Nombre minimum d'étoiles",
 | 
			
		||||
    "addInfoBelow": "Ajoutez ces informations ci-dessous.",
 | 
			
		||||
    "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 limite de débit GitHub peut être évitée à l'aide d'une clé API.",
 | 
			
		||||
    "sortByLastLinkSegment": "Trier uniquement sur le dernier segment du lien",
 | 
			
		||||
    "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 du lien APK personnalisé par expression régulière (par défaut '.apk$')",
 | 
			
		||||
    "appsPossiblyUpdated": "Tentative de mise à jour de l'application",
 | 
			
		||||
    "appsPossiblyUpdatedNotifDescription": "Avertit l'utilisateur que des mises à jour d'une ou plusieurs applications ont été potentiellement appliquées en arrière-plan",
 | 
			
		||||
    "xWasPossiblyUpdatedToY": "{} a peut-être été mis à jour vers {}.",
 | 
			
		||||
    "xWasPossiblyUpdatedToY": "{} pourrait avoir été mis à jour vers {}.",
 | 
			
		||||
    "enableBackgroundUpdates": "Activer les mises à jour en arrière-plan",
 | 
			
		||||
    "backgroundUpdateReqsExplanation": "Les mises à jour en arrière-plan peuvent ne pas être possibles pour toutes les applications.",
 | 
			
		||||
    "backgroundUpdateLimitsExplanation": "Le succès d'une installation en arrière-plan ne peut être déterminé qu'à l'ouverture d'Obetium.",
 | 
			
		||||
    "verifyLatestTag": "Vérifiez la balise 'dernière'",
 | 
			
		||||
    "backgroundUpdateLimitsExplanation": "Le succès d'une installation en arrière-plan ne peut être déterminé qu'à l'ouverture d'Obtainium.",
 | 
			
		||||
    "verifyLatestTag": "Vérifier la balise 'latest'",
 | 
			
		||||
    "intermediateLinkRegex": " Filtrer un lien \" intermédiaire \" à visiter ",
 | 
			
		||||
    "filterByLinkText": "Filtrer les liens par texte de lien",
 | 
			
		||||
    "filterByLinkText": "Filtrer les liens par le texte du lien",
 | 
			
		||||
    "intermediateLinkNotFound": "Lien intermédiaire introuvable",
 | 
			
		||||
    "intermediateLink": "Lien intermédiaire",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "Exempt des mises à jour en arrière-plan (si activé)",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "Exempté des mises à jour en arrière-plan (si activé)",
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "Désactiver les mises à jour en arrière-plan lorsque vous n'êtes pas connecté au WiFi",
 | 
			
		||||
    "autoSelectHighestVersionCode": "Sélection automatique de la version la plus élevéeCode APK",
 | 
			
		||||
    "versionExtractionRegEx": "Version Extraction RegEx",
 | 
			
		||||
    "matchGroupToUse": "Match Group to Use",
 | 
			
		||||
    "highlightTouchTargets": "Mettez en évidence les cibles tactiles moins évidentes",
 | 
			
		||||
    "autoSelectHighestVersionCode": "Sélection automatique du code de version le plus élevé de l'APK",
 | 
			
		||||
    "versionExtractionRegEx": "Expression régulière d'extraction de version",
 | 
			
		||||
    "matchGroupToUse": "Groupe de correspondance pour l'expression régulière d'extraction de version",
 | 
			
		||||
    "highlightTouchTargets": "Mettre en évidence les cibles tactiles moins évidentes",
 | 
			
		||||
    "pickExportDir": "Choisir le répertoire d'exportation",
 | 
			
		||||
    "autoExportOnChanges": "Exportation automatique sur modifications",
 | 
			
		||||
    "autoExportOnChanges": "Exporter automatiquement après modification",
 | 
			
		||||
    "includeSettings": "Inclure les paramètres",
 | 
			
		||||
    "filterVersionsByRegEx": "Filtrer les versions par expression régulière",
 | 
			
		||||
    "trySelectingSuggestedVersionCode": "Essayez de sélectionner la version suggéréeCode APK",
 | 
			
		||||
    "dontSortReleasesList": "Conserver la commande de version de l'API",
 | 
			
		||||
    "trySelectingSuggestedVersionCode": "Essayer de sélectionner le code de la version suggérée de l'APK",
 | 
			
		||||
    "dontSortReleasesList": "Conserver l'ordre des versions de l'API",
 | 
			
		||||
    "reverseSort": "Tri inversé",
 | 
			
		||||
    "takeFirstLink": "Prendre le premier lien",
 | 
			
		||||
    "skipSort": "Sauter le tri",
 | 
			
		||||
    "skipSort": "Éviter le tri",
 | 
			
		||||
    "debugMenu": "Menu de débogage",
 | 
			
		||||
    "bgTaskStarted": "Tâche en arrière-plan démarrée - vérifier les journaux.",
 | 
			
		||||
    "runBgCheckNow": "Exécuter la vérification de la mise à jour en arrière-plan maintenant",
 | 
			
		||||
    "versionExtractWholePage": "Apply Version Extraction Regex to Entire Page",
 | 
			
		||||
    "bgTaskStarted": "Tâche en arrière-plan démarrée — vérifier les journaux.",
 | 
			
		||||
    "runBgCheckNow": "Exécuter maintenant la vérification de la mise à jour en arrière-plan",
 | 
			
		||||
    "versionExtractWholePage": "Appliquer l'expression régulière d'extraction de version sur l'ensemble de la page",
 | 
			
		||||
    "installing": "Installation",
 | 
			
		||||
    "skipUpdateNotifications": "Ignorer les notifications de mise à jour",
 | 
			
		||||
    "updatesAvailableNotifChannel": "Mises à jour disponibles",
 | 
			
		||||
@@ -275,19 +284,19 @@
 | 
			
		||||
    "downloadingXNotifChannel": "Téléchargement {}",
 | 
			
		||||
    "completeAppInstallationNotifChannel": "Installation complète de l'application",
 | 
			
		||||
    "checkingForUpdatesNotifChannel": "Vérification des mises à jour",
 | 
			
		||||
    "onlyCheckInstalledOrTrackOnlyApps": "Vérifiez uniquement les mises à jour des applications installées et de suivi uniquement",
 | 
			
		||||
    "onlyCheckInstalledOrTrackOnlyApps": "Vérifier uniquement les mises à jour des applications installées et 'Suivi uniquement'",
 | 
			
		||||
    "supportFixedAPKURL": "Prise en charge des URL APK fixes",
 | 
			
		||||
    "selectX": "Sélectionner {}",
 | 
			
		||||
    "parallelDownloads": "Autoriser les téléchargements parallèles",
 | 
			
		||||
    "installMethod": "Méthode d'installation",
 | 
			
		||||
    "normal": "Normale",
 | 
			
		||||
    "root": "Racine",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku is not running",
 | 
			
		||||
    "useSystemFont": "Utiliser la police système",
 | 
			
		||||
    "systemFontError": "Erreur de chargement de la police système : {}",
 | 
			
		||||
    "parallelDownloads": "Autoriser le téléchargement en parallèle",
 | 
			
		||||
    "useShizuku": "Utiliser Shizuku ou Sui pour l'installation",
 | 
			
		||||
    "shizukuBinderNotFound": "Service Shizuku compatible non trouvé",
 | 
			
		||||
    "shizukuOld": "Ancienne version de Shizuku (<11) — la mettre à jour",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku fonctionne sur Android < 8.1 avec ADB — mettez à jour Android ou utilisez Sui à la place",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Définir Google Play comme source d'installation (si Shizuku est utilisé)",
 | 
			
		||||
    "useSystemFont": "Utiliser la police du système",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Utiliser le code de version de l'application comme version détectée par le système d'exploitation",
 | 
			
		||||
    "requestHeader": "En-tête de demande",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Utiliser le dernier téléchargement d'élément comme date de sortie",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Utiliser le dernier élément téléversé comme date de sortie",
 | 
			
		||||
    "defaultPseudoVersioningMethod": "Méthode de pseudo-version par défaut",
 | 
			
		||||
    "partialAPKHash": "Hash APK partiel",
 | 
			
		||||
    "APKLinkHash": "Hash de lien APK",
 | 
			
		||||
@@ -299,21 +308,25 @@
 | 
			
		||||
    "note": "Note",
 | 
			
		||||
    "selfHostedNote": "La liste déroulante \"{}\" peut être utilisée pour accéder aux instances auto-hébergées/personnalisées de n'importe quelle source.",
 | 
			
		||||
    "badDownload": "L'APK n'a pas pu être analysé (téléchargement incompatible ou partiel)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Partager les nouvelles applications avec AppVerifier (si disponible)",
 | 
			
		||||
    "appVerifierInstructionToast": "Partagez avec AppVerifier, puis revenez ici lorsque vous êtes prêt.",
 | 
			
		||||
    "wiki": "Aide/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Configurations d'applications participative (utilisation à vos risques et périls)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Supprimer l'application ?",
 | 
			
		||||
        "other": "Supprimer les applications ?"
 | 
			
		||||
        "one": "Supprimer l'application ?",
 | 
			
		||||
        "other": "Supprimer les applications ?"
 | 
			
		||||
    },
 | 
			
		||||
    "tooManyRequestsTryAgainInMinutes": {
 | 
			
		||||
        "one": "Trop de demandes (taux limité) - réessayez dans {} minute",
 | 
			
		||||
        "other": "Trop de demandes (taux limité) - réessayez dans {} minutes"
 | 
			
		||||
        "one": "Trop de demandes (taux limité) — réessayez dans {} minute",
 | 
			
		||||
        "other": "Trop de demandes (taux limité) — réessayez dans {} minutes"
 | 
			
		||||
    },
 | 
			
		||||
    "bgUpdateGotErrorRetryInMinutes": {
 | 
			
		||||
        "one": "La vérification de la mise à jour en arrière-plan a rencontré un {}, planifiera une nouvelle tentative de vérification dans {} minute",
 | 
			
		||||
        "other": "La vérification de la mise à jour en arrière-plan a rencontré un {}, planifiera une nouvelle tentative de vérification dans {} minutes"
 | 
			
		||||
        "one": "La vérification de la mise à jour en arrière-plan a rencontré un {}, une nouvelle tentative de vérification sera planifié dans {} minute",
 | 
			
		||||
        "other": "La vérification de la mise à jour en arrière-plan a rencontré un {}, une nouvelle tentative de vérification sera planifié dans {} minutes"
 | 
			
		||||
    },
 | 
			
		||||
    "bgCheckFoundUpdatesWillNotifyIfNeeded": {
 | 
			
		||||
        "one": "La vérification des mises à jour en arrière-plan trouvée {} mise à jour - avertira l'utilisateur si nécessaire",
 | 
			
		||||
        "other": "La vérification des mises à jour en arrière-plan a trouvé {} mises à jour - avertira l'utilisateur si nécessaire"
 | 
			
		||||
        "one": "La vérification des mises à jour en arrière-plan a trouvée {} mise à jour — l'utilisateur sera notifié si nécessaire",
 | 
			
		||||
        "other": "La vérification des mises à jour en arrière-plan a trouvée {} mises à jour — l'utilisateur sera notifié si nécessaire"
 | 
			
		||||
    },
 | 
			
		||||
    "apps": {
 | 
			
		||||
        "one": "{} Application",
 | 
			
		||||
@@ -347,9 +360,13 @@
 | 
			
		||||
        "one": "{} et 1 autre application ont été mises à jour.",
 | 
			
		||||
        "other": "{} et {} autres applications ont été mises à jour."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Échec de la mise à jour de {} et d'une autre application.",
 | 
			
		||||
        "other": "Échec de la mise à jour de {} et {} autres applications."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "une": "{} et 1 application supplémentaire ont peut-être été mises à jour.",
 | 
			
		||||
        "other": "{} et {} autres applications peuvent avoir été mises à jour."
 | 
			
		||||
        "une": "{} et 1 application supplémentaire pourraient avoir été mises à jour.",
 | 
			
		||||
        "other": "{} et {} autres applications pourraient avoir été mises à jour."
 | 
			
		||||
    },
 | 
			
		||||
    "apk": {
 | 
			
		||||
        "one": "{} APK",
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(Kötelező)",
 | 
			
		||||
    "dropdownNoOptsError": "HIBA: A LEDOBÁST LEGALÁBB EGY OPCIÓHOZ KELL RENDELNI",
 | 
			
		||||
    "colour": "Szín",
 | 
			
		||||
    "standard": "Standard",
 | 
			
		||||
    "custom": "Custom",
 | 
			
		||||
    "useMaterialYou": "Használja az Ön által használt anyagot",
 | 
			
		||||
    "githubStarredRepos": "GitHub Csillagos Repo-k",
 | 
			
		||||
    "uname": "Felh.név",
 | 
			
		||||
    "wrongArgNum": "Rossz számú argumentumot adott meg",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Sötét",
 | 
			
		||||
    "light": "Világos",
 | 
			
		||||
    "followSystem": "Rendszer szerint",
 | 
			
		||||
    "followSystemThemeExplanation": "A következő rendszer téma csak harmadik féltől származó alkalmazások használatával lehetséges",
 | 
			
		||||
    "useBlackTheme": "Használjon teljesen fekete sötét témát",
 | 
			
		||||
    "appSortBy": "App rendezés...",
 | 
			
		||||
    "authorName": "Szerző/Név",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "Nincsenek új frissítések.",
 | 
			
		||||
    "xHasAnUpdate": "A(z) {} frissítést kapott.",
 | 
			
		||||
    "appsUpdated": "Alkalmazások frissítve",
 | 
			
		||||
    "appsNotUpdated": "Nem sikerült frissíteni az alkalmazásokat",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Értesíti a felhasználót, hogy egy/több app frissítése megtörtént a háttérben",
 | 
			
		||||
    "xWasUpdatedToY": "{} frissítve a következőre: {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "A {} frissítése a {}-ra nem sikerült.",
 | 
			
		||||
    "errorCheckingUpdates": "Hiba a frissítések keresésekor",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Értesítés, amely akkor jelenik meg, ha a háttérbeli frissítések ellenőrzése sikertelen",
 | 
			
		||||
    "appsRemoved": "Alkalmazások eltávolítva",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "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.",
 | 
			
		||||
    "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",
 | 
			
		||||
    "noAPKFound": "Nem található APK",
 | 
			
		||||
    "noVersionDetection": "Nincs verzió érzékelés",
 | 
			
		||||
@@ -218,7 +227,7 @@
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Ne jelenítsen meg 'Csak nyomon követés' figyelmeztetést",
 | 
			
		||||
    "dontShowAPKOriginWarnings": "Ne jelenítsen meg az APK eredetére vonatkozó figyelmeztetéseket",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Helyezze át a nem telepített appokat az App nézet aljára",
 | 
			
		||||
    "gitlabPATLabel": "GitLab Personal Access Token",
 | 
			
		||||
    "gitlabPATLabel": "GitLab személyes hozzáférési token",
 | 
			
		||||
    "about": "Rólunk",
 | 
			
		||||
    "requiresCredentialsInSettings": "{}: Ehhez további hitelesítő adatokra van szükség (a Beállításokban)",
 | 
			
		||||
    "checkOnStart": "Egyszer az alkalmazás indításakor is",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "Támogatja a rögzített APK URL-eket",
 | 
			
		||||
    "selectX": "Kiválaszt {}",
 | 
			
		||||
    "parallelDownloads": "Párhuzamos letöltéseket enged",
 | 
			
		||||
    "installMethod": "Telepítési mód",
 | 
			
		||||
    "normal": "Normál",
 | 
			
		||||
    "root": "Root",
 | 
			
		||||
    "useShizuku": "Használja Shizuku vagy Sui telepítéséhez",
 | 
			
		||||
    "shizukuBinderNotFound": "A Shizuku nem fut",
 | 
			
		||||
    "shizukuOld": "Régi Shizuku verzió (<11) - frissítsd!",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku fut Android < 8.1 ADB-vel - frissítse az Androidot vagy használja a Sui-t helyette",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Állítsa be a Google Play-t telepítési forrásként (ha Shizuku-t használ)",
 | 
			
		||||
    "useSystemFont": "Használja a rendszer betűtípusát",
 | 
			
		||||
    "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",
 | 
			
		||||
    "requestHeader": "Kérelem fejléc",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Használja a legújabb tartalomfeltöltést megjelenési dátumként",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Megjegyzés:",
 | 
			
		||||
    "selfHostedNote": "A \"{}\" legördülő menü használható bármely forrás saját üzemeltetésű/egyéni példányainak eléréséhez.",
 | 
			
		||||
    "badDownload": "Az APK-t nem lehetett elemezni (inkompatibilis vagy részleges letöltés)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Új alkalmazások megosztása az AppVerifierrel (ha elérhető)",
 | 
			
		||||
    "appVerifierInstructionToast": "Ossza meg az AppVerifierrel, majd térjen vissza ide, ha kész.",
 | 
			
		||||
    "wiki": "Súgó/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (használat saját felelősségre)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Eltávolítja az alkalmazást?",
 | 
			
		||||
        "other": "Eltávolítja az alkalmazásokat?"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "A(z) {} és 1 további alkalmazás frissítve.",
 | 
			
		||||
        "other": "{} és {} további alkalmazás frissítve."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Nem sikerült frissíteni {} és még 1 alkalmazást.",
 | 
			
		||||
        "other": "Nem sikerült frissíteni {} és {} további alkalmazásokat."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} és 1 további alkalmazás is frissült.",
 | 
			
		||||
        "other": "{} és {} további alkalmazás is frissült."
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(richiesto)",
 | 
			
		||||
    "dropdownNoOptsError": "ERRORE: LA TENDINA DEVE AVERE ALMENO UN'OPZIONE",
 | 
			
		||||
    "colour": "Colore",
 | 
			
		||||
    "standard": "Standard",
 | 
			
		||||
    "custom": "Personalizzato",
 | 
			
		||||
    "useMaterialYou": "Utilizzate il materiale che avete a disposizione",
 | 
			
		||||
    "githubStarredRepos": "repository stellati da GitHub",
 | 
			
		||||
    "uname": "Nome utente",
 | 
			
		||||
    "wrongArgNum": "Numero di argomenti forniti errato",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Scuro",
 | 
			
		||||
    "light": "Chiaro",
 | 
			
		||||
    "followSystem": "Segui il sistema",
 | 
			
		||||
    "followSystemThemeExplanation": "È possibile seguire il tema di sistema solo utilizzando applicazioni di terze parti.",
 | 
			
		||||
    "useBlackTheme": "Usa il tema nero puro",
 | 
			
		||||
    "appSortBy": "App ordinate per",
 | 
			
		||||
    "authorName": "Autore/Nome",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "Nessun nuovo aggiornamento.",
 | 
			
		||||
    "xHasAnUpdate": "Aggiornamento disponibile per {}",
 | 
			
		||||
    "appsUpdated": "App aggiornate",
 | 
			
		||||
    "appsNotUpdated": "Impossibile aggiornare le applicazioni",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Notifica all'utente che una o più app sono state aggiornate in secondo piano",
 | 
			
		||||
    "xWasUpdatedToY": "{} è stato aggiornato alla {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Impossibile aggiornare {} a {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Controllo degli errori per gli aggiornamenti",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Una notifica che mostra quando il controllo degli aggiornamenti in secondo piano fallisce",
 | 
			
		||||
    "appsRemoved": "App rimosse",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "Disattiva il rilevamento della versione",
 | 
			
		||||
    "noVersionDetectionExplanation": "Questa opzione dovrebbe essere usata solo per le app la cui versione non viene rilevata correttamente.",
 | 
			
		||||
    "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",
 | 
			
		||||
    "noAPKFound": "Nessun APK trovato",
 | 
			
		||||
    "noVersionDetection": "Disattiva rilevamento di versione",
 | 
			
		||||
@@ -218,7 +227,7 @@
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Non mostrare gli avvisi 'Solo-Monitoraggio'",
 | 
			
		||||
    "dontShowAPKOriginWarnings": "Non mostrare gli avvisi di origine dell'APK",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Sposta le app non installate in fondo alla lista",
 | 
			
		||||
    "gitlabPATLabel": "GitLab Personal Access Token",
 | 
			
		||||
    "gitlabPATLabel": "GitLab Token di accesso personale",
 | 
			
		||||
    "about": "Informazioni",
 | 
			
		||||
    "requiresCredentialsInSettings": "{}: Servono credenziali aggiuntive (in Impostazioni)",
 | 
			
		||||
    "checkOnStart": "Controlla una volta all'avvio",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "Supporta URL fissi di APK",
 | 
			
		||||
    "selectX": "Seleziona {}",
 | 
			
		||||
    "parallelDownloads": "Permetti download paralleli",
 | 
			
		||||
    "installMethod": "Metodo d'installazione",
 | 
			
		||||
    "normal": "Normale",
 | 
			
		||||
    "root": "Root",
 | 
			
		||||
    "useShizuku": "Utilizzare Shizuku o Sui per installare",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku non è in esecuzione",
 | 
			
		||||
    "shizukuOld": "Vecchia versione di Shizuku (<11) - aggiornarla",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku funziona su Android < 8.1 con ADB - aggiornare Android o utilizzare Sui al suo posto",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Impostare Google Play come fonte di installazione (se si usa Shizuku)",
 | 
			
		||||
    "useSystemFont": "Usa i caratteri di sistema",
 | 
			
		||||
    "systemFontError": "Errore durante il caricamento dei caratteri di sistema: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Usa il codice versione dell'app come versione rilevata dal sistema operativo",
 | 
			
		||||
    "requestHeader": "Intestazione della richiesta",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Usa l'ultimo caricamento della risorsa come data di rilascio",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Nota",
 | 
			
		||||
    "selfHostedNote": "Il menu a tendina \"{}\" può essere usato per raggiungere istanze autogestite/personali di qualsiasi fonte.",
 | 
			
		||||
    "badDownload": "Non è stato possibile analizzare l'APK (download incompatibile o parziale).",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Condividere le nuove applicazioni con AppVerifier (se disponibile)",
 | 
			
		||||
    "appVerifierInstructionToast": "Condividete con AppVerifier, quindi tornate qui quando siete pronti.",
 | 
			
		||||
    "wiki": "Aiuto/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Configurazioni di app in crowdsourcing (uso a proprio rischio)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Rimuovere l'app?",
 | 
			
		||||
        "other": "Rimuovere le app?"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} e un'altra app sono state aggiornate.",
 | 
			
		||||
        "other": "{} e altre {} app sono state aggiornate."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Non è riuscito ad aggiornare {} e altre 1 app.",
 | 
			
		||||
        "other": "Non è riuscito ad aggiornare {} e {} altre applicazioni."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} e un'altra app potrebbero essere state aggiornate.",
 | 
			
		||||
        "other": "{} e altre {} app potrebbero essere state aggiornate."
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(必須)",
 | 
			
		||||
    "dropdownNoOptsError": "エラー: ドロップダウンには、少なくとも1つのオプションが必要です",
 | 
			
		||||
    "colour": "カラー",
 | 
			
		||||
    "standard": "スタンダード",
 | 
			
		||||
    "custom": "カスタム",
 | 
			
		||||
    "useMaterialYou": "Material Youを使用する",
 | 
			
		||||
    "githubStarredRepos": "Githubでスターしたリポジトリ",
 | 
			
		||||
    "uname": "ユーザー名",
 | 
			
		||||
    "wrongArgNum": "提供する引数の数が間違っています",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "ダーク",
 | 
			
		||||
    "light": "ライト",
 | 
			
		||||
    "followSystem": "システムに従う",
 | 
			
		||||
    "followSystemThemeExplanation": "以下のシステムテーマは、サードパーティのアプリケーションを使用することによってのみ可能です。",
 | 
			
		||||
    "useBlackTheme": "ピュアブラックダークテーマを使用する",
 | 
			
		||||
    "appSortBy": "アプリの並び方",
 | 
			
		||||
    "authorName": "作者名/アプリ名",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "新しいアップデートはありません",
 | 
			
		||||
    "xHasAnUpdate": "{} のアップデートが利用可能です。",
 | 
			
		||||
    "appsUpdated": "アプリをアップデートしました",
 | 
			
		||||
    "appsNotUpdated": "アプリケーションの更新に失敗",
 | 
			
		||||
    "appsUpdatedNotifDescription": "1つまたは複数のAppのアップデートがバックグラウンドで適用されたことをユーザーに通知する",
 | 
			
		||||
    "xWasUpdatedToY": "{} が {} にアップデートされました",
 | 
			
		||||
    "xWasNotUpdatedToY": "への更新に失敗しました。",
 | 
			
		||||
    "errorCheckingUpdates": "アップデート確認中のエラー",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "バックグラウンドでのアップデート確認に失敗した際に表示される通知",
 | 
			
		||||
    "appsRemoved": "削除されたアプリ",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "バージョン検出を無効にする",
 | 
			
		||||
    "noVersionDetectionExplanation": "このオプションは、バージョン検出が正しく機能しないアプリにのみ使用する必要があります。",
 | 
			
		||||
    "downloadingX": "{} をダウンロード中",
 | 
			
		||||
    "downloadX": "ダウンロード",
 | 
			
		||||
    "downloadedX": "ダウンロード",
 | 
			
		||||
    "releaseAsset": "リリース資産",
 | 
			
		||||
    "downloadNotifDescription": "アプリのダウンロード状況を通知する",
 | 
			
		||||
    "noAPKFound": "APKが見つかりません",
 | 
			
		||||
    "noVersionDetection": "バージョン検出を行わない",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "固定されたAPKのURLをサポートする",
 | 
			
		||||
    "selectX": "{} 選択",
 | 
			
		||||
    "parallelDownloads": "並行ダウンロードを許可する",
 | 
			
		||||
    "installMethod": "インストール方法",
 | 
			
		||||
    "normal": "通常",
 | 
			
		||||
    "root": "Root",
 | 
			
		||||
    "useShizuku": "ShizukuまたはSuiを使用してインストールする",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizukuが起動していません",
 | 
			
		||||
    "shizukuOld": "古いShizukuのバージョン (<11) - アップデートしてください",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "ShizukuがAndroid 8.1未満でADBを使用して動作しています - Androidをアップデートするか、代わりにSuiを使用してください",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Google Playをインストール元として設定する(Shizukuを使用する場合)",
 | 
			
		||||
    "useSystemFont": "システムフォントを使用する",
 | 
			
		||||
    "systemFontError": "システムフォントの読み込みエラー: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "アプリのバージョンコードをOSで検出されたバージョンとして使用する",
 | 
			
		||||
    "requestHeader": "リクエストヘッダー",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "最新のアセットアップロードをリリース日として使用する",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "注",
 | 
			
		||||
    "selfHostedNote": "ドロップダウン\"{}\"を使用すると、あらゆるソースのセルフホスト/カスタムインスタンスにアクセスできます。",
 | 
			
		||||
    "badDownload": "APK を解析できませんでした(互換性がないか、部分的にダウンロードされています)。",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "AppVerifierで新しいアプリを共有する(利用可能な場合)",
 | 
			
		||||
    "appVerifierInstructionToast": "AppVerifierに共有し、準備ができたらここに戻ってください。",
 | 
			
		||||
    "wiki": "ヘルプ/ウィキ",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "クラウドソーシングによるアプリの設定(利用は自己責任で)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "アプリを削除しますか?",
 | 
			
		||||
        "other": "アプリを削除しますか?"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} とさらに {} 個のアプリがアップデートされました。",
 | 
			
		||||
        "other": "{} とさらに {} 個のアプリがアップデートされました。"
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "更新に失敗しました。",
 | 
			
		||||
        "other": "アプリのアップデートに失敗しました。"
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} とさらに 1 個のアプリがアップデートされた可能性があります。",
 | 
			
		||||
        "other": "{} とさらに {} 個のアプリがアップデートされた可能性があります。"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,131 +1,135 @@
 | 
			
		||||
{
 | 
			
		||||
    "invalidURLForSource": "Geen valide {} app URL",
 | 
			
		||||
    "noReleaseFound": "Kan geen geschikte release vinden",
 | 
			
		||||
    "noVersionFound": "Kan de versie niet bepalen",
 | 
			
		||||
    "invalidURLForSource": "Ongeldige app-URL voor {}",
 | 
			
		||||
    "noReleaseFound": "Geen geschikte release gevonden",
 | 
			
		||||
    "noVersionFound": "Geen versie kunnen bepalen",
 | 
			
		||||
    "urlMatchesNoSource": "URL komt niet overeen met bekende bron",
 | 
			
		||||
    "cantInstallOlderVersion": "Kan geen oudere versie van de app installeren",
 | 
			
		||||
    "appIdMismatch": "Gedownloade pakket-ID komt niet overeen met de bestaande app-ID",
 | 
			
		||||
    "functionNotImplemented": "Deze class heeft deze functie niet geïmplementeerd.",
 | 
			
		||||
    "placeholder": "Plaatshouder",
 | 
			
		||||
    "appIdMismatch": "Gedownload pakket-ID komt niet overeen met de bestaande app-ID",
 | 
			
		||||
    "functionNotImplemented": "Deze klasse heeft deze functie niet geïmplementeerd.",
 | 
			
		||||
    "placeholder": "Dummy",
 | 
			
		||||
    "someErrors": "Er zijn enkele fouten opgetreden",
 | 
			
		||||
    "unexpectedError": "Onverwachte fout",
 | 
			
		||||
    "ok": "Ok",
 | 
			
		||||
    "ok": "Oké",
 | 
			
		||||
    "and": "en",
 | 
			
		||||
    "githubPATLabel": "GitHub Personal Access Token\n(Verhoogt limiet aantal verzoeken)",
 | 
			
		||||
    "includePrereleases": "Bevat prereleases",
 | 
			
		||||
    "includePrereleases": "Inclusief pre-releases",
 | 
			
		||||
    "fallbackToOlderReleases": "Terugvallen op oudere releases",
 | 
			
		||||
    "filterReleaseTitlesByRegEx": "Filter release-titels met reguliere expressies.",
 | 
			
		||||
    "filterReleaseTitlesByRegEx": "Release-titels filteren met reguliere expressies.",
 | 
			
		||||
    "invalidRegEx": "Ongeldige reguliere expressie",
 | 
			
		||||
    "noDescription": "Geen omschrijving",
 | 
			
		||||
    "cancel": "Annuleer",
 | 
			
		||||
    "continue": "Ga verder",
 | 
			
		||||
    "cancel": "Annuleren",
 | 
			
		||||
    "continue": "Doorgaan",
 | 
			
		||||
    "requiredInBrackets": "(Verplicht)",
 | 
			
		||||
    "dropdownNoOptsError": "FOUTMELDING: DROPDOWN MOET TENMINSTE ÉÉN OPT HEBBEN",
 | 
			
		||||
    "dropdownNoOptsError": "FOUTMELDING: UITKLAPMENU MOET TENMINSTE EEN OPT HEBBEN",
 | 
			
		||||
    "colour": "Kleur",
 | 
			
		||||
    "standard": "Standaard",
 | 
			
		||||
    "custom": "Aangepast",
 | 
			
		||||
    "useMaterialYou": "Material You gebruiken",
 | 
			
		||||
    "githubStarredRepos": "GitHub-repo's met ster",
 | 
			
		||||
    "uname": "Gebruikersnaam",
 | 
			
		||||
    "wrongArgNum": "Onjuist aantal argumenten verstrekt.",
 | 
			
		||||
    "xIsTrackOnly": "{} is alleen tracken",
 | 
			
		||||
    "wrongArgNum": "Incorrect aantal argumenten.",
 | 
			
		||||
    "xIsTrackOnly": "{} is 'Alleen volgen'",
 | 
			
		||||
    "source": "Bron",
 | 
			
		||||
    "app": "App",
 | 
			
		||||
    "appsFromSourceAreTrackOnly": "Apps van deze bron zijn 'Track-Only'.",
 | 
			
		||||
    "youPickedTrackOnly": "Je hebt de 'Track-Only' optie geselecteerd.",
 | 
			
		||||
    "appsFromSourceAreTrackOnly": "Apps van deze bron zijn 'Alleen volgen'.",
 | 
			
		||||
    "youPickedTrackOnly": "De optie 'Alleen volgen' is geselecteerd.",
 | 
			
		||||
    "trackOnlyAppDescription": "De app zal worden gevolgd voor updates, maar Obtainium zal niet in staat zijn om deze te downloaden of te installeren.",
 | 
			
		||||
    "cancelled": "Geannuleerd",
 | 
			
		||||
    "appAlreadyAdded": "App al toegevoegd",
 | 
			
		||||
    "alreadyUpToDateQuestion": "Is de app al up-to-date?",
 | 
			
		||||
    "appAlreadyAdded": "App reeds toegevoegd",
 | 
			
		||||
    "alreadyUpToDateQuestion": "App al bijgewerkt?",
 | 
			
		||||
    "addApp": "App toevoegen",
 | 
			
		||||
    "appSourceURL": "App bron URL",
 | 
			
		||||
    "appSourceURL": "App-bron URL",
 | 
			
		||||
    "error": "Foutmelding",
 | 
			
		||||
    "add": "Toevoegen",
 | 
			
		||||
    "searchSomeSourcesLabel": "Zoeken (Alleen sommige bronnen)",
 | 
			
		||||
    "searchSomeSourcesLabel": "Zoeken (sommige bronnen)",
 | 
			
		||||
    "search": "Zoeken",
 | 
			
		||||
    "additionalOptsFor": "Aanvullende opties voor {}",
 | 
			
		||||
    "supportedSources": "Ondersteunde bronnen",
 | 
			
		||||
    "trackOnlyInBrackets": "(Alleen track)",
 | 
			
		||||
    "trackOnlyInBrackets": "(Alleen volgen)",
 | 
			
		||||
    "searchableInBrackets": "(Doorzoekbaar)",
 | 
			
		||||
    "appsString": "Apps",
 | 
			
		||||
    "noApps": "Geen Apps",
 | 
			
		||||
    "noAppsForFilter": "Geen Apps voor filter",
 | 
			
		||||
    "byX": "Door {}",
 | 
			
		||||
    "percentProgress": "Vooruitgang: {}%",
 | 
			
		||||
    "percentProgress": "Voortgang: {}%",
 | 
			
		||||
    "pleaseWait": "Even geduld",
 | 
			
		||||
    "updateAvailable": "Update beschikbaar",
 | 
			
		||||
    "notInstalled": "Niet geinstalleerd",
 | 
			
		||||
    "pseudoVersion": "pseudo-versie",
 | 
			
		||||
    "selectAll": "Selecteer alles",
 | 
			
		||||
    "deselectX": "Deselecteer {}",
 | 
			
		||||
    "xWillBeRemovedButRemainInstalled": "{} zal worden verwijderd uit Obtainium, maar blijft geïnstalleerd op het apparaat.",
 | 
			
		||||
    "removeSelectedAppsQuestion": "Geselecteerde apps verwijderen??",
 | 
			
		||||
    "selectAll": "Alles selecteren",
 | 
			
		||||
    "deselectX": "Selectie opheffen {}",
 | 
			
		||||
    "xWillBeRemovedButRemainInstalled": "{} zal worden gewist uit Obtainium, maar blijft geïnstalleerd op het apparaat.",
 | 
			
		||||
    "removeSelectedAppsQuestion": "Geselecteerde apps verwijderen?",
 | 
			
		||||
    "removeSelectedApps": "Geselecteerde apps verwijderen",
 | 
			
		||||
    "updateX": "Update {}",
 | 
			
		||||
    "installX": "Installeer {}",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "Markeer {}\n(Track-Only)\nals up-to-date",
 | 
			
		||||
    "changeX": "Verander {}",
 | 
			
		||||
    "installUpdateApps": "Installeer/Update apps",
 | 
			
		||||
    "installUpdateSelectedApps": "Installeer/Update geselecteerde apps",
 | 
			
		||||
    "markXSelectedAppsAsUpdated": "{} geselecteerde apps markeren als up-to-date?",
 | 
			
		||||
    "updateX": "{} bijwerken",
 | 
			
		||||
    "installX": "{} installeren",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "{}\n(Alleen volgen)\nmarkeren als bijgewerkt",
 | 
			
		||||
    "changeX": "{} wijzigen",
 | 
			
		||||
    "installUpdateApps": "Apps installeren/bijwerken",
 | 
			
		||||
    "installUpdateSelectedApps": "Geselecteerde apps installeren/bijwerken",
 | 
			
		||||
    "markXSelectedAppsAsUpdated": "{} geselecteerde apps markeren als bijgewerkt?",
 | 
			
		||||
    "no": "Nee",
 | 
			
		||||
    "yes": "Ja",
 | 
			
		||||
    "markSelectedAppsUpdated": "Markeer geselecteerde aps als up-to-date",
 | 
			
		||||
    "pinToTop": "Vastzetten aan de bovenkant",
 | 
			
		||||
    "unpinFromTop": "Losmaken van de bovenkant",
 | 
			
		||||
    "resetInstallStatusForSelectedAppsQuestion": "Installatiestatus resetten voor geselecteerde apps?",
 | 
			
		||||
    "installStatusOfXWillBeResetExplanation": "De installatiestatus van alle geselecteerde apps zal worden gereset.\n\nDit kan helpen wanneer de versie van de app die in Obtainium wordt weergegeven onjuist is vanwege mislukte updates of andere problemen.",
 | 
			
		||||
    "customLinkMessage": "Deze links werken op apparaten waarop Obtainium is geïnstalleerd",
 | 
			
		||||
    "markSelectedAppsUpdated": "Geselecteerde apps markeren als bijgewerkt",
 | 
			
		||||
    "pinToTop": "Bovenaan plaatsen",
 | 
			
		||||
    "unpinFromTop": "Bovenaan wegnemen",
 | 
			
		||||
    "resetInstallStatusForSelectedAppsQuestion": "Installatiestatus herstellen voor geselecteerde apps?",
 | 
			
		||||
    "installStatusOfXWillBeResetExplanation": "De installatiestatus van alle geselecteerde apps zal worden hersteld.\n\nDit kan helpen wanneer de versie van de app die in Obtainium wordt weergegeven onjuist is vanwege mislukte updates of andere problemen.",
 | 
			
		||||
    "customLinkMessage": "Deze koppelingen werken op apparaten waarop Obtainium is geïnstalleerd",
 | 
			
		||||
    "shareAppConfigLinks": "App-configuratie delen als HTML-link",
 | 
			
		||||
    "shareSelectedAppURLs": "Deel geselecteerde app URL's",
 | 
			
		||||
    "resetInstallStatus": "Reset installatiestatus",
 | 
			
		||||
    "shareSelectedAppURLs": "Geselecteerde app-URL's delen",
 | 
			
		||||
    "resetInstallStatus": "Installatiestatus herstellen",
 | 
			
		||||
    "more": "Meer",
 | 
			
		||||
    "removeOutdatedFilter": "Verwijder out-of-date app filter",
 | 
			
		||||
    "showOutdatedOnly": "Toon alleen out-of-date apps",
 | 
			
		||||
    "filter": "Filter",
 | 
			
		||||
    "filterApps": "Filter apps",
 | 
			
		||||
    "appName": "App naam",
 | 
			
		||||
    "removeOutdatedFilter": "Verouderde apps-filter verwijderen",
 | 
			
		||||
    "showOutdatedOnly": "Alleen verouderde apps weergeven",
 | 
			
		||||
    "filter": "Filteren",
 | 
			
		||||
    "filterApps": "Apps filteren",
 | 
			
		||||
    "appName": "App-naam",
 | 
			
		||||
    "author": "Auteur",
 | 
			
		||||
    "upToDateApps": "Up-to-date apps",
 | 
			
		||||
    "upToDateApps": "Bijgewerkte apps",
 | 
			
		||||
    "nonInstalledApps": "Niet-geïnstalleerde apps",
 | 
			
		||||
    "importExport": "Importeren/Exporteren",
 | 
			
		||||
    "importExport": "Importeren/exporteren",
 | 
			
		||||
    "settings": "Instellingen",
 | 
			
		||||
    "exportedTo": "Geëxporteerd naar {}",
 | 
			
		||||
    "obtainiumExport": "Obtainium export",
 | 
			
		||||
    "invalidInput": "Ongeldige invoer",
 | 
			
		||||
    "importedX": "Geïmporteerd {}",
 | 
			
		||||
    "importedX": "{} geïmporteerd",
 | 
			
		||||
    "obtainiumImport": "Obtainium import",
 | 
			
		||||
    "importFromURLList": "Importeer van URL-lijsten",
 | 
			
		||||
    "importFromURLList": "Importeren van URL-lijsten",
 | 
			
		||||
    "searchQuery": "Zoekopdracht",
 | 
			
		||||
    "appURLList": "App URL-lijst",
 | 
			
		||||
    "line": "Lijn",
 | 
			
		||||
    "searchX": "Zoek {}",
 | 
			
		||||
    "line": "Regel",
 | 
			
		||||
    "searchX": "{} zoeken",
 | 
			
		||||
    "noResults": "Geen resultaten gevonden",
 | 
			
		||||
    "importX": "Importeer {}",
 | 
			
		||||
    "importedAppsIdDisclaimer": "Geïmporteerde apps kunnen mogelijk onjuist worden weergegeven als \"Niet geïnstalleerd\".\nOm dit op te lossen, herinstalleer ze via Obtainium.\nDit zou geen invloed moeten hebben op app-gegevens.\n\nDit heeft alleen invloed op URL- en importmethoden van derden.",
 | 
			
		||||
    "importErrors": "Import foutmeldingen",
 | 
			
		||||
    "importX": "{} importeren",
 | 
			
		||||
    "importedAppsIdDisclaimer": "Geïmporteerde apps kunnen mogelijk onjuist worden weergegeven als \"Niet geïnstalleerd\".\nOm dit op te lossen, installeer deze opnieuw via Obtainium.\nDit zou geen invloed moeten hebben op app-gegevens.\n\nDit heeft alleen invloed op URL- en importmethoden van derden.",
 | 
			
		||||
    "importErrors": "Fouten bij het importeren",
 | 
			
		||||
    "importedXOfYApps": "{} van {} apps geïmporteerd.",
 | 
			
		||||
    "followingURLsHadErrors": "De volgende URL's bevatten fouten:",
 | 
			
		||||
    "selectURL": "Selecteer URL",
 | 
			
		||||
    "selectURLs": "Selecteer URL's",
 | 
			
		||||
    "pick": "Kies",
 | 
			
		||||
    "selectURL": "URL selecteren",
 | 
			
		||||
    "selectURLs": "URL's selecteren",
 | 
			
		||||
    "pick": "Kiezen",
 | 
			
		||||
    "theme": "Thema",
 | 
			
		||||
    "dark": "Donker",
 | 
			
		||||
    "light": "Licht",
 | 
			
		||||
    "followSystem": "Volg systeem",
 | 
			
		||||
    "useBlackTheme": "Gebruik zwart thema",
 | 
			
		||||
    "appSortBy": "App sorteren op",
 | 
			
		||||
    "followSystem": "Systeem volgen",
 | 
			
		||||
    "followSystemThemeExplanation": "Het volgen van het systeemthema is alleen mogelijk met applicaties van derden",
 | 
			
		||||
    "useBlackTheme": "Zwart thema gebruiken",
 | 
			
		||||
    "appSortBy": "Sortering",
 | 
			
		||||
    "authorName": "Auteur/Naam",
 | 
			
		||||
    "nameAuthor": "Naam/Auteur",
 | 
			
		||||
    "asAdded": "Zoals toegevoegd",
 | 
			
		||||
    "appSortOrder": "App sorteervolgorde",
 | 
			
		||||
    "asAdded": "Datum toegevoegd",
 | 
			
		||||
    "appSortOrder": "Volgorde",
 | 
			
		||||
    "ascending": "Oplopend",
 | 
			
		||||
    "descending": "Aflopend",
 | 
			
		||||
    "bgUpdateCheckInterval": "Frequentie voor achtergrondupdatecontrole",
 | 
			
		||||
    "bgUpdateCheckInterval": "Frequentie voor achtergrond-updatecontrole",
 | 
			
		||||
    "neverManualOnly": "Nooit - Alleen handmatig",
 | 
			
		||||
    "appearance": "Weergave",
 | 
			
		||||
    "showWebInAppView": "Toon de bronwebpagina in app-weergave",
 | 
			
		||||
    "pinUpdates": "Updates bovenaan in de apps-weergave vastpinnen",
 | 
			
		||||
    "showWebInAppView": "Bron-webpagina weergeven in app-weergave",
 | 
			
		||||
    "pinUpdates": "Updates bovenaan plaatsen in de apps-weergave",
 | 
			
		||||
    "updates": "Updates",
 | 
			
		||||
    "sourceSpecific": "Bron-specifiek",
 | 
			
		||||
    "appSource": "App bron",
 | 
			
		||||
    "appSource": "App-bron",
 | 
			
		||||
    "noLogs": "Geen logs",
 | 
			
		||||
    "appLogs": "App logs",
 | 
			
		||||
    "close": "Sluiten",
 | 
			
		||||
@@ -133,30 +137,32 @@
 | 
			
		||||
    "appNotFound": "App niet gevonden",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "obtainium-export",
 | 
			
		||||
    "pickAnAPK": "Kies een APK",
 | 
			
		||||
    "appHasMoreThanOnePackage": "{} heeft meer dan één package:",
 | 
			
		||||
    "deviceSupportsXArch": "Jouw apparaat support de {} CPU-architectuur.",
 | 
			
		||||
    "deviceSupportsFollowingArchs": "Je apparaat ondersteunt de volgende CPU-architecturen:",
 | 
			
		||||
    "appHasMoreThanOnePackage": "{} biedt verschillende pakketten:",
 | 
			
		||||
    "deviceSupportsXArch": "Dit apparaat ondersteunt de {} CPU-architectuur.",
 | 
			
		||||
    "deviceSupportsFollowingArchs": "Dit apparaat ondersteunt de volgende CPU-architecturen:",
 | 
			
		||||
    "warning": "Waarschuwing",
 | 
			
		||||
    "sourceIsXButPackageFromYPrompt": "De appbron is '{}' maar de release package komt van '{}'. Doorgaan?",
 | 
			
		||||
    "sourceIsXButPackageFromYPrompt": "De app-bron is '{}' maar het release-pakket komt van '{}'. Doorgaan?",
 | 
			
		||||
    "updatesAvailable": "Updates beschikbaar",
 | 
			
		||||
    "updatesAvailableNotifDescription": "Stelt de gebruiker op de hoogte dat er updates beschikbaar zijn voor één of meer apps die worden bijgehouden door Obtainium.",
 | 
			
		||||
    "updatesAvailableNotifDescription": "Stelt de gebruiker op de hoogte dat er updates beschikbaar zijn voor een of meer apps die worden bijgehouden door Obtainium.",
 | 
			
		||||
    "noNewUpdates": "Geen nieuwe updates.",
 | 
			
		||||
    "xHasAnUpdate": "{} heeft een update.",
 | 
			
		||||
    "appsUpdated": "Apps bijgewerkt",
 | 
			
		||||
    "appsNotUpdated": "Applicaties konden niet worden bijgewerkt",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Stelt de gebruiker op de hoogte dat updates voor één of meer apps in de achtergrond zijn toegepast.",
 | 
			
		||||
    "xWasUpdatedToY": "{} is bijgewerkt naar {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Het bijwerken van {} naar {} is mislukt.",
 | 
			
		||||
    "errorCheckingUpdates": "Fout bij het controleren op updates",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Een melding die verschijnt wanneer het controleren op updates in de achtergrond mislukt",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Een melding die verschijnt wanneer de achtergrondcontrole op updates mislukt",
 | 
			
		||||
    "appsRemoved": "Apps verwijderd",
 | 
			
		||||
    "appsRemovedNotifDescription": "Stelt de gebruiker op de hoogte dat één of meer apps zijn verwijderd vanwege fouten tijdens het laden ervan",
 | 
			
		||||
    "xWasRemovedDueToErrorY": "{} is verwijderd vanwege deze foutmelding: {}",
 | 
			
		||||
    "completeAppInstallation": "Complete app installatie",
 | 
			
		||||
    "appsRemovedNotifDescription": "Stelt de gebruiker op de hoogte dat een of meer apps zijn verwijderd vanwege fouten tijdens het laden",
 | 
			
		||||
    "xWasRemovedDueToErrorY": "{} is verwijderd vanwege de fout: {}",
 | 
			
		||||
    "completeAppInstallation": "App-installatie voltooien",
 | 
			
		||||
    "obtainiumMustBeOpenToInstallApps": "Obtainium moet geopend zijn om apps te installeren",
 | 
			
		||||
    "completeAppInstallationNotifDescription": "Vraagt de gebruiker om terug te keren naar Obtainium om de installatie van een app af te ronden",
 | 
			
		||||
    "checkingForUpdates": "Controleren op updates",
 | 
			
		||||
    "checkingForUpdatesNotifDescription": "Tijdelijke melding die verschijnt tijdens het controleren op updates",
 | 
			
		||||
    "pleaseAllowInstallPerm": "Sta Obtainium toe om apps te installeren",
 | 
			
		||||
    "trackOnly": "Alleen track",
 | 
			
		||||
    "pleaseAllowInstallPerm": "Toestaan dat Obtainium apps installeert",
 | 
			
		||||
    "trackOnly": "'Alleen volgen'",
 | 
			
		||||
    "errorWithHttpStatusCode": "Foutmelding {}",
 | 
			
		||||
    "versionCorrectionDisabled": "Versiecorrectie uitgeschakeld (de plug-in lijkt niet te werken)",
 | 
			
		||||
    "unknown": "Onbekend",
 | 
			
		||||
@@ -166,23 +172,26 @@
 | 
			
		||||
    "installedVersionX": "Geïnstalleerde versie: {}",
 | 
			
		||||
    "lastUpdateCheckX": "Laatste updatecontrole: {}",
 | 
			
		||||
    "remove": "Verwijderen",
 | 
			
		||||
    "yesMarkUpdated": "Ja, markeer als bijgewerkt",
 | 
			
		||||
    "fdroid": "F-Droid-ambtenaar",
 | 
			
		||||
    "appIdOrName": "App ID of naam",
 | 
			
		||||
    "yesMarkUpdated": "Ja, markeren als bijgewerkt",
 | 
			
		||||
    "fdroid": "F-Droid (Officieel)",
 | 
			
		||||
    "appIdOrName": "App-ID of naam",
 | 
			
		||||
    "appId": "App-ID",
 | 
			
		||||
    "appWithIdOrNameNotFound": "Er werd geen app gevonden met dat ID of die naam",
 | 
			
		||||
    "appWithIdOrNameNotFound": "Er is geen app gevonden met dat ID of die naam",
 | 
			
		||||
    "reposHaveMultipleApps": "Repositories kunnen meerdere apps bevatten",
 | 
			
		||||
    "fdroidThirdPartyRepo": "F-Droid Repository van derden",
 | 
			
		||||
    "steamMobile": "Stoommobiel",
 | 
			
		||||
    "steamChat": "Steamchat",
 | 
			
		||||
    "fdroidThirdPartyRepo": "F-Droid Repository voor derden",
 | 
			
		||||
    "steamMobile": "Steam Mobile",
 | 
			
		||||
    "steamChat": "Steam Chat",
 | 
			
		||||
    "install": "Installeren",
 | 
			
		||||
    "markInstalled": "Als geïnstalleerd markere",
 | 
			
		||||
    "update": "Update",
 | 
			
		||||
    "markUpdated": "Markeren als bijgewerkt",
 | 
			
		||||
    "markInstalled": "Als geïnstalleerd markeren",
 | 
			
		||||
    "update": "Bijwerken",
 | 
			
		||||
    "markUpdated": "Als bijgewerkt markeren",
 | 
			
		||||
    "additionalOptions": "Aanvullende opties",
 | 
			
		||||
    "disableVersionDetection": "Versieherkenning uitschakelen",
 | 
			
		||||
    "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",
 | 
			
		||||
    "noAPKFound": "Geen APK gevonden",
 | 
			
		||||
    "noVersionDetection": "Geen versieherkenning",
 | 
			
		||||
@@ -194,100 +203,100 @@
 | 
			
		||||
    "deleteCategoriesQuestion": "Categorieën verwijderen?",
 | 
			
		||||
    "categoryDeleteWarning": "Alle apps in verwijderde categorieën worden teruggezet naar 'ongecategoriseerd'.",
 | 
			
		||||
    "addCategory": "Categorie toevoegen",
 | 
			
		||||
    "label": "Etiket",
 | 
			
		||||
    "label": "Label",
 | 
			
		||||
    "language": "Taal",
 | 
			
		||||
    "copiedToClipboard": "Gekopieerd naar klembord",
 | 
			
		||||
    "storagePermissionDenied": "Toegang tot opslag geweigerd",
 | 
			
		||||
    "selectedCategorizeWarning": "Dit zal eventuele bestaande categorie-instellingen voor de geselecteerde apps vervangen.",
 | 
			
		||||
    "filterAPKsByRegEx": "Filter APK's op reguliere expressie",
 | 
			
		||||
    "removeFromObtainium": "Verwijder van Obtainium",
 | 
			
		||||
    "uninstallFromDevice": "Verwijder van apparaat",
 | 
			
		||||
    "filterAPKsByRegEx": "APK's flteren met reguliere expressie",
 | 
			
		||||
    "removeFromObtainium": "Uit Obtainium verwijderen",
 | 
			
		||||
    "uninstallFromDevice": "Van apparaat verwijderen",
 | 
			
		||||
    "onlyWorksWithNonVersionDetectApps": "Werkt alleen voor apps waarbij versieherkenning is uitgeschakeld.",
 | 
			
		||||
    "releaseDateAsVersion": "Gebruik de releasedatum als versie",
 | 
			
		||||
    "releaseDateAsVersion": "Releasedatum als versie gebruiken",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt, maar waar wel een releasedatum beschikbaar is.",
 | 
			
		||||
    "changes": "Veranderingen",
 | 
			
		||||
    "changes": "Aanpassingen",
 | 
			
		||||
    "releaseDate": "Releasedatum",
 | 
			
		||||
    "importFromURLsInFile": "Importeren vanaf URL's in een bestand (zoals OPML)",
 | 
			
		||||
    "versionDetectionExplanation": "Versiereeks afstemmen met versie gedetecteerd door besturingssysteem",
 | 
			
		||||
    "versionDetection": "Versieherkenning",
 | 
			
		||||
    "standardVersionDetection": "Standaard versieherkenning",
 | 
			
		||||
    "groupByCategory": "Groepeer op categorie",
 | 
			
		||||
    "autoApkFilterByArch": "Poging om APK's te filteren op CPU-architectuur indien mogelijk",
 | 
			
		||||
    "groupByCategory": "Groeperen op categorie",
 | 
			
		||||
    "autoApkFilterByArch": "Probeer APK's te filteren op CPU-architectuur, indien mogelijk",
 | 
			
		||||
    "overrideSource": "Bron overschrijven",
 | 
			
		||||
    "dontShowAgain": "Laat dit niet meer zien",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Geen waarschuwingen voor 'Track-Only' weergeven",
 | 
			
		||||
    "dontShowAPKOriginWarnings": "APK-herkomstwaarschuwingen niet weergeven",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Verplaats niet-geïnstalleerde apps naar de onderkant van de apps-weergave",
 | 
			
		||||
    "gitlabPATLabel": "GitLab Personal Access Token",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Geen waarschuwingen weergeven voor 'Alleen volgen'",
 | 
			
		||||
    "dontShowAPKOriginWarnings": "Geen waarschuwingen weergeven voor APK-herkomst",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Niet-geïnstalleerde apps onderaan de apps-lijst plaatsen",
 | 
			
		||||
    "gitlabPATLabel": "GitLab persoonlijk toegangskenmerk",
 | 
			
		||||
    "about": "Over",
 | 
			
		||||
    "requiresCredentialsInSettings": "{}: Dit vereist aanvullende referenties (in Instellingen)",
 | 
			
		||||
    "checkOnStart": "Controleren op updates bij opstarten",
 | 
			
		||||
    "requiresCredentialsInSettings": "{} vereist aanvullende referenties (in Instellingen)",
 | 
			
		||||
    "checkOnStart": "Bij opstarten op updates controleren",
 | 
			
		||||
    "tryInferAppIdFromCode": "Probeer de app-ID af te leiden uit de broncode",
 | 
			
		||||
    "removeOnExternalUninstall": "Automatisch extern verwijderde apps verwijderen",
 | 
			
		||||
    "pickHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren",
 | 
			
		||||
    "removeOnExternalUninstall": "Extern verwijderde apps automatisch verwijderen",
 | 
			
		||||
    "pickHighestVersionCode": "De APK met de hoogste versiecode automatisch selecteren",
 | 
			
		||||
    "checkUpdateOnDetailPage": "Controleren op updates bij het openen van een app-detailpagina",
 | 
			
		||||
    "disablePageTransitions": "Schakel overgangsanimaties tussen pagina's uit",
 | 
			
		||||
    "reversePageTransitions": "Omgekeerde overgangsanimaties tussen pagina's",
 | 
			
		||||
    "minStarCount": "Minimale Github Stars",
 | 
			
		||||
    "addInfoBelow": "Voeg deze informatie hieronder toe.",
 | 
			
		||||
    "addInfoInSettings": "Voeg deze informatie toe in de instellingen.",
 | 
			
		||||
    "disablePageTransitions": "Overgangsanimaties tussen pagina's uitschakelen",
 | 
			
		||||
    "reversePageTransitions": "Overgangsanimaties tussen pagina's herstellen",
 | 
			
		||||
    "minStarCount": "Minimum Github Stars",
 | 
			
		||||
    "addInfoBelow": "Deze informatie hieronder toevoegen.",
 | 
			
		||||
    "addInfoInSettings": "Deze informatie toevoegen in de instellingen.",
 | 
			
		||||
    "githubSourceNote": "Beperkingen van GitHub kunnen worden vermeden door het gebruik van een API-sleutel.",
 | 
			
		||||
    "sortByLastLinkSegment": "Sorteren op alleen het laatste segment van de link",
 | 
			
		||||
    "filterReleaseNotesByRegEx": "Filter release-opmerkingen met een reguliere expressie.",
 | 
			
		||||
    "customLinkFilterRegex": "Aangepaste APK-linkfilter met een reguliere expressie (Standaard '.apk$').",
 | 
			
		||||
    "appsPossiblyUpdated": "Poging tot app-updates",
 | 
			
		||||
    "sortByLastLinkSegment": "Alleen sorteren op het laatste segment van de link",
 | 
			
		||||
    "filterReleaseNotesByRegEx": "Release-opmerkingen fiteren met een reguliere expressie.",
 | 
			
		||||
    "customLinkFilterRegex": "Aangepaste APK-links filteren met een reguliere expressie (Standaard '.apk$').",
 | 
			
		||||
    "appsPossiblyUpdated": "Pogingen tot app-updates",
 | 
			
		||||
    "appsPossiblyUpdatedNotifDescription": "Stelt de gebruiker op de hoogte dat updates voor één of meer apps mogelijk in de achtergrond zijn toegepast",
 | 
			
		||||
    "xWasPossiblyUpdatedToY": "{} mogelijk bijgewerkt naar {}.",
 | 
			
		||||
    "enableBackgroundUpdates": "Achtergrondupdates inschakelen",
 | 
			
		||||
    "backgroundUpdateReqsExplanation": "Achtergrondupdates zijn mogelijk niet voor alle apps mogelijk.",
 | 
			
		||||
    "xWasPossiblyUpdatedToY": "{} kan bijgewerkt zijn naar {}.",
 | 
			
		||||
    "enableBackgroundUpdates": "Achtergrond-updates inschakelen",
 | 
			
		||||
    "backgroundUpdateReqsExplanation": "Achtergrond-updates zijn niet voor alle apps mogelijk.",
 | 
			
		||||
    "backgroundUpdateLimitsExplanation": "Het succes van een installatie in de achtergrond kan alleen worden bepaald wanneer Obtainium is geopend.",
 | 
			
		||||
    "verifyLatestTag": "Verifieer de 'Laatste'-tag",
 | 
			
		||||
    "intermediateLinkRegex": "Filter voor een 'Intermediaire' link om te bezoeken",
 | 
			
		||||
    "verifyLatestTag": "Het label 'Laatste' verifiëren",
 | 
			
		||||
    "intermediateLinkRegex": "Filteren op een 'Intermediaire' link om te bezoeken",
 | 
			
		||||
    "filterByLinkText": "Links filteren op linktekst",
 | 
			
		||||
    "intermediateLinkNotFound": "Tussenliggende link niet gevonden",
 | 
			
		||||
    "intermediateLinkNotFound": "Intermediaire link niet gevonden",
 | 
			
		||||
    "intermediateLink": "Intermediaire link",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "Vrijgesteld van achtergrondupdates (indien ingeschakeld)",
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "Achtergrondupdates uitschakelen wanneer niet verbonden met WiFi",
 | 
			
		||||
    "autoSelectHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "Vrijgesteld van achtergrond-updates (indien ingeschakeld)",
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "Achtergrond-updates uitschakelen wanneer niet verbonden met WiFi",
 | 
			
		||||
    "autoSelectHighestVersionCode": "De APK met de hoogste versiecode automatisch selecteren",
 | 
			
		||||
    "versionExtractionRegEx": "Reguliere expressie voor versie-extractie",
 | 
			
		||||
    "matchGroupToUse": "Overeenkomende groep om te gebruiken voor de reguliere expressie voor versie-extractie",
 | 
			
		||||
    "highlightTouchTargets": "Markeer minder voor de hand liggende aanraakdoelen.",
 | 
			
		||||
    "highlightTouchTargets": "Minder voor de hand liggende aanraakdoelen markeren.",
 | 
			
		||||
    "pickExportDir": "Kies de exportmap",
 | 
			
		||||
    "autoExportOnChanges": "Automatisch exporteren bij wijzigingen",
 | 
			
		||||
    "autoExportOnChanges": "Bij wijzigingen automatisch exporteren",
 | 
			
		||||
    "includeSettings": "Instellingen opnemen",
 | 
			
		||||
    "filterVersionsByRegEx": "Filter versies met een reguliere expressie",
 | 
			
		||||
    "filterVersionsByRegEx": "Versies met een reguliere expressie filteren",
 | 
			
		||||
    "trySelectingSuggestedVersionCode": "Probeer de voorgestelde versiecode APK te selecteren",
 | 
			
		||||
    "dontSortReleasesList": "Volgorde van releases behouden vanuit de API",
 | 
			
		||||
    "reverseSort": "Sortering omkeren",
 | 
			
		||||
    "reverseSort": "Omgekeerde sortering",
 | 
			
		||||
    "takeFirstLink": "Neem de eerste link",
 | 
			
		||||
    "skipSort": "Sorteren overslaan",
 | 
			
		||||
    "debugMenu": "Debug menu",
 | 
			
		||||
    "skipSort": "Sortering overslaan",
 | 
			
		||||
    "debugMenu": "Debug-menu",
 | 
			
		||||
    "bgTaskStarted": "Achtergrondtaak gestart - controleer de logs.",
 | 
			
		||||
    "runBgCheckNow": "Voer nu een achtergrondupdatecontrole uit",
 | 
			
		||||
    "runBgCheckNow": "Nu een achtergrond-updatecontrole uitvoeren",
 | 
			
		||||
    "versionExtractWholePage": "De reguliere expressie voor versie-extractie toepassen op de hele pagina",
 | 
			
		||||
    "installing": "Installeren",
 | 
			
		||||
    "skipUpdateNotifications": "Updatemeldingen overslaan",
 | 
			
		||||
    "updatesAvailableNotifChannel": "Updates beschikbaar",
 | 
			
		||||
    "appsUpdatedNotifChannel": "Apps bijgewerkt",
 | 
			
		||||
    "appsPossiblyUpdatedNotifChannel": "Poging tot app-updates",
 | 
			
		||||
    "appsPossiblyUpdatedNotifChannel": "Pogingen tot app-updates",
 | 
			
		||||
    "errorCheckingUpdatesNotifChannel": "Foutcontrole bij het zoeken naar updates",
 | 
			
		||||
    "appsRemovedNotifChannel": "Apps verwijderd",
 | 
			
		||||
    "downloadingXNotifChannel": "{} downloaden",
 | 
			
		||||
    "completeAppInstallationNotifChannel": "Voltooien van de app-installatie",
 | 
			
		||||
    "completeAppInstallationNotifChannel": "App-installatie voltooien",
 | 
			
		||||
    "checkingForUpdatesNotifChannel": "Controleren op updates",
 | 
			
		||||
    "onlyCheckInstalledOrTrackOnlyApps": "Alleen geïnstalleerde en Track-Only apps controleren op updates",
 | 
			
		||||
    "supportFixedAPKURL": "Ondersteuning vaste APK URL's",
 | 
			
		||||
    "selectX": "Selecteer {}",
 | 
			
		||||
    "onlyCheckInstalledOrTrackOnlyApps": "Alleen geïnstalleerde apps en 'Alleen volgen' controleren op updates",
 | 
			
		||||
    "supportFixedAPKURL": "Vaste APK-URL's ondersteunen",
 | 
			
		||||
    "selectX": "{} selecteren",
 | 
			
		||||
    "parallelDownloads": "Parallelle downloads toestaan",
 | 
			
		||||
    "installMethod": "Installatiemethode",
 | 
			
		||||
    "normal": "Normaal",
 | 
			
		||||
    "root": "Wortel",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku draait niet",
 | 
			
		||||
    "useSystemFont": "Gebruik het systeemlettertype",
 | 
			
		||||
    "systemFontError": "Fout bij het laden van het systeemlettertype: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Gebruik app versieCode als door OS gedetecteerde versie",
 | 
			
		||||
    "useShizuku": "Shizuku of Sui gebruiken om te installeren",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku is niet actief",
 | 
			
		||||
    "shizukuOld": "Verouderde Shizuku-versie (<11) - bijwerken",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku draait op Android < 8.1 met ADB - update Android of gebruik in plaats daarvan Sui",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Google Play instellen als installatiebron (bij Shizuku)",
 | 
			
		||||
    "useSystemFont": "Systeemlettertype gebruiken",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "App versiecode gebruiken als door OS gedetecteerde versie",
 | 
			
		||||
    "requestHeader": "Verzoekkoptekst",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Gebruik laatste upload als releasedatum",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Laatste upload als releasedatum gebruiken",
 | 
			
		||||
    "defaultPseudoVersioningMethod": "Standaard pseudo-versiebeheermethode",
 | 
			
		||||
    "partialAPKHash": "Gedeeltelijke APK-hash",
 | 
			
		||||
    "APKLinkHash": "APK-link-hash",
 | 
			
		||||
@@ -299,21 +308,25 @@
 | 
			
		||||
    "note": "Opmerking",
 | 
			
		||||
    "selfHostedNote": "De \"{}\" dropdown kan gebruikt worden om zelf gehoste/aangepaste instanties van elke bron te bereiken.",
 | 
			
		||||
    "badDownload": "De APK kon niet worden verwerkt (incompatibele of gedeeltelijke download)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Nieuwe Apps delen met AppVerifier (indien beschikbaar)",
 | 
			
		||||
    "appVerifierInstructionToast": "Deel het met AppVerifier en keer daarna hier terug.",
 | 
			
		||||
    "wiki": "Help/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App-configuraties (gebruik op eigen risico)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "App verwijderen?",
 | 
			
		||||
        "other": "Apps verwijderen?"
 | 
			
		||||
    },
 | 
			
		||||
    "tooManyRequestsTryAgainInMinutes": {
 | 
			
		||||
        "one": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuut",
 | 
			
		||||
        "other": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuten"
 | 
			
		||||
        "one": "Te veel verzoeken (aantal beperkt) - opnieuw proberen over {} minuut",
 | 
			
		||||
        "other": "Te veel verzoeken (aantal beperkt) - opnieuw proberen over {} minuten"
 | 
			
		||||
    },
 | 
			
		||||
    "bgUpdateGotErrorRetryInMinutes": {
 | 
			
		||||
        "one": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuut",
 | 
			
		||||
        "other": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuten"
 | 
			
		||||
        "one": "Achtergrond-updatecontrole heeft een {}, zal een nieuwe controle plannen over {} minuut",
 | 
			
		||||
        "other": "Achtergrond-updatecontrole heeft een {}, zal een nieuwe controle plannen over {} minuten"
 | 
			
		||||
    },
 | 
			
		||||
    "bgCheckFoundUpdatesWillNotifyIfNeeded": {
 | 
			
		||||
        "one": "Achtergrondupdatecontrole heeft {} update gevonden - zal de gebruiker op de hoogte stellen indien nodig",
 | 
			
		||||
        "other": "Achtergrondupdatecontrole heeft {} updates gevonden - zal de gebruiker op de hoogte stellen indien nodig"
 | 
			
		||||
        "one": "Achtergrond-updatecontrole heeft {} update gevonden - zal de gebruiker op de hoogte stellen indien nodig",
 | 
			
		||||
        "other": "Achtergrond-updatecontrole heeft {} updates gevonden - zal de gebruiker op de hoogte stellen indien nodig"
 | 
			
		||||
    },
 | 
			
		||||
    "apps": {
 | 
			
		||||
        "one": "{} app",
 | 
			
		||||
@@ -341,15 +354,19 @@
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesAvailable": {
 | 
			
		||||
        "one": "{} en nog 1 app hebben updates.",
 | 
			
		||||
        "other": "{} en {} meer apps hebben updates."
 | 
			
		||||
        "other": "{} en nog {} apps hebben updates."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesInstalled": {
 | 
			
		||||
        "one": "{} en nog 1 app is bijgewerkt.",
 | 
			
		||||
        "other": "{} en {} meer apps zijn bijgewerkt."
 | 
			
		||||
        "other": "{} en nog {} apps zijn bijgewerkt."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Bijwerken mislukt voor {} en nog 1 app.",
 | 
			
		||||
        "other": "Bijwerken mislukt voor {} en nog {} apps."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} en nog 1 app zijn mogelijk bijgewerkt.",
 | 
			
		||||
        "other": "{} en {} meer apps zijn mogelijk bijgwerkt."
 | 
			
		||||
        "other": "{} en nog {} apps zijn mogelijk bijgwerkt."
 | 
			
		||||
    },
 | 
			
		||||
    "apk": {
 | 
			
		||||
        "one": "{} APK",
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(Wymagane)",
 | 
			
		||||
    "dropdownNoOptsError": "BŁĄD: LISTA ROZWIJANA MUSI MIEĆ CO NAJMNIEJ JEDNĄ OPCJĘ",
 | 
			
		||||
    "colour": "Kolor",
 | 
			
		||||
    "standard": "Standard",
 | 
			
		||||
    "custom": "Niestandardowe",
 | 
			
		||||
    "useMaterialYou": "Używaj materiałów",
 | 
			
		||||
    "githubStarredRepos": "Repozytoria GitHub oznaczone gwiazdką",
 | 
			
		||||
    "uname": "Nazwa użytkownika",
 | 
			
		||||
    "wrongArgNum": "Nieprawidłowa liczba podanych argumentów",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Ciemny",
 | 
			
		||||
    "light": "Jasny",
 | 
			
		||||
    "followSystem": "Zgodny z systemem",
 | 
			
		||||
    "followSystemThemeExplanation": "Podążanie za motywem systemowym jest możliwe tylko przy użyciu aplikacji firm trzecich",
 | 
			
		||||
    "useBlackTheme": "Użyj czarnego motywu",
 | 
			
		||||
    "appSortBy": "Sortuj aplikacje według",
 | 
			
		||||
    "authorName": "Autor/Nazwa",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "Brak nowych aktualizacji.",
 | 
			
		||||
    "xHasAnUpdate": "{} ma aktualizację.",
 | 
			
		||||
    "appsUpdated": "Zaktualizowano aplikacje",
 | 
			
		||||
    "appsNotUpdated": "Nie udało się zaktualizować aplikacji",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Informuje, gdy co najmniej jedna aplikacja została zaktualizowana w tle",
 | 
			
		||||
    "xWasUpdatedToY": "{} zaktualizowano do {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Nie udało się zaktualizować {} do {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Błąd sprawdzania aktualizacji",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Jest wyświetlane, gdy sprawdzanie aktualizacji w tle nie powiedzie się",
 | 
			
		||||
    "appsRemoved": "Usunięte aplikacje",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "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.",
 | 
			
		||||
    "downloadingX": "Pobieranie {}",
 | 
			
		||||
    "downloadX": "Pobierz {}",
 | 
			
		||||
    "downloadedX": "Pobrano {}",
 | 
			
		||||
    "releaseAsset": "Release Asset",
 | 
			
		||||
    "downloadNotifDescription": "Informuje o postępach w pobieraniu aplikacji",
 | 
			
		||||
    "noAPKFound": "Nie znaleziono pakietu APK",
 | 
			
		||||
    "noVersionDetection": "Bez wykrywania wersji",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "Obsługuj stałe adresy URL APK",
 | 
			
		||||
    "selectX": "Wybierz {}",
 | 
			
		||||
    "parallelDownloads": "Zezwól na pobieranie równoległe",
 | 
			
		||||
    "installMethod": "Metoda instalacji",
 | 
			
		||||
    "normal": "Normalna",
 | 
			
		||||
    "root": "Źródło",
 | 
			
		||||
    "useShizuku": "Użyj Shizuku lub Sui, aby zainstalować",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku is not running",
 | 
			
		||||
    "shizukuOld": "Stara wersja Shizuku (<11) - zaktualizuj ją",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku działa na Androidzie < 8.1 z ADB - zaktualizuj Androida lub użyj zamiast tego Sui",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Ustaw Google Play jako źródło instalacji (jeśli używana jest aplikacja Shizuku).",
 | 
			
		||||
    "useSystemFont": "Użyj czcionki systemowej",
 | 
			
		||||
    "systemFontError": "Błąd podczas ładowania czcionki systemowej: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Użyj kodu wersji aplikacji jako wersji wykrytej przez system operacyjny",
 | 
			
		||||
    "requestHeader": "Nagłówek żądania",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Użyj najnowszego przesłanego zasobu jako daty wydania",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Uwaga",
 | 
			
		||||
    "selfHostedNote": "Lista rozwijana \"{}\" może być używana do uzyskiwania dostępu do samodzielnie hostowanych / niestandardowych instancji dowolnego źródła.",
 | 
			
		||||
    "badDownload": "Nie można przeanalizować pliku APK (niekompatybilny lub częściowo pobrany).",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Udostępnianie nowych aplikacji za pomocą AppVerifier (jeśli dostępne)",
 | 
			
		||||
    "appVerifierInstructionToast": "Udostępnij w AppVerifier, a następnie wróć tutaj, gdy będziesz gotowy.",
 | 
			
		||||
    "wiki": "Pomoc/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Konfiguracje aplikacji pochodzące z crowdsourcingu (korzystanie na własne ryzyko)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Usunąć aplikację?",
 | 
			
		||||
        "few": "Usunąć aplikacje?",
 | 
			
		||||
@@ -371,6 +384,10 @@
 | 
			
		||||
        "many": "{} i {} innych apek zostało zaktualizowanych.",
 | 
			
		||||
        "other": "{} i {} inne apki zostały zaktualizowane."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Nie udało się zaktualizować {} i 1 innej aplikacji.",
 | 
			
		||||
        "other": "Nie udało się zaktualizować {} i {} więcej aplikacji."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} i 1 inna apka mogły zostać zaktualizowane.",
 | 
			
		||||
        "few": "{} i {} inne apki mogły zostać zaktualizowane.",
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(Necessário)",
 | 
			
		||||
    "dropdownNoOptsError": "ERRO: O DROPDOWN DEVE TER PELO MENOS UMA OPÇÃO",
 | 
			
		||||
    "colour": "Cor",
 | 
			
		||||
    "standard": "Padrão",
 | 
			
		||||
    "custom": "Personalizado",
 | 
			
		||||
    "useMaterialYou": "Utilizar o material que",
 | 
			
		||||
    "githubStarredRepos": "repositórios favoritos no GitHub",
 | 
			
		||||
    "uname": "Nome de usuário",
 | 
			
		||||
    "wrongArgNum": "Número de argumentos errado",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Escuro",
 | 
			
		||||
    "light": "Claro",
 | 
			
		||||
    "followSystem": "Padrão do sistema",
 | 
			
		||||
    "followSystemThemeExplanation": "O tema do sistema seguinte só é possível através da utilização de aplicações de terceiros",
 | 
			
		||||
    "useBlackTheme": "Usar tema preto AMOLED",
 | 
			
		||||
    "appSortBy": "Classificar aplicativo por",
 | 
			
		||||
    "authorName": "Autor/Nome",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "Sem novas atualizações.",
 | 
			
		||||
    "xHasAnUpdate": "{} tem uma atualização.",
 | 
			
		||||
    "appsUpdated": "Aplicativos atualizados",
 | 
			
		||||
    "appsNotUpdated": "Falha na atualização das aplicações",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Notifica o usuário quando atualizações foram aplicadas em segundo-plano para um ou mais aplicativos ",
 | 
			
		||||
    "xWasUpdatedToY": "{} foi atualizado para {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Falha ao atualizar {} para {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Erro ao procurar por atualizações",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Uma notificação que mostra quando a checagem por atualizações em segundo-plano falha",
 | 
			
		||||
    "appsRemoved": "Aplicativos removidos",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "Desativar detecção de versão",
 | 
			
		||||
    "noVersionDetectionExplanation": "Essa opção deve apenas ser usada por aplicativos onde a detecção de versão não funciona corretamente.",
 | 
			
		||||
    "downloadingX": "Baixando {}",
 | 
			
		||||
    "downloadX": "Descarregar {}",
 | 
			
		||||
    "downloadedX": "Descarregado {}",
 | 
			
		||||
    "releaseAsset": "Libertação de activos",
 | 
			
		||||
    "downloadNotifDescription": "Notifica o usuário o progresso do download de um aplicativo",
 | 
			
		||||
    "noAPKFound": "APK não encontrado",
 | 
			
		||||
    "noVersionDetection": "Sem detecção de versão",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "Suporte a APK com URLs fixas",
 | 
			
		||||
    "selectX": "Selecionar {}",
 | 
			
		||||
    "parallelDownloads": "Permitir downloads paralelos",
 | 
			
		||||
    "installMethod": "Método de instalação",
 | 
			
		||||
    "normal": "Normal",
 | 
			
		||||
    "root": "Root",
 | 
			
		||||
    "useShizuku": "Utilizar Shizuku ou Sui para instalar",
 | 
			
		||||
    "shizukuBinderNotFound": "O Shizuku não está rodando",
 | 
			
		||||
    "shizukuOld": "Versão antiga do Shizuku (<11) - atualizar",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku a funcionar no Android < 8.1 com ADB - atualizar o Android ou utilizar o Sui",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Definir o Google Play como fonte de instalação (se for utilizado o Shizuku)",
 | 
			
		||||
    "useSystemFont": "Usar fonte padrão do sistema",
 | 
			
		||||
    "systemFontError": "Erro ao carregar a fonte do sistema: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Usar versionCode do aplicativo como versão detectada pelo sistema operacional",
 | 
			
		||||
    "requestHeader": "Requisitar cabeçalho",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Use o último upload de recursos como data de lançamento",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Nota",
 | 
			
		||||
    "selfHostedNote": "O menu suspenso \"{}\" pode ser usado para acessar instâncias auto-hospedadas/personalizadas de qualquer fonte.",
 | 
			
		||||
    "badDownload": "Não foi possível analisar o APK (transferência incompatível ou parcial)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Partilhar novas aplicações com o AppVerifier (se disponível)",
 | 
			
		||||
    "appVerifierInstructionToast": "Partilhe com o AppVerifier e, em seguida, regresse aqui quando estiver pronto.",
 | 
			
		||||
    "wiki": "Ajuda/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Configurações de aplicações de crowdsourcing (utilização por sua conta e risco)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Remover aplicativo?",
 | 
			
		||||
        "other": "Remover aplicativos?"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} e um outro aplicativo foram atualizado.",
 | 
			
		||||
        "other": "{} e {} outros aplicativos foram atualizados."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Falha ao atualizar {} e mais 1 aplicação.",
 | 
			
		||||
        "other": "Falha ao atualizar {} e {} mais aplicações."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} e um outro aplicativo podem ter sido atualizados.",
 | 
			
		||||
        "other": "{} e {} outros aplicativos podem ter sido atualizados."
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    "placeholder": "Заполнитель",
 | 
			
		||||
    "someErrors": "Возникли некоторые ошибки",
 | 
			
		||||
    "unexpectedError": "Неожиданная ошибка",
 | 
			
		||||
    "ok": "Ok",
 | 
			
		||||
    "ok": "Ок",
 | 
			
		||||
    "and": "и",
 | 
			
		||||
    "githubPATLabel": "Персональный токен доступа GitHub\n(увеличивает лимит запросов)",
 | 
			
		||||
    "includePrereleases": "Включить предварительные релизы",
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(обязательно)",
 | 
			
		||||
    "dropdownNoOptsError": "Ошибка: в выпадающем списке должна быть выбрана хотя бы одна настройка",
 | 
			
		||||
    "colour": "Цвет",
 | 
			
		||||
    "standard": "Стандартный",
 | 
			
		||||
    "custom": "Индивидуальный",
 | 
			
		||||
    "useMaterialYou": "Использовать Material You",
 | 
			
		||||
    "githubStarredRepos": "Избранные репозитории GitHub",
 | 
			
		||||
    "uname": "Имя пользователя",
 | 
			
		||||
    "wrongArgNum": "Неправильное количество предоставленных аргументов",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Тёмная",
 | 
			
		||||
    "light": "Светлая",
 | 
			
		||||
    "followSystem": "Системная",
 | 
			
		||||
    "followSystemThemeExplanation": "Следование системной теме возможно только при использовании сторонних приложений",
 | 
			
		||||
    "useBlackTheme": "Использовать чёрную тему",
 | 
			
		||||
    "appSortBy": "Сортировка приложений",
 | 
			
		||||
    "authorName": "Автор/Название",
 | 
			
		||||
@@ -131,7 +135,7 @@
 | 
			
		||||
    "close": "Закрыть",
 | 
			
		||||
    "share": "Поделиться",
 | 
			
		||||
    "appNotFound": "Приложение не найдено",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "получение-экспорт",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "экспорт-obtainium",
 | 
			
		||||
    "pickAnAPK": "Выберите APK-файл",
 | 
			
		||||
    "appHasMoreThanOnePackage": "{} имеет более одного пакета:",
 | 
			
		||||
    "deviceSupportsXArch": "Ваше устройство поддерживает архитектуру процессора {}",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "Нет новых обновлений",
 | 
			
		||||
    "xHasAnUpdate": "{} есть обновление",
 | 
			
		||||
    "appsUpdated": "Приложения обновлены",
 | 
			
		||||
    "appsNotUpdated": "Не удалось обновить приложения",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Уведомляет об обновлении одного или нескольких приложений в фоновом режиме",
 | 
			
		||||
    "xWasUpdatedToY": "{} была обновлена до версии {}",
 | 
			
		||||
    "xWasNotUpdatedToY": "Не удалось обновить {} до версии {}",
 | 
			
		||||
    "errorCheckingUpdates": "Ошибка при проверке обновлений",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Уведомление о завершении проверки обновлений в фоновом режиме с ошибкой",
 | 
			
		||||
    "appsRemoved": "Приложение удалено",
 | 
			
		||||
@@ -173,8 +179,8 @@
 | 
			
		||||
    "appWithIdOrNameNotFound": "Приложение с таким ID или названием не было найдено",
 | 
			
		||||
    "reposHaveMultipleApps": "В хранилище несколько приложений",
 | 
			
		||||
    "fdroidThirdPartyRepo": "Сторонние репозитории F-Droid",
 | 
			
		||||
    "steamMobile": "Стим Мобайл",
 | 
			
		||||
    "steamChat": "Стим-чат",
 | 
			
		||||
    "steamMobile": "Приложение Steam",
 | 
			
		||||
    "steamChat": "Steam Chat",
 | 
			
		||||
    "install": "Установить",
 | 
			
		||||
    "markInstalled": "Пометить как установленное",
 | 
			
		||||
    "update": "Обновить",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "Отключить обнаружение версии",
 | 
			
		||||
    "noVersionDetectionExplanation": "Эта настройка должна использоваться только для приложений, где обнаружение версии не работает корректно",
 | 
			
		||||
    "downloadingX": "Загрузка {}",
 | 
			
		||||
    "downloadX": "Скачать {}",
 | 
			
		||||
    "downloadedX": "Загружено {}",
 | 
			
		||||
    "releaseAsset": "Релизный объект",
 | 
			
		||||
    "downloadNotifDescription": "Уведомляет пользователя о прогрессе загрузки приложения",
 | 
			
		||||
    "noAPKFound": "APK не найден",
 | 
			
		||||
    "noVersionDetection": "Обнаружение версий отключено",
 | 
			
		||||
@@ -245,7 +254,7 @@
 | 
			
		||||
    "intermediateLinkRegex": "Фильтр для \"промежуточной\" ссылки для посещения",
 | 
			
		||||
    "filterByLinkText": "Фильтрация ссылок по тексту ссылки",
 | 
			
		||||
    "intermediateLinkNotFound": "Промежуточная ссылка не найдена",
 | 
			
		||||
    "intermediateLink": "Промежуточное звено",
 | 
			
		||||
    "intermediateLink": "Промежуточная ссылка",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "Исключить из фоновых обновлений (если включено)",
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "Отключить фоновые обновления, если нет соединения с Wi-Fi",
 | 
			
		||||
    "autoSelectHighestVersionCode": "Автоматически выбирать APK с актуальной версией кода",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "Поддержка фиксированных URL-адресов APK",
 | 
			
		||||
    "selectX": "Выбрать {}",
 | 
			
		||||
    "parallelDownloads": "Разрешить параллельные загрузки",
 | 
			
		||||
    "installMethod": "Метод установки",
 | 
			
		||||
    "normal": "Нормальный",
 | 
			
		||||
    "root": "Суперпользователь",
 | 
			
		||||
    "shizukuBinderNotFound": "Совместимый сервис Shizuku не найден",
 | 
			
		||||
    "useShizuku": "Использовать Shizuku или Sui для установки",
 | 
			
		||||
    "shizukuBinderNotFound": "Совместимый сервис Shizuku не найден, возможно он не запущен",
 | 
			
		||||
    "shizukuOld": "Устаревшая версия Shizuku (<11), обновите",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku работает на Android < 8.1 с ADB, обновите Android или используйте Sui",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Указать Google Play как источник установки (если используется Shizuku)",
 | 
			
		||||
    "useSystemFont": "Использовать системный шрифт",
 | 
			
		||||
    "systemFontError": "Ошибка загрузки системного шрифта: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Использовать код версии приложения как версию, обнаруженную ОС",
 | 
			
		||||
    "requestHeader": "Заголовок запроса",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Использовать последнюю загрузку ресурса в качестве даты выпуска",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Примечание",
 | 
			
		||||
    "selfHostedNote": "Выпадающий список \"{}\" можно использовать для доступа к самостоятельно размещенным/настроенным экземплярам любого источника.",
 | 
			
		||||
    "badDownload": "APK не удалось разобрать (несовместимая или неполная загрузка)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Поделитесь новыми приложениями с AppVerifier (если доступно)",
 | 
			
		||||
    "appVerifierInstructionToast": "Поделитесь с AppVerifier, а затем вернитесь сюда, когда будете готовы.",
 | 
			
		||||
    "wiki": "Помощь/Вики",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Конфигурации приложений на основе краудсорсинга (используйте на свой страх и риск)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Удалить приложение?",
 | 
			
		||||
        "other": "Удалить приложения?"
 | 
			
		||||
@@ -347,12 +360,16 @@
 | 
			
		||||
        "one": "{} и ещё 1 приложение были обновлены",
 | 
			
		||||
        "other": "{} и ещё {} приложений были обновлены"
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Не удалось обновить {} и ещё 1 приложение",
 | 
			
		||||
        "other": "Не удалось обновить {} и ещё {} приложений"
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} и ещё 1 приложение могли быть обновлены",
 | 
			
		||||
        "other": "{} и ещё {} приложений могли быть обновлены"
 | 
			
		||||
    },
 | 
			
		||||
    "apk": {
 | 
			
		||||
        "one": "{} APK",
 | 
			
		||||
        "other": "{} APKs"
 | 
			
		||||
        "other": "{} APKи"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(Kräver)",
 | 
			
		||||
    "dropdownNoOptsError": "FEL: DROPDOWN MÅSTE HA MINST ETT OPT",
 | 
			
		||||
    "colour": "Färg",
 | 
			
		||||
    "standard": "Standard",
 | 
			
		||||
    "custom": "Anpassad",
 | 
			
		||||
    "useMaterialYou": "Använd material Du",
 | 
			
		||||
    "githubStarredRepos": "GitHub Stjärnmärkta Förråd",
 | 
			
		||||
    "uname": "Användarnamn",
 | 
			
		||||
    "wrongArgNum": "Fel antal argument har angetts",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Mörkt",
 | 
			
		||||
    "light": "Ljust",
 | 
			
		||||
    "followSystem": "Följ System",
 | 
			
		||||
    "followSystemThemeExplanation": "Följande systemtema är endast möjligt med hjälp av tredjepartsapplikationer",
 | 
			
		||||
    "useBlackTheme": "Använd svart tema",
 | 
			
		||||
    "appSortBy": "Sortera Appar via",
 | 
			
		||||
    "authorName": "Utvecklare/Namn",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "Inga nya uppdateringar.",
 | 
			
		||||
    "xHasAnUpdate": "{} har en uppdatering.",
 | 
			
		||||
    "appsUpdated": "Appar Uppdaterade",
 | 
			
		||||
    "appsNotUpdated": "Misslyckades med att uppdatera applikationer",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Meddelar användaren att uppdateringar av en eller flera appar har tillämpats i bakgrunden",
 | 
			
		||||
    "xWasUpdatedToY": "{} uppdaterades till {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Det gick inte att uppdatera {} till {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Fel vid uppdateringskoll",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "En aviserings som visar när bakgrundsuppdateringarkollar misslyckas",
 | 
			
		||||
    "appsRemoved": "Appar borttagna",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "Inaktivera versionsdetektering",
 | 
			
		||||
    "noVersionDetectionExplanation": "Det här alternativet bör endast användas för appar där versionsidentifiering inte fungerar korrekt.",
 | 
			
		||||
    "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",
 | 
			
		||||
    "noAPKFound": "Ingen APK funnen",
 | 
			
		||||
    "noVersionDetection": "Ingen versiondetektering",
 | 
			
		||||
@@ -218,7 +227,7 @@
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Visa inte 'Följ-Endast' varningar",
 | 
			
		||||
    "dontShowAPKOriginWarnings": "Visa inte APK-ursprung varningar",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Flytta icke-installerade appar till botten av appvyn",
 | 
			
		||||
    "gitlabPATLabel": "GitLab Personal Access Token",
 | 
			
		||||
    "gitlabPATLabel": "Personligt åtkomsttoken för GitLab",
 | 
			
		||||
    "about": "Om",
 | 
			
		||||
    "requiresCredentialsInSettings": "{}: This needs additional credentials (in Settings)",
 | 
			
		||||
    "checkOnStart": "Kolla efter uppdateringar vid start",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "Stöd fasta APK-webbadresser",
 | 
			
		||||
    "selectX": "Välj {}",
 | 
			
		||||
    "parallelDownloads": "Tillåt parallella nedladdningar",
 | 
			
		||||
    "installMethod": "Installationsmetod",
 | 
			
		||||
    "normal": "Vanligt",
 | 
			
		||||
    "root": "Rot",
 | 
			
		||||
    "useShizuku": "Använd Shizuku eller Sui för att installera",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku is not running",
 | 
			
		||||
    "shizukuOld": "Gammal Shizuku-version (<11) - uppdatera den",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku körs på Android < 8.1 med ADB - uppdatera Android eller använd Sui istället",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Ange Google Play som installationskälla (om Shizuku används)",
 | 
			
		||||
    "useSystemFont": "Använd systemteckensnittet",
 | 
			
		||||
    "systemFontError": "Fel vid laddning av systemteckensnittet: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Använd appversionskoden som OS-upptäckt version",
 | 
			
		||||
    "requestHeader": "Rubrik för begäran",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Använd senaste tillgångsuppladdning som releasedatum",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Anmärkning",
 | 
			
		||||
    "selfHostedNote": "Rullgardinsmenyn \"{}\" kan användas för att nå självhostade/anpassade instanser av valfri källa.",
 | 
			
		||||
    "badDownload": "APK kunde inte analyseras (inkompatibel eller partiell nedladdning)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Dela nya appar med AppVerifier (om tillgängligt)",
 | 
			
		||||
    "appVerifierInstructionToast": "Dela till AppVerifier och återvänd sedan hit när du är klar.",
 | 
			
		||||
    "wiki": "Hjälp/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourcade appkonfigurationer (använd på egen risk)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Ta Bort App?",
 | 
			
		||||
        "other": "Ta Bort Appar?"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} och 1 till app uppdaterades.",
 | 
			
		||||
        "other": "{} och {} appar till uppdaterades."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Misslyckades med att uppdatera {} och ytterligare 1 app.",
 | 
			
		||||
        "other": "Det gick inte att uppdatera {} och {} fler appar."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} och 1 till app kan ha uppdaterats.",
 | 
			
		||||
        "other": "{} och {} appar till kan ha uppdaterats."
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(Gerekli)",
 | 
			
		||||
    "dropdownNoOptsError": "HATA: DİPLOMADA EN AZ BİR SEÇENEK OLMALI",
 | 
			
		||||
    "colour": "Renk",
 | 
			
		||||
    "standard": "Standart",
 | 
			
		||||
    "custom": "Özel",
 | 
			
		||||
    "useMaterialYou": "Sizin Malzemenizi Kullanın",
 | 
			
		||||
    "githubStarredRepos": "GitHub'a Yıldızlı Depolar",
 | 
			
		||||
    "uname": "Kullanıcı Adı",
 | 
			
		||||
    "wrongArgNum": "Hatalı argüman sayısı sağlandı",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Koyu",
 | 
			
		||||
    "light": "Aydınlık",
 | 
			
		||||
    "followSystem": "Sistemi Takip Et",
 | 
			
		||||
    "followSystemThemeExplanation": "Sistem temasını takip etmek yalnızca üçüncü taraf uygulamaları kullanarak mümkündür",
 | 
			
		||||
    "useBlackTheme": "Saf siyah koyu temasını kullan",
 | 
			
		||||
    "appSortBy": "Uygulama Sıralama Ölçütü",
 | 
			
		||||
    "authorName": "Yazar/Ad",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "Yeni güncelleme yok.",
 | 
			
		||||
    "xHasAnUpdate": "{} güncelleme alıyor.",
 | 
			
		||||
    "appsUpdated": "Uygulamalar Güncellendi",
 | 
			
		||||
    "appsNotUpdated": "Uygulamalar güncellenemedi",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Kullanıcıya bir veya daha fazla uygulamanın arka planda güncellendiğine dair bilgi verir",
 | 
			
		||||
    "xWasUpdatedToY": "{} şu sürüme güncellendi: {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "{} öğesi {} olarak güncellenemedi.",
 | 
			
		||||
    "errorCheckingUpdates": "Güncellemeler Kontrol Edilirken Hata Oluştu",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Arka planda güncelleme kontrolü sırasında hata oluştuğunda görünen bir bildirim",
 | 
			
		||||
    "appsRemoved": "Uygulamalar Kaldırıldı",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "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.",
 | 
			
		||||
    "downloadingX": "{} İndiriliyor",
 | 
			
		||||
    "downloadX": "İndir {}",
 | 
			
		||||
    "downloadedX": "İndirildi {}",
 | 
			
		||||
    "releaseAsset": "Varlık Serbest Bırakma",
 | 
			
		||||
    "downloadNotifDescription": "Bir uygulamanın indirme sürecinde ilerlemeyi bildiren bir bildirim",
 | 
			
		||||
    "noAPKFound": "APK bulunamadı",
 | 
			
		||||
    "noVersionDetection": "Sürüm Algılanamıyor",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "Sabit APK URL'lerini destekleyin",
 | 
			
		||||
    "selectX": "Seçme {}",
 | 
			
		||||
    "parallelDownloads": "Paralel indirmelere izin ver",
 | 
			
		||||
    "installMethod": "Kurulum yöntemi",
 | 
			
		||||
    "normal": "Normal",
 | 
			
		||||
    "root": "Kök",
 | 
			
		||||
    "useShizuku": "Yüklemek için Shizuku veya Sui'yi kullanın",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku is not running",
 | 
			
		||||
    "shizukuOld": "Eski Shizuku sürümü (<11) - güncelleyin",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku ADB ile Android < 8.1 üzerinde çalışıyor - Android'i güncelleyin veya bunun yerine Sui kullanın",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Google Play'i yükleme kaynağı olarak ayarlayın (Shizuku kullanılıyorsa)",
 | 
			
		||||
    "useSystemFont": "Sistem yazı tipini kullan",
 | 
			
		||||
    "systemFontError": "Sistem yazı tipi yüklenirken hata oluştu: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Uygulama versionCode'unu işletim sistemi tarafından algılanan sürüm olarak kullan",
 | 
			
		||||
    "requestHeader": "Başlık talep et",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Yayın tarihi olarak en son öğe yüklemesini kullan",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Not",
 | 
			
		||||
    "selfHostedNote": "\"{}\" açılır menüsü, herhangi bir kaynağın kendi kendine barındırılan/özel örneklerine ulaşmak için kullanılabilir.",
 | 
			
		||||
    "badDownload": "APK ayrıştırılamadı (uyumsuz veya kısmi indirme)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Yeni Uygulamaları AppVerifier ile paylaşın (varsa)",
 | 
			
		||||
    "appVerifierInstructionToast": "AppVerifier ile paylaşın, hazır olduğunuzda buraya dönün.",
 | 
			
		||||
    "wiki": "Yardım/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Kitle Kaynaklı Uygulama Yapılandırmaları (riski size ait olmak üzere kullanın)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Uygulamayı Kaldır?",
 | 
			
		||||
        "other": "Uygulamaları Kaldır?"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} ve 1 diğer uygulama güncellendi.",
 | 
			
		||||
        "other": "{} ve {} daha fazla uygulama güncellendi."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "{} ve 1 uygulama daha güncellenemedi.",
 | 
			
		||||
        "other": "{} ve {} daha fazla uygulama güncellenemedi."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} ve 1 diğer uygulama muhtemelen güncellendi.",
 | 
			
		||||
        "other": "{} ve {} daha fazla uygulama muhtemelen güncellendi."
 | 
			
		||||
 
 | 
			
		||||
@@ -22,19 +22,22 @@
 | 
			
		||||
    "requiredInBrackets": "(Обов'язково)",
 | 
			
		||||
    "dropdownNoOptsError": "ПОМИЛКА: В ВИПАДАЮЧОМУ СПИСКУ МАЄ БУТИ ХОЧА Б ОДИН ЕЛЕМЕНТ",
 | 
			
		||||
    "colour": "Колір",
 | 
			
		||||
    "standard": "Стандартний",
 | 
			
		||||
    "custom": "Нестандартний",
 | 
			
		||||
    "useMaterialYou": "Використовуйте матеріал, який ви",
 | 
			
		||||
    "githubStarredRepos": "Відзначені репозиторії GitHub",
 | 
			
		||||
    "uname": "Ім'я користувача",
 | 
			
		||||
    "wrongArgNum": "Надано неправильну кількість аргументів",
 | 
			
		||||
    "xIsTrackOnly": "{} - тільки відстежування",
 | 
			
		||||
    "source": "Джерело",
 | 
			
		||||
    "app": "застосунок",
 | 
			
		||||
    "appsFromSourceAreTrackOnly": "Додатки з цього джерела є лише для відстежування.",
 | 
			
		||||
    "appsFromSourceAreTrackOnly": "Застосунки з цього джерела є лише для відстежування.",
 | 
			
		||||
    "youPickedTrackOnly": "Ви вибрали опцію лише для відстежування.",
 | 
			
		||||
    "trackOnlyAppDescription": "Застосунок буде відстежуватися для оновлень, але Obtainium не зможе його завантажити або встановити.",
 | 
			
		||||
    "cancelled": "Скасовано",
 | 
			
		||||
    "appAlreadyAdded": "Застосунок вже додано",
 | 
			
		||||
    "alreadyUpToDateQuestion": "Застосунок вже оновлено?",
 | 
			
		||||
    "addApp": "Додати Застосунок",
 | 
			
		||||
    "addApp": "Додати",
 | 
			
		||||
    "appSourceURL": "URL-адреса джерела застосунку",
 | 
			
		||||
    "error": "Помилка",
 | 
			
		||||
    "add": "Додати",
 | 
			
		||||
@@ -44,10 +47,10 @@
 | 
			
		||||
    "supportedSources": "Підтримувані джерела",
 | 
			
		||||
    "trackOnlyInBrackets": "(Тільки для відстеження)",
 | 
			
		||||
    "searchableInBrackets": "(Можливий пошук)",
 | 
			
		||||
    "appsString": "Додатки",
 | 
			
		||||
    "noApps": "Додатків немає",
 | 
			
		||||
    "noAppsForFilter": "Додатків для фільтрації немає",
 | 
			
		||||
    "byX": "За {}",
 | 
			
		||||
    "appsString": "Застосунки",
 | 
			
		||||
    "noApps": "Застосунків немає",
 | 
			
		||||
    "noAppsForFilter": "Застосунків для фільтрації немає",
 | 
			
		||||
    "byX": "Від {}",
 | 
			
		||||
    "percentProgress": "Прогрес: {}%",
 | 
			
		||||
    "pleaseWait": "Будь ласка, зачекайте",
 | 
			
		||||
    "updateAvailable": "Доступно оновлення",
 | 
			
		||||
@@ -56,35 +59,35 @@
 | 
			
		||||
    "selectAll": "Вибрати все",
 | 
			
		||||
    "deselectX": "Скасувати вибір {}",
 | 
			
		||||
    "xWillBeRemovedButRemainInstalled": "{} буде видалено з Obtainium, але залишиться встановленим на пристрої.",
 | 
			
		||||
    "removeSelectedAppsQuestion": "Видалити вибрані додатки?",
 | 
			
		||||
    "removeSelectedApps": "Видалити вибрані додатки",
 | 
			
		||||
    "removeSelectedAppsQuestion": "Видалити вибрані застосунки?",
 | 
			
		||||
    "removeSelectedApps": "Видалити вибрані застосунки",
 | 
			
		||||
    "updateX": "Оновити {}",
 | 
			
		||||
    "installX": "Встановити {}",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "Позначити {}\n(Тільки відстежування)\nяк оновлено",
 | 
			
		||||
    "changeX": "Змінити {}",
 | 
			
		||||
    "installUpdateApps": "Встановити/Оновити додатки",
 | 
			
		||||
    "installUpdateSelectedApps": "Встановити/Оновити вибрані додатки",
 | 
			
		||||
    "markXSelectedAppsAsUpdated": "Позначити {} вибрані додатки як оновлені?",
 | 
			
		||||
    "installUpdateApps": "Встановити/Оновити застосунки",
 | 
			
		||||
    "installUpdateSelectedApps": "Встановити/Оновити вибрані застосунки",
 | 
			
		||||
    "markXSelectedAppsAsUpdated": "Позначити {} вибрані застосунки як оновлені?",
 | 
			
		||||
    "no": "Ні",
 | 
			
		||||
    "yes": "Так",
 | 
			
		||||
    "markSelectedAppsUpdated": "Позначити вибрані додатки як оновлені",
 | 
			
		||||
    "markSelectedAppsUpdated": "Позначити вибрані застосунки як оновлені",
 | 
			
		||||
    "pinToTop": "Закріпити угорі",
 | 
			
		||||
    "unpinFromTop": "Відкріпити зверху",
 | 
			
		||||
    "resetInstallStatusForSelectedAppsQuestion": "Скинути статус встановлення для вибраних додатків?",
 | 
			
		||||
    "installStatusOfXWillBeResetExplanation": "Статус встановлення будь-яких вибраних додатків буде скинутий.\n\nЦе може допомогти, коли версія застосунку, відображена в Obtainium, є неправильною через невдалі оновлення або інші проблеми.",
 | 
			
		||||
    "resetInstallStatusForSelectedAppsQuestion": "Скинути статус встановлення для вибраних застосунків?",
 | 
			
		||||
    "installStatusOfXWillBeResetExplanation": "Статус встановлення будь-яких вибраних застосунків буде скинутий.\n\nЦе може допомогти, коли версія застосунку, відображена в Obtainium, є неправильною через невдалі оновлення або інші проблеми.",
 | 
			
		||||
    "customLinkMessage": "Ці посилання працюють на пристроях з встановленим Obtainium",
 | 
			
		||||
    "shareAppConfigLinks": "Поділитися посиланнями на конфігурацію Застосунку як HTML",
 | 
			
		||||
    "shareSelectedAppURLs": "Поділитися вибраними URL-адресами додатків",
 | 
			
		||||
    "shareSelectedAppURLs": "Поділитися вибраними URL-адресами застосунків",
 | 
			
		||||
    "resetInstallStatus": "Скинути статус встановлення",
 | 
			
		||||
    "more": "Більше",
 | 
			
		||||
    "removeOutdatedFilter": "Видалити фільтр застарілих додатків",
 | 
			
		||||
    "showOutdatedOnly": "Показати лише застарілі додатки",
 | 
			
		||||
    "removeOutdatedFilter": "Видалити фільтр застарілих застосунків",
 | 
			
		||||
    "showOutdatedOnly": "Показати лише застарілі застосунки",
 | 
			
		||||
    "filter": "Фільтр",
 | 
			
		||||
    "filterApps": "Фільтрувати додатки",
 | 
			
		||||
    "filterApps": "Фільтрувати застосунки",
 | 
			
		||||
    "appName": "Назва застосунку",
 | 
			
		||||
    "author": "Автор",
 | 
			
		||||
    "upToDateApps": "Актуальні додатки",
 | 
			
		||||
    "nonInstalledApps": "Невстановлені додатки",
 | 
			
		||||
    "upToDateApps": "Актуальні застосунки",
 | 
			
		||||
    "nonInstalledApps": "Невстановлені застосунки",
 | 
			
		||||
    "importExport": "Імпорт/Експорт",
 | 
			
		||||
    "settings": "Налаштування",
 | 
			
		||||
    "exportedTo": "Експортовано в {}",
 | 
			
		||||
@@ -94,14 +97,14 @@
 | 
			
		||||
    "obtainiumImport": "Імпорт в Obtainium",
 | 
			
		||||
    "importFromURLList": "Імпорт зі списку URL-адрес",
 | 
			
		||||
    "searchQuery": "Пошуковий запит",
 | 
			
		||||
    "appURLList": "Список URL-адрес додатків",
 | 
			
		||||
    "appURLList": "Список URL-адрес застосунків",
 | 
			
		||||
    "line": "Лінія",
 | 
			
		||||
    "searchX": "Пошук {}",
 | 
			
		||||
    "noResults": "Результати відсутні",
 | 
			
		||||
    "importX": "Імпорт {}",
 | 
			
		||||
    "importedAppsIdDisclaimer": "Імпортовані додатки можуть неправильно відображатися як \"Не встановлені\".\nДля виправлення цього перевстановіть їх через Obtainium.\nЦе не повинно вплинути на дані додатків.\n\nПов'язано лише з URL-адресами та імпортом від третіх сторін.",
 | 
			
		||||
    "importedAppsIdDisclaimer": "Імпортовані застосунки можуть неправильно відображатися як \"Не встановлені\".\nДля виправлення цього перевстановіть їх через Obtainium.\nЦе не повинно вплинути на дані застосунків.\n\nПов'язано лише з URL-адресами та імпортом від третіх сторін.",
 | 
			
		||||
    "importErrors": "Помилки імпорту",
 | 
			
		||||
    "importedXOfYApps": "Імпортовано {} з {} додатків.",
 | 
			
		||||
    "importedXOfYApps": "Імпортовано {} з {} застосунків.",
 | 
			
		||||
    "followingURLsHadErrors": "Помилки в наступних URL-адресах:",
 | 
			
		||||
    "selectURL": "Вибрати URL",
 | 
			
		||||
    "selectURLs": "Вибрати URL-адреси",
 | 
			
		||||
@@ -110,19 +113,20 @@
 | 
			
		||||
    "dark": "Темна",
 | 
			
		||||
    "light": "Світла",
 | 
			
		||||
    "followSystem": "Дотримуватися системи",
 | 
			
		||||
    "useBlackTheme": "Використовувати чисто чорну темну тему",
 | 
			
		||||
    "appSortBy": "Сортувати додатки за",
 | 
			
		||||
    "followSystemThemeExplanation": "Зміна теми системи можлива лише за допомогою сторонніх додатків",
 | 
			
		||||
    "useBlackTheme": "Використовувати чорну тему (Amoled)",
 | 
			
		||||
    "appSortBy": "Сортувати застосунки за",
 | 
			
		||||
    "authorName": "Автор/Назва",
 | 
			
		||||
    "nameAuthor": "Назва/Автор",
 | 
			
		||||
    "asAdded": "За додаванням",
 | 
			
		||||
    "appSortOrder": "Порядок сортування додатків",
 | 
			
		||||
    "appSortOrder": "Порядок сортування застосунків",
 | 
			
		||||
    "ascending": "За зростанням",
 | 
			
		||||
    "descending": "За спаданням",
 | 
			
		||||
    "bgUpdateCheckInterval": "Інтервал перевірки оновлень у фоновому режимі",
 | 
			
		||||
    "neverManualOnly": "Ніколи - Тільки вручну",
 | 
			
		||||
    "appearance": "Вигляд",
 | 
			
		||||
    "showWebInAppView": "Показати джерело застосунку у вигляді веб-сторінки",
 | 
			
		||||
    "pinUpdates": "Закріпити оновлення у верхній частині вигляду додатків",
 | 
			
		||||
    "pinUpdates": "Закріпити оновлення у верхній частині вигляду застосунків",
 | 
			
		||||
    "updates": "Оновлення",
 | 
			
		||||
    "sourceSpecific": "Певне джерело",
 | 
			
		||||
    "appSource": "Джерело застосунку",
 | 
			
		||||
@@ -139,23 +143,25 @@
 | 
			
		||||
    "warning": "Попередження",
 | 
			
		||||
    "sourceIsXButPackageFromYPrompt": "Джерело застосунку - '{}' але пакет випуску походить з '{}'. Продовжити?",
 | 
			
		||||
    "updatesAvailable": "Доступні оновлення",
 | 
			
		||||
    "updatesAvailableNotifDescription": "Повідомляє користувача, що доступні оновлення для одного чи декількох додатків, які відстежує Obtainium",
 | 
			
		||||
    "updatesAvailableNotifDescription": "Повідомляє користувача, що доступні оновлення для одного чи декількох застосунків, які відстежує Obtainium",
 | 
			
		||||
    "noNewUpdates": "Немає нових оновлень.",
 | 
			
		||||
    "xHasAnUpdate": "{} має оновлення.",
 | 
			
		||||
    "appsUpdated": "Додатки оновлено",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Повідомляє користувача, що оновлення одного чи декількох додатків було застосовано в фоновому режимі",
 | 
			
		||||
    "appsUpdated": "Застосунки оновлено",
 | 
			
		||||
    "appsNotUpdated": "Не вдалося оновити програми",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Повідомляє користувача, що оновлення одного чи декількох застосунків було застосовано в фоновому режимі",
 | 
			
		||||
    "xWasUpdatedToY": "{} було оновлено до {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Не вдалося оновити {} на {}.",
 | 
			
		||||
    "errorCheckingUpdates": "Помилка перевірки оновлень",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Повідомлення, яке з'являється, коли перевірка оновлень в фоновому режимі завершується невдачею",
 | 
			
		||||
    "appsRemoved": "Додатки видалено",
 | 
			
		||||
    "appsRemovedNotifDescription": "Повідомляє користувача, що один чи декілька додатків були видалені через помилки при завантаженні",
 | 
			
		||||
    "appsRemoved": "Застосунки видалено",
 | 
			
		||||
    "appsRemovedNotifDescription": "Повідомляє користувача, що один чи декілька застосунків були видалені через помилки при завантаженні",
 | 
			
		||||
    "xWasRemovedDueToErrorY": "{} було видалено через цю помилку: {}",
 | 
			
		||||
    "completeAppInstallation": "Завершення установки застосунку",
 | 
			
		||||
    "obtainiumMustBeOpenToInstallApps": "Для встановлення додатків Obtainium має бути відкритий",
 | 
			
		||||
    "obtainiumMustBeOpenToInstallApps": "Для встановлення застосунків Obtainium має бути відкритий",
 | 
			
		||||
    "completeAppInstallationNotifDescription": "Прохання користувача повернутися до Obtainium для завершення установки застосунку",
 | 
			
		||||
    "checkingForUpdates": "Перевірка оновлень",
 | 
			
		||||
    "checkingForUpdatesNotifDescription": "Тимчасове повідомлення, яке з'являється при перевірці оновлень",
 | 
			
		||||
    "pleaseAllowInstallPerm": "Будь ласка, дозвольте Obtainium встановлювати додатки",
 | 
			
		||||
    "pleaseAllowInstallPerm": "Будь ласка, дозвольте Obtainium встановлювати застосунки",
 | 
			
		||||
    "trackOnly": "Тільки відстеження",
 | 
			
		||||
    "errorWithHttpStatusCode": "Помилка {} HTTP-коду",
 | 
			
		||||
    "versionCorrectionDisabled": "Виправлення версії вимкнено (здається, плагін не працює)",
 | 
			
		||||
@@ -171,7 +177,7 @@
 | 
			
		||||
    "appIdOrName": "Ідентифікатор або назва застосунку",
 | 
			
		||||
    "appId": "Ідентифікатор застосунку",
 | 
			
		||||
    "appWithIdOrNameNotFound": "Застосунок з таким ідентифікатором або назвою не знайдено",
 | 
			
		||||
    "reposHaveMultipleApps": "Сховища можуть містити кілька додатків",
 | 
			
		||||
    "reposHaveMultipleApps": "Сховища можуть містити кілька застосунків",
 | 
			
		||||
    "fdroidThirdPartyRepo": "F-Droid Стороннє сховище",
 | 
			
		||||
    "steamMobile": "Мобільний Steam",
 | 
			
		||||
    "steamChat": "Чат Steam",
 | 
			
		||||
@@ -181,8 +187,11 @@
 | 
			
		||||
    "markUpdated": "Позначити як оновлене",
 | 
			
		||||
    "additionalOptions": "Додаткові опції",
 | 
			
		||||
    "disableVersionDetection": "Вимкнути визначення версії",
 | 
			
		||||
    "noVersionDetectionExplanation": "Цю опцію слід використовувати лише для додатків, де визначення версії працює неправильно.",
 | 
			
		||||
    "noVersionDetectionExplanation": "Цю опцію слід використовувати лише для застосунків, де визначення версії працює неправильно.",
 | 
			
		||||
    "downloadingX": "Завантаження {}",
 | 
			
		||||
    "downloadX": "Завантажити {}",
 | 
			
		||||
    "downloadedX": "Завантажено {}",
 | 
			
		||||
    "releaseAsset": "Звільнити актив",
 | 
			
		||||
    "downloadNotifDescription": "Повідомляє користувача про прогрес завантаження застосунку",
 | 
			
		||||
    "noAPKFound": "APK не знайдено",
 | 
			
		||||
    "noVersionDetection": "Визначення версії відключено",
 | 
			
		||||
@@ -192,19 +201,19 @@
 | 
			
		||||
    "noCategory": "Без категорії",
 | 
			
		||||
    "noCategories": "Немає категорій",
 | 
			
		||||
    "deleteCategoriesQuestion": "Видалити категорії?",
 | 
			
		||||
    "categoryDeleteWarning": "Усі додатки у видалених категоріях будуть переведені у некатегоризовані.",
 | 
			
		||||
    "categoryDeleteWarning": "Усі застосунки у видалених категоріях будуть переведені у некатегоризовані.",
 | 
			
		||||
    "addCategory": "Додати категорію",
 | 
			
		||||
    "label": "Мітка",
 | 
			
		||||
    "language": "Мова",
 | 
			
		||||
    "copiedToClipboard": "Скопійовано в буфер обміну",
 | 
			
		||||
    "storagePermissionDenied": "Відмовлено у дозволі на доступ до сховища",
 | 
			
		||||
    "selectedCategorizeWarning": "Це замінить будь-які існуючі налаштування категорій для вибраних додатків.",
 | 
			
		||||
    "selectedCategorizeWarning": "Це замінить будь-які існуючі налаштування категорій для вибраних застосунків.",
 | 
			
		||||
    "filterAPKsByRegEx": "Фільтрувати APK за регулярним виразом",
 | 
			
		||||
    "removeFromObtainium": "Видалити з Obtainium",
 | 
			
		||||
    "uninstallFromDevice": "Видалити з пристрою",
 | 
			
		||||
    "onlyWorksWithNonVersionDetectApps": "Працює лише з застосунками з вимкненим визначенням версії.",
 | 
			
		||||
    "releaseDateAsVersion": "Використовувати дату випуску як рядок версії",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "Цю опцію слід використовувати лише для додатків, де визначення версії працює неправильно, але є дата випуску.",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "Цю опцію слід використовувати лише для застосунків, де визначення версії працює неправильно, але є дата випуску.",
 | 
			
		||||
    "changes": "Зміни",
 | 
			
		||||
    "releaseDate": "Дата випуску",
 | 
			
		||||
    "importFromURLsInFile": "Імпорт з URL-адрес у файлі (наприклад, OPML)",
 | 
			
		||||
@@ -217,13 +226,13 @@
 | 
			
		||||
    "dontShowAgain": "Не показувати це знову",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Не показувати попередження про 'Тільки відстеження'",
 | 
			
		||||
    "dontShowAPKOriginWarnings": "Не показувати попередження про походження APK",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Перемістити невстановлені додатки вниз у перегляді додатків",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Перемістити невстановлені застосунки вниз у перегляді застосунків",
 | 
			
		||||
    "gitlabPATLabel": "Особистий токен GitLab (Увімкнення пошуку та краще виявлення APK)",
 | 
			
		||||
    "about": "Про програму",
 | 
			
		||||
    "requiresCredentialsInSettings": "{} потребує додаткових облікових даних (у налаштуваннях)",
 | 
			
		||||
    "checkOnStart": "Перевірити наявність оновлень при запуску",
 | 
			
		||||
    "tryInferAppIdFromCode": "Спробувати вивести ідентифікатор застосунку з вихідного коду",
 | 
			
		||||
    "removeOnExternalUninstall": "Автоматично видаляти додатки, які було видалено зовнішнім чином",
 | 
			
		||||
    "removeOnExternalUninstall": "Автоматично видаляти застосунки, які було видалено зовнішнім чином",
 | 
			
		||||
    "pickHighestVersionCode": "Автоматично вибрати APK з найвищим кодом версії",
 | 
			
		||||
    "checkUpdateOnDetailPage": "Перевіряти наявність оновлень при відкритті сторінки деталей застосунку",
 | 
			
		||||
    "disablePageTransitions": "Вимкнути анімації переходів між сторінками",
 | 
			
		||||
@@ -232,15 +241,14 @@
 | 
			
		||||
    "addInfoBelow": "Додати цю інформацію нижче.",
 | 
			
		||||
    "addInfoInSettings": "Додати цю інформацію у налаштуваннях.",
 | 
			
		||||
    "githubSourceNote": "Лімітування швидкості GitHub можна уникнути, використовуючи ключ API.",
 | 
			
		||||
    "gitlabSourceNote": "Вилучення APK з GitLab може не працювати без ключа API.",
 | 
			
		||||
    "sortByLastLinkSegment": "Сортувати лише за останнім сегментом посилання",
 | 
			
		||||
    "filterReleaseNotesByRegEx": "Фільтрувати примітки до релізу за регулярним виразом",
 | 
			
		||||
    "customLinkFilterRegex": "Фільтр кастомного посилання на APK за регулярним виразом (за замовчуванням '.apk$')",
 | 
			
		||||
    "appsPossiblyUpdated": "Оновлення додатків спробовано",
 | 
			
		||||
    "appsPossiblyUpdatedNotifDescription": "Повідомляє користувача, що оновлення одного або декількох додатків можливо були застосовані в фоновому режимі",
 | 
			
		||||
    "appsPossiblyUpdated": "Спроб оновлення застосунків",
 | 
			
		||||
    "appsPossiblyUpdatedNotifDescription": "Повідомляє користувача, що оновлення одного або декількох застосунків можливо були застосовані в фоновому режимі",
 | 
			
		||||
    "xWasPossiblyUpdatedToY": "{} можливо було оновлено до {}.",
 | 
			
		||||
    "enableBackgroundUpdates": "Увімкнути оновлення в фоновому режимі",
 | 
			
		||||
    "backgroundUpdateReqsExplanation": "Оновлення в фоновому режимі може бути неможливим для всіх додатків.",
 | 
			
		||||
    "backgroundUpdateReqsExplanation": "Оновлення в фоновому режимі може бути неможливим для всіх застосунків.",
 | 
			
		||||
    "backgroundUpdateLimitsExplanation": "Успіх фонової установки може бути визначений лише після відкриття Obtainium.",
 | 
			
		||||
    "verifyLatestTag": "Перевірити тег 'latest'",
 | 
			
		||||
    "intermediateLinkRegex": "Фільтр для 'Проміжного' Посилання для Відвідування",
 | 
			
		||||
@@ -269,23 +277,23 @@
 | 
			
		||||
    "installing": "Встановлення",
 | 
			
		||||
    "skipUpdateNotifications": "Пропустити сповіщення про оновлення",
 | 
			
		||||
    "updatesAvailableNotifChannel": "Доступні оновлення",
 | 
			
		||||
    "appsUpdatedNotifChannel": "Додатки оновлені",
 | 
			
		||||
    "appsPossiblyUpdatedNotifChannel": "Спроба оновлення додатків",
 | 
			
		||||
    "appsUpdatedNotifChannel": "Застосунки оновлені",
 | 
			
		||||
    "appsPossiblyUpdatedNotifChannel": "Спроба оновлення застосунків",
 | 
			
		||||
    "errorCheckingUpdatesNotifChannel": "Помилка перевірки оновлень",
 | 
			
		||||
    "appsRemovedNotifChannel": "Додатки видалені",
 | 
			
		||||
    "appsRemovedNotifChannel": "Застосунки видалені",
 | 
			
		||||
    "downloadingXNotifChannel": "Завантаження {}",
 | 
			
		||||
    "completeAppInstallationNotifChannel": "Завершення встановлення застосунку",
 | 
			
		||||
    "checkingForUpdatesNotifChannel": "Перевірка оновлень",
 | 
			
		||||
    "onlyCheckInstalledOrTrackOnlyApps": "Перевіряти лише встановлені та додатки, які відстежуються для оновлень",
 | 
			
		||||
    "onlyCheckInstalledOrTrackOnlyApps": "Перевіряти лише встановлені та застосунки, які відстежуються для оновлень",
 | 
			
		||||
    "supportFixedAPKURL": "Підтримка фіксованих посилань на APK",
 | 
			
		||||
    "selectX": "Вибрати {}",
 | 
			
		||||
    "parallelDownloads": "Дозволити паралельні завантаження",
 | 
			
		||||
    "installMethod": "Метод встановлення",
 | 
			
		||||
    "normal": "Звичайний",
 | 
			
		||||
    "root": "Root",
 | 
			
		||||
    "useShizuku": "Використовуйте Shizuku або Sui для встановлення",
 | 
			
		||||
    "shizukuBinderNotFound": "Сумісний сервіс Shizuku не було знайдено",
 | 
			
		||||
    "shizukuOld": "Стара версія Shizuku (<11) - оновіть її",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku працює на Android < 8.1 з ADB - оновіть Android або використовуйте Sui замість нього",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Виберіть Google Play як джерело встановлення (якщо використовується Shizuku)",
 | 
			
		||||
    "useSystemFont": "Використовувати системний шрифт",
 | 
			
		||||
    "systemFontError": "Помилка завантаження системного шрифту: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Використовувати код версії застосунку як версію, визначену операційною системою",
 | 
			
		||||
    "requestHeader": "Заголовок запиту",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Використовувати останню дату завантаження ресурсу як дату випуску",
 | 
			
		||||
@@ -300,9 +308,13 @@
 | 
			
		||||
    "note": "Примітка",
 | 
			
		||||
    "selfHostedNote": "Випадаючий список \"{}\" може використовуватися для доступу до власних/призначених для самостійного використання екземплярів будь-якого джерела.",
 | 
			
		||||
    "badDownload": "APK не вдалося розпарсити (несумісний або часткове завантаження)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Діліться новими додатками з AppVerifier (якщо доступно)",
 | 
			
		||||
    "appVerifierInstructionToast": "Надішліть на AppVerifier, а потім поверніться сюди, коли будете готові.",
 | 
			
		||||
    "wiki": "Довідка/Вікі",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Краудсорсингові конфігурації додатків (використовуйте на свій страх і ризик)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Видалити Застосунок?",
 | 
			
		||||
        "other": "Видалити додатки?"
 | 
			
		||||
        "one": "Видалити застосунок?",
 | 
			
		||||
        "other": "Видалити застосунки?"
 | 
			
		||||
    },
 | 
			
		||||
    "tooManyRequestsTryAgainInMinutes": {
 | 
			
		||||
        "one": "Забагато запитів (обмеження швидкості) - повторіть спробу через {} хвилину",
 | 
			
		||||
@@ -313,44 +325,48 @@
 | 
			
		||||
        "other": "Помилка перевірки оновлень у фоновому режимі - спробую знову через {} хвилин"
 | 
			
		||||
    },
 | 
			
		||||
    "bgCheckFoundUpdatesWillNotifyIfNeeded": {
 | 
			
		||||
        "one": "Фонова перевірка оновлень знайшла {} оновлення - сповістить користувача, якщо це необхідно",
 | 
			
		||||
        "other": "Фонова перевірка оновлень знайшла {} оновлень - сповістить користувача, якщо це необхідно"
 | 
			
		||||
        "one": "Фонова перевірка оновлень знайшла {} оновлення - сповістити користувача, якщо це необхідно",
 | 
			
		||||
        "other": "Фонова перевірка оновлень знайшла {} оновлень - сповістити користувача, якщо це необхідно"
 | 
			
		||||
    },
 | 
			
		||||
    "apps": {
 | 
			
		||||
        "one": "{} Застосунок",
 | 
			
		||||
        "other": "{} Додатки"
 | 
			
		||||
        "one": "{} застосунок",
 | 
			
		||||
        "other": "{} застосунки"
 | 
			
		||||
    },
 | 
			
		||||
    "url": {
 | 
			
		||||
        "one": "{} URL",
 | 
			
		||||
        "one": "{} URL-адреса",
 | 
			
		||||
        "other": "{} URL-адреси"
 | 
			
		||||
    },
 | 
			
		||||
    "minute": {
 | 
			
		||||
        "one": "{} Хвилина",
 | 
			
		||||
        "other": "{} Хвилин"
 | 
			
		||||
        "one": "{} хвилина",
 | 
			
		||||
        "other": "{} хвилин"
 | 
			
		||||
    },
 | 
			
		||||
    "hour": {
 | 
			
		||||
        "one": "{} Година",
 | 
			
		||||
        "other": "{} Годин"
 | 
			
		||||
        "one": "{} година",
 | 
			
		||||
        "other": "{} годин"
 | 
			
		||||
    },
 | 
			
		||||
    "day": {
 | 
			
		||||
        "one": "{} День",
 | 
			
		||||
        "other": "{} Днів"
 | 
			
		||||
        "one": "{} день",
 | 
			
		||||
        "other": "{} днів"
 | 
			
		||||
    },
 | 
			
		||||
    "clearedNLogsBeforeXAfterY": {
 | 
			
		||||
        "one": "Очищено {n} журнал (до = {before}, після = {after})",
 | 
			
		||||
        "other": "Очищено {n} журналів (до = {before}, після = {after})"
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesAvailable": {
 | 
			
		||||
        "one": "{} і 1 інше Застосунок мають оновлення.",
 | 
			
		||||
        "other": "{} і {} інших додатки мають оновлення."
 | 
			
		||||
        "one": "{} та ще 1 застосунок мають оновлення.",
 | 
			
		||||
        "other": "{} та ще {} застосунки мають оновлення."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesInstalled": {
 | 
			
		||||
        "one": "{} і 1 інше Застосунок було оновлено.",
 | 
			
		||||
        "other": "{} і {} інших додатків було оновлено."
 | 
			
		||||
        "one": "{} та ще 1 застосунок було оновлено.",
 | 
			
		||||
        "other": "{} та ще {} застосунків було оновлено."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Не вдалося оновити {} та ще 1 програму.",
 | 
			
		||||
        "other": "Не вдалося оновити {} і {} та інші програми."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} і 1 інше Застосунок можливо було оновлено.",
 | 
			
		||||
        "other": "{} і {} інших додатків можливо було оновлено."
 | 
			
		||||
        "one": "{} та ще 1 застосунок можливо було оновлено.",
 | 
			
		||||
        "other": "{} та ще {} застосунків можливо було оновлено."
 | 
			
		||||
    },
 | 
			
		||||
    "apk": {
 | 
			
		||||
        "one": "{} APK",
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
    "unexpectedError": "Lỗi không mong đợi",
 | 
			
		||||
    "ok": "OK",
 | 
			
		||||
    "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",
 | 
			
		||||
    "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",
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(Yêu cầu)",
 | 
			
		||||
    "dropdownNoOptsError": "LỖI: TẢI XUỐNG PHẢI CÓ ÍT NHẤT MỘT LỰA CHỌN",
 | 
			
		||||
    "colour": "Màu sắc",
 | 
			
		||||
    "standard": "Mặc định",
 | 
			
		||||
    "custom": "Tùy chỉnh",
 | 
			
		||||
    "useMaterialYou": "Sử dụng Material You",
 | 
			
		||||
    "githubStarredRepos": "Kho lưu trữ có gắn dấu sao GitHub",
 | 
			
		||||
    "uname": "Tên người dùng",
 | 
			
		||||
    "wrongArgNum": "Số lượng đối số được cung cấp sai",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "Tối",
 | 
			
		||||
    "light": "Sáng",
 | 
			
		||||
    "followSystem": "Theo hệ thống",
 | 
			
		||||
    "followSystemThemeExplanation": "Following system theme is possible only by using third-party applications",
 | 
			
		||||
    "useBlackTheme": "Nền đen",
 | 
			
		||||
    "appSortBy": "Sắp xếp ứng dụng",
 | 
			
		||||
    "authorName": "Tác giả",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "Không có bản cập nhật mới.",
 | 
			
		||||
    "xHasAnUpdate": "{} có bản cập nhật.",
 | 
			
		||||
    "appsUpdated": "Ứng dụng đã cập nhật ",
 | 
			
		||||
    "appsNotUpdated": "Ứng dụng đã cập nhật không thành công",
 | 
			
		||||
    "appsUpdatedNotifDescription": "Thông báo cho người dùng rằng các bản cập nhật cho một hoặc nhiều Ứng dụng đã được áp dụng trong nền",
 | 
			
		||||
    "xWasUpdatedToY": "{} đã được cập nhật thành {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "{} đã cập nhật thành {} không thành công.",
 | 
			
		||||
    "errorCheckingUpdates": "Lỗi kiểm tra bản cập nhật",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Thông báo hiển thị khi kiểm tra cập nhật nền không thành công",
 | 
			
		||||
    "appsRemoved": "Ứng dụng đã loại bỏ",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "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.",
 | 
			
		||||
    "downloadingX": "Đang tải xuống {}",
 | 
			
		||||
    "downloadX": "Tải xuống {}",
 | 
			
		||||
    "downloadedX": "Đã tải xuống {}",
 | 
			
		||||
    "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",
 | 
			
		||||
    "noAPKFound": "Không tìm thấy APK",
 | 
			
		||||
    "noVersionDetection": "Không phát hiện phiên bản",
 | 
			
		||||
@@ -218,7 +227,7 @@
 | 
			
		||||
    "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",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Chuyển Ứng dụng chưa được cài đặt xuống cuối danh sách",
 | 
			
		||||
    "gitlabPATLabel": "GitLab Token",
 | 
			
		||||
    "gitlabPATLabel": "Token truy cập cá nhân GitLab",
 | 
			
		||||
    "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)",
 | 
			
		||||
    "checkOnStart": "Kiểm tra các bản cập nhật khi khởi động",
 | 
			
		||||
@@ -279,12 +288,12 @@
 | 
			
		||||
    "supportFixedAPKURL": "Hỗ trợ URL APK cố định",
 | 
			
		||||
    "selectX": "Lựa chọn {}",
 | 
			
		||||
    "parallelDownloads": "Cho phép tải đa luồng",
 | 
			
		||||
    "installMethod": "Phương thức cài đặt",
 | 
			
		||||
    "normal": "Mặc định",
 | 
			
		||||
    "root": "Root",
 | 
			
		||||
    "useShizuku": "Sử dụng Shizuku hoặc Sui để cài đặt",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku chưa khởi động",
 | 
			
		||||
    "shizukuOld": "Phiên bản Shizuku lỗi thời (<11) - hãy cập nhật nó",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku chạy trên Android < 8.1 với ADB - hãy cập nhật Android hoặc thay bằng Sui",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Set Google Play as the installation source (if Shizuku is used)",
 | 
			
		||||
    "useSystemFont": "Sử dụng phông chữ hệ thống",
 | 
			
		||||
    "systemFontError": "Lỗi tải phông chữ hệ thống: {}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Sử dụng Mã phiên bản ứng dụng làm phiên bản do hệ điều hành phát hiện",
 | 
			
		||||
    "requestHeader": "Tiêu đề yêu cầu",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Sử dụng nội dung tải lên mới nhất làm ngày phát hành",
 | 
			
		||||
@@ -299,6 +308,10 @@
 | 
			
		||||
    "note": "Ghi chú",
 | 
			
		||||
    "selfHostedNote": "Trình đơn thả xuống \"{}\" có thể được dùng để tiếp cận các phiên bản tự lưu trữ/tùy chỉnh của bất kỳ nguồn nào.",
 | 
			
		||||
    "badDownload": "Không thể phân tích cú pháp APK (tải xuống một phần hoặc không tương thích)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "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.",
 | 
			
		||||
    "wiki": "Trợ giúp/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Gỡ ứng dụng?",
 | 
			
		||||
        "other": "Gỡ ứng dụng?"
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} và 1 ứng dụng khác đã được cập nhật.",
 | 
			
		||||
        "other": "{} và {} ứng dụng khác đã được cập nhật."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "{} và 1 ứng dụng khác đã cập nhật không thành công.",
 | 
			
		||||
        "other": "{} và {} ứng dụng khác đã cập nhật không thảnh công."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} và 1 ứng dụng khác có thể đã được cập nhật.",
 | 
			
		||||
        "other": "{} và {} ứng dụng khác có thể đã được cập nhật."
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										375
									
								
								assets/translations/zh-TW.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										375
									
								
								assets/translations/zh-TW.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,375 @@
 | 
			
		||||
{
 | 
			
		||||
  "invalidURLForSource": "不是有效的 {} 應用程式 URL",
 | 
			
		||||
  "noReleaseFound": "找不到合適的版本",
 | 
			
		||||
  "noVersionFound": "無法確定版本",
 | 
			
		||||
  "urlMatchesNoSource": "URL 不符合已知來源",
 | 
			
		||||
  "cantInstallOlderVersion": "無法安裝舊版本的應用程式",
 | 
			
		||||
  "appIdMismatch": "下載的套件 ID 與現有的應用程式 ID 不匹配",
 | 
			
		||||
  "functionNotImplemented": "此類別尚未實作此功能",
 | 
			
		||||
  "placeholder": "佔位",
 | 
			
		||||
  "someErrors": "發生了一些錯誤",
 | 
			
		||||
  "unexpectedError": "意外錯誤",
 | 
			
		||||
  "ok": "確定",
 | 
			
		||||
  "and": "和",
 | 
			
		||||
  "githubPATLabel": "GitHub 個人存取權杖(增加速率限制)",
 | 
			
		||||
  "includePrereleases": "包含預發佈版本",
 | 
			
		||||
  "fallbackToOlderReleases": "回退到舊版本",
 | 
			
		||||
  "filterReleaseTitlesByRegEx": "用正則表達式過濾版本標題",
 | 
			
		||||
  "invalidRegEx": "無效的正則表達式",
 | 
			
		||||
  "noDescription": "無描述",
 | 
			
		||||
  "cancel": "取消",
 | 
			
		||||
  "continue": "繼續",
 | 
			
		||||
  "requiredInBrackets": "(必填)",
 | 
			
		||||
  "dropdownNoOptsError": "錯誤:下拉選單必須至少有一個選項",
 | 
			
		||||
  "colour": "顏色",
 | 
			
		||||
  "standard": "標準",
 | 
			
		||||
  "custom": "自訂",
 | 
			
		||||
  "useMaterialYou": "使用 Material You",
 | 
			
		||||
  "githubStarredRepos": "GitHub Starred Repos",
 | 
			
		||||
  "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": "跟隨系統",
 | 
			
		||||
  "followSystemThemeExplanation": "僅使用第三方應用程式時才可跟隨系統主題",
 | 
			
		||||
  "useBlackTheme": "使用純黑色深色主題",
 | 
			
		||||
  "appSortBy": "應用程式排序依據",
 | 
			
		||||
  "authorName": "作者/名稱",
 | 
			
		||||
  "nameAuthor": "名稱/作者",
 | 
			
		||||
  "asAdded": "添加順序",
 | 
			
		||||
  "appSortOrder": "應用程式排序順序",
 | 
			
		||||
  "ascending": "升序",
 | 
			
		||||
  "descending": "降序",
 | 
			
		||||
  "bgUpdateCheckInterval": "背景更新檢查間隔",
 | 
			
		||||
  "neverManualOnly": "從不 - 僅手動",
 | 
			
		||||
  "appearance": "外觀",
 | 
			
		||||
  "showWebInAppView": "在應用程式檢視中顯示來源網頁",
 | 
			
		||||
  "pinUpdates": "將更新釘選至應用程式檢視的頂端",
 | 
			
		||||
  "updates": "更新",
 | 
			
		||||
  "sourceSpecific": "特定來源",
 | 
			
		||||
  "appSource": "應用程式來源",
 | 
			
		||||
  "noLogs": "無日誌",
 | 
			
		||||
  "appLogs": "應用程式日誌",
 | 
			
		||||
  "close": "關閉",
 | 
			
		||||
  "share": "分享",
 | 
			
		||||
  "appNotFound": "未找到應用程式",
 | 
			
		||||
  "obtainiumExportHyphenatedLowercase": "obtainium-export",
 | 
			
		||||
  "pickAnAPK": "選擇一個 APK",
 | 
			
		||||
  "appHasMoreThanOnePackage": "{} 有多個套件:",
 | 
			
		||||
  "deviceSupportsXArch": "您的設備支持 {} CPU 架構。",
 | 
			
		||||
  "deviceSupportsFollowingArchs": "您的設備支持以下 CPU 架構:",
 | 
			
		||||
  "warning": "警告",
 | 
			
		||||
  "sourceIsXButPackageFromYPrompt": "應用程式來源是 「{}」,但發佈套件來自 「{}」。要繼續嗎?",
 | 
			
		||||
  "updatesAvailable": "有可用的更新",
 | 
			
		||||
  "updatesAvailableNotifDescription": "通知使用者有一個或多個由 Obtainium 追蹤的應用程式有更新",
 | 
			
		||||
  "noNewUpdates": "沒有新更新。",
 | 
			
		||||
  "xHasAnUpdate": "{} 有一個更新。",
 | 
			
		||||
  "appsUpdated": "應用程式已更新",
 | 
			
		||||
  "appsNotUpdated": "未能更新應用程式",
 | 
			
		||||
  "appsUpdatedNotifDescription": "通知使用者一個或多個應用程式的更新已在背景中應用",
 | 
			
		||||
  "xWasUpdatedToY": "{} 已更新到 {}。",
 | 
			
		||||
  "xWasNotUpdatedToY": "未能將 {} 更新到 {}。",
 | 
			
		||||
  "errorCheckingUpdates": "檢查更新時出錯",
 | 
			
		||||
  "errorCheckingUpdatesNotifDescription": "背景檢查更新失敗時顯示的通知",
 | 
			
		||||
  "appsRemoved": "應用程式已移除",
 | 
			
		||||
  "appsRemovedNotifDescription": "通知使用者由於載入時出錯,一個或多個應用程式已被移除",
 | 
			
		||||
  "xWasRemovedDueToErrorY": "{} 已因以下錯誤被移除:{}",
 | 
			
		||||
  "completeAppInstallation": "完成應用程式安裝",
 | 
			
		||||
  "obtainiumMustBeOpenToInstallApps": "Obtainium 必須開啟才能安裝應用程式",
 | 
			
		||||
  "completeAppInstallationNotifDescription": "請使用者返回 Obtainium 以完成應用程式安裝",
 | 
			
		||||
  "checkingForUpdates": "正在檢查更新",
 | 
			
		||||
  "checkingForUpdatesNotifDescription": "檢查更新時顯示的暫時性通知",
 | 
			
		||||
  "pleaseAllowInstallPerm": "請允許 Obtainium 安裝應用程式",
 | 
			
		||||
  "trackOnly": "僅追蹤",
 | 
			
		||||
  "errorWithHttpStatusCode": "錯誤 {}",
 | 
			
		||||
  "versionCorrectionDisabled": "版本校正已禁用(外掛程式似乎無法正常工作)",
 | 
			
		||||
  "unknown": "未知",
 | 
			
		||||
  "none": "無",
 | 
			
		||||
  "never": "從不",
 | 
			
		||||
  "latestVersionX": "最新版本:{}",
 | 
			
		||||
  "installedVersionX": "已安裝版本:{}",
 | 
			
		||||
  "lastUpdateCheckX": "上次檢查更新時間:{}",
 | 
			
		||||
  "remove": "移除",
 | 
			
		||||
  "yesMarkUpdated": "是,標記為已更新",
 | 
			
		||||
  "fdroid": "F-Droid 官方",
 | 
			
		||||
  "appIdOrName": "應用程式 ID 或名稱",
 | 
			
		||||
  "appId": "應用程式 ID",
 | 
			
		||||
  "appWithIdOrNameNotFound": "找不到具有該 ID 或名稱的應用程式",
 | 
			
		||||
  "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": "如果可能,嘗試按 CPU 架構過濾 APK",
 | 
			
		||||
  "overrideSource": "覆蓋來源",
 | 
			
		||||
  "dontShowAgain": "不要再顯示",
 | 
			
		||||
  "dontShowTrackOnlyWarnings": "不要顯示「僅追蹤」警告",
 | 
			
		||||
  "dontShowAPKOriginWarnings": "不要顯示 APK 來源警告",
 | 
			
		||||
  "moveNonInstalledAppsToBottom": "將未安裝的應用程式移到應用程式視圖的底部",
 | 
			
		||||
  "gitlabPATLabel": "GitLab 個人存取權杖",
 | 
			
		||||
  "about": "關於",
 | 
			
		||||
  "requiresCredentialsInSettings": "{} 需要額外的憑證(在設定中)",
 | 
			
		||||
  "checkOnStart": "啟動時檢查更新",
 | 
			
		||||
  "tryInferAppIdFromCode": "嘗試從原始碼推斷應用程式 ID",
 | 
			
		||||
  "removeOnExternalUninstall": "自動移除外部解除安裝的應用程式",
 | 
			
		||||
  "pickHighestVersionCode": "自動選取最高版本號的 APK",
 | 
			
		||||
  "checkUpdateOnDetailPage": "在打開應用程式詳細頁面時檢查更新",
 | 
			
		||||
  "disablePageTransitions": "禁用頁面過渡動畫",
 | 
			
		||||
  "reversePageTransitions": "反轉頁面過渡動畫",
 | 
			
		||||
  "minStarCount": "最少星數",
 | 
			
		||||
  "addInfoBelow": "在下方添加此資訊。",
 | 
			
		||||
  "addInfoInSettings": "在設定中增加此資訊。",
 | 
			
		||||
  "githubSourceNote": "使用 API 金鑰可以避免 GitHub 的速率限制。",
 | 
			
		||||
  "sortByLastLinkSegment": "僅按連結的最後一段排序",
 | 
			
		||||
  "filterReleaseNotesByRegEx": "用正則表達式過濾發佈說明",
 | 
			
		||||
  "customLinkFilterRegex": "自定 APK 連結過濾正則表達式(預設為 '.apk$')",
 | 
			
		||||
  "appsPossiblyUpdated": "嘗試更新應用程式",
 | 
			
		||||
  "appsPossiblyUpdatedNotifDescription": "通知使用者一個或多個應用程式的更新可能已在背景中應用",
 | 
			
		||||
  "xWasPossiblyUpdatedToY": "{} 可能已更新到 {}。",
 | 
			
		||||
  "enableBackgroundUpdates": "啟用背景更新",
 | 
			
		||||
  "backgroundUpdateReqsExplanation": "並非所有應用程式都能進行背景更新。",
 | 
			
		||||
  "backgroundUpdateLimitsExplanation": "背景安裝的成功與否只能在打開 Obtainium 時確定。",
 | 
			
		||||
  "verifyLatestTag": "驗證「最新」標籤",
 | 
			
		||||
  "intermediateLinkRegex": "過濾要訪問的「中間」連結",
 | 
			
		||||
  "filterByLinkText": "按連結文本過濾連結",
 | 
			
		||||
  "intermediateLinkNotFound": "未找到中間連結",
 | 
			
		||||
  "intermediateLink": "中間連結",
 | 
			
		||||
  "exemptFromBackgroundUpdates": "免除背景更新(若已啟用)",
 | 
			
		||||
  "bgUpdatesOnWiFiOnly": "禁用非 WiFi 的背景更新",
 | 
			
		||||
  "autoSelectHighestVersionCode": "自動選擇最高 versionCode 的 APK",
 | 
			
		||||
  "versionExtractionRegEx": "版本字串提取正則表達式",
 | 
			
		||||
  "matchGroupToUse": "要用於版本字串提取的匹配組",
 | 
			
		||||
  "highlightTouchTargets": "突出顯示不明顯的觸控目標",
 | 
			
		||||
  "pickExportDir": "選擇匯出目錄",
 | 
			
		||||
  "autoExportOnChanges": "更改時自動匯出",
 | 
			
		||||
  "includeSettings": "包含設定",
 | 
			
		||||
  "filterVersionsByRegEx": "用正則表達式過濾版本",
 | 
			
		||||
  "trySelectingSuggestedVersionCode": "嘗試選擇建議的 versionCode 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": "允許平行下載",
 | 
			
		||||
  "useShizuku": "使用 Shizuku 或 Sui 來安裝",
 | 
			
		||||
  "shizukuBinderNotFound": "Shizuku 服務未運行",
 | 
			
		||||
  "shizukuOld": "舊版 Shizuku (<11) - 請更新",
 | 
			
		||||
  "shizukuOldAndroidWithADB": "Shizuku 在 Android 8.1 以下版本使用 ADB 運行 - 請更新 Android 或改用 Sui",
 | 
			
		||||
  "shizukuPretendToBeGooglePlay": "設置 Google Play 為安裝來源(如果使用 Shizuku)",
 | 
			
		||||
  "useSystemFont": "使用系統字體",
 | 
			
		||||
  "useVersionCodeAsOSVersion": "使用應用程式 versionCode 作為操作系統檢測的版本",
 | 
			
		||||
  "requestHeader": "請求標頭",
 | 
			
		||||
  "useLatestAssetDateAsReleaseDate": "使用最新資源上傳日期作為發佈日期",
 | 
			
		||||
  "defaultPseudoVersioningMethod": "預設偽版本管理方法",
 | 
			
		||||
  "partialAPKHash": "部分 APK Hash",
 | 
			
		||||
  "APKLinkHash": "APK 連結 Hash",
 | 
			
		||||
  "directAPKLink": "直接 APK 連結",
 | 
			
		||||
  "pseudoVersionInUse": "正在使用偽版本",
 | 
			
		||||
  "installed": "已安裝",
 | 
			
		||||
  "latest": "最新",
 | 
			
		||||
  "invertRegEx": "反轉正則表達式",
 | 
			
		||||
  "note": "備註",
 | 
			
		||||
  "selfHostedNote": "可使用「{}」下拉選單來訪問任何來源的自託管/自定義實例。",
 | 
			
		||||
  "badDownload": "無法解析 APK(不兼容或下載不完整)",
 | 
			
		||||
  "beforeNewInstallsShareToAppVerifier": "將新應用程式分享到 AppVerifier(如果可用)",
 | 
			
		||||
  "appVerifierInstructionToast": "分享至 AppVerifier,然後準備好時返回此處。",
 | 
			
		||||
  "wiki": "幫助/維基",
 | 
			
		||||
  "crowdsourcedConfigsLabel": "群眾外包的應用程式配置(使用風險自負)",
 | 
			
		||||
  "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": "{} 和另外 {} 個應用程式已更新。"
 | 
			
		||||
  },
 | 
			
		||||
  "xAndNMoreUpdatesFailed": {
 | 
			
		||||
    "one": "更新 {} 和另外 1 個應用程式失敗。",
 | 
			
		||||
    "other": "更新 {} 和另外 {} 個應用程式失敗。"
 | 
			
		||||
  },
 | 
			
		||||
  "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
    "one": "{} 和另外 1 個應用程式可能已更新。",
 | 
			
		||||
    "other": "{} 和另外 {} 個應用程式可能已更新。"
 | 
			
		||||
  },
 | 
			
		||||
  "apk": {
 | 
			
		||||
    "one": "{} 個 APK",
 | 
			
		||||
    "other": "{} 個 APK"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -13,8 +13,8 @@
 | 
			
		||||
    "and": "和",
 | 
			
		||||
    "githubPATLabel": "GitHub 个人访问令牌(提升 API 请求限额)",
 | 
			
		||||
    "includePrereleases": "包含预发行版",
 | 
			
		||||
    "fallbackToOlderReleases": "将旧发行版作为备选",
 | 
			
		||||
    "filterReleaseTitlesByRegEx": "筛选发行标题(正则表达式)",
 | 
			
		||||
    "fallbackToOlderReleases": "将过往的发行版作为备选",
 | 
			
		||||
    "filterReleaseTitlesByRegEx": "筛选发行标题的正则表达式",
 | 
			
		||||
    "invalidRegEx": "无效的正则表达式",
 | 
			
		||||
    "noDescription": "无描述",
 | 
			
		||||
    "cancel": "取消",
 | 
			
		||||
@@ -22,6 +22,9 @@
 | 
			
		||||
    "requiredInBrackets": "(必填)",
 | 
			
		||||
    "dropdownNoOptsError": "错误:下拉菜单必须包含至少一个选项",
 | 
			
		||||
    "colour": "配色",
 | 
			
		||||
    "standard": "标准",
 | 
			
		||||
    "custom": "定制",
 | 
			
		||||
    "useMaterialYou": "使用 Material You",
 | 
			
		||||
    "githubStarredRepos": "已星标的 GitHub 仓库",
 | 
			
		||||
    "uname": "用户名",
 | 
			
		||||
    "wrongArgNum": "参数数量错误",
 | 
			
		||||
@@ -42,8 +45,8 @@
 | 
			
		||||
    "search": "搜索",
 | 
			
		||||
    "additionalOptsFor": "{} 的更多选项",
 | 
			
		||||
    "supportedSources": "支持的来源",
 | 
			
		||||
    "trackOnlyInBrackets": "(仅追踪)",
 | 
			
		||||
    "searchableInBrackets": "(可搜索)",
 | 
			
		||||
    "trackOnlyInBrackets": "(仅追踪)",
 | 
			
		||||
    "searchableInBrackets": "(可搜索)",
 | 
			
		||||
    "appsString": "应用列表",
 | 
			
		||||
    "noApps": "无应用",
 | 
			
		||||
    "noAppsForFilter": "没有符合条件的应用",
 | 
			
		||||
@@ -72,8 +75,8 @@
 | 
			
		||||
    "unpinFromTop": "取消置顶",
 | 
			
		||||
    "resetInstallStatusForSelectedAppsQuestion": "是否重置选中应用的安装状态?",
 | 
			
		||||
    "installStatusOfXWillBeResetExplanation": "选中应用的安装状态将会被重置。\n\n当更新安装失败或其他问题导致 Obtainium 中的应用版本显示错误时,可以尝试通过此方法解决。",
 | 
			
		||||
    "customLinkMessage": "这些链接适用于安装了 Gettingium 的设备",
 | 
			
		||||
    "shareAppConfigLinks": "将应用程序配置共享为 HTML 链接",
 | 
			
		||||
    "customLinkMessage": "分享链接仅适用于已安装 Obtainium 的设备",
 | 
			
		||||
    "shareAppConfigLinks": "通过链接分享应用配置",
 | 
			
		||||
    "shareSelectedAppURLs": "分享选中应用的 URL",
 | 
			
		||||
    "resetInstallStatus": "重置安装状态",
 | 
			
		||||
    "more": "更多",
 | 
			
		||||
@@ -110,6 +113,7 @@
 | 
			
		||||
    "dark": "深色",
 | 
			
		||||
    "light": "浅色",
 | 
			
		||||
    "followSystem": "跟随系统",
 | 
			
		||||
    "followSystemThemeExplanation": "跟随系统主题仅在使用第三方应用时有效",
 | 
			
		||||
    "useBlackTheme": "使用纯黑深色主题",
 | 
			
		||||
    "appSortBy": "排序依据",
 | 
			
		||||
    "authorName": "作者 / 应用名称",
 | 
			
		||||
@@ -121,7 +125,7 @@
 | 
			
		||||
    "bgUpdateCheckInterval": "后台更新检查间隔",
 | 
			
		||||
    "neverManualOnly": "手动",
 | 
			
		||||
    "appearance": "外观",
 | 
			
		||||
    "showWebInAppView": "应用详情页显示来源网页",
 | 
			
		||||
    "showWebInAppView": "应用详情页显示来源网站内容",
 | 
			
		||||
    "pinUpdates": "将待更新应用置顶",
 | 
			
		||||
    "updates": "更新",
 | 
			
		||||
    "sourceSpecific": "来源",
 | 
			
		||||
@@ -131,7 +135,7 @@
 | 
			
		||||
    "close": "关闭",
 | 
			
		||||
    "share": "分享",
 | 
			
		||||
    "appNotFound": "未找到应用",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "获取出口",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "obtainium-export",
 | 
			
		||||
    "pickAnAPK": "选择一个 APK 文件",
 | 
			
		||||
    "appHasMoreThanOnePackage": "“{}”有多个架构可用:",
 | 
			
		||||
    "deviceSupportsXArch": "您的设备支持 {} 架构。",
 | 
			
		||||
@@ -143,8 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "全部应用已是最新。",
 | 
			
		||||
    "xHasAnUpdate": "“{}”可以更新了。",
 | 
			
		||||
    "appsUpdated": "应用已更新",
 | 
			
		||||
    "appsNotUpdated": "更新应用失败",
 | 
			
		||||
    "appsUpdatedNotifDescription": "当应用在后台安装更新时发送通知",
 | 
			
		||||
    "xWasUpdatedToY": "“{}”已更新至 {}。",
 | 
			
		||||
    "xWasNotUpdatedToY": "未能将 {} 更新为 {}。",
 | 
			
		||||
    "errorCheckingUpdates": "检查更新出错",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "当后台检查更新失败时显示的通知",
 | 
			
		||||
    "appsRemoved": "应用已删除",
 | 
			
		||||
@@ -173,8 +179,8 @@
 | 
			
		||||
    "appWithIdOrNameNotFound": "未找到符合此 ID 或名称的应用",
 | 
			
		||||
    "reposHaveMultipleApps": "存储库中可能包含多个应用",
 | 
			
		||||
    "fdroidThirdPartyRepo": "F-Droid 第三方存储库",
 | 
			
		||||
    "steamMobile": "蒸汽手机",
 | 
			
		||||
    "steamChat": "蒸汽聊天",
 | 
			
		||||
    "steamMobile": "Steam Mobile",
 | 
			
		||||
    "steamChat": "Steam Chat",
 | 
			
		||||
    "install": "安装",
 | 
			
		||||
    "markInstalled": "标记为已安装",
 | 
			
		||||
    "update": "更新",
 | 
			
		||||
@@ -183,6 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "禁用版本检测",
 | 
			
		||||
    "noVersionDetectionExplanation": "此选项应该仅用于无法进行版本检测的应用。",
 | 
			
		||||
    "downloadingX": "正在下载“{}”",
 | 
			
		||||
    "downloadX": "下载 {}",
 | 
			
		||||
    "downloadedX": "下载 {}",
 | 
			
		||||
    "releaseAsset": "发行版附件",
 | 
			
		||||
    "downloadNotifDescription": "提示应用的下载进度",
 | 
			
		||||
    "noAPKFound": "未找到 APK 文件",
 | 
			
		||||
    "noVersionDetection": "禁用版本检测",
 | 
			
		||||
@@ -192,14 +201,14 @@
 | 
			
		||||
    "noCategory": "无类别",
 | 
			
		||||
    "noCategories": "无类别",
 | 
			
		||||
    "deleteCategoriesQuestion": "是否删除选中的类别?",
 | 
			
		||||
    "categoryDeleteWarning": "被删除类别下的应用将恢复为未分类状态。",
 | 
			
		||||
    "categoryDeleteWarning": "被删除类别的应用将恢复为未分类状态。",
 | 
			
		||||
    "addCategory": "添加类别",
 | 
			
		||||
    "label": "标签",
 | 
			
		||||
    "language": "语言",
 | 
			
		||||
    "copiedToClipboard": "已复制至剪贴板",
 | 
			
		||||
    "storagePermissionDenied": "已拒绝授予存储权限",
 | 
			
		||||
    "selectedCategorizeWarning": "这将覆盖选中应用当前的类别设置。",
 | 
			
		||||
    "filterAPKsByRegEx": "筛选 APK 文件(正则表达式)",
 | 
			
		||||
    "filterAPKsByRegEx": "筛选 APK 文件的正则表达式",
 | 
			
		||||
    "removeFromObtainium": "从 Obtainium 中删除",
 | 
			
		||||
    "uninstallFromDevice": "从设备中卸载",
 | 
			
		||||
    "onlyWorksWithNonVersionDetectApps": "仅适用于禁用版本检测的应用。",
 | 
			
		||||
@@ -233,29 +242,29 @@
 | 
			
		||||
    "addInfoInSettings": "在“设置”中添加此凭据。",
 | 
			
		||||
    "githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。",
 | 
			
		||||
    "sortByLastLinkSegment": "仅根据链接的末尾部分进行筛选",
 | 
			
		||||
    "filterReleaseNotesByRegEx": "筛选发行说明(正则表达式)",
 | 
			
		||||
    "filterReleaseNotesByRegEx": "筛选发行说明的正则表达式",
 | 
			
		||||
    "customLinkFilterRegex": "筛选自定义来源的 APK 文件链接\n(正则表达式,默认匹配模式为“.apk$”)",
 | 
			
		||||
    "appsPossiblyUpdated": "已尝试更新应用",
 | 
			
		||||
    "appsPossiblyUpdatedNotifDescription": "当应用已尝试在后台更新时发送通知",
 | 
			
		||||
    "xWasPossiblyUpdatedToY": "已尝试将“{}”更新至 {}。",
 | 
			
		||||
    "enableBackgroundUpdates": "启用后台更新",
 | 
			
		||||
    "enableBackgroundUpdates": "启用全局后台更新",
 | 
			
		||||
    "backgroundUpdateReqsExplanation": "后台更新未必适用于所有的应用。",
 | 
			
		||||
    "backgroundUpdateLimitsExplanation": "只有在启动 Obtainium 时才能确认安装是否成功。",
 | 
			
		||||
    "verifyLatestTag": "验证“Latest”标签",
 | 
			
		||||
    "intermediateLinkRegex": "筛选中转链接(正则表达式)",
 | 
			
		||||
    "intermediateLinkRegex": "筛选中转链接的正则表达式",
 | 
			
		||||
    "filterByLinkText": "根据链接文本进行筛选",
 | 
			
		||||
    "intermediateLinkNotFound": "未找到中转链接",
 | 
			
		||||
    "intermediateLink": "中转链接",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "禁用后台更新(如果已经全局启用)",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "禁用后台更新(仅此应用生效,即使已启用全局后台更新)",
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "未连接 Wi-Fi 时禁用后台更新",
 | 
			
		||||
    "autoSelectHighestVersionCode": "自动选择内部版本号最高的 APK 文件",
 | 
			
		||||
    "versionExtractionRegEx": "版本号提取规则(正则表达式)",
 | 
			
		||||
    "matchGroupToUse": "引用的捕获组",
 | 
			
		||||
    "highlightTouchTargets": "突出展示不明显的触摸区域",
 | 
			
		||||
    "versionExtractionRegEx": "提取版本号的正则表达式",
 | 
			
		||||
    "matchGroupToUse": "从上述匹配结果中引用的捕获组",
 | 
			
		||||
    "highlightTouchTargets": "突出展示不明显的可交互区域",
 | 
			
		||||
    "pickExportDir": "选择导出文件夹",
 | 
			
		||||
    "autoExportOnChanges": "数据变更时自动导出",
 | 
			
		||||
    "includeSettings": "同时导出应用设置",
 | 
			
		||||
    "filterVersionsByRegEx": "筛选版本号(正则表达式)",
 | 
			
		||||
    "filterVersionsByRegEx": "筛选版本号的正则表达式",
 | 
			
		||||
    "trySelectingSuggestedVersionCode": "尝试选择推荐版本的 APK 文件",
 | 
			
		||||
    "dontSortReleasesList": "保持来自 API 的发行顺序",
 | 
			
		||||
    "reverseSort": "反转排序",
 | 
			
		||||
@@ -279,15 +288,15 @@
 | 
			
		||||
    "supportFixedAPKURL": "支持固定的 APK 文件链接",
 | 
			
		||||
    "selectX": "选择{}",
 | 
			
		||||
    "parallelDownloads": "启用并行下载",
 | 
			
		||||
    "installMethod": "安装方式",
 | 
			
		||||
    "normal": "常规",
 | 
			
		||||
    "root": "root",
 | 
			
		||||
    "useShizuku": "使用 Shizuku 或 Sui 安装",
 | 
			
		||||
    "shizukuBinderNotFound": "未发现兼容的 Shizuku 服务",
 | 
			
		||||
    "shizukuOld": "Shizuku 版本过低(<11)- 请更新",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "正在低版本 Android(<8.1)系统中以 ADB 模式运行 Shizuku - 请更新 Android 系统版本或使用 Sui 代替",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "将安装来源伪装为 Google Play(需要使用 Shizuku)",
 | 
			
		||||
    "useSystemFont": "使用系统字体",
 | 
			
		||||
    "systemFontError": "加载系统字体出错:{}",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "使用内部版本号代替应用定义的版本号",
 | 
			
		||||
    "requestHeader": "请求标头",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "使用最近文件上传时间作为发行日期",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "使用最新文件上传时间作为发行日期",
 | 
			
		||||
    "defaultPseudoVersioningMethod": "默认虚拟版本方案",
 | 
			
		||||
    "partialAPKHash": "APK 文件散列值片段",
 | 
			
		||||
    "APKLinkHash": "APK 文件链接散列值",
 | 
			
		||||
@@ -299,17 +308,21 @@
 | 
			
		||||
    "note": "备注",
 | 
			
		||||
    "selfHostedNote": "可以通过“{}”下拉菜单来指向任意来源的自托管/自定义实例。",
 | 
			
		||||
    "badDownload": "无法解析 APK 文件(不兼容或文件不完整)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "通过 AppVerifier 校验新应用(如果可用)",
 | 
			
		||||
    "appVerifierInstructionToast": "分享至 AppVerifier,完成后返回此处。",
 | 
			
		||||
    "wiki": "帮助/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "众包应用程序配置(使用风险自负)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "是否删除应用?",
 | 
			
		||||
        "other": "是否删除应用?"
 | 
			
		||||
    },
 | 
			
		||||
    "tooManyRequestsTryAgainInMinutes": {
 | 
			
		||||
        "one": "API 请求过于频繁(速率限制)- 在 {} 分钟后重试",
 | 
			
		||||
        "other": "API 请求过于频繁(速率限制)- 在 {} 分钟后重试"
 | 
			
		||||
        "one": "API 请求过于频繁(速率限制)- 请在 {} 分钟后重试",
 | 
			
		||||
        "other": "API 请求过于频繁(速率限制)- 请在 {} 分钟后重试"
 | 
			
		||||
    },
 | 
			
		||||
    "bgUpdateGotErrorRetryInMinutes": {
 | 
			
		||||
        "one": "后台更新检查遇到了“{}”问题,预定于 {} 分钟后重试",
 | 
			
		||||
        "other": "后台更新检查遇到了“{}”问题,预定于 {} 分钟后重试"
 | 
			
		||||
        "one": "后台更新检查遇到了“{}”问题,将于 {} 分钟后重试",
 | 
			
		||||
        "other": "后台更新检查遇到了“{}”问题,将于 {} 分钟后重试"
 | 
			
		||||
    },
 | 
			
		||||
    "bgCheckFoundUpdatesWillNotifyIfNeeded": {
 | 
			
		||||
        "one": "后台检查发现 {} 个应用更新 - 如有需要将发送通知",
 | 
			
		||||
@@ -347,6 +360,10 @@
 | 
			
		||||
        "one": "{} 和另外 1 个应用已更新。",
 | 
			
		||||
        "other": "“{}”和另外 {} 个应用已更新。"
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "{} 和另外 1 个应用更新失败。",
 | 
			
		||||
        "other": "{} 和另外 {} 个应用更新失败。"
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} 和另外 1 个应用已尝试更新。",
 | 
			
		||||
        "other": "“{}”和另外 {} 个应用已尝试更新。"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								fastlane/metadata/android/ru/full_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								fastlane/metadata/android/ru/full_description.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
<p>Obtainium позволяет вам устанавливать и обновлять приложения прямо с их объявлений о выпусках и получать уведомления о новых выпусках.</p>
 | 
			
		||||
<p>Для деталей читайте <a href="https://github.com/ImranR98/Obtainium/wiki">Вики</a></p>
 | 
			
		||||
<p>
 | 
			
		||||
	<b>Поддерживаемые источники приложений:</b>
 | 
			
		||||
</p>
 | 
			
		||||
<ul>
 | 
			
		||||
	<li>
 | 
			
		||||
		<p>Свободное ПО - Общие:</p>
 | 
			
		||||
		<ul>
 | 
			
		||||
			<li>GitHub</li>
 | 
			
		||||
			<li>GitLab</li>
 | 
			
		||||
			<li>Codeberg</li>
 | 
			
		||||
			<li>F-Droid</li>
 | 
			
		||||
			<li>Third Party F-Droid Repos</li>
 | 
			
		||||
			<li>IzzyOnDroid</li>
 | 
			
		||||
			<li>SourceForge</li>
 | 
			
		||||
			<li>SourceHut</li>
 | 
			
		||||
		</ul>
 | 
			
		||||
	</li>
 | 
			
		||||
	<li>
 | 
			
		||||
		<p>Другие - Общие:</p>
 | 
			
		||||
		<ul>
 | 
			
		||||
			<li>APKPure</li>
 | 
			
		||||
			<li>Aptoide</li>
 | 
			
		||||
			<li>Uptodowng</li>
 | 
			
		||||
			<li>APKMirror (Track-Only)</li>
 | 
			
		||||
			<li>Huawei AppGallery</li>
 | 
			
		||||
			<li>Jenkins Jobs</li>
 | 
			
		||||
		</ul>
 | 
			
		||||
	</li>
 | 
			
		||||
	<li>
 | 
			
		||||
		<p>Свободное ПО - Для отдельных приложений:</p>
 | 
			
		||||
		<ul>
 | 
			
		||||
			<li>Mullvad</li>
 | 
			
		||||
			<li>Signal</li>
 | 
			
		||||
			<li>VLC</li>
 | 
			
		||||
		</ul>
 | 
			
		||||
	</li>
 | 
			
		||||
	<li>
 | 
			
		||||
		<p>Другие - Для отдельных приложений:</p>
 | 
			
		||||
		<ul>
 | 
			
		||||
			<li>WhatsApp</li>
 | 
			
		||||
			<li>Telegram App</li>
 | 
			
		||||
			<li>Neutron Code</li>
 | 
			
		||||
		</ul>
 | 
			
		||||
	</li>
 | 
			
		||||
	<li><p>"HTML" (Подстраховка): Любой другой URL-адрес, который возвращает HTML-страницу со ссылками на APK-файлы.</p></li>
 | 
			
		||||
</ul>
 | 
			
		||||
<p>
 | 
			
		||||
	<b>Ограничения:</b>
 | 
			
		||||
</p>
 | 
			
		||||
<p>
 | 
			
		||||
	Для некоторых источников данные собираются с помощью веб-скрапинга и могут легко сломаться из-за изменений в дизайне веб-сайта. В таких случаях более надежные методы могут быть недоступны.
 | 
			
		||||
</p>
 | 
			
		||||
							
								
								
									
										1
									
								
								fastlane/metadata/android/ru/short_description.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								fastlane/metadata/android/ru/short_description.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
Получайте обновления приложений прямо из источника
 | 
			
		||||
@@ -24,6 +24,14 @@ class DirectAPKLink extends AppSource {
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Future<Map<String, String>?> getRequestHeaders(
 | 
			
		||||
      Map<String, dynamic> additionalSettings,
 | 
			
		||||
      {bool forAPKDownload = false}) {
 | 
			
		||||
    return html.getRequestHeaders(additionalSettings,
 | 
			
		||||
        forAPKDownload: forAPKDownload);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Future<APKDetails> getLatestAPKDetails(
 | 
			
		||||
    String standardUrl,
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ class FDroidRepo extends AppSource {
 | 
			
		||||
  FDroidRepo() {
 | 
			
		||||
    name = tr('fdroidThirdPartyRepo');
 | 
			
		||||
    canSearch = true;
 | 
			
		||||
    excludeFromMassSearch = true;
 | 
			
		||||
    includeAdditionalOptsInMainSearch = true;
 | 
			
		||||
    neverAutoSelect = true;
 | 
			
		||||
    showReleaseDateAsVersionToggle = true;
 | 
			
		||||
 | 
			
		||||
@@ -86,6 +86,27 @@ class FDroidRepo extends AppSource {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void runOnAddAppInputChange(String userInput) {
 | 
			
		||||
    additionalSourceAppSpecificSettingFormItems =
 | 
			
		||||
        additionalSourceAppSpecificSettingFormItems.map((row) {
 | 
			
		||||
      row = row.map((item) {
 | 
			
		||||
        if (item.key == 'appIdOrName') {
 | 
			
		||||
          try {
 | 
			
		||||
            var appId = Uri.parse(userInput).queryParameters['appId'];
 | 
			
		||||
            if (appId != null && item is GeneratedFormTextField) {
 | 
			
		||||
              item.required = false;
 | 
			
		||||
            }
 | 
			
		||||
          } catch (e) {
 | 
			
		||||
            //
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        return item;
 | 
			
		||||
      }).toList();
 | 
			
		||||
      return row;
 | 
			
		||||
    }).toList();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  App endOfGetAppChanges(App app) {
 | 
			
		||||
    var uri = Uri.parse(app.url);
 | 
			
		||||
@@ -142,6 +163,7 @@ class FDroidRepo extends AppSource {
 | 
			
		||||
    if (appIdOrName == null) {
 | 
			
		||||
      throw NoReleasesError();
 | 
			
		||||
    }
 | 
			
		||||
    additionalSettings['appIdOrName'] = appIdOrName;
 | 
			
		||||
    var res =
 | 
			
		||||
        await sourceRequestWithURLVariants(standardUrl, additionalSettings);
 | 
			
		||||
    if (res.statusCode == 200) {
 | 
			
		||||
 
 | 
			
		||||
@@ -271,23 +271,23 @@ class GitHub extends AppSource {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      List<MapEntry<String, String>> getReleaseAPKUrls(dynamic release) =>
 | 
			
		||||
          (release['assets'] as List<dynamic>?)
 | 
			
		||||
              ?.map((e) {
 | 
			
		||||
                return (e['name'] != null) &&
 | 
			
		||||
                        ((e['url'] ?? e['browser_download_url']) != null)
 | 
			
		||||
                    ? MapEntry(e['name'] as String,
 | 
			
		||||
                        (e['url'] ?? e['browser_download_url']) as String)
 | 
			
		||||
                    : const MapEntry('', '');
 | 
			
		||||
              })
 | 
			
		||||
              .where((element) => element.key.toLowerCase().endsWith('.apk'))
 | 
			
		||||
              .toList() ??
 | 
			
		||||
      List<MapEntry<String, String>> getReleaseAssetUrls(dynamic release) =>
 | 
			
		||||
          (release['assets'] as List<dynamic>?)?.map((e) {
 | 
			
		||||
            var url = !e['name'].toString().toLowerCase().endsWith('.apk')
 | 
			
		||||
                ? (e['browser_download_url'] ?? e['url'])
 | 
			
		||||
                : (e['url'] ?? e['browser_download_url']);
 | 
			
		||||
            return (e['name'] != null) && (url != null)
 | 
			
		||||
                ? MapEntry(e['name'] as String, url as String)
 | 
			
		||||
                : const MapEntry('', '');
 | 
			
		||||
          }).toList() ??
 | 
			
		||||
          [];
 | 
			
		||||
 | 
			
		||||
      DateTime? getPublishDateFromRelease(dynamic rel) =>
 | 
			
		||||
          rel?['published_at'] != null
 | 
			
		||||
              ? DateTime.parse(rel['published_at'])
 | 
			
		||||
              : null;
 | 
			
		||||
              : rel?['commit']?['created'] != null
 | 
			
		||||
                  ? DateTime.parse(rel['commit']['created'])
 | 
			
		||||
                  : null;
 | 
			
		||||
      DateTime? getNewestAssetDateFromRelease(dynamic rel) {
 | 
			
		||||
        var t = (rel['assets'] as List<dynamic>?)
 | 
			
		||||
            ?.map((e) {
 | 
			
		||||
@@ -383,7 +383,11 @@ class GitHub extends AppSource {
 | 
			
		||||
                .hasMatch(((releases[i]['body'] as String?) ?? '').trim())) {
 | 
			
		||||
          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'],
 | 
			
		||||
            additionalSettings['invertAPKFilter']);
 | 
			
		||||
        if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) {
 | 
			
		||||
@@ -391,12 +395,25 @@ class GitHub extends AppSource {
 | 
			
		||||
        }
 | 
			
		||||
        targetRelease = releases[i];
 | 
			
		||||
        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;
 | 
			
		||||
      }
 | 
			
		||||
      if (targetRelease == null) {
 | 
			
		||||
        throw NoReleasesError();
 | 
			
		||||
      }
 | 
			
		||||
      String? version = targetRelease['tag_name'] ?? targetRelease['name'];
 | 
			
		||||
      String? version = targetRelease['version'];
 | 
			
		||||
      DateTime? releaseDate = getReleaseDateFromRelease(
 | 
			
		||||
          targetRelease, useLatestAssetDateAsReleaseDate);
 | 
			
		||||
      if (version == null) {
 | 
			
		||||
@@ -408,7 +425,9 @@ class GitHub extends AppSource {
 | 
			
		||||
          targetRelease['apkUrls'] as List<MapEntry<String, String>>,
 | 
			
		||||
          getAppNames(standardUrl),
 | 
			
		||||
          releaseDate: releaseDate,
 | 
			
		||||
          changeLog: changeLog.isEmpty ? null : changeLog);
 | 
			
		||||
          changeLog: changeLog.isEmpty ? null : changeLog,
 | 
			
		||||
          allAssetUrls:
 | 
			
		||||
              targetRelease['allAssetUrls'] as List<MapEntry<String, String>>);
 | 
			
		||||
    } else {
 | 
			
		||||
      if (onHttpErrorCode != null) {
 | 
			
		||||
        onHttpErrorCode(res);
 | 
			
		||||
 
 | 
			
		||||
@@ -111,6 +111,14 @@ class GitLab extends AppSource {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Future<String> apkUrlPrefetchModifier(String apkUrl, String standardUrl,
 | 
			
		||||
      Map<String, dynamic> additionalSettings) async {
 | 
			
		||||
    String? PAT = await getPATIfAny(hostChanged ? additionalSettings : {});
 | 
			
		||||
    String optionalAuth = (PAT != null) ? 'private_token=$PAT' : '';
 | 
			
		||||
    return '$apkUrl?$optionalAuth';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Future<APKDetails> getLatestAPKDetails(
 | 
			
		||||
    String standardUrl,
 | 
			
		||||
@@ -121,9 +129,11 @@ class GitLab extends AppSource {
 | 
			
		||||
    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(
 | 
			
		||||
        'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/releases?$optionalAuth',
 | 
			
		||||
        'https://${hosts[0]}/api/v4/projects/${names.author}%2F${names.name}/${trackOnly ? 'repository/tags' : 'releases'}?$optionalAuth',
 | 
			
		||||
        additionalSettings);
 | 
			
		||||
    if (res.statusCode != 200) {
 | 
			
		||||
      throw getObtainiumHttpError(res);
 | 
			
		||||
@@ -151,10 +161,10 @@ class GitLab extends AppSource {
 | 
			
		||||
              .toList();
 | 
			
		||||
      var apkUrlsSet = apkUrlsFromAssets.toSet();
 | 
			
		||||
      apkUrlsSet.addAll(uploadedAPKsFromDescription);
 | 
			
		||||
      var releaseDateString = e['released_at'] ?? e['created_at'];
 | 
			
		||||
      DateTime? releaseDate = releaseDateString != null
 | 
			
		||||
          ? DateTime.parse(releaseDateString)
 | 
			
		||||
          : null;
 | 
			
		||||
      var releaseDateString =
 | 
			
		||||
          e['released_at'] ?? e['created_at'] ?? e['commit']?['created_at'];
 | 
			
		||||
      DateTime? releaseDate =
 | 
			
		||||
          releaseDateString != null ? DateTime.parse(releaseDateString) : null;
 | 
			
		||||
      return APKDetails(
 | 
			
		||||
          e['tag_name'] ?? e['name'],
 | 
			
		||||
          getApkUrlsFromUrls(apkUrlsSet.toList()),
 | 
			
		||||
@@ -164,20 +174,31 @@ class GitLab extends AppSource {
 | 
			
		||||
    if (apkDetailsList.isEmpty) {
 | 
			
		||||
      throw NoReleasesError();
 | 
			
		||||
    }
 | 
			
		||||
    var finalResult = apkDetailsList.first;
 | 
			
		||||
 | 
			
		||||
    // Fallback procedure
 | 
			
		||||
    bool fallbackToOlderReleases =
 | 
			
		||||
        additionalSettings['fallbackToOlderReleases'] == true;
 | 
			
		||||
    if (fallbackToOlderReleases) {
 | 
			
		||||
      if (additionalSettings['trackOnly'] != true) {
 | 
			
		||||
        apkDetailsList =
 | 
			
		||||
            apkDetailsList.where((e) => e.apkUrls.isNotEmpty).toList();
 | 
			
		||||
      }
 | 
			
		||||
      if (apkDetailsList.isEmpty) {
 | 
			
		||||
        throw NoReleasesError();
 | 
			
		||||
      }
 | 
			
		||||
    if (finalResult.apkUrls.isEmpty && fallbackToOlderReleases && !trackOnly) {
 | 
			
		||||
      apkDetailsList =
 | 
			
		||||
          apkDetailsList.where((e) => e.apkUrls.isNotEmpty).toList();
 | 
			
		||||
      finalResult = apkDetailsList.first;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return apkDetailsList.first;
 | 
			
		||||
    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;
 | 
			
		||||
      }
 | 
			
		||||
    }).toList();
 | 
			
		||||
 | 
			
		||||
    return finalResult;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -243,18 +243,28 @@ class HTML extends AppSource {
 | 
			
		||||
    if ((additionalSettings['customLinkFilterRegex'] as String?)?.isNotEmpty ==
 | 
			
		||||
        true) {
 | 
			
		||||
      var reg = RegExp(additionalSettings['customLinkFilterRegex']);
 | 
			
		||||
      links = allLinks
 | 
			
		||||
          .where((element) =>
 | 
			
		||||
              reg.hasMatch(filterLinkByText ? element.value : element.key))
 | 
			
		||||
          .toList();
 | 
			
		||||
      links = allLinks.where((element) {
 | 
			
		||||
        var link = element.key;
 | 
			
		||||
        try {
 | 
			
		||||
          link = Uri.decodeFull(element.key);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          // Some links may not have valid encoding
 | 
			
		||||
        }
 | 
			
		||||
        return reg.hasMatch(filterLinkByText ? element.value : link);
 | 
			
		||||
      }).toList();
 | 
			
		||||
    } else {
 | 
			
		||||
      links = allLinks
 | 
			
		||||
          .where((element) =>
 | 
			
		||||
              Uri.parse(filterLinkByText ? element.value : element.key)
 | 
			
		||||
                  .path
 | 
			
		||||
                  .toLowerCase()
 | 
			
		||||
                  .endsWith('.apk'))
 | 
			
		||||
          .toList();
 | 
			
		||||
      links = allLinks.where((element) {
 | 
			
		||||
        var link = element.key;
 | 
			
		||||
        try {
 | 
			
		||||
          link = Uri.decodeFull(element.key);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          // Some links may not have valid encoding
 | 
			
		||||
        }
 | 
			
		||||
        return Uri.parse(filterLinkByText ? element.value : link)
 | 
			
		||||
            .path
 | 
			
		||||
            .toLowerCase()
 | 
			
		||||
            .endsWith('.apk');
 | 
			
		||||
      }).toList();
 | 
			
		||||
    }
 | 
			
		||||
    if (!skipSort) {
 | 
			
		||||
      links.sort((a, b) => additionalSettings['sortByLastLinkSegment'] == true
 | 
			
		||||
@@ -309,17 +319,26 @@ class HTML extends AppSource {
 | 
			
		||||
      links = [MapEntry(currentUrl, currentUrl)];
 | 
			
		||||
    }
 | 
			
		||||
    var rel = links.last.key;
 | 
			
		||||
    var relDecoded = rel;
 | 
			
		||||
    try {
 | 
			
		||||
      relDecoded = Uri.decodeFull(rel);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      // Some links may not have valid encoding
 | 
			
		||||
    }
 | 
			
		||||
    String? version;
 | 
			
		||||
    version = extractVersion(
 | 
			
		||||
        additionalSettings['versionExtractionRegEx'] as String?,
 | 
			
		||||
        additionalSettings['matchGroupToUse'] as String?,
 | 
			
		||||
        additionalSettings['versionExtractWholePage'] == true
 | 
			
		||||
            ? versionExtractionWholePageString
 | 
			
		||||
            : rel);
 | 
			
		||||
    version ??=
 | 
			
		||||
        additionalSettings['defaultPseudoVersioningMethod'] == 'APKLinkHash'
 | 
			
		||||
            ? rel.hashCode.toString()
 | 
			
		||||
            : (await checkPartialDownloadHashDynamic(rel)).toString();
 | 
			
		||||
            : relDecoded);
 | 
			
		||||
    version ??= additionalSettings['defaultPseudoVersioningMethod'] ==
 | 
			
		||||
            'APKLinkHash'
 | 
			
		||||
        ? rel.hashCode.toString()
 | 
			
		||||
        : (await checkPartialDownloadHashDynamic(rel,
 | 
			
		||||
                headers: await getRequestHeaders(additionalSettings,
 | 
			
		||||
                    forAPKDownload: true)))
 | 
			
		||||
            .toString();
 | 
			
		||||
    return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(),
 | 
			
		||||
        AppNames(uri.host, tr('app')));
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ import 'package:obtainium/providers/source_provider.dart';
 | 
			
		||||
class HuaweiAppGallery extends AppSource {
 | 
			
		||||
  HuaweiAppGallery() {
 | 
			
		||||
    name = 'Huawei AppGallery';
 | 
			
		||||
    hosts = ['appgallery.huawei.com'];
 | 
			
		||||
    hosts = ['appgallery.huawei.com', 'appgallery.cloud.huawei.com'];
 | 
			
		||||
    versionDetectionDisallowed = true;
 | 
			
		||||
    showReleaseDateAsVersionToggle = true;
 | 
			
		||||
  }
 | 
			
		||||
@@ -14,7 +14,7 @@ class HuaweiAppGallery extends AppSource {
 | 
			
		||||
  @override
 | 
			
		||||
  String sourceSpecificStandardizeURL(String url) {
 | 
			
		||||
    RegExp standardUrlRegEx = RegExp(
 | 
			
		||||
        '^https?://(www\\.)?${getSourceRegex(hosts)}/app/[^/]+',
 | 
			
		||||
        '^https?://(www\\.)?${getSourceRegex(hosts)}(/#)?/(app|appdl)/[^/]+',
 | 
			
		||||
        caseSensitive: false);
 | 
			
		||||
    RegExpMatch? match = standardUrlRegEx.firstMatch(url);
 | 
			
		||||
    if (match == null) {
 | 
			
		||||
@@ -24,7 +24,7 @@ class HuaweiAppGallery extends AppSource {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getDlUrl(String standardUrl) =>
 | 
			
		||||
      'https://${hosts[0].replaceAll('appgallery.', 'appgallery.cloud.')}/appdl/${standardUrl.split('/').last}';
 | 
			
		||||
      'https://${hosts[0].replaceAll('appgallery.huawei', 'appgallery.cloud.huawei')}/appdl/${standardUrl.split('/').last}';
 | 
			
		||||
 | 
			
		||||
  requestAppdlRedirect(
 | 
			
		||||
      String dlUrl, Map<String, dynamic> additionalSettings) async {
 | 
			
		||||
@@ -73,21 +73,23 @@ class HuaweiAppGallery extends AppSource {
 | 
			
		||||
      throw NoReleasesError();
 | 
			
		||||
    }
 | 
			
		||||
    String appId = appIdFromRedirectDlUrl(res.headers['location']!);
 | 
			
		||||
    if (appId.isEmpty) {
 | 
			
		||||
      throw NoReleasesError();
 | 
			
		||||
    }
 | 
			
		||||
    var relDateStr =
 | 
			
		||||
        res.headers['location']?.split('?')[0].split('.').reversed.toList()[1];
 | 
			
		||||
    var relDateStrAdj = relDateStr?.split('');
 | 
			
		||||
    var tempLen = relDateStrAdj?.length ?? 0;
 | 
			
		||||
    var i = 2;
 | 
			
		||||
    while (i < tempLen) {
 | 
			
		||||
      relDateStrAdj?.insert((i + i ~/ 2 - 1), '-');
 | 
			
		||||
      i += 2;
 | 
			
		||||
    }
 | 
			
		||||
    var relDate = relDateStrAdj == null
 | 
			
		||||
        ? null
 | 
			
		||||
        : DateFormat('yy-MM-dd-HH-mm').parse(relDateStrAdj.join(''));
 | 
			
		||||
    if (relDateStr == null) {
 | 
			
		||||
    if (relDateStr == null || relDateStr.length != 10) {
 | 
			
		||||
      throw NoVersionError();
 | 
			
		||||
    }
 | 
			
		||||
    var relDateStrAdj = relDateStr.split('');
 | 
			
		||||
    var tempLen = relDateStrAdj.length;
 | 
			
		||||
    var i = 2;
 | 
			
		||||
    while (i < tempLen) {
 | 
			
		||||
      relDateStrAdj.insert((i + i ~/ 2 - 1), '-');
 | 
			
		||||
      i += 2;
 | 
			
		||||
    }
 | 
			
		||||
    var relDate =
 | 
			
		||||
        DateFormat('yy-MM-dd-HH-mm', 'en_US').parse(relDateStrAdj.join(''));
 | 
			
		||||
    return APKDetails(
 | 
			
		||||
        relDateStr, [MapEntry('$appId.apk', dlUrl)], AppNames(name, appId),
 | 
			
		||||
        releaseDate: relDate);
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import 'package:easy_localization/easy_localization.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:obtainium/components/generated_form_modal.dart';
 | 
			
		||||
import 'package:obtainium/providers/source_provider.dart';
 | 
			
		||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
 | 
			
		||||
 | 
			
		||||
abstract class GeneratedFormItem {
 | 
			
		||||
  late String key;
 | 
			
		||||
@@ -28,6 +29,7 @@ class GeneratedFormTextField extends GeneratedFormItem {
 | 
			
		||||
  late String? hint;
 | 
			
		||||
  late bool password;
 | 
			
		||||
  late TextInputType? textInputType;
 | 
			
		||||
  late List<String>? autoCompleteOptions;
 | 
			
		||||
 | 
			
		||||
  GeneratedFormTextField(super.key,
 | 
			
		||||
      {super.label,
 | 
			
		||||
@@ -39,7 +41,8 @@ class GeneratedFormTextField extends GeneratedFormItem {
 | 
			
		||||
      this.max = 1,
 | 
			
		||||
      this.hint,
 | 
			
		||||
      this.password = false,
 | 
			
		||||
      this.textInputType});
 | 
			
		||||
      this.textInputType,
 | 
			
		||||
      this.autoCompleteOptions});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  String ensureType(val) {
 | 
			
		||||
@@ -245,8 +248,8 @@ class _GeneratedFormState extends State<GeneratedForm> {
 | 
			
		||||
  void someValueChanged({bool isBuilding = false, bool forceInvalid = false}) {
 | 
			
		||||
    Map<String, dynamic> returnValues = values;
 | 
			
		||||
    var valid = true;
 | 
			
		||||
    for (int r = 0; r < widget.items.length; r++) {
 | 
			
		||||
      for (int i = 0; i < widget.items[r].length; i++) {
 | 
			
		||||
    for (int r = 0; r < formInputs.length; r++) {
 | 
			
		||||
      for (int i = 0; i < formInputs[r].length; i++) {
 | 
			
		||||
        if (formInputs[r][i] is TextFormField) {
 | 
			
		||||
          valid = valid && validateTextField(formInputs[r][i] as TextFormField);
 | 
			
		||||
        }
 | 
			
		||||
@@ -274,38 +277,62 @@ class _GeneratedFormState extends State<GeneratedForm> {
 | 
			
		||||
        var formItem = e.value;
 | 
			
		||||
        if (formItem is GeneratedFormTextField) {
 | 
			
		||||
          final formFieldKey = GlobalKey<FormFieldState>();
 | 
			
		||||
          return TextFormField(
 | 
			
		||||
            keyboardType: formItem.textInputType,
 | 
			
		||||
            obscureText: formItem.password,
 | 
			
		||||
            autocorrect: !formItem.password,
 | 
			
		||||
            enableSuggestions: !formItem.password,
 | 
			
		||||
            key: formFieldKey,
 | 
			
		||||
            initialValue: values[formItem.key],
 | 
			
		||||
            autovalidateMode: AutovalidateMode.onUserInteraction,
 | 
			
		||||
            onChanged: (value) {
 | 
			
		||||
          var ctrl = TextEditingController(text: values[formItem.key]);
 | 
			
		||||
          return TypeAheadField<String>(
 | 
			
		||||
            controller: ctrl,
 | 
			
		||||
            builder: (context, controller, focusNode) {
 | 
			
		||||
              return TextFormField(
 | 
			
		||||
                controller: ctrl,
 | 
			
		||||
                focusNode: focusNode,
 | 
			
		||||
                keyboardType: formItem.textInputType,
 | 
			
		||||
                obscureText: formItem.password,
 | 
			
		||||
                autocorrect: !formItem.password,
 | 
			
		||||
                enableSuggestions: !formItem.password,
 | 
			
		||||
                key: formFieldKey,
 | 
			
		||||
                autovalidateMode: AutovalidateMode.onUserInteraction,
 | 
			
		||||
                onChanged: (value) {
 | 
			
		||||
                  setState(() {
 | 
			
		||||
                    values[formItem.key] = value;
 | 
			
		||||
                    someValueChanged();
 | 
			
		||||
                  });
 | 
			
		||||
                },
 | 
			
		||||
                decoration: InputDecoration(
 | 
			
		||||
                    helperText:
 | 
			
		||||
                        formItem.label + (formItem.required ? ' *' : ''),
 | 
			
		||||
                    hintText: formItem.hint),
 | 
			
		||||
                minLines: formItem.max <= 1 ? null : formItem.max,
 | 
			
		||||
                maxLines: formItem.max <= 1 ? 1 : formItem.max,
 | 
			
		||||
                validator: (value) {
 | 
			
		||||
                  if (formItem.required &&
 | 
			
		||||
                      (value == null || value.trim().isEmpty)) {
 | 
			
		||||
                    return '${formItem.label} ${tr('requiredInBrackets')}';
 | 
			
		||||
                  }
 | 
			
		||||
                  for (var validator in formItem.additionalValidators) {
 | 
			
		||||
                    String? result = validator(value);
 | 
			
		||||
                    if (result != null) {
 | 
			
		||||
                      return result;
 | 
			
		||||
                    }
 | 
			
		||||
                  }
 | 
			
		||||
                  return null;
 | 
			
		||||
                },
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
            itemBuilder: (context, value) {
 | 
			
		||||
              return ListTile(title: Text(value));
 | 
			
		||||
            },
 | 
			
		||||
            onSelected: (value) {
 | 
			
		||||
              ctrl.text = value;
 | 
			
		||||
              setState(() {
 | 
			
		||||
                values[formItem.key] = value;
 | 
			
		||||
                someValueChanged();
 | 
			
		||||
              });
 | 
			
		||||
            },
 | 
			
		||||
            decoration: InputDecoration(
 | 
			
		||||
                helperText: formItem.label + (formItem.required ? ' *' : ''),
 | 
			
		||||
                hintText: formItem.hint),
 | 
			
		||||
            minLines: formItem.max <= 1 ? null : formItem.max,
 | 
			
		||||
            maxLines: formItem.max <= 1 ? 1 : formItem.max,
 | 
			
		||||
            validator: (value) {
 | 
			
		||||
              if (formItem.required &&
 | 
			
		||||
                  (value == null || value.trim().isEmpty)) {
 | 
			
		||||
                return '${formItem.label} ${tr('requiredInBrackets')}';
 | 
			
		||||
              }
 | 
			
		||||
              for (var validator in formItem.additionalValidators) {
 | 
			
		||||
                String? result = validator(value);
 | 
			
		||||
                if (result != null) {
 | 
			
		||||
                  return result;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              return null;
 | 
			
		||||
            suggestionsCallback: (search) {
 | 
			
		||||
              return formItem.autoCompleteOptions
 | 
			
		||||
                  ?.where((t) => t.toLowerCase().contains(search.toLowerCase()))
 | 
			
		||||
                  .toList();
 | 
			
		||||
            },
 | 
			
		||||
            hideOnEmpty: true,
 | 
			
		||||
          );
 | 
			
		||||
        } else if (formItem is GeneratedFormDropdown) {
 | 
			
		||||
          if (formItem.opts!.isEmpty) {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
 | 
			
		||||
import 'package:obtainium/pages/home.dart';
 | 
			
		||||
import 'package:obtainium/providers/apps_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/logs_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/native_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/notifications_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/settings_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/source_provider.dart';
 | 
			
		||||
@@ -39,6 +40,7 @@ List<MapEntry<Locale, String>> supportedLocales = const [
 | 
			
		||||
  MapEntry(Locale('vi'), 'Tiếng Việt'),
 | 
			
		||||
  MapEntry(Locale('tr'), 'Türkçe'),
 | 
			
		||||
  MapEntry(Locale('uk'), 'Українська'),
 | 
			
		||||
  MapEntry(Locale('da'), 'Dansk'),
 | 
			
		||||
];
 | 
			
		||||
const fallbackLocale = Locale('en');
 | 
			
		||||
const localeDir = 'assets/translations';
 | 
			
		||||
@@ -118,8 +120,6 @@ void main() async {
 | 
			
		||||
  BackgroundFetch.registerHeadlessTask(backgroundFetchHeadlessTask);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var defaultThemeColour = Colors.deepPurple;
 | 
			
		||||
 | 
			
		||||
class Obtainium extends StatefulWidget {
 | 
			
		||||
  const Obtainium({super.key});
 | 
			
		||||
 | 
			
		||||
@@ -215,22 +215,25 @@ class _ObtainiumState extends State<Obtainium> {
 | 
			
		||||
      ColorScheme darkColorScheme;
 | 
			
		||||
      if (lightDynamic != null &&
 | 
			
		||||
          darkDynamic != null &&
 | 
			
		||||
          settingsProvider.colour == ColourSettings.materialYou) {
 | 
			
		||||
          settingsProvider.useMaterialYou) {
 | 
			
		||||
        lightColorScheme = lightDynamic.harmonized();
 | 
			
		||||
        darkColorScheme = darkDynamic.harmonized();
 | 
			
		||||
      } else {
 | 
			
		||||
        lightColorScheme = ColorScheme.fromSeed(seedColor: defaultThemeColour);
 | 
			
		||||
        lightColorScheme =
 | 
			
		||||
            ColorScheme.fromSeed(seedColor: settingsProvider.themeColor);
 | 
			
		||||
        darkColorScheme = ColorScheme.fromSeed(
 | 
			
		||||
            seedColor: defaultThemeColour, brightness: Brightness.dark);
 | 
			
		||||
            seedColor: settingsProvider.themeColor,
 | 
			
		||||
            brightness: Brightness.dark);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // set the background and surface colors to pure black in the amoled theme
 | 
			
		||||
      if (settingsProvider.useBlackTheme) {
 | 
			
		||||
        darkColorScheme = darkColorScheme
 | 
			
		||||
            .copyWith(background: Colors.black, surface: Colors.black)
 | 
			
		||||
            .harmonized();
 | 
			
		||||
        darkColorScheme =
 | 
			
		||||
            darkColorScheme.copyWith(surface: Colors.black).harmonized();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (settingsProvider.useSystemFont) NativeFeatures.loadSystemFont();
 | 
			
		||||
 | 
			
		||||
      return MaterialApp(
 | 
			
		||||
          title: 'Obtainium',
 | 
			
		||||
          localizationsDelegates: context.localizationDelegates,
 | 
			
		||||
 
 | 
			
		||||
@@ -51,10 +51,13 @@ class AddAppPageState extends State<AddAppPage> {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  changeUserInput(String input, bool valid, bool isBuilding,
 | 
			
		||||
      {bool updateUrlInput = false}) {
 | 
			
		||||
      {bool updateUrlInput = false, String? overrideSource}) {
 | 
			
		||||
    userInput = input;
 | 
			
		||||
    if (!isBuilding) {
 | 
			
		||||
      setState(() {
 | 
			
		||||
        if (overrideSource != null) {
 | 
			
		||||
          pickedSourceOverride = overrideSource;
 | 
			
		||||
        }
 | 
			
		||||
        if (updateUrlInput) {
 | 
			
		||||
          urlInputKey++;
 | 
			
		||||
        }
 | 
			
		||||
@@ -68,6 +71,7 @@ class AddAppPageState extends State<AddAppPage> {
 | 
			
		||||
        if (pickedSource.runtimeType != source.runtimeType ||
 | 
			
		||||
            (prevHost != null && prevHost != source?.hosts[0])) {
 | 
			
		||||
          pickedSource = source;
 | 
			
		||||
          pickedSource?.runOnAddAppInputChange(userInput);
 | 
			
		||||
          additionalSettings = source != null
 | 
			
		||||
              ? getDefaultValuesFromFormItems(
 | 
			
		||||
                  source.combinedAppSpecificSettingFormItems)
 | 
			
		||||
@@ -155,7 +159,8 @@ class AddAppPageState extends State<AddAppPage> {
 | 
			
		||||
          // Only download the APK here if you need to for the package ID
 | 
			
		||||
          if (isTempId(app) && app.additionalSettings['trackOnly'] != true) {
 | 
			
		||||
            // ignore: use_build_context_synchronously
 | 
			
		||||
            var apkUrl = await appsProvider.confirmApkUrl(app, context);
 | 
			
		||||
            var apkUrl =
 | 
			
		||||
                await appsProvider.confirmAppFileUrl(app, context, false);
 | 
			
		||||
            if (apkUrl == null) {
 | 
			
		||||
              throw ObtainiumError(tr('cancelled'));
 | 
			
		||||
            }
 | 
			
		||||
@@ -258,9 +263,7 @@ class AddAppPageState extends State<AddAppPage> {
 | 
			
		||||
        searching = true;
 | 
			
		||||
      });
 | 
			
		||||
      var sourceStrings = <String, List<String>>{};
 | 
			
		||||
      sourceProvider.sources
 | 
			
		||||
          .where((e) => e.canSearch && !e.excludeFromMassSearch)
 | 
			
		||||
          .forEach((s) {
 | 
			
		||||
      sourceProvider.sources.where((e) => e.canSearch).forEach((s) {
 | 
			
		||||
        sourceStrings[s.name] = [s.name];
 | 
			
		||||
      });
 | 
			
		||||
      try {
 | 
			
		||||
@@ -281,32 +284,78 @@ class AddAppPageState extends State<AddAppPage> {
 | 
			
		||||
          settingsProvider.searchDeselected = sourceStrings.keys
 | 
			
		||||
              .where((s) => !searchSources.contains(s))
 | 
			
		||||
              .toList();
 | 
			
		||||
          var results = await Future.wait(sourceProvider.sources
 | 
			
		||||
              .where((e) => searchSources.contains(e.name))
 | 
			
		||||
              .map((e) async {
 | 
			
		||||
          List<MapEntry<String, Map<String, List<String>>>?> results =
 | 
			
		||||
              (await Future.wait(sourceProvider.sources
 | 
			
		||||
                      .where((e) => searchSources.contains(e.name))
 | 
			
		||||
                      .map((e) async {
 | 
			
		||||
            try {
 | 
			
		||||
              return await e.search(searchQuery);
 | 
			
		||||
              Map<String, dynamic>? querySettings = {};
 | 
			
		||||
              if (e.includeAdditionalOptsInMainSearch) {
 | 
			
		||||
                querySettings = await showDialog<Map<String, dynamic>?>(
 | 
			
		||||
                    context: context,
 | 
			
		||||
                    builder: (BuildContext ctx) {
 | 
			
		||||
                      return GeneratedFormModal(
 | 
			
		||||
                        title: tr('searchX', args: [e.name]),
 | 
			
		||||
                        items: [
 | 
			
		||||
                          ...e.searchQuerySettingFormItems.map((e) => [e]),
 | 
			
		||||
                          [
 | 
			
		||||
                            GeneratedFormTextField('url',
 | 
			
		||||
                                label: e.hosts.isNotEmpty
 | 
			
		||||
                                    ? tr('overrideSource')
 | 
			
		||||
                                    : plural('url', 1).substring(2),
 | 
			
		||||
                                autoCompleteOptions: [
 | 
			
		||||
                                  ...(e.hosts.isNotEmpty ? [e.hosts[0]] : []),
 | 
			
		||||
                                  ...appsProvider.apps.values
 | 
			
		||||
                                      .where((a) =>
 | 
			
		||||
                                          sourceProvider
 | 
			
		||||
                                              .getSource(a.app.url,
 | 
			
		||||
                                                  overrideSource:
 | 
			
		||||
                                                      a.app.overrideSource)
 | 
			
		||||
                                              .runtimeType ==
 | 
			
		||||
                                          e.runtimeType)
 | 
			
		||||
                                      .map((a) {
 | 
			
		||||
                                    var uri = Uri.parse(a.app.url);
 | 
			
		||||
                                    return '${uri.origin}${uri.path}';
 | 
			
		||||
                                  })
 | 
			
		||||
                                ],
 | 
			
		||||
                                defaultValue:
 | 
			
		||||
                                    e.hosts.isNotEmpty ? e.hosts[0] : '',
 | 
			
		||||
                                required: true)
 | 
			
		||||
                          ],
 | 
			
		||||
                        ],
 | 
			
		||||
                      );
 | 
			
		||||
                    });
 | 
			
		||||
                if (querySettings == null) {
 | 
			
		||||
                  return null;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              return MapEntry(e.runtimeType.toString(),
 | 
			
		||||
                  await e.search(searchQuery, querySettings: querySettings));
 | 
			
		||||
            } catch (err) {
 | 
			
		||||
              if (err is! CredsNeededError) {
 | 
			
		||||
                rethrow;
 | 
			
		||||
              } else {
 | 
			
		||||
                err.unexpected = true;
 | 
			
		||||
                showError(err, context);
 | 
			
		||||
                return <String, List<String>>{};
 | 
			
		||||
                return null;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }));
 | 
			
		||||
          })))
 | 
			
		||||
                  .where((a) => a != null)
 | 
			
		||||
                  .toList();
 | 
			
		||||
 | 
			
		||||
          // Interleave results instead of simple reduce
 | 
			
		||||
          Map<String, List<String>> res = {};
 | 
			
		||||
          Map<String, MapEntry<String, List<String>>> res = {};
 | 
			
		||||
          var si = 0;
 | 
			
		||||
          var done = false;
 | 
			
		||||
          while (!done) {
 | 
			
		||||
            done = true;
 | 
			
		||||
            for (var r in results) {
 | 
			
		||||
              if (r.length > si) {
 | 
			
		||||
              var sourceName = r!.key;
 | 
			
		||||
              if (r.value.length > si) {
 | 
			
		||||
                done = false;
 | 
			
		||||
                res.addEntries([r.entries.elementAt(si)]);
 | 
			
		||||
                var singleRes = r.value.entries.elementAt(si);
 | 
			
		||||
                res[singleRes.key] = MapEntry(sourceName, singleRes.value);
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            si++;
 | 
			
		||||
@@ -321,13 +370,15 @@ class AddAppPageState extends State<AddAppPage> {
 | 
			
		||||
                  context: context,
 | 
			
		||||
                  builder: (BuildContext ctx) {
 | 
			
		||||
                    return SelectionModal(
 | 
			
		||||
                      entries: res,
 | 
			
		||||
                      entries: res.map((k, v) => MapEntry(k, v.value)),
 | 
			
		||||
                      selectedByDefault: false,
 | 
			
		||||
                      onlyOneSelectionAllowed: true,
 | 
			
		||||
                    );
 | 
			
		||||
                  });
 | 
			
		||||
          if (selectedUrls != null && selectedUrls.isNotEmpty) {
 | 
			
		||||
            changeUserInput(selectedUrls[0], true, false, updateUrlInput: true);
 | 
			
		||||
            var sourceName = res[selectedUrls[0]]?.key;
 | 
			
		||||
            changeUserInput(selectedUrls[0], true, false,
 | 
			
		||||
                updateUrlInput: true, overrideSource: sourceName);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
@@ -348,7 +399,7 @@ class AddAppPageState extends State<AddAppPage> {
 | 
			
		||||
                  [
 | 
			
		||||
                    GeneratedFormDropdown(
 | 
			
		||||
                        'overrideSource',
 | 
			
		||||
                        defaultValue: '',
 | 
			
		||||
                        defaultValue: pickedSourceOverride ?? '',
 | 
			
		||||
                        [
 | 
			
		||||
                          MapEntry('', tr('none')),
 | 
			
		||||
                          ...sourceProvider.sources.map(
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
 | 
			
		||||
import 'package:obtainium/components/generated_form_modal.dart';
 | 
			
		||||
import 'package:obtainium/custom_errors.dart';
 | 
			
		||||
import 'package:obtainium/main.dart';
 | 
			
		||||
import 'package:obtainium/pages/apps.dart';
 | 
			
		||||
import 'package:obtainium/pages/settings.dart';
 | 
			
		||||
import 'package:obtainium/providers/apps_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/settings_provider.dart';
 | 
			
		||||
@@ -108,6 +109,7 @@ class _AppPageState extends State<AppPage> {
 | 
			
		||||
        infoLines =
 | 
			
		||||
            '$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(
 | 
			
		||||
        mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
        crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
			
		||||
@@ -125,13 +127,26 @@ class _AppPageState extends State<AppPage> {
 | 
			
		||||
                        .textTheme
 | 
			
		||||
                        .bodyLarge!
 | 
			
		||||
                        .copyWith(fontWeight: FontWeight.bold)),
 | 
			
		||||
                app?.app.releaseDate == null
 | 
			
		||||
                    ? const SizedBox.shrink()
 | 
			
		||||
                    : Text(
 | 
			
		||||
                        app!.app.releaseDate.toString(),
 | 
			
		||||
                        textAlign: TextAlign.center,
 | 
			
		||||
                        style: Theme.of(context).textTheme.labelSmall,
 | 
			
		||||
                      ),
 | 
			
		||||
                changeLogFn != null || app?.app.releaseDate != null
 | 
			
		||||
                    ? GestureDetector(
 | 
			
		||||
                        onTap: changeLogFn,
 | 
			
		||||
                        child: Text(
 | 
			
		||||
                          app?.app.releaseDate == null
 | 
			
		||||
                              ? tr('changes')
 | 
			
		||||
                              : app!.app.releaseDate!.toLocal().toString(),
 | 
			
		||||
                          textAlign: TextAlign.center,
 | 
			
		||||
                          style:
 | 
			
		||||
                              Theme.of(context).textTheme.labelSmall!.copyWith(
 | 
			
		||||
                                    decoration: changeLogFn != null
 | 
			
		||||
                                        ? TextDecoration.underline
 | 
			
		||||
                                        : null,
 | 
			
		||||
                                    fontStyle: changeLogFn != null
 | 
			
		||||
                                        ? FontStyle.italic
 | 
			
		||||
                                        : null,
 | 
			
		||||
                                  ),
 | 
			
		||||
                        ),
 | 
			
		||||
                      )
 | 
			
		||||
                    : const SizedBox.shrink(),
 | 
			
		||||
                const SizedBox(
 | 
			
		||||
                  height: 8,
 | 
			
		||||
                ),
 | 
			
		||||
@@ -143,6 +158,49 @@ class _AppPageState extends State<AppPage> {
 | 
			
		||||
            textAlign: TextAlign.center,
 | 
			
		||||
            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: Row(
 | 
			
		||||
                  mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
                  children: [
 | 
			
		||||
                    Container(
 | 
			
		||||
                        decoration: BoxDecoration(
 | 
			
		||||
                            borderRadius: BorderRadius.circular(12),
 | 
			
		||||
                            color: settingsProvider.highlightTouchTargets
 | 
			
		||||
                                ? (Theme.of(context).brightness ==
 | 
			
		||||
                                            Brightness.light
 | 
			
		||||
                                        ? Theme.of(context).primaryColor
 | 
			
		||||
                                        : Theme.of(context).primaryColorLight)
 | 
			
		||||
                                    .withAlpha(20)
 | 
			
		||||
                                : null),
 | 
			
		||||
                        padding: settingsProvider.highlightTouchTargets
 | 
			
		||||
                            ? const EdgeInsetsDirectional.fromSTEB(12, 6, 12, 6)
 | 
			
		||||
                            : const EdgeInsetsDirectional.fromSTEB(0, 6, 0, 6),
 | 
			
		||||
                        margin:
 | 
			
		||||
                            const EdgeInsetsDirectional.fromSTEB(0, 6, 0, 0),
 | 
			
		||||
                        child: Text(
 | 
			
		||||
                          tr('downloadX',
 | 
			
		||||
                              args: [tr('releaseAsset').toLowerCase()]),
 | 
			
		||||
                          textAlign: TextAlign.center,
 | 
			
		||||
                          style:
 | 
			
		||||
                              Theme.of(context).textTheme.labelSmall!.copyWith(
 | 
			
		||||
                                    decoration: TextDecoration.underline,
 | 
			
		||||
                                    fontStyle: FontStyle.italic,
 | 
			
		||||
                                  ),
 | 
			
		||||
                        ))
 | 
			
		||||
                  ],
 | 
			
		||||
                )),
 | 
			
		||||
          const SizedBox(
 | 
			
		||||
            height: 48,
 | 
			
		||||
          ),
 | 
			
		||||
@@ -189,18 +247,26 @@ class _AppPageState extends State<AppPage> {
 | 
			
		||||
          crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
			
		||||
          children: [
 | 
			
		||||
            const SizedBox(height: 20),
 | 
			
		||||
            app?.icon != null
 | 
			
		||||
                ? Row(mainAxisAlignment: MainAxisAlignment.center, children: [
 | 
			
		||||
                    GestureDetector(
 | 
			
		||||
                      child: Image.memory(
 | 
			
		||||
                        app!.icon!,
 | 
			
		||||
                        height: 150,
 | 
			
		||||
                        gaplessPlayback: true,
 | 
			
		||||
                      ),
 | 
			
		||||
                      onTap: () => pm.openApp(app.app.id),
 | 
			
		||||
                    )
 | 
			
		||||
                  ])
 | 
			
		||||
                : Container(),
 | 
			
		||||
            FutureBuilder(
 | 
			
		||||
                future: appsProvider.updateAppIcon(app?.app.id),
 | 
			
		||||
                builder: (ctx, val) {
 | 
			
		||||
                  return app?.icon != null
 | 
			
		||||
                      ? Row(
 | 
			
		||||
                          mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
                          children: [
 | 
			
		||||
                              GestureDetector(
 | 
			
		||||
                                onTap: app == null
 | 
			
		||||
                                    ? null
 | 
			
		||||
                                    : () => pm.openApp(app.app.id),
 | 
			
		||||
                                child: Image.memory(
 | 
			
		||||
                                  app!.icon!,
 | 
			
		||||
                                  height: 150,
 | 
			
		||||
                                  gaplessPlayback: true,
 | 
			
		||||
                                ),
 | 
			
		||||
                              )
 | 
			
		||||
                            ])
 | 
			
		||||
                      : Container();
 | 
			
		||||
                }),
 | 
			
		||||
            const SizedBox(
 | 
			
		||||
              height: 25,
 | 
			
		||||
            ),
 | 
			
		||||
@@ -249,7 +315,7 @@ class _AppPageState extends State<AppPage> {
 | 
			
		||||
        ? WebViewWidget(
 | 
			
		||||
            controller: WebViewController()
 | 
			
		||||
              ..setJavaScriptMode(JavaScriptMode.unrestricted)
 | 
			
		||||
              ..setBackgroundColor(Theme.of(context).colorScheme.background)
 | 
			
		||||
              ..setBackgroundColor(Theme.of(context).colorScheme.surface)
 | 
			
		||||
              ..setJavaScriptMode(JavaScriptMode.unrestricted)
 | 
			
		||||
              ..setNavigationDelegate(
 | 
			
		||||
                NavigationDelegate(
 | 
			
		||||
@@ -361,6 +427,9 @@ class _AppPageState extends State<AppPage> {
 | 
			
		||||
                !areDownloadsRunning
 | 
			
		||||
            ? () async {
 | 
			
		||||
                try {
 | 
			
		||||
                  var successMessage = app?.app.installedVersion == null
 | 
			
		||||
                      ? tr('installed')
 | 
			
		||||
                      : tr('appsUpdated');
 | 
			
		||||
                  HapticFeedback.heavyImpact();
 | 
			
		||||
                  var res = await appsProvider.downloadAndInstallLatestApps(
 | 
			
		||||
                    app?.app.id != null ? [app!.app.id] : [],
 | 
			
		||||
@@ -368,7 +437,7 @@ class _AppPageState extends State<AppPage> {
 | 
			
		||||
                  );
 | 
			
		||||
                  if (res.isNotEmpty && !trackOnly) {
 | 
			
		||||
                    // ignore: use_build_context_synchronously
 | 
			
		||||
                    showMessage(tr('appsUpdated'), context);
 | 
			
		||||
                    showMessage(successMessage, context);
 | 
			
		||||
                  }
 | 
			
		||||
                  if (res.isNotEmpty && mounted) {
 | 
			
		||||
                    Navigator.of(context).pop();
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,92 @@ class AppsPage extends StatefulWidget {
 | 
			
		||||
  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> {
 | 
			
		||||
  AppsFilter filter = AppsFilter();
 | 
			
		||||
  final AppsFilter neutralFilter = AppsFilter();
 | 
			
		||||
@@ -57,11 +143,14 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
  final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
 | 
			
		||||
      GlobalKey<RefreshIndicatorState>();
 | 
			
		||||
 | 
			
		||||
  late final ScrollController scrollController = ScrollController();
 | 
			
		||||
 | 
			
		||||
  var sourceProvider = SourceProvider();
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    var appsProvider = context.watch<AppsProvider>();
 | 
			
		||||
    var settingsProvider = context.watch<SettingsProvider>();
 | 
			
		||||
    var sourceProvider = SourceProvider();
 | 
			
		||||
    var listedApps = appsProvider.getAppValues().toList();
 | 
			
		||||
 | 
			
		||||
    refresh() {
 | 
			
		||||
@@ -262,73 +351,17 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
        .where((a) => selectedAppIds.contains(a.id))
 | 
			
		||||
        .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() {
 | 
			
		||||
      return [
 | 
			
		||||
        if (listedApps.isEmpty)
 | 
			
		||||
          SliverFillRemaining(
 | 
			
		||||
              child: Center(
 | 
			
		||||
                  child: Text(
 | 
			
		||||
            appsProvider.apps.isEmpty ? tr('noApps') : tr('noAppsForFilter'),
 | 
			
		||||
            appsProvider.apps.isEmpty
 | 
			
		||||
                ? appsProvider.loadingApps
 | 
			
		||||
                    ? tr('pleaseWait')
 | 
			
		||||
                    : tr('noApps')
 | 
			
		||||
                : tr('noAppsForFilter'),
 | 
			
		||||
            style: Theme.of(context).textTheme.headlineMedium,
 | 
			
		||||
            textAlign: TextAlign.center,
 | 
			
		||||
          ))),
 | 
			
		||||
@@ -351,35 +384,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) {
 | 
			
		||||
      return IconButton(
 | 
			
		||||
          visualDensity: VisualDensity.compact,
 | 
			
		||||
@@ -405,29 +409,36 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getAppIcon(int appIndex) {
 | 
			
		||||
      return listedApps[appIndex].icon != null
 | 
			
		||||
          ? Image.memory(
 | 
			
		||||
              listedApps[appIndex].icon!,
 | 
			
		||||
              gaplessPlayback: true,
 | 
			
		||||
            )
 | 
			
		||||
          : Row(
 | 
			
		||||
              mainAxisSize: MainAxisSize.min,
 | 
			
		||||
              mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
              children: [
 | 
			
		||||
                  Transform(
 | 
			
		||||
                      alignment: Alignment.center,
 | 
			
		||||
                      transform: Matrix4.rotationZ(0.31),
 | 
			
		||||
                      child: Padding(
 | 
			
		||||
                        padding: const EdgeInsets.all(15),
 | 
			
		||||
                        child: Image(
 | 
			
		||||
                          image: const AssetImage(
 | 
			
		||||
                              'assets/graphics/icon_small.png'),
 | 
			
		||||
                          color: Colors.white.withOpacity(0.3),
 | 
			
		||||
                          colorBlendMode: BlendMode.modulate,
 | 
			
		||||
                          gaplessPlayback: true,
 | 
			
		||||
                        ),
 | 
			
		||||
                      )),
 | 
			
		||||
                ]);
 | 
			
		||||
      return FutureBuilder(
 | 
			
		||||
          future: appsProvider.updateAppIcon(listedApps[appIndex].app.id),
 | 
			
		||||
          builder: (ctx, val) {
 | 
			
		||||
            return listedApps[appIndex].icon != null
 | 
			
		||||
                ? Image.memory(
 | 
			
		||||
                    listedApps[appIndex].icon!,
 | 
			
		||||
                    gaplessPlayback: true,
 | 
			
		||||
                  )
 | 
			
		||||
                : Row(
 | 
			
		||||
                    mainAxisSize: MainAxisSize.min,
 | 
			
		||||
                    mainAxisAlignment: MainAxisAlignment.center,
 | 
			
		||||
                    children: [
 | 
			
		||||
                        Transform(
 | 
			
		||||
                            alignment: Alignment.center,
 | 
			
		||||
                            transform: Matrix4.rotationZ(0.31),
 | 
			
		||||
                            child: Padding(
 | 
			
		||||
                              padding: const EdgeInsets.all(15),
 | 
			
		||||
                              child: Image(
 | 
			
		||||
                                image: const AssetImage(
 | 
			
		||||
                                    'assets/graphics/icon_small.png'),
 | 
			
		||||
                                color: Theme.of(context).brightness ==
 | 
			
		||||
                                        Brightness.dark
 | 
			
		||||
                                    ? Colors.white.withOpacity(0.4)
 | 
			
		||||
                                    : Colors.white.withOpacity(0.3),
 | 
			
		||||
                                colorBlendMode: BlendMode.modulate,
 | 
			
		||||
                                gaplessPlayback: true,
 | 
			
		||||
                              ),
 | 
			
		||||
                            )),
 | 
			
		||||
                      ]);
 | 
			
		||||
          });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getVersionText(int appIndex) {
 | 
			
		||||
@@ -440,11 +451,11 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
              ? tr('changes')
 | 
			
		||||
              : ''
 | 
			
		||||
          : DateFormat('yyyy-MM-dd')
 | 
			
		||||
              .format(listedApps[appIndex].app.releaseDate!);
 | 
			
		||||
              .format(listedApps[appIndex].app.releaseDate!.toLocal());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getSingleAppHorizTile(int index) {
 | 
			
		||||
      var showChangesFn = getChangeLogFn(index);
 | 
			
		||||
      var showChangesFn = getChangeLogFn(context, listedApps[index].app);
 | 
			
		||||
      var hasUpdate = listedApps[index].app.installedVersion != null &&
 | 
			
		||||
          listedApps[index].app.installedVersion !=
 | 
			
		||||
              listedApps[index].app.latestVersion;
 | 
			
		||||
@@ -455,7 +466,7 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
          hasUpdate ? getUpdateButton(index) : const SizedBox.shrink(),
 | 
			
		||||
          hasUpdate
 | 
			
		||||
              ? const SizedBox(
 | 
			
		||||
                  width: 10,
 | 
			
		||||
                  width: 5,
 | 
			
		||||
                )
 | 
			
		||||
              : const SizedBox.shrink(),
 | 
			
		||||
          GestureDetector(
 | 
			
		||||
@@ -506,7 +517,7 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      var transparent =
 | 
			
		||||
          Theme.of(context).colorScheme.background.withAlpha(0).value;
 | 
			
		||||
          Theme.of(context).colorScheme.surface.withAlpha(0).value;
 | 
			
		||||
      List<double> stops = [
 | 
			
		||||
        ...listedApps[index].app.categories.asMap().entries.map(
 | 
			
		||||
            (e) => ((e.key / (listedApps[index].app.categories.length - 1)))),
 | 
			
		||||
@@ -857,69 +868,76 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
              scrollable: true,
 | 
			
		||||
              content: Padding(
 | 
			
		||||
                padding: const EdgeInsets.only(top: 6),
 | 
			
		||||
                child: Row(
 | 
			
		||||
                child: Column(
 | 
			
		||||
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
 | 
			
		||||
                    children: [
 | 
			
		||||
                      IconButton(
 | 
			
		||||
                      TextButton(
 | 
			
		||||
                          onPressed: pinSelectedApps,
 | 
			
		||||
                          child: Text(selectedApps
 | 
			
		||||
                                  .where((element) => element.pinned)
 | 
			
		||||
                                  .isEmpty
 | 
			
		||||
                              ? tr('pinToTop')
 | 
			
		||||
                              : tr('unpinFromTop'))),
 | 
			
		||||
                      const Divider(),
 | 
			
		||||
                      TextButton(
 | 
			
		||||
                          onPressed: () {
 | 
			
		||||
                            String urls = '';
 | 
			
		||||
                            for (var a in selectedApps) {
 | 
			
		||||
                              urls += '${a.url}\n';
 | 
			
		||||
                            }
 | 
			
		||||
                            urls = urls.substring(0, urls.length - 1);
 | 
			
		||||
                            Share.share(urls,
 | 
			
		||||
                                subject: 'Obtainium - ${tr('appsString')}');
 | 
			
		||||
                            Navigator.of(context).pop();
 | 
			
		||||
                          },
 | 
			
		||||
                          child: Text(tr('shareSelectedAppURLs'))),
 | 
			
		||||
                      const Divider(),
 | 
			
		||||
                      TextButton(
 | 
			
		||||
                          onPressed: selectedAppIds.isEmpty
 | 
			
		||||
                              ? null
 | 
			
		||||
                              : () {
 | 
			
		||||
                                  String urls = '';
 | 
			
		||||
                                  for (var a in selectedApps) {
 | 
			
		||||
                                    urls +=
 | 
			
		||||
                                        'https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/${Uri.encodeComponent(jsonEncode({
 | 
			
		||||
                                          'id': a.id,
 | 
			
		||||
                                          'url': a.url,
 | 
			
		||||
                                          'author': a.author,
 | 
			
		||||
                                          'name': a.name,
 | 
			
		||||
                                          'preferredApkIndex':
 | 
			
		||||
                                              a.preferredApkIndex,
 | 
			
		||||
                                          'additionalSettings':
 | 
			
		||||
                                              jsonEncode(a.additionalSettings),
 | 
			
		||||
                                          'overrideSource': a.overrideSource
 | 
			
		||||
                                        }))}\n\n';
 | 
			
		||||
                                  }
 | 
			
		||||
                                  Share.share(urls,
 | 
			
		||||
                                      subject:
 | 
			
		||||
                                          'Obtainium - ${tr('appsString')}');
 | 
			
		||||
                                },
 | 
			
		||||
                          child: Text(tr('shareAppConfigLinks'))),
 | 
			
		||||
                      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,
 | 
			
		||||
                          tooltip: tr('markSelectedAppsUpdated'),
 | 
			
		||||
                          icon: const Icon(Icons.done)),
 | 
			
		||||
                      IconButton(
 | 
			
		||||
                        onPressed: pinSelectedApps,
 | 
			
		||||
                        tooltip: selectedApps
 | 
			
		||||
                                .where((element) => element.pinned)
 | 
			
		||||
                                .isEmpty
 | 
			
		||||
                            ? tr('pinToTop')
 | 
			
		||||
                            : tr('unpinFromTop'),
 | 
			
		||||
                        icon: Icon(selectedApps
 | 
			
		||||
                                .where((element) => element.pinned)
 | 
			
		||||
                                .isEmpty
 | 
			
		||||
                            ? Icons.bookmark_outline_rounded
 | 
			
		||||
                            : Icons.bookmark_remove_outlined),
 | 
			
		||||
                      ),
 | 
			
		||||
                      IconButton(
 | 
			
		||||
                        onPressed: () {
 | 
			
		||||
                          String urls = '';
 | 
			
		||||
                          for (var a in selectedApps) {
 | 
			
		||||
                            urls += '${a.url}\n';
 | 
			
		||||
                          }
 | 
			
		||||
                          urls = urls.substring(0, urls.length - 1);
 | 
			
		||||
                          Share.share(urls,
 | 
			
		||||
                              subject: 'Obtainium - ${tr('appsString')}');
 | 
			
		||||
                          Navigator.of(context).pop();
 | 
			
		||||
                        },
 | 
			
		||||
                        tooltip: tr('shareSelectedAppURLs'),
 | 
			
		||||
                        icon: const Icon(Icons.share_rounded),
 | 
			
		||||
                      ),
 | 
			
		||||
                      IconButton(
 | 
			
		||||
                        onPressed: selectedAppIds.isEmpty
 | 
			
		||||
                            ? null
 | 
			
		||||
                            : () {
 | 
			
		||||
                                String urls =
 | 
			
		||||
                                    '<p>${tr('customLinkMessage')}:</p>\n\n<ul>\n';
 | 
			
		||||
                                for (var a in selectedApps) {
 | 
			
		||||
                                  urls +=
 | 
			
		||||
                                      '    <li><a href="obtainium://app/${Uri.encodeComponent(jsonEncode({
 | 
			
		||||
                                        'id': a.id,
 | 
			
		||||
                                        'url': a.url,
 | 
			
		||||
                                        'author': a.author,
 | 
			
		||||
                                        'name': a.name,
 | 
			
		||||
                                        'preferredApkIndex':
 | 
			
		||||
                                            a.preferredApkIndex,
 | 
			
		||||
                                        'additionalSettings':
 | 
			
		||||
                                            jsonEncode(a.additionalSettings)
 | 
			
		||||
                                      }))}">${a.name}</a></li>\n';
 | 
			
		||||
                                }
 | 
			
		||||
                                urls +=
 | 
			
		||||
                                    '</ul>\n\n<p><a href="$obtainiumUrl">${tr('about')}</a></p>';
 | 
			
		||||
                                Share.share(urls,
 | 
			
		||||
                                    subject: 'Obtainium - ${tr('appsString')}');
 | 
			
		||||
                              },
 | 
			
		||||
                        tooltip: tr('shareAppConfigLinks'),
 | 
			
		||||
                        icon: const Icon(Icons.ios_share),
 | 
			
		||||
                      ),
 | 
			
		||||
                          child: Text(tr('markSelectedAppsUpdated'))),
 | 
			
		||||
                    ]),
 | 
			
		||||
              ),
 | 
			
		||||
            );
 | 
			
		||||
@@ -1083,11 +1101,17 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
      body: RefreshIndicator(
 | 
			
		||||
          key: _refreshIndicatorKey,
 | 
			
		||||
          onRefresh: refresh,
 | 
			
		||||
          child: CustomScrollView(slivers: <Widget>[
 | 
			
		||||
            CustomAppBar(title: tr('appsString')),
 | 
			
		||||
            ...getLoadingWidgets(),
 | 
			
		||||
            getDisplayedList()
 | 
			
		||||
          ])),
 | 
			
		||||
          child: Scrollbar(
 | 
			
		||||
              interactive: true,
 | 
			
		||||
              controller: scrollController,
 | 
			
		||||
              child: CustomScrollView(
 | 
			
		||||
                  physics: const AlwaysScrollableScrollPhysics(),
 | 
			
		||||
                  controller: scrollController,
 | 
			
		||||
                  slivers: <Widget>[
 | 
			
		||||
                    CustomAppBar(title: tr('appsString')),
 | 
			
		||||
                    ...getLoadingWidgets(),
 | 
			
		||||
                    getDisplayedList()
 | 
			
		||||
                  ]))),
 | 
			
		||||
      persistentFooterButtons: appsProvider.apps.isEmpty
 | 
			
		||||
          ? null
 | 
			
		||||
          : [
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ import 'package:obtainium/pages/import_export.dart';
 | 
			
		||||
import 'package:obtainium/pages/settings.dart';
 | 
			
		||||
import 'package:obtainium/providers/apps_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/settings_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/source_provider.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
 | 
			
		||||
class HomePage extends StatefulWidget {
 | 
			
		||||
@@ -102,13 +103,22 @@ class _HomePageState extends State<HomePage> {
 | 
			
		||||
                  }) !=
 | 
			
		||||
              null) {
 | 
			
		||||
            // ignore: use_build_context_synchronously
 | 
			
		||||
            var result = await context.read<AppsProvider>().import(
 | 
			
		||||
                action == 'app'
 | 
			
		||||
                    ? '{ "apps": [$dataStr] }'
 | 
			
		||||
                    : '{ "apps": $dataStr }');
 | 
			
		||||
            var appsProvider = context.read<AppsProvider>();
 | 
			
		||||
            var result = await appsProvider.import(action == 'app'
 | 
			
		||||
                ? '{ "apps": [$dataStr] }'
 | 
			
		||||
                : '{ "apps": $dataStr }');
 | 
			
		||||
            // ignore: use_build_context_synchronously
 | 
			
		||||
            showMessage(
 | 
			
		||||
                tr('importedX', args: [plural('apps', result.key)]), context);
 | 
			
		||||
                tr('importedX', args: [plural('apps', result.key.length)]),
 | 
			
		||||
                context);
 | 
			
		||||
            await appsProvider
 | 
			
		||||
                .checkUpdates(specificIds: result.key.map((e) => e.id).toList())
 | 
			
		||||
                .catchError((e) {
 | 
			
		||||
              if (e is Map && e['errors'] is MultiAppMultiError) {
 | 
			
		||||
                showError(e['errors'].toString(), context);
 | 
			
		||||
              }
 | 
			
		||||
              return <App>[];
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          throw ObtainiumError(tr('unknown'));
 | 
			
		||||
@@ -119,7 +129,7 @@ class _HomePageState extends State<HomePage> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check initial link if app was in cold state (terminated)
 | 
			
		||||
    final appLink = await _appLinks.getInitialAppLink();
 | 
			
		||||
    final appLink = await _appLinks.getInitialLink();
 | 
			
		||||
    if (appLink != null) {
 | 
			
		||||
      await interpretLink(appLink);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
 | 
			
		||||
    var settingsProvider = context.watch<SettingsProvider>();
 | 
			
		||||
 | 
			
		||||
    var outlineButtonStyle = ButtonStyle(
 | 
			
		||||
      shape: MaterialStateProperty.all(
 | 
			
		||||
      shape: WidgetStateProperty.all(
 | 
			
		||||
        StadiumBorder(
 | 
			
		||||
          side: BorderSide(
 | 
			
		||||
            width: 1,
 | 
			
		||||
@@ -144,7 +144,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
 | 
			
		||||
            appsProvider.addMissingCategories(settingsProvider);
 | 
			
		||||
            showMessage(
 | 
			
		||||
                '${tr('importedX', args: [
 | 
			
		||||
                      plural('apps', value.key)
 | 
			
		||||
                      plural('apps', value.key.length)
 | 
			
		||||
                    ])}${value.value ? ' + ${tr('settings')}' : ''}',
 | 
			
		||||
                context);
 | 
			
		||||
          });
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,11 @@
 | 
			
		||||
import 'package:device_info_plus/device_info_plus.dart';
 | 
			
		||||
import 'package:easy_localization/easy_localization.dart';
 | 
			
		||||
import 'package:equations/equations.dart';
 | 
			
		||||
import 'package:flex_color_picker/flex_color_picker.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:obtainium/components/custom_app_bar.dart';
 | 
			
		||||
import 'package:obtainium/components/generated_form.dart';
 | 
			
		||||
import 'package:obtainium/components/generated_form_modal.dart';
 | 
			
		||||
import 'package:obtainium/custom_errors.dart';
 | 
			
		||||
import 'package:obtainium/main.dart';
 | 
			
		||||
import 'package:obtainium/providers/apps_provider.dart';
 | 
			
		||||
@@ -12,6 +15,7 @@ import 'package:obtainium/providers/settings_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/source_provider.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
import 'package:share_plus/share_plus.dart';
 | 
			
		||||
import 'package:shizuku_apk_installer/shizuku_apk_installer.dart';
 | 
			
		||||
import 'package:url_launcher/url_launcher_string.dart';
 | 
			
		||||
 | 
			
		||||
class SettingsPage extends StatefulWidget {
 | 
			
		||||
@@ -22,78 +26,184 @@ class SettingsPage extends StatefulWidget {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
  List<int> updateIntervalNodes = [
 | 
			
		||||
    15,
 | 
			
		||||
    30,
 | 
			
		||||
    60,
 | 
			
		||||
    120,
 | 
			
		||||
    180,
 | 
			
		||||
    360,
 | 
			
		||||
    720,
 | 
			
		||||
    1440,
 | 
			
		||||
    4320,
 | 
			
		||||
    10080,
 | 
			
		||||
    20160,
 | 
			
		||||
    43200
 | 
			
		||||
  ];
 | 
			
		||||
  int updateInterval = 0;
 | 
			
		||||
  late SplineInterpolation updateIntervalInterpolator; // 🤓
 | 
			
		||||
  String updateIntervalLabel = tr('neverManualOnly');
 | 
			
		||||
  bool showIntervalLabel = true;
 | 
			
		||||
  final Map<ColorSwatch<Object>, String> colorsNameMap =
 | 
			
		||||
      <ColorSwatch<Object>, String>{
 | 
			
		||||
    ColorTools.createPrimarySwatch(obtainiumThemeColor): 'Obtainium'
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  void initUpdateIntervalInterpolator() {
 | 
			
		||||
    List<InterpolationNode> nodes = [];
 | 
			
		||||
    for (final (index, element) in updateIntervalNodes.indexed) {
 | 
			
		||||
      nodes.add(
 | 
			
		||||
          InterpolationNode(x: index.toDouble() + 1, y: element.toDouble()));
 | 
			
		||||
    }
 | 
			
		||||
    updateIntervalInterpolator = SplineInterpolation(nodes: nodes);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void processIntervalSliderValue(double val) {
 | 
			
		||||
    if (val < 0.5) {
 | 
			
		||||
      updateInterval = 0;
 | 
			
		||||
      updateIntervalLabel = tr('neverManualOnly');
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    int valInterpolated = 0;
 | 
			
		||||
    if (val < 1) {
 | 
			
		||||
      valInterpolated = 15;
 | 
			
		||||
    } else {
 | 
			
		||||
      valInterpolated = updateIntervalInterpolator.compute(val).round();
 | 
			
		||||
    }
 | 
			
		||||
    if (valInterpolated < 60) {
 | 
			
		||||
      updateInterval = valInterpolated;
 | 
			
		||||
      updateIntervalLabel = plural('minute', valInterpolated);
 | 
			
		||||
    } else if (valInterpolated < 8 * 60) {
 | 
			
		||||
      int valRounded = (valInterpolated / 15).floor() * 15;
 | 
			
		||||
      updateInterval = valRounded;
 | 
			
		||||
      updateIntervalLabel = plural('hour', valRounded ~/ 60);
 | 
			
		||||
      int mins = valRounded % 60;
 | 
			
		||||
      if (mins != 0) updateIntervalLabel += " ${plural('minute', mins)}";
 | 
			
		||||
    } else if (valInterpolated < 24 * 60) {
 | 
			
		||||
      int valRounded = (valInterpolated / 30).floor() * 30;
 | 
			
		||||
      updateInterval = valRounded;
 | 
			
		||||
      updateIntervalLabel = plural('hour', valRounded / 60);
 | 
			
		||||
    } else if (valInterpolated < 7 * 24 * 60) {
 | 
			
		||||
      int valRounded = (valInterpolated / (12 * 60)).floor() * 12 * 60;
 | 
			
		||||
      updateInterval = valRounded;
 | 
			
		||||
      updateIntervalLabel = plural('day', valRounded / (24 * 60));
 | 
			
		||||
    } else {
 | 
			
		||||
      int valRounded = (valInterpolated / (24 * 60)).floor() * 24 * 60;
 | 
			
		||||
      updateInterval = valRounded;
 | 
			
		||||
      updateIntervalLabel = plural('day', valRounded ~/ (24 * 60));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    SettingsProvider settingsProvider = context.watch<SettingsProvider>();
 | 
			
		||||
    SourceProvider sourceProvider = SourceProvider();
 | 
			
		||||
    if (settingsProvider.prefs == null) {
 | 
			
		||||
      settingsProvider.initializeSettings();
 | 
			
		||||
    if (settingsProvider.prefs == null) settingsProvider.initializeSettings();
 | 
			
		||||
    initUpdateIntervalInterpolator();
 | 
			
		||||
    processIntervalSliderValue(settingsProvider.updateIntervalSliderVal);
 | 
			
		||||
 | 
			
		||||
    var followSystemThemeExplanation = FutureBuilder(
 | 
			
		||||
        builder: (ctx, val) {
 | 
			
		||||
          return ((val.data?.version.sdkInt ?? 30) < 29)
 | 
			
		||||
              ? Text(tr('followSystemThemeExplanation'),
 | 
			
		||||
                  style: Theme.of(context).textTheme.labelSmall)
 | 
			
		||||
              : const SizedBox.shrink();
 | 
			
		||||
        },
 | 
			
		||||
        future: DeviceInfoPlugin().androidInfo);
 | 
			
		||||
 | 
			
		||||
    Future<bool> colorPickerDialog() async {
 | 
			
		||||
      return ColorPicker(
 | 
			
		||||
        color: settingsProvider.themeColor,
 | 
			
		||||
        onColorChanged: (Color color) =>
 | 
			
		||||
            setState(() => settingsProvider.themeColor = color),
 | 
			
		||||
        actionButtons: const ColorPickerActionButtons(
 | 
			
		||||
          okButton: true,
 | 
			
		||||
          closeButton: true,
 | 
			
		||||
          dialogActionButtons: false,
 | 
			
		||||
        ),
 | 
			
		||||
        pickersEnabled: const <ColorPickerType, bool>{
 | 
			
		||||
          ColorPickerType.both: false,
 | 
			
		||||
          ColorPickerType.primary: false,
 | 
			
		||||
          ColorPickerType.accent: false,
 | 
			
		||||
          ColorPickerType.bw: false,
 | 
			
		||||
          ColorPickerType.custom: true,
 | 
			
		||||
          ColorPickerType.wheel: true,
 | 
			
		||||
        },
 | 
			
		||||
        pickerTypeLabels: <ColorPickerType, String>{
 | 
			
		||||
          ColorPickerType.custom: tr('standard'),
 | 
			
		||||
          ColorPickerType.wheel: tr('custom')
 | 
			
		||||
        },
 | 
			
		||||
        title: Text(tr('selectX', args: [tr('colour')]),
 | 
			
		||||
            style: Theme.of(context).textTheme.titleLarge),
 | 
			
		||||
        wheelDiameter: 192,
 | 
			
		||||
        wheelSquareBorderRadius: 32,
 | 
			
		||||
        width: 48,
 | 
			
		||||
        height: 48,
 | 
			
		||||
        borderRadius: 24,
 | 
			
		||||
        spacing: 8,
 | 
			
		||||
        runSpacing: 8,
 | 
			
		||||
        enableShadesSelection: false,
 | 
			
		||||
        customColorSwatchesAndNames: colorsNameMap,
 | 
			
		||||
        showMaterialName: true,
 | 
			
		||||
        showColorName: true,
 | 
			
		||||
        materialNameTextStyle: Theme.of(context).textTheme.bodySmall,
 | 
			
		||||
        colorNameTextStyle: Theme.of(context).textTheme.bodySmall,
 | 
			
		||||
        copyPasteBehavior:
 | 
			
		||||
            const ColorPickerCopyPasteBehavior(longPressMenu: true),
 | 
			
		||||
      ).showPickerDialog(
 | 
			
		||||
        context,
 | 
			
		||||
        transitionBuilder: (BuildContext context, Animation<double> a1,
 | 
			
		||||
            Animation<double> a2, Widget widget) {
 | 
			
		||||
          final double curvedValue = Curves.easeInCubic.transform(a1.value);
 | 
			
		||||
          return Transform(
 | 
			
		||||
            alignment: Alignment.center,
 | 
			
		||||
            transform: Matrix4.diagonal3Values(curvedValue, curvedValue, 1),
 | 
			
		||||
            child: Opacity(opacity: curvedValue, child: widget),
 | 
			
		||||
          );
 | 
			
		||||
        },
 | 
			
		||||
        transitionDuration: const Duration(milliseconds: 250),
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var installMethodDropdown = DropdownButtonFormField(
 | 
			
		||||
        decoration: InputDecoration(labelText: tr('installMethod')),
 | 
			
		||||
        value: settingsProvider.installMethod,
 | 
			
		||||
        items: [
 | 
			
		||||
          DropdownMenuItem(
 | 
			
		||||
            value: InstallMethodSettings.normal,
 | 
			
		||||
            child: Text(tr('normal')),
 | 
			
		||||
          ),
 | 
			
		||||
          const DropdownMenuItem(
 | 
			
		||||
            value: InstallMethodSettings.shizuku,
 | 
			
		||||
            child: Text('Shizuku'),
 | 
			
		||||
          ),
 | 
			
		||||
          DropdownMenuItem(
 | 
			
		||||
            value: InstallMethodSettings.root,
 | 
			
		||||
            child: Text(tr('root')),
 | 
			
		||||
          )
 | 
			
		||||
        ],
 | 
			
		||||
        onChanged: (value) {
 | 
			
		||||
          if (value != null) {
 | 
			
		||||
            settingsProvider.installMethod = value;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
    var colorPicker = ListTile(
 | 
			
		||||
        dense: true,
 | 
			
		||||
        contentPadding: EdgeInsets.zero,
 | 
			
		||||
        title: Text(tr('selectX', args: [tr('colour')])),
 | 
			
		||||
        subtitle: Text(
 | 
			
		||||
            "${ColorTools.nameThatColor(settingsProvider.themeColor)} "
 | 
			
		||||
            "(${ColorTools.materialNameAndCode(settingsProvider.themeColor, colorSwatchNameMap: colorsNameMap)})"),
 | 
			
		||||
        trailing: ColorIndicator(
 | 
			
		||||
            width: 40,
 | 
			
		||||
            height: 40,
 | 
			
		||||
            borderRadius: 20,
 | 
			
		||||
            color: settingsProvider.themeColor,
 | 
			
		||||
            onSelectFocus: false,
 | 
			
		||||
            onSelect: () async {
 | 
			
		||||
              final Color colorBeforeDialog = settingsProvider.themeColor;
 | 
			
		||||
              if (!(await colorPickerDialog())) {
 | 
			
		||||
                setState(() {
 | 
			
		||||
                  settingsProvider.themeColor = colorBeforeDialog;
 | 
			
		||||
                });
 | 
			
		||||
              }
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
    var themeDropdown = DropdownButtonFormField(
 | 
			
		||||
        decoration: InputDecoration(labelText: tr('theme')),
 | 
			
		||||
        value: settingsProvider.theme,
 | 
			
		||||
        items: [
 | 
			
		||||
          DropdownMenuItem(
 | 
			
		||||
            value: ThemeSettings.dark,
 | 
			
		||||
            child: Text(tr('dark')),
 | 
			
		||||
          ),
 | 
			
		||||
          DropdownMenuItem(
 | 
			
		||||
            value: ThemeSettings.light,
 | 
			
		||||
            child: Text(tr('light')),
 | 
			
		||||
          ),
 | 
			
		||||
          DropdownMenuItem(
 | 
			
		||||
            value: ThemeSettings.system,
 | 
			
		||||
            child: Text(tr('followSystem')),
 | 
			
		||||
          )
 | 
			
		||||
        ],
 | 
			
		||||
        onChanged: (value) {
 | 
			
		||||
          if (value != null) {
 | 
			
		||||
            settingsProvider.theme = value;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    var colourDropdown = DropdownButtonFormField(
 | 
			
		||||
        decoration: InputDecoration(labelText: tr('colour')),
 | 
			
		||||
        value: settingsProvider.colour,
 | 
			
		||||
        items: const [
 | 
			
		||||
          DropdownMenuItem(
 | 
			
		||||
            value: ColourSettings.basic,
 | 
			
		||||
            child: Text('Obtainium'),
 | 
			
		||||
          ),
 | 
			
		||||
          DropdownMenuItem(
 | 
			
		||||
            value: ColourSettings.materialYou,
 | 
			
		||||
            child: Text('Material You'),
 | 
			
		||||
          )
 | 
			
		||||
        ],
 | 
			
		||||
        onChanged: (value) {
 | 
			
		||||
          if (value != null) {
 | 
			
		||||
            settingsProvider.colour = value;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
    var useMaterialThemeSwitch = FutureBuilder(
 | 
			
		||||
        builder: (ctx, val) {
 | 
			
		||||
          return ((val.data?.version.sdkInt ?? 0) >= 31)
 | 
			
		||||
              ? Row(
 | 
			
		||||
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                  children: [
 | 
			
		||||
                    Flexible(child: Text(tr('useMaterialYou'))),
 | 
			
		||||
                    Switch(
 | 
			
		||||
                        value: settingsProvider.useMaterialYou,
 | 
			
		||||
                        onChanged: (value) {
 | 
			
		||||
                          settingsProvider.useMaterialYou = value;
 | 
			
		||||
                        })
 | 
			
		||||
                  ],
 | 
			
		||||
                )
 | 
			
		||||
              : const SizedBox.shrink();
 | 
			
		||||
        },
 | 
			
		||||
        future: DeviceInfoPlugin().androidInfo);
 | 
			
		||||
 | 
			
		||||
    var sortDropdown = DropdownButtonFormField(
 | 
			
		||||
        isExpanded: true,
 | 
			
		||||
@@ -165,30 +275,29 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    var intervalDropdown = DropdownButtonFormField(
 | 
			
		||||
        decoration: InputDecoration(labelText: tr('bgUpdateCheckInterval')),
 | 
			
		||||
        value: settingsProvider.updateInterval,
 | 
			
		||||
        items: updateIntervals.map((e) {
 | 
			
		||||
          int displayNum = (e < 60
 | 
			
		||||
                  ? e
 | 
			
		||||
                  : e < 1440
 | 
			
		||||
                      ? e / 60
 | 
			
		||||
                      : e / 1440)
 | 
			
		||||
              .round();
 | 
			
		||||
          String display = e == 0
 | 
			
		||||
              ? tr('neverManualOnly')
 | 
			
		||||
              : (e < 60
 | 
			
		||||
                  ? plural('minute', displayNum)
 | 
			
		||||
                  : e < 1440
 | 
			
		||||
                      ? plural('hour', displayNum)
 | 
			
		||||
                      : plural('day', displayNum));
 | 
			
		||||
          return DropdownMenuItem(value: e, child: Text(display));
 | 
			
		||||
        }).toList(),
 | 
			
		||||
        onChanged: (value) {
 | 
			
		||||
          if (value != null) {
 | 
			
		||||
            settingsProvider.updateInterval = value;
 | 
			
		||||
          }
 | 
			
		||||
    var intervalSlider = Slider(
 | 
			
		||||
      value: settingsProvider.updateIntervalSliderVal,
 | 
			
		||||
      max: updateIntervalNodes.length.toDouble(),
 | 
			
		||||
      divisions: updateIntervalNodes.length * 20,
 | 
			
		||||
      label: updateIntervalLabel,
 | 
			
		||||
      onChanged: (double value) {
 | 
			
		||||
        setState(() {
 | 
			
		||||
          settingsProvider.updateIntervalSliderVal = value;
 | 
			
		||||
          processIntervalSliderValue(value);
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
      onChangeStart: (double value) {
 | 
			
		||||
        setState(() {
 | 
			
		||||
          showIntervalLabel = false;
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
      onChangeEnd: (double value) {
 | 
			
		||||
        setState(() {
 | 
			
		||||
          showIntervalLabel = true;
 | 
			
		||||
          settingsProvider.updateInterval = updateInterval;
 | 
			
		||||
        });
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    var sourceSpecificFields = sourceProvider.sources.map((e) {
 | 
			
		||||
      if (e.sourceConfigSettingFormItems.isNotEmpty) {
 | 
			
		||||
@@ -239,15 +348,26 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                                  fontWeight: FontWeight.bold,
 | 
			
		||||
                                  color: Theme.of(context).colorScheme.primary),
 | 
			
		||||
                            ),
 | 
			
		||||
                            intervalDropdown,
 | 
			
		||||
                            //intervalDropdown,
 | 
			
		||||
                            height16,
 | 
			
		||||
                            if (showIntervalLabel)
 | 
			
		||||
                              SizedBox(
 | 
			
		||||
                                  child: Text(
 | 
			
		||||
                                      "${tr('bgUpdateCheckInterval')}: $updateIntervalLabel"))
 | 
			
		||||
                            else
 | 
			
		||||
                              const SizedBox(height: 16),
 | 
			
		||||
                            intervalSlider,
 | 
			
		||||
                            FutureBuilder(
 | 
			
		||||
                                builder: (ctx, val) {
 | 
			
		||||
                                  return (val.data?.version.sdkInt ?? 0) >= 30
 | 
			
		||||
                                  return (settingsProvider.updateInterval >
 | 
			
		||||
                                              0) &&
 | 
			
		||||
                                          (((val.data?.version.sdkInt ?? 0) >=
 | 
			
		||||
                                                  30) ||
 | 
			
		||||
                                              settingsProvider.useShizuku)
 | 
			
		||||
                                      ? Column(
 | 
			
		||||
                                          crossAxisAlignment:
 | 
			
		||||
                                              CrossAxisAlignment.start,
 | 
			
		||||
                                          children: [
 | 
			
		||||
                                            height16,
 | 
			
		||||
                                            Row(
 | 
			
		||||
                                              mainAxisAlignment:
 | 
			
		||||
                                                  MainAxisAlignment
 | 
			
		||||
@@ -351,6 +471,22 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                            height16,
 | 
			
		||||
                            Row(
 | 
			
		||||
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                              children: [
 | 
			
		||||
                                Flexible(
 | 
			
		||||
                                    child:
 | 
			
		||||
                                        Text(tr('removeOnExternalUninstall'))),
 | 
			
		||||
                                Switch(
 | 
			
		||||
                                    value: settingsProvider
 | 
			
		||||
                                        .removeOnExternalUninstall,
 | 
			
		||||
                                    onChanged: (value) {
 | 
			
		||||
                                      settingsProvider
 | 
			
		||||
                                          .removeOnExternalUninstall = value;
 | 
			
		||||
                                    })
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                            height16,
 | 
			
		||||
                            Row(
 | 
			
		||||
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                              children: [
 | 
			
		||||
@@ -363,7 +499,85 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                                    })
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                            installMethodDropdown,
 | 
			
		||||
                            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;
 | 
			
		||||
                                    })
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                            height16,
 | 
			
		||||
                            Row(
 | 
			
		||||
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                              children: [
 | 
			
		||||
                                Flexible(child: Text(tr('useShizuku'))),
 | 
			
		||||
                                Switch(
 | 
			
		||||
                                    value: settingsProvider.useShizuku,
 | 
			
		||||
                                    onChanged: (useShizuku) {
 | 
			
		||||
                                      if (useShizuku) {
 | 
			
		||||
                                        ShizukuApkInstaller.checkPermission()
 | 
			
		||||
                                            .then((resCode) {
 | 
			
		||||
                                          settingsProvider.useShizuku =
 | 
			
		||||
                                              resCode!.startsWith('granted');
 | 
			
		||||
                                          switch (resCode) {
 | 
			
		||||
                                            case 'binder_not_found':
 | 
			
		||||
                                              showError(
 | 
			
		||||
                                                  ObtainiumError(tr(
 | 
			
		||||
                                                      'shizukuBinderNotFound')),
 | 
			
		||||
                                                  context);
 | 
			
		||||
                                            case 'old_shizuku':
 | 
			
		||||
                                              showError(
 | 
			
		||||
                                                  ObtainiumError(
 | 
			
		||||
                                                      tr('shizukuOld')),
 | 
			
		||||
                                                  context);
 | 
			
		||||
                                            case 'old_android_with_adb':
 | 
			
		||||
                                              showError(
 | 
			
		||||
                                                  ObtainiumError(tr(
 | 
			
		||||
                                                      'shizukuOldAndroidWithADB')),
 | 
			
		||||
                                                  context);
 | 
			
		||||
                                            case 'denied':
 | 
			
		||||
                                              showError(
 | 
			
		||||
                                                  ObtainiumError(
 | 
			
		||||
                                                      tr('cancelled')),
 | 
			
		||||
                                                  context);
 | 
			
		||||
                                          }
 | 
			
		||||
                                        });
 | 
			
		||||
                                      } else {
 | 
			
		||||
                                        settingsProvider.useShizuku = false;
 | 
			
		||||
                                      }
 | 
			
		||||
                                    })
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                            height32,
 | 
			
		||||
                            Text(
 | 
			
		||||
                              tr('sourceSpecific'),
 | 
			
		||||
@@ -379,21 +593,49 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                                  fontWeight: FontWeight.bold,
 | 
			
		||||
                                  color: Theme.of(context).colorScheme.primary),
 | 
			
		||||
                            ),
 | 
			
		||||
                            themeDropdown,
 | 
			
		||||
                            height16,
 | 
			
		||||
                            Row(
 | 
			
		||||
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                              children: [
 | 
			
		||||
                                Flexible(child: Text(tr('useBlackTheme'))),
 | 
			
		||||
                                Switch(
 | 
			
		||||
                                    value: settingsProvider.useBlackTheme,
 | 
			
		||||
                                    onChanged: (value) {
 | 
			
		||||
                                      settingsProvider.useBlackTheme = value;
 | 
			
		||||
                                    })
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                            colourDropdown,
 | 
			
		||||
                            DropdownButtonFormField(
 | 
			
		||||
                                decoration:
 | 
			
		||||
                                    InputDecoration(labelText: tr('theme')),
 | 
			
		||||
                                value: settingsProvider.theme,
 | 
			
		||||
                                items: [
 | 
			
		||||
                                  DropdownMenuItem(
 | 
			
		||||
                                    value: ThemeSettings.system,
 | 
			
		||||
                                    child: Text(tr('followSystem')),
 | 
			
		||||
                                  ),
 | 
			
		||||
                                  DropdownMenuItem(
 | 
			
		||||
                                    value: ThemeSettings.light,
 | 
			
		||||
                                    child: Text(tr('light')),
 | 
			
		||||
                                  ),
 | 
			
		||||
                                  DropdownMenuItem(
 | 
			
		||||
                                    value: ThemeSettings.dark,
 | 
			
		||||
                                    child: Text(tr('dark')),
 | 
			
		||||
                                  )
 | 
			
		||||
                                ],
 | 
			
		||||
                                onChanged: (value) {
 | 
			
		||||
                                  if (value != null) {
 | 
			
		||||
                                    settingsProvider.theme = value;
 | 
			
		||||
                                  }
 | 
			
		||||
                                }),
 | 
			
		||||
                            height8,
 | 
			
		||||
                            if (settingsProvider.theme == ThemeSettings.system)
 | 
			
		||||
                              followSystemThemeExplanation,
 | 
			
		||||
                            height16,
 | 
			
		||||
                            if (settingsProvider.theme != ThemeSettings.light)
 | 
			
		||||
                              Row(
 | 
			
		||||
                                  mainAxisAlignment:
 | 
			
		||||
                                      MainAxisAlignment.spaceBetween,
 | 
			
		||||
                                  children: [
 | 
			
		||||
                                    Flexible(child: Text(tr('useBlackTheme'))),
 | 
			
		||||
                                    Switch(
 | 
			
		||||
                                        value: settingsProvider.useBlackTheme,
 | 
			
		||||
                                        onChanged: (value) {
 | 
			
		||||
                                          settingsProvider.useBlackTheme =
 | 
			
		||||
                                              value;
 | 
			
		||||
                                        })
 | 
			
		||||
                                  ]),
 | 
			
		||||
                            height8,
 | 
			
		||||
                            useMaterialThemeSwitch,
 | 
			
		||||
                            if (!settingsProvider.useMaterialYou) colorPicker,
 | 
			
		||||
                            Row(
 | 
			
		||||
                              mainAxisAlignment: MainAxisAlignment.start,
 | 
			
		||||
                              crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
@@ -407,34 +649,46 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                            ),
 | 
			
		||||
                            height16,
 | 
			
		||||
                            localeDropdown,
 | 
			
		||||
                            height16,
 | 
			
		||||
                            Row(
 | 
			
		||||
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                              children: [
 | 
			
		||||
                                Flexible(child: Text(tr('useSystemFont'))),
 | 
			
		||||
                                Switch(
 | 
			
		||||
                                    value: settingsProvider.useSystemFont,
 | 
			
		||||
                                    onChanged: (useSystemFont) {
 | 
			
		||||
                                      if (useSystemFont) {
 | 
			
		||||
                                        NativeFeatures.loadSystemFont()
 | 
			
		||||
                                            .then((fontLoadRes) {
 | 
			
		||||
                                          if (fontLoadRes == 'ok') {
 | 
			
		||||
                                            settingsProvider.useSystemFont =
 | 
			
		||||
                                                true;
 | 
			
		||||
                                          } else {
 | 
			
		||||
                                            showError(
 | 
			
		||||
                                                ObtainiumError(tr(
 | 
			
		||||
                                                    'systemFontError',
 | 
			
		||||
                                                    args: [fontLoadRes])),
 | 
			
		||||
                                                context);
 | 
			
		||||
                                          }
 | 
			
		||||
                                        });
 | 
			
		||||
                                      } else {
 | 
			
		||||
                                        settingsProvider.useSystemFont = false;
 | 
			
		||||
                                      }
 | 
			
		||||
                                    })
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                            FutureBuilder(
 | 
			
		||||
                                builder: (ctx, val) {
 | 
			
		||||
                                  return (val.data?.version.sdkInt ?? 0) >= 34
 | 
			
		||||
                                      ? Column(
 | 
			
		||||
                                          crossAxisAlignment:
 | 
			
		||||
                                              CrossAxisAlignment.start,
 | 
			
		||||
                                          children: [
 | 
			
		||||
                                              height16,
 | 
			
		||||
                                              Row(
 | 
			
		||||
                                                  mainAxisAlignment:
 | 
			
		||||
                                                      MainAxisAlignment
 | 
			
		||||
                                                          .spaceBetween,
 | 
			
		||||
                                                  children: [
 | 
			
		||||
                                                    Flexible(
 | 
			
		||||
                                                        child: Text(tr(
 | 
			
		||||
                                                            'useSystemFont'))),
 | 
			
		||||
                                                    Switch(
 | 
			
		||||
                                                        value: settingsProvider
 | 
			
		||||
                                                            .useSystemFont,
 | 
			
		||||
                                                        onChanged:
 | 
			
		||||
                                                            (useSystemFont) {
 | 
			
		||||
                                                          if (useSystemFont) {
 | 
			
		||||
                                                            NativeFeatures
 | 
			
		||||
                                                                    .loadSystemFont()
 | 
			
		||||
                                                                .then((val) {
 | 
			
		||||
                                                              settingsProvider
 | 
			
		||||
                                                                      .useSystemFont =
 | 
			
		||||
                                                                  true;
 | 
			
		||||
                                                            });
 | 
			
		||||
                                                          } else {
 | 
			
		||||
                                                            settingsProvider
 | 
			
		||||
                                                                    .useSystemFont =
 | 
			
		||||
                                                                false;
 | 
			
		||||
                                                          }
 | 
			
		||||
                                                        })
 | 
			
		||||
                                                  ])
 | 
			
		||||
                                            ])
 | 
			
		||||
                                      : const SizedBox.shrink();
 | 
			
		||||
                                },
 | 
			
		||||
                                future: DeviceInfoPlugin().androidInfo),
 | 
			
		||||
                            height16,
 | 
			
		||||
                            Row(
 | 
			
		||||
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
@@ -474,22 +728,6 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                            height16,
 | 
			
		||||
                            Row(
 | 
			
		||||
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                              children: [
 | 
			
		||||
                                Flexible(
 | 
			
		||||
                                    child:
 | 
			
		||||
                                        Text(tr('removeOnExternalUninstall'))),
 | 
			
		||||
                                Switch(
 | 
			
		||||
                                    value: settingsProvider
 | 
			
		||||
                                        .removeOnExternalUninstall,
 | 
			
		||||
                                    onChanged: (value) {
 | 
			
		||||
                                      settingsProvider
 | 
			
		||||
                                          .removeOnExternalUninstall = value;
 | 
			
		||||
                                    })
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                            height16,
 | 
			
		||||
                            Row(
 | 
			
		||||
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                              children: [
 | 
			
		||||
@@ -603,17 +841,31 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                Row(
 | 
			
		||||
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
 | 
			
		||||
                  children: [
 | 
			
		||||
                    TextButton.icon(
 | 
			
		||||
                    IconButton(
 | 
			
		||||
                      onPressed: () {
 | 
			
		||||
                        launchUrlString(settingsProvider.sourceUrl,
 | 
			
		||||
                            mode: LaunchMode.externalApplication);
 | 
			
		||||
                      },
 | 
			
		||||
                      icon: const Icon(Icons.code),
 | 
			
		||||
                      label: Text(
 | 
			
		||||
                        tr('appSource'),
 | 
			
		||||
                      ),
 | 
			
		||||
                      tooltip: tr('appSource'),
 | 
			
		||||
                    ),
 | 
			
		||||
                    TextButton.icon(
 | 
			
		||||
                    IconButton(
 | 
			
		||||
                      onPressed: () {
 | 
			
		||||
                        launchUrlString('${settingsProvider.sourceUrl}/wiki',
 | 
			
		||||
                            mode: LaunchMode.externalApplication);
 | 
			
		||||
                      },
 | 
			
		||||
                      icon: const Icon(Icons.help_outline_rounded),
 | 
			
		||||
                      tooltip: tr('wiki'),
 | 
			
		||||
                    ),
 | 
			
		||||
                    IconButton(
 | 
			
		||||
                      onPressed: () {
 | 
			
		||||
                        launchUrlString('https://apps.obtainium.imranr.dev/',
 | 
			
		||||
                            mode: LaunchMode.externalApplication);
 | 
			
		||||
                      },
 | 
			
		||||
                      icon: const Icon(Icons.apps_rounded),
 | 
			
		||||
                      tooltip: tr('crowdsourcedConfigsLabel'),
 | 
			
		||||
                    ),
 | 
			
		||||
                    IconButton(
 | 
			
		||||
                        onPressed: () {
 | 
			
		||||
                          context.read<LogsProvider>().get().then((logs) {
 | 
			
		||||
                            if (logs.isEmpty) {
 | 
			
		||||
@@ -629,7 +881,7 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                          });
 | 
			
		||||
                        },
 | 
			
		||||
                        icon: const Icon(Icons.bug_report_outlined),
 | 
			
		||||
                        label: Text(tr('appLogs'))),
 | 
			
		||||
                        tooltip: tr('appLogs'))
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
                const SizedBox(
 | 
			
		||||
@@ -694,6 +946,25 @@ class _LogsDialogState extends State<LogsDialog> {
 | 
			
		||||
        ],
 | 
			
		||||
      ),
 | 
			
		||||
      actions: [
 | 
			
		||||
        TextButton(
 | 
			
		||||
            onPressed: () async {
 | 
			
		||||
              var cont = (await showDialog<Map<String, dynamic>?>(
 | 
			
		||||
                      context: context,
 | 
			
		||||
                      builder: (BuildContext ctx) {
 | 
			
		||||
                        return GeneratedFormModal(
 | 
			
		||||
                          title: tr('appLogs'),
 | 
			
		||||
                          items: const [],
 | 
			
		||||
                          initValid: true,
 | 
			
		||||
                          message: tr('removeFromObtainium'),
 | 
			
		||||
                        );
 | 
			
		||||
                      })) !=
 | 
			
		||||
                  null;
 | 
			
		||||
              if (cont) {
 | 
			
		||||
                logsProvider.clear();
 | 
			
		||||
                Navigator.of(context).pop();
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
            child: Text(tr('remove'))),
 | 
			
		||||
        TextButton(
 | 
			
		||||
            onPressed: () {
 | 
			
		||||
              Navigator.of(context).pop();
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,75 +1,22 @@
 | 
			
		||||
import 'dart:async';
 | 
			
		||||
import 'dart:io';
 | 
			
		||||
import 'package:android_system_font/android_system_font.dart';
 | 
			
		||||
import 'package:flutter/services.dart';
 | 
			
		||||
 | 
			
		||||
class NativeFeatures {
 | 
			
		||||
  static const MethodChannel _channel = MethodChannel('native');
 | 
			
		||||
  static bool _systemFontLoaded = false;
 | 
			
		||||
  static bool _callbacksApplied = false;
 | 
			
		||||
  static int _resPermShizuku = -2;  // not set
 | 
			
		||||
 | 
			
		||||
  static Future<ByteData> _readFileBytes(String path) async {
 | 
			
		||||
    var file = File(path);
 | 
			
		||||
    var bytes = await file.readAsBytes();
 | 
			
		||||
    var bytes = await File(path).readAsBytes();
 | 
			
		||||
    return ByteData.view(bytes.buffer);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static Future _handleCalls(MethodCall call) async {
 | 
			
		||||
    if (call.method == 'resPermShizuku') {
 | 
			
		||||
      _resPermShizuku = call.arguments['res'];
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static Future _waitWhile(bool Function() test,
 | 
			
		||||
      [Duration pollInterval = const Duration(milliseconds: 250)]) {
 | 
			
		||||
    var completer = Completer();
 | 
			
		||||
    check() {
 | 
			
		||||
      if (test()) {
 | 
			
		||||
        Timer(pollInterval, check);
 | 
			
		||||
      } else {
 | 
			
		||||
        completer.complete();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    check();
 | 
			
		||||
    return completer.future;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static Future<String> loadSystemFont() async {
 | 
			
		||||
    if (_systemFontLoaded) { return "ok"; }
 | 
			
		||||
    var getFontRes = await _channel.invokeMethod('getSystemFont');
 | 
			
		||||
    if (getFontRes[0] != '/') { return getFontRes; }  // Error
 | 
			
		||||
  static Future loadSystemFont() async {
 | 
			
		||||
    if (_systemFontLoaded) return;
 | 
			
		||||
    var fontLoader = FontLoader('SystemFont');
 | 
			
		||||
    fontLoader.addFont(_readFileBytes(getFontRes));
 | 
			
		||||
    await fontLoader.load();
 | 
			
		||||
    var fontFilePath = await AndroidSystemFont().getFilePath();
 | 
			
		||||
    fontLoader.addFont(_readFileBytes(fontFilePath!));
 | 
			
		||||
    fontLoader.load();
 | 
			
		||||
    _systemFontLoaded = true;
 | 
			
		||||
    return "ok";
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static Future<int> checkPermissionShizuku() async {
 | 
			
		||||
    if (!_callbacksApplied) {
 | 
			
		||||
      _channel.setMethodCallHandler(_handleCalls);
 | 
			
		||||
      _callbacksApplied = true;
 | 
			
		||||
    }
 | 
			
		||||
    int res = await _channel.invokeMethod('checkPermissionShizuku');
 | 
			
		||||
    if (res == -2) {
 | 
			
		||||
      await _waitWhile(() => _resPermShizuku == -2);
 | 
			
		||||
      res = _resPermShizuku;
 | 
			
		||||
      _resPermShizuku = -2;
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static Future<bool> checkPermissionRoot() async {
 | 
			
		||||
    return await _channel.invokeMethod('checkPermissionRoot');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static Future<bool> installWithShizuku({required String apkFileUri}) async {
 | 
			
		||||
    return await _channel.invokeMethod(
 | 
			
		||||
        'installWithShizuku', {'apkFileUri': apkFileUri});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static Future<bool> installWithRoot({required String apkFilePath}) async {
 | 
			
		||||
    return await _channel.invokeMethod(
 | 
			
		||||
        'installWithRoot', {'apkFilePath': apkFilePath});
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -41,20 +41,26 @@ class UpdateNotification extends ObtainiumNotification {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class SilentUpdateNotification extends ObtainiumNotification {
 | 
			
		||||
  SilentUpdateNotification(List<App> updates, {int? id})
 | 
			
		||||
  SilentUpdateNotification(List<App> updates, bool succeeded, {int? id})
 | 
			
		||||
      : super(
 | 
			
		||||
            id ?? 3,
 | 
			
		||||
            tr('appsUpdated'),
 | 
			
		||||
            succeeded
 | 
			
		||||
                ? tr('appsUpdated')
 | 
			
		||||
                : tr('appsNotUpdated'),
 | 
			
		||||
            '',
 | 
			
		||||
            'APPS_UPDATED',
 | 
			
		||||
            tr('appsUpdatedNotifChannel'),
 | 
			
		||||
            tr('appsUpdatedNotifDescription'),
 | 
			
		||||
            Importance.defaultImportance) {
 | 
			
		||||
    message = updates.length == 1
 | 
			
		||||
        ? tr('xWasUpdatedToY',
 | 
			
		||||
            args: [updates[0].finalName, updates[0].latestVersion])
 | 
			
		||||
        : plural('xAndNMoreUpdatesInstalled', updates.length - 1,
 | 
			
		||||
            args: [updates[0].finalName, (updates.length - 1).toString()]);
 | 
			
		||||
        ? tr(succeeded
 | 
			
		||||
            ? 'xWasUpdatedToY'
 | 
			
		||||
            : 'xWasNotUpdatedToY',
 | 
			
		||||
                args: [updates[0].finalName, updates[0].latestVersion])
 | 
			
		||||
        : plural(succeeded
 | 
			
		||||
            ? 'xAndNMoreUpdatesInstalled'
 | 
			
		||||
            : "xAndNMoreUpdatesFailed",
 | 
			
		||||
                updates.length - 1, args: [updates[0].finalName, (updates.length - 1).toString()]);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -120,6 +126,18 @@ class DownloadNotification extends ObtainiumNotification {
 | 
			
		||||
            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(
 | 
			
		||||
    1,
 | 
			
		||||
    tr('completeAppInstallation'),
 | 
			
		||||
 
 | 
			
		||||
@@ -17,41 +17,14 @@ import 'package:shared_storage/shared_storage.dart' as saf;
 | 
			
		||||
String obtainiumTempId = 'imranr98_obtainium_${GitHub().hosts[0]}';
 | 
			
		||||
String obtainiumId = 'dev.imranr.obtainium';
 | 
			
		||||
String obtainiumUrl = 'https://github.com/ImranR98/Obtainium';
 | 
			
		||||
 | 
			
		||||
enum InstallMethodSettings { normal, shizuku, root }
 | 
			
		||||
Color obtainiumThemeColor = const Color(0xFF6438B5);
 | 
			
		||||
 | 
			
		||||
enum ThemeSettings { system, light, dark }
 | 
			
		||||
 | 
			
		||||
enum ColourSettings { basic, materialYou }
 | 
			
		||||
 | 
			
		||||
enum SortColumnSettings { added, nameAuthor, authorName, releaseDate }
 | 
			
		||||
 | 
			
		||||
enum SortOrderSettings { ascending, descending }
 | 
			
		||||
 | 
			
		||||
const maxAPIRateLimitMinutes = 30;
 | 
			
		||||
const minUpdateIntervalMinutes = maxAPIRateLimitMinutes + 30;
 | 
			
		||||
const maxUpdateIntervalMinutes = 43200;
 | 
			
		||||
List<int> updateIntervals = [
 | 
			
		||||
  15,
 | 
			
		||||
  30,
 | 
			
		||||
  60,
 | 
			
		||||
  120,
 | 
			
		||||
  180,
 | 
			
		||||
  360,
 | 
			
		||||
  720,
 | 
			
		||||
  1440,
 | 
			
		||||
  4320,
 | 
			
		||||
  10080,
 | 
			
		||||
  20160,
 | 
			
		||||
  43200,
 | 
			
		||||
  0
 | 
			
		||||
]
 | 
			
		||||
    .where((element) =>
 | 
			
		||||
        (element >= minUpdateIntervalMinutes &&
 | 
			
		||||
            element <= maxUpdateIntervalMinutes) ||
 | 
			
		||||
        element == 0)
 | 
			
		||||
    .toList();
 | 
			
		||||
 | 
			
		||||
class SettingsProvider with ChangeNotifier {
 | 
			
		||||
  SharedPreferences? prefs;
 | 
			
		||||
  String? defaultAppDir;
 | 
			
		||||
@@ -75,13 +48,12 @@ class SettingsProvider with ChangeNotifier {
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  InstallMethodSettings get installMethod {
 | 
			
		||||
    return InstallMethodSettings.values[
 | 
			
		||||
        prefs?.getInt('installMethod') ?? InstallMethodSettings.normal.index];
 | 
			
		||||
  bool get useShizuku{
 | 
			
		||||
    return prefs?.getBool('useShizuku') ?? false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  set installMethod(InstallMethodSettings t) {
 | 
			
		||||
    prefs?.setInt('installMethod', t.index);
 | 
			
		||||
  set useShizuku(bool useShizuku) {
 | 
			
		||||
    prefs?.setBool('useShizuku', useShizuku);
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -95,13 +67,23 @@ class SettingsProvider with ChangeNotifier {
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ColourSettings get colour {
 | 
			
		||||
    return ColourSettings
 | 
			
		||||
        .values[prefs?.getInt('colour') ?? ColourSettings.basic.index];
 | 
			
		||||
  Color get themeColor {
 | 
			
		||||
    int? colorCode = prefs?.getInt('themeColor');
 | 
			
		||||
    return (colorCode != null) ?
 | 
			
		||||
        Color(colorCode) : obtainiumThemeColor;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  set colour(ColourSettings t) {
 | 
			
		||||
    prefs?.setInt('colour', t.index);
 | 
			
		||||
  set themeColor(Color themeColor) {
 | 
			
		||||
    prefs?.setInt('themeColor', themeColor.value);
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool get useMaterialYou {
 | 
			
		||||
    return prefs?.getBool('useMaterialYou') ?? false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  set useMaterialYou(bool useMaterialYou) {
 | 
			
		||||
    prefs?.setBool('useMaterialYou', useMaterialYou);
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -115,21 +97,20 @@ class SettingsProvider with ChangeNotifier {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int get updateInterval {
 | 
			
		||||
    var min = prefs?.getInt('updateInterval') ?? 360;
 | 
			
		||||
    if (!updateIntervals.contains(min)) {
 | 
			
		||||
      var temp = updateIntervals[0];
 | 
			
		||||
      for (var i in updateIntervals) {
 | 
			
		||||
        if (min > i && i != 0) {
 | 
			
		||||
          temp = i;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      min = temp;
 | 
			
		||||
    }
 | 
			
		||||
    return min;
 | 
			
		||||
    return prefs?.getInt('updateInterval') ?? 360;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  set updateInterval(int min) {
 | 
			
		||||
    prefs?.setInt('updateInterval', (min < 15 && min != 0) ? 15 : min);
 | 
			
		||||
    prefs?.setInt('updateInterval', min);
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  double get updateIntervalSliderVal {
 | 
			
		||||
    return prefs?.getDouble('updateIntervalSliderVal') ?? 6.0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  set updateIntervalSliderVal(double val) {
 | 
			
		||||
    prefs?.setDouble('updateIntervalSliderVal', val);
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -479,4 +460,13 @@ class SettingsProvider with ChangeNotifier {
 | 
			
		||||
    prefs?.setStringList('searchDeselected', list);
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool get beforeNewInstallsShareToAppVerifier {
 | 
			
		||||
    return prefs?.getBool('beforeNewInstallsShareToAppVerifier') ?? true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  set beforeNewInstallsShareToAppVerifier(bool val) {
 | 
			
		||||
    prefs?.setBool('beforeNewInstallsShareToAppVerifier', val);
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -47,9 +47,10 @@ class APKDetails {
 | 
			
		||||
  late AppNames names;
 | 
			
		||||
  late DateTime? releaseDate;
 | 
			
		||||
  late String? changeLog;
 | 
			
		||||
  late List<MapEntry<String, String>> allAssetUrls;
 | 
			
		||||
 | 
			
		||||
  APKDetails(this.version, this.apkUrls, this.names,
 | 
			
		||||
      {this.releaseDate, this.changeLog});
 | 
			
		||||
      {this.releaseDate, this.changeLog, this.allAssetUrls = const []});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
stringMapListTo2DList(List<MapEntry<String, String>> mapList) =>
 | 
			
		||||
@@ -223,6 +224,7 @@ class App {
 | 
			
		||||
  String? installedVersion;
 | 
			
		||||
  late String latestVersion;
 | 
			
		||||
  List<MapEntry<String, String>> apkUrls = [];
 | 
			
		||||
  List<MapEntry<String, String>> otherAssetUrls = [];
 | 
			
		||||
  late int preferredApkIndex;
 | 
			
		||||
  late Map<String, dynamic> additionalSettings;
 | 
			
		||||
  late DateTime? lastUpdateCheck;
 | 
			
		||||
@@ -248,7 +250,8 @@ class App {
 | 
			
		||||
      this.releaseDate,
 | 
			
		||||
      this.changeLog,
 | 
			
		||||
      this.overrideSource,
 | 
			
		||||
      this.allowIdChange = false});
 | 
			
		||||
      this.allowIdChange = false,
 | 
			
		||||
      this.otherAssetUrls = const []});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  String toString() {
 | 
			
		||||
@@ -280,41 +283,44 @@ class App {
 | 
			
		||||
      changeLog: changeLog,
 | 
			
		||||
      releaseDate: releaseDate,
 | 
			
		||||
      overrideSource: overrideSource,
 | 
			
		||||
      allowIdChange: allowIdChange);
 | 
			
		||||
      allowIdChange: allowIdChange,
 | 
			
		||||
      otherAssetUrls: otherAssetUrls);
 | 
			
		||||
 | 
			
		||||
  factory App.fromJson(Map<String, dynamic> json) {
 | 
			
		||||
    json = appJSONCompatibilityModifiers(json);
 | 
			
		||||
    return App(
 | 
			
		||||
        json['id'] as String,
 | 
			
		||||
        json['url'] as String,
 | 
			
		||||
        json['author'] as String,
 | 
			
		||||
        json['name'] as String,
 | 
			
		||||
        json['installedVersion'] == null
 | 
			
		||||
            ? null
 | 
			
		||||
            : json['installedVersion'] as String,
 | 
			
		||||
        (json['latestVersion'] ?? tr('unknown')) as String,
 | 
			
		||||
        assumed2DlistToStringMapList(jsonDecode(
 | 
			
		||||
            (json['apkUrls'] ?? '[["placeholder", "placeholder"]]'))),
 | 
			
		||||
        (json['preferredApkIndex'] ?? -1) as int,
 | 
			
		||||
        jsonDecode(json['additionalSettings']) as Map<String, dynamic>,
 | 
			
		||||
        json['lastUpdateCheck'] == null
 | 
			
		||||
            ? null
 | 
			
		||||
            : DateTime.fromMicrosecondsSinceEpoch(json['lastUpdateCheck']),
 | 
			
		||||
        json['pinned'] ?? false,
 | 
			
		||||
        categories: json['categories'] != null
 | 
			
		||||
            ? (json['categories'] as List<dynamic>)
 | 
			
		||||
                .map((e) => e.toString())
 | 
			
		||||
                .toList()
 | 
			
		||||
            : json['category'] != null
 | 
			
		||||
                ? [json['category'] as String]
 | 
			
		||||
                : [],
 | 
			
		||||
        releaseDate: json['releaseDate'] == null
 | 
			
		||||
            ? null
 | 
			
		||||
            : DateTime.fromMicrosecondsSinceEpoch(json['releaseDate']),
 | 
			
		||||
        changeLog:
 | 
			
		||||
            json['changeLog'] == null ? null : json['changeLog'] as String,
 | 
			
		||||
        overrideSource: json['overrideSource'],
 | 
			
		||||
        allowIdChange: json['allowIdChange'] ?? false);
 | 
			
		||||
      json['id'] as String,
 | 
			
		||||
      json['url'] as String,
 | 
			
		||||
      json['author'] as String,
 | 
			
		||||
      json['name'] as String,
 | 
			
		||||
      json['installedVersion'] == null
 | 
			
		||||
          ? null
 | 
			
		||||
          : json['installedVersion'] as String,
 | 
			
		||||
      (json['latestVersion'] ?? tr('unknown')) as String,
 | 
			
		||||
      assumed2DlistToStringMapList(
 | 
			
		||||
          jsonDecode((json['apkUrls'] ?? '[["placeholder", "placeholder"]]'))),
 | 
			
		||||
      (json['preferredApkIndex'] ?? -1) as int,
 | 
			
		||||
      jsonDecode(json['additionalSettings']) as Map<String, dynamic>,
 | 
			
		||||
      json['lastUpdateCheck'] == null
 | 
			
		||||
          ? null
 | 
			
		||||
          : DateTime.fromMicrosecondsSinceEpoch(json['lastUpdateCheck']),
 | 
			
		||||
      json['pinned'] ?? false,
 | 
			
		||||
      categories: json['categories'] != null
 | 
			
		||||
          ? (json['categories'] as List<dynamic>)
 | 
			
		||||
              .map((e) => e.toString())
 | 
			
		||||
              .toList()
 | 
			
		||||
          : json['category'] != null
 | 
			
		||||
              ? [json['category'] as String]
 | 
			
		||||
              : [],
 | 
			
		||||
      releaseDate: json['releaseDate'] == null
 | 
			
		||||
          ? null
 | 
			
		||||
          : DateTime.fromMicrosecondsSinceEpoch(json['releaseDate']),
 | 
			
		||||
      changeLog: json['changeLog'] == null ? null : json['changeLog'] as String,
 | 
			
		||||
      overrideSource: json['overrideSource'],
 | 
			
		||||
      allowIdChange: json['allowIdChange'] ?? false,
 | 
			
		||||
      otherAssetUrls: assumed2DlistToStringMapList(
 | 
			
		||||
          jsonDecode((json['otherAssetUrls'] ?? '[]'))),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Map<String, dynamic> toJson() => {
 | 
			
		||||
@@ -325,6 +331,7 @@ class App {
 | 
			
		||||
        'installedVersion': installedVersion,
 | 
			
		||||
        'latestVersion': latestVersion,
 | 
			
		||||
        'apkUrls': jsonEncode(stringMapListTo2DList(apkUrls)),
 | 
			
		||||
        'otherAssetUrls': jsonEncode(stringMapListTo2DList(otherAssetUrls)),
 | 
			
		||||
        'preferredApkIndex': preferredApkIndex,
 | 
			
		||||
        'additionalSettings': jsonEncode(additionalSettings),
 | 
			
		||||
        'lastUpdateCheck': lastUpdateCheck?.microsecondsSinceEpoch,
 | 
			
		||||
@@ -347,11 +354,15 @@ preStandardizeUrl(String url) {
 | 
			
		||||
      url.toLowerCase().indexOf('https://') != 0) {
 | 
			
		||||
    url = 'https://$url';
 | 
			
		||||
  }
 | 
			
		||||
  var uri = Uri.tryParse(url);
 | 
			
		||||
  var trailingSlash = (uri?.path.endsWith('/') ?? false) &&
 | 
			
		||||
      (uri?.queryParameters.isEmpty ?? false);
 | 
			
		||||
  url = url
 | 
			
		||||
      .split('/')
 | 
			
		||||
      .where((e) => e.isNotEmpty)
 | 
			
		||||
      .join('/')
 | 
			
		||||
      .replaceFirst(':/', '://');
 | 
			
		||||
          .split('/')
 | 
			
		||||
          .where((e) => e.isNotEmpty)
 | 
			
		||||
          .join('/')
 | 
			
		||||
          .replaceFirst(':/', '://') +
 | 
			
		||||
      (trailingSlash ? '/' : '');
 | 
			
		||||
  return url;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -454,6 +465,10 @@ abstract class AppSource {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void runOnAddAppInputChange(String inputUrl) {
 | 
			
		||||
    //
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  String sourceSpecificStandardizeURL(String url) {
 | 
			
		||||
    throw NotImplementedError();
 | 
			
		||||
  }
 | 
			
		||||
@@ -514,6 +529,10 @@ abstract class AppSource {
 | 
			
		||||
          label: tr('autoApkFilterByArch'), defaultValue: true)
 | 
			
		||||
    ],
 | 
			
		||||
    [GeneratedFormTextField('appName', label: tr('appName'), required: false)],
 | 
			
		||||
    [
 | 
			
		||||
      GeneratedFormSwitch('shizukuPretendToBeGooglePlay',
 | 
			
		||||
          label: tr('shizukuPretendToBeGooglePlay'), defaultValue: false)
 | 
			
		||||
    ],
 | 
			
		||||
    [
 | 
			
		||||
      GeneratedFormSwitch('exemptFromBackgroundUpdates',
 | 
			
		||||
          label: tr('exemptFromBackgroundUpdates'))
 | 
			
		||||
@@ -604,7 +623,7 @@ abstract class AppSource {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool canSearch = false;
 | 
			
		||||
  bool excludeFromMassSearch = false;
 | 
			
		||||
  bool includeAdditionalOptsInMainSearch = false;
 | 
			
		||||
  List<GeneratedFormItem> searchQuerySettingFormItems = [];
 | 
			
		||||
  Future<Map<String, List<String>>> search(String query,
 | 
			
		||||
      {Map<String, dynamic> querySettings = const {}}) {
 | 
			
		||||
@@ -736,7 +755,6 @@ class SourceProvider {
 | 
			
		||||
        FDroid(),
 | 
			
		||||
        FDroidRepo(),
 | 
			
		||||
        IzzyOnDroid(),
 | 
			
		||||
        SourceForge(),
 | 
			
		||||
        SourceHut(),
 | 
			
		||||
        APKPure(),
 | 
			
		||||
        Aptoide(),
 | 
			
		||||
@@ -893,8 +911,10 @@ class SourceProvider {
 | 
			
		||||
        allowIdChange: currentApp?.allowIdChange ??
 | 
			
		||||
            trackOnly ||
 | 
			
		||||
                (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);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										412
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										412
									
								
								pubspec.lock
									
									
									
									
									
								
							@@ -5,10 +5,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: android_intent_plus
 | 
			
		||||
      sha256: e1c62bb41c90e15083b7fb84dc327fe90396cc9c1445b55ff1082144fabfb4d9
 | 
			
		||||
      sha256: "2bfdbee8d65e7c26f88b66f0a91f2863da4d3596d8a658b4162c8de5cf04b074"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "4.0.3"
 | 
			
		||||
    version: "5.0.2"
 | 
			
		||||
  android_package_installer:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
@@ -26,6 +26,15 @@ packages:
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.7.1"
 | 
			
		||||
  android_system_font:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      path: "."
 | 
			
		||||
      ref: master
 | 
			
		||||
      resolved-ref: "355f897e92a58a803f91d9270d389d9ec40ba550"
 | 
			
		||||
      url: "https://github.com/re7gog/android_system_font"
 | 
			
		||||
    source: git
 | 
			
		||||
    version: "1.0.0"
 | 
			
		||||
  animations:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
@@ -38,26 +47,50 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: app_links
 | 
			
		||||
      sha256: "3ced568a5d9e309e99af71285666f1f3117bddd0bd5b3317979dccc1a40cada4"
 | 
			
		||||
      sha256: a9905d6a60e814503fabc7523a9ed161b812d7ca69c99ad8ceea14279dc4f06b
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.5.1"
 | 
			
		||||
    version: "6.1.3"
 | 
			
		||||
  app_links_linux:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: app_links_linux
 | 
			
		||||
      sha256: "567139eca3ca9fb113f2082f3aaa75a26f30f0ebdbe5fa7f09a3913c5bebd630"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.0.2"
 | 
			
		||||
  app_links_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: app_links_platform_interface
 | 
			
		||||
      sha256: "58cff6f11df59b0e514dd5e4a61e988348ad5662f0e75d45d4e214ebea55c94c"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.0"
 | 
			
		||||
  app_links_web:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: app_links_web
 | 
			
		||||
      sha256: "74586ed5f3c4786341e82a0fa43c39ec3f13108a550f74e80d8bf68aa11349d1"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.0.3"
 | 
			
		||||
  archive:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: archive
 | 
			
		||||
      sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
 | 
			
		||||
      sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.4.10"
 | 
			
		||||
    version: "3.6.1"
 | 
			
		||||
  args:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: args
 | 
			
		||||
      sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
 | 
			
		||||
      sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.4.2"
 | 
			
		||||
    version: "2.5.0"
 | 
			
		||||
  async:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -70,10 +103,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: background_fetch
 | 
			
		||||
      sha256: eb3af263d390d7e68ecb90f2ae984d2bfd96dceb4c7b4f72418dd5383b49de0a
 | 
			
		||||
      sha256: b5c298c911bc2ce41152668bc72eb0488f0665d75bc6d1e69e7d8367763eddcd
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.2.4"
 | 
			
		||||
    version: "1.3.5"
 | 
			
		||||
  boolean_selector:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -126,26 +159,18 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: connectivity_plus
 | 
			
		||||
      sha256: "224a77051d52a11fbad53dd57827594d3bd24f945af28bd70bab376d68d437f0"
 | 
			
		||||
      sha256: db7a4e143dc72cc3cb2044ef9b052a7ebfe729513e6a82943bc3526f784365b8
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "5.0.2"
 | 
			
		||||
    version: "6.0.3"
 | 
			
		||||
  connectivity_plus_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: connectivity_plus_platform_interface
 | 
			
		||||
      sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a
 | 
			
		||||
      sha256: b6a56efe1e6675be240de39107281d4034b64ac23438026355b4234042a35adb
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.2.4"
 | 
			
		||||
  convert:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: convert
 | 
			
		||||
      sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.1.1"
 | 
			
		||||
    version: "2.0.0"
 | 
			
		||||
  cross_file:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -174,10 +199,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: cupertino_icons
 | 
			
		||||
      sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
 | 
			
		||||
      sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.0.6"
 | 
			
		||||
    version: "1.0.8"
 | 
			
		||||
  dbus:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -190,10 +215,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: device_info_plus
 | 
			
		||||
      sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110"
 | 
			
		||||
      sha256: eead12d1a1ed83d8283ab4c2f3fca23ac4082f29f25f29dff0f758f57d06ec91
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "9.1.2"
 | 
			
		||||
    version: "10.1.0"
 | 
			
		||||
  device_info_plus_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -214,10 +239,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: easy_localization
 | 
			
		||||
      sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c
 | 
			
		||||
      sha256: fa59bcdbbb911a764aa6acf96bbb6fa7a5cf8234354fc45ec1a43a0349ef0201
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.0.5"
 | 
			
		||||
    version: "3.0.7"
 | 
			
		||||
  easy_logger:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -226,6 +251,14 @@ packages:
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.0.2"
 | 
			
		||||
  equations:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: equations
 | 
			
		||||
      sha256: ae30e977d601e19aa1fc3409736c5eac01559d1d653a4c30141fbc4e86aa605c
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "5.0.2"
 | 
			
		||||
  fake_async:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -254,10 +287,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: file_picker
 | 
			
		||||
      sha256: caa6bc229eab3e32eb2f37b53a5f9d22a6981474afd210c512a7546c1e1a04f6
 | 
			
		||||
      sha256: "2ca051989f69d1b2ca012b2cf3ccf78c70d40144f0861ff2c063493f7c8c3d45"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.2.0"
 | 
			
		||||
    version: "8.0.5"
 | 
			
		||||
  fixnum:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -266,6 +299,22 @@ packages:
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.1.0"
 | 
			
		||||
  flex_color_picker:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: flex_color_picker
 | 
			
		||||
      sha256: "809af4ec82ede3b140ed0219b97d548de99e47aa4b99b14a10f705a2dbbcba5e"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.5.1"
 | 
			
		||||
  flex_seed_scheme:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flex_seed_scheme
 | 
			
		||||
      sha256: "6c595e545b0678e1fe17e8eec3d1fbca7237482da194fadc20ad8607dc7a7f3d"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.0.0"
 | 
			
		||||
  flutter:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description: flutter
 | 
			
		||||
@@ -275,10 +324,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_archive
 | 
			
		||||
      sha256: "004132780d382df5171589ab793e2efc9c3eef570fe72d78b4ccfbfbe52762ae"
 | 
			
		||||
      sha256: "5ca235f304c12bf468979235f400f79846d204169d715939e39197106f5fc970"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.0.0"
 | 
			
		||||
    version: "6.0.3"
 | 
			
		||||
  flutter_fgbg:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
@@ -287,6 +336,54 @@ packages:
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.3.0"
 | 
			
		||||
  flutter_keyboard_visibility:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_keyboard_visibility
 | 
			
		||||
      sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.0.0"
 | 
			
		||||
  flutter_keyboard_visibility_linux:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_keyboard_visibility_linux
 | 
			
		||||
      sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.0.0"
 | 
			
		||||
  flutter_keyboard_visibility_macos:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_keyboard_visibility_macos
 | 
			
		||||
      sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.0.0"
 | 
			
		||||
  flutter_keyboard_visibility_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_keyboard_visibility_platform_interface
 | 
			
		||||
      sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.0"
 | 
			
		||||
  flutter_keyboard_visibility_web:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_keyboard_visibility_web
 | 
			
		||||
      sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.0"
 | 
			
		||||
  flutter_keyboard_visibility_windows:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_keyboard_visibility_windows
 | 
			
		||||
      sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.0.0"
 | 
			
		||||
  flutter_launcher_icons:
 | 
			
		||||
    dependency: "direct dev"
 | 
			
		||||
    description:
 | 
			
		||||
@@ -299,18 +396,18 @@ packages:
 | 
			
		||||
    dependency: "direct dev"
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_lints
 | 
			
		||||
      sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
 | 
			
		||||
      sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.0.1"
 | 
			
		||||
    version: "4.0.0"
 | 
			
		||||
  flutter_local_notifications:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_local_notifications
 | 
			
		||||
      sha256: "55b9b229307a10974b26296ff29f2e132256ba4bd74266939118eaefa941cb00"
 | 
			
		||||
      sha256: ced76d337f54de33d7d9f06092137b4ac2da5079e00cee8a11a1794ffc7c61c6
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "16.3.3"
 | 
			
		||||
    version: "17.2.1"
 | 
			
		||||
  flutter_local_notifications_linux:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -323,10 +420,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_local_notifications_platform_interface
 | 
			
		||||
      sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef"
 | 
			
		||||
      sha256: "85f8d07fe708c1bdcf45037f2c0109753b26ae077e9d9e899d55971711a4ea66"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "7.0.0+1"
 | 
			
		||||
    version: "7.2.0"
 | 
			
		||||
  flutter_localizations:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description: flutter
 | 
			
		||||
@@ -336,23 +433,31 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_markdown
 | 
			
		||||
      sha256: cb44f7831b23a6bdd0f501718b0d2e8045cbc625a15f668af37ddb80314821db
 | 
			
		||||
      sha256: "2e8a801b1ded5ea001a4529c97b1f213dcb11c6b20668e081cafb23468593514"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.6.21"
 | 
			
		||||
    version: "0.7.3"
 | 
			
		||||
  flutter_plugin_android_lifecycle:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_plugin_android_lifecycle
 | 
			
		||||
      sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da
 | 
			
		||||
      sha256: c6b0b4c05c458e1c01ad9bcc14041dd7b1f6783d487be4386f793f47a8a4d03e
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.17"
 | 
			
		||||
    version: "2.0.20"
 | 
			
		||||
  flutter_test:
 | 
			
		||||
    dependency: "direct dev"
 | 
			
		||||
    description: flutter
 | 
			
		||||
    source: sdk
 | 
			
		||||
    version: "0.0.0"
 | 
			
		||||
  flutter_typeahead:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_typeahead
 | 
			
		||||
      sha256: d64712c65db240b1057559b952398ebb6e498077baeebf9b0731dade62438a6d
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "5.2.0"
 | 
			
		||||
  flutter_web_plugins:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description: flutter
 | 
			
		||||
@@ -362,10 +467,18 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: fluttertoast
 | 
			
		||||
      sha256: dfdde255317af381bfc1c486ed968d5a43a2ded9c931e87cbecd88767d6a71c1
 | 
			
		||||
      sha256: "7eae679e596a44fdf761853a706f74979f8dd3cd92cf4e23cae161fda091b847"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "8.2.4"
 | 
			
		||||
    version: "8.2.6"
 | 
			
		||||
  fraction:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: fraction
 | 
			
		||||
      sha256: "09e9504c9177bbd77df56e5d147abfbb3b43360e64bf61510059c14d6a82d524"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "5.0.2"
 | 
			
		||||
  gtk:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -410,68 +523,60 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: image
 | 
			
		||||
      sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e"
 | 
			
		||||
      sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "4.1.7"
 | 
			
		||||
    version: "4.2.0"
 | 
			
		||||
  intl:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: intl
 | 
			
		||||
      sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
 | 
			
		||||
      sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.18.1"
 | 
			
		||||
  js:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: js
 | 
			
		||||
      sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.6.7"
 | 
			
		||||
    version: "0.19.0"
 | 
			
		||||
  json_annotation:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: json_annotation
 | 
			
		||||
      sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
 | 
			
		||||
      sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "4.8.1"
 | 
			
		||||
    version: "4.9.0"
 | 
			
		||||
  leak_tracker:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: leak_tracker
 | 
			
		||||
      sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
 | 
			
		||||
      sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "10.0.0"
 | 
			
		||||
    version: "10.0.4"
 | 
			
		||||
  leak_tracker_flutter_testing:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: leak_tracker_flutter_testing
 | 
			
		||||
      sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
 | 
			
		||||
      sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.1"
 | 
			
		||||
    version: "3.0.3"
 | 
			
		||||
  leak_tracker_testing:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: leak_tracker_testing
 | 
			
		||||
      sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
 | 
			
		||||
      sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.1"
 | 
			
		||||
    version: "3.0.1"
 | 
			
		||||
  lints:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: lints
 | 
			
		||||
      sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
 | 
			
		||||
      sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.0.0"
 | 
			
		||||
    version: "4.0.0"
 | 
			
		||||
  markdown:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: markdown
 | 
			
		||||
      sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051
 | 
			
		||||
@@ -498,10 +603,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: meta
 | 
			
		||||
      sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
 | 
			
		||||
      sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.11.0"
 | 
			
		||||
    version: "1.12.0"
 | 
			
		||||
  mime:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -538,26 +643,26 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: path_provider
 | 
			
		||||
      sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
 | 
			
		||||
      sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.1.2"
 | 
			
		||||
    version: "2.1.3"
 | 
			
		||||
  path_provider_android:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: path_provider_android
 | 
			
		||||
      sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
 | 
			
		||||
      sha256: bca87b0165ffd7cdb9cad8edd22d18d2201e886d9a9f19b4fb3452ea7df3a72a
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.2.2"
 | 
			
		||||
    version: "2.2.6"
 | 
			
		||||
  path_provider_foundation:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: path_provider_foundation
 | 
			
		||||
      sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
 | 
			
		||||
      sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.3.2"
 | 
			
		||||
    version: "2.4.0"
 | 
			
		||||
  path_provider_linux:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -586,26 +691,26 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: permission_handler
 | 
			
		||||
      sha256: "74e962b7fad7ff75959161bb2c0ad8fe7f2568ee82621c9c2660b751146bfe44"
 | 
			
		||||
      sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "11.3.0"
 | 
			
		||||
    version: "11.3.1"
 | 
			
		||||
  permission_handler_android:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: permission_handler_android
 | 
			
		||||
      sha256: "1acac6bae58144b442f11e66621c062aead9c99841093c38f5bcdcc24c1c3474"
 | 
			
		||||
      sha256: b29a799ca03be9f999aa6c39f7de5209482d638e6f857f6b93b0875c618b7e54
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "12.0.5"
 | 
			
		||||
    version: "12.0.7"
 | 
			
		||||
  permission_handler_apple:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: permission_handler_apple
 | 
			
		||||
      sha256: bdafc6db74253abb63907f4e357302e6bb786ab41465e8635f362ee71fd8707b
 | 
			
		||||
      sha256: e6f6d73b12438ef13e648c4ae56bd106ec60d17e90a59c4545db6781229082a0
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "9.4.0"
 | 
			
		||||
    version: "9.4.5"
 | 
			
		||||
  permission_handler_html:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -618,10 +723,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: permission_handler_platform_interface
 | 
			
		||||
      sha256: "23dfba8447c076ab5be3dee9ceb66aad345c4a648f0cac292c77b1eb0e800b78"
 | 
			
		||||
      sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "4.2.0"
 | 
			
		||||
    version: "4.2.1"
 | 
			
		||||
  permission_handler_windows:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -634,18 +739,18 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: petitparser
 | 
			
		||||
      sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
 | 
			
		||||
      sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.0.2"
 | 
			
		||||
    version: "5.4.0"
 | 
			
		||||
  platform:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: platform
 | 
			
		||||
      sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
 | 
			
		||||
      sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.1.4"
 | 
			
		||||
    version: "3.1.5"
 | 
			
		||||
  plugin_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -654,14 +759,38 @@ packages:
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.1.8"
 | 
			
		||||
  pointycastle:
 | 
			
		||||
  pointer_interceptor:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: pointycastle
 | 
			
		||||
      sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29"
 | 
			
		||||
      name: pointer_interceptor
 | 
			
		||||
      sha256: d0a8e660d1204eaec5bd34b34cc92174690e076d2e4f893d9d68c486a13b07c4
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.7.4"
 | 
			
		||||
    version: "0.10.1+1"
 | 
			
		||||
  pointer_interceptor_ios:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: pointer_interceptor_ios
 | 
			
		||||
      sha256: a6906772b3205b42c44614fcea28f818b1e5fdad73a4ca742a7bd49818d9c917
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.10.1"
 | 
			
		||||
  pointer_interceptor_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: pointer_interceptor_platform_interface
 | 
			
		||||
      sha256: "0597b0560e14354baeb23f8375cd612e8bd4841bf8306ecb71fcd0bb78552506"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.10.0+1"
 | 
			
		||||
  pointer_interceptor_web:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: pointer_interceptor_web
 | 
			
		||||
      sha256: a6237528b46c411d8d55cdfad8fcb3269fc4cbb26060b14bff94879165887d1e
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.10.2"
 | 
			
		||||
  provider:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
@@ -674,42 +803,42 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: share_plus
 | 
			
		||||
      sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900"
 | 
			
		||||
      sha256: ef3489a969683c4f3d0239010cc8b7a2a46543a8d139e111c06c558875083544
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "7.2.2"
 | 
			
		||||
    version: "9.0.0"
 | 
			
		||||
  share_plus_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: share_plus_platform_interface
 | 
			
		||||
      sha256: df08bc3a07d01f5ea47b45d03ffcba1fa9cd5370fb44b3f38c70e42cced0f956
 | 
			
		||||
      sha256: "0f9e4418835d1b2c3ae78fdb918251959106cefdbc4dd43526e182f80e82f6d4"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.3.1"
 | 
			
		||||
    version: "4.0.0"
 | 
			
		||||
  shared_preferences:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: shared_preferences
 | 
			
		||||
      sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
 | 
			
		||||
      sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.2.2"
 | 
			
		||||
    version: "2.2.3"
 | 
			
		||||
  shared_preferences_android:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: shared_preferences_android
 | 
			
		||||
      sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
 | 
			
		||||
      sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.2.1"
 | 
			
		||||
    version: "2.2.3"
 | 
			
		||||
  shared_preferences_foundation:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: shared_preferences_foundation
 | 
			
		||||
      sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
 | 
			
		||||
      sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.3.5"
 | 
			
		||||
    version: "2.4.0"
 | 
			
		||||
  shared_preferences_linux:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -750,6 +879,15 @@ packages:
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.8.1"
 | 
			
		||||
  shizuku_apk_installer:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      path: "."
 | 
			
		||||
      ref: master
 | 
			
		||||
      resolved-ref: "25acc02612c2e0fcae40d312e047ac48106f8f6b"
 | 
			
		||||
      url: "https://github.com/re7gog/shizuku_apk_installer"
 | 
			
		||||
    source: git
 | 
			
		||||
    version: "0.0.1"
 | 
			
		||||
  sky_engine:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description: flutter
 | 
			
		||||
@@ -775,18 +913,18 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: sqflite
 | 
			
		||||
      sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6
 | 
			
		||||
      sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.3.2"
 | 
			
		||||
    version: "2.3.3+1"
 | 
			
		||||
  sqflite_common:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: sqflite_common
 | 
			
		||||
      sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5"
 | 
			
		||||
      sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.5.3"
 | 
			
		||||
    version: "2.5.4"
 | 
			
		||||
  stack_trace:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -831,18 +969,18 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: test_api
 | 
			
		||||
      sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
 | 
			
		||||
      sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.6.1"
 | 
			
		||||
    version: "0.7.0"
 | 
			
		||||
  timezone:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: timezone
 | 
			
		||||
      sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0"
 | 
			
		||||
      sha256: a6ccda4a69a442098b602c44e61a1e2b4bf6f5516e875bbf0f427d5df14745d5
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.9.2"
 | 
			
		||||
    version: "0.9.3"
 | 
			
		||||
  typed_data:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -855,26 +993,26 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: url_launcher
 | 
			
		||||
      sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e"
 | 
			
		||||
      sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.2.5"
 | 
			
		||||
    version: "6.3.0"
 | 
			
		||||
  url_launcher_android:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: url_launcher_android
 | 
			
		||||
      sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745
 | 
			
		||||
      sha256: ceb2625f0c24ade6ef6778d1de0b2e44f2db71fded235eb52295247feba8c5cf
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.3.0"
 | 
			
		||||
    version: "6.3.3"
 | 
			
		||||
  url_launcher_ios:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: url_launcher_ios
 | 
			
		||||
      sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5"
 | 
			
		||||
      sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.2.5"
 | 
			
		||||
    version: "6.3.0"
 | 
			
		||||
  url_launcher_linux:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -887,10 +1025,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: url_launcher_macos
 | 
			
		||||
      sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234
 | 
			
		||||
      sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.1.0"
 | 
			
		||||
    version: "3.2.0"
 | 
			
		||||
  url_launcher_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -903,10 +1041,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: url_launcher_web
 | 
			
		||||
      sha256: "3692a459204a33e04bc94f5fb91158faf4f2c8903281ddd82915adecdb1a901d"
 | 
			
		||||
      sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.3.0"
 | 
			
		||||
    version: "2.3.1"
 | 
			
		||||
  url_launcher_windows:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -919,10 +1057,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: uuid
 | 
			
		||||
      sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8
 | 
			
		||||
      sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "4.3.3"
 | 
			
		||||
    version: "4.4.0"
 | 
			
		||||
  vector_math:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -935,10 +1073,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: vm_service
 | 
			
		||||
      sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
 | 
			
		||||
      sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "13.0.0"
 | 
			
		||||
    version: "14.2.1"
 | 
			
		||||
  web:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -951,18 +1089,18 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: webview_flutter
 | 
			
		||||
      sha256: "25e1b6e839e8cbfbd708abc6f85ed09d1727e24e08e08c6b8590d7c65c9a8932"
 | 
			
		||||
      sha256: "6869c8786d179f929144b4a1f86e09ac0eddfe475984951ea6c634774c16b522"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "4.7.0"
 | 
			
		||||
    version: "4.8.0"
 | 
			
		||||
  webview_flutter_android:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: webview_flutter_android
 | 
			
		||||
      sha256: "3e5f4e9d818086b0d01a66fb1ff9cc72ab0cc58c71980e3d3661c5685ea0efb0"
 | 
			
		||||
      sha256: f42447ca49523f11d8f70abea55ea211b3cafe172dd7a0e7ac007bb35dd356dc
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.15.0"
 | 
			
		||||
    version: "3.16.4"
 | 
			
		||||
  webview_flutter_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -975,26 +1113,26 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: webview_flutter_wkwebview
 | 
			
		||||
      sha256: "9bf168bccdf179ce90450b5f37e36fe263f591c9338828d6bf09b6f8d0f57f86"
 | 
			
		||||
      sha256: "7affdf9d680c015b11587181171d3cad8093e449db1f7d9f0f08f4f33d24f9a0"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.12.0"
 | 
			
		||||
    version: "3.13.1"
 | 
			
		||||
  win32:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: win32
 | 
			
		||||
      sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480"
 | 
			
		||||
      sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "5.3.0"
 | 
			
		||||
    version: "5.5.1"
 | 
			
		||||
  win32_registry:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: win32_registry
 | 
			
		||||
      sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a"
 | 
			
		||||
      sha256: "10589e0d7f4e053f2c61023a31c9ce01146656a70b7b7f0828c0b46d7da2a9bb"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.1.2"
 | 
			
		||||
    version: "1.1.3"
 | 
			
		||||
  xdg_directories:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -1007,10 +1145,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: xml
 | 
			
		||||
      sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
 | 
			
		||||
      sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.5.0"
 | 
			
		||||
    version: "6.3.0"
 | 
			
		||||
  yaml:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -1020,5 +1158,5 @@ packages:
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.1.2"
 | 
			
		||||
sdks:
 | 
			
		||||
  dart: ">=3.3.0 <4.0.0"
 | 
			
		||||
  flutter: ">=3.19.0"
 | 
			
		||||
  dart: ">=3.4.0 <4.0.0"
 | 
			
		||||
  flutter: ">=3.22.0"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								pubspec.yaml
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								pubspec.yaml
									
									
									
									
									
								
							@@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 | 
			
		||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
			
		||||
# In Windows, build-name is used as the major, minor, and patch parts
 | 
			
		||||
# of the product and file versions while build-number is used as the build suffix.
 | 
			
		||||
version: 1.0.5+2255 # When changing this, update the tag in main() accordingly
 | 
			
		||||
version: 1.1.13+2270
 | 
			
		||||
 | 
			
		||||
environment:
 | 
			
		||||
  sdk: '>=3.0.0 <4.0.0'
 | 
			
		||||
@@ -38,7 +38,7 @@ dependencies:
 | 
			
		||||
  cupertino_icons: ^1.0.5
 | 
			
		||||
  path_provider: ^2.0.11
 | 
			
		||||
  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
 | 
			
		||||
  http: ^1.0.0
 | 
			
		||||
  webview_flutter: ^4.0.0
 | 
			
		||||
@@ -48,27 +48,39 @@ dependencies:
 | 
			
		||||
  url_launcher: ^6.1.5
 | 
			
		||||
  permission_handler: ^11.0.0
 | 
			
		||||
  fluttertoast: ^8.0.9
 | 
			
		||||
  device_info_plus: ^9.0.0
 | 
			
		||||
  file_picker: ^6.0.0
 | 
			
		||||
  device_info_plus: ^10.0.1
 | 
			
		||||
  file_picker: ^8.0.0+1
 | 
			
		||||
  animations: ^2.0.4
 | 
			
		||||
  android_package_installer:
 | 
			
		||||
    git:
 | 
			
		||||
      url: https://github.com/ImranR98/android_package_installer
 | 
			
		||||
      ref: main
 | 
			
		||||
  android_package_manager: ^0.7.0
 | 
			
		||||
  share_plus: ^7.0.0
 | 
			
		||||
  share_plus: ^9.0.0
 | 
			
		||||
  sqflite: ^2.2.0+3
 | 
			
		||||
  easy_localization: ^3.0.1
 | 
			
		||||
  android_intent_plus: ^4.0.0
 | 
			
		||||
  flutter_markdown: ^0.6.14
 | 
			
		||||
  android_intent_plus: ^5.0.1
 | 
			
		||||
  flutter_markdown: ^0.7.1
 | 
			
		||||
  flutter_archive: ^6.0.0
 | 
			
		||||
  hsluv: ^1.1.3
 | 
			
		||||
  connectivity_plus: ^5.0.0
 | 
			
		||||
  connectivity_plus: ^6.0.1
 | 
			
		||||
  shared_storage: ^0.8.0
 | 
			
		||||
  crypto: ^3.0.3
 | 
			
		||||
  app_links: ^3.5.0
 | 
			
		||||
  app_links: ^6.0.1
 | 
			
		||||
  background_fetch: ^1.2.1
 | 
			
		||||
  equations: ^5.0.2
 | 
			
		||||
  flex_color_picker: ^3.4.1
 | 
			
		||||
  android_system_font:
 | 
			
		||||
    git:
 | 
			
		||||
      url: https://github.com/re7gog/android_system_font
 | 
			
		||||
      ref: master
 | 
			
		||||
  shizuku_apk_installer:
 | 
			
		||||
    git:
 | 
			
		||||
      url: https://github.com/re7gog/shizuku_apk_installer
 | 
			
		||||
      ref: master
 | 
			
		||||
 | 
			
		||||
  markdown: any
 | 
			
		||||
  flutter_typeahead: ^5.2.0
 | 
			
		||||
dev_dependencies:
 | 
			
		||||
  flutter_test:
 | 
			
		||||
    sdk: flutter
 | 
			
		||||
@@ -79,7 +91,7 @@ dev_dependencies:
 | 
			
		||||
  # activated in the `analysis_options.yaml` file located at the root of your
 | 
			
		||||
  # package. See that file for information about deactivating specific lint
 | 
			
		||||
  # rules and activating additional ones.
 | 
			
		||||
  flutter_lints: ^3.0.0
 | 
			
		||||
  flutter_lints: ^4.0.0
 | 
			
		||||
 | 
			
		||||
flutter_launcher_icons:
 | 
			
		||||
  android: "ic_launcher"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user