mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-11-04 15:23:28 +01:00 
			
		
		
		
	Compare commits
	
		
			43 Commits
		
	
	
		
			v0.15.3-be
			...
			v0.15.5-be
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9187ac6684 | ||
| 
						 | 
					9640e43bc5 | ||
| 
						 | 
					09b24b36f2 | ||
| 
						 | 
					06a761c0d0 | ||
| 
						 | 
					6ff7d7fcd7 | ||
| 
						 | 
					0f27c79303 | ||
| 
						 | 
					9961ad081f | ||
| 
						 | 
					02056b4f78 | ||
| 
						 | 
					0492588c25 | ||
| 
						 | 
					ad8463ac8b | ||
| 
						 | 
					7843de240a | ||
| 
						 | 
					0037a08017 | ||
| 
						 | 
					92ba432992 | ||
| 
						 | 
					3a521f4014 | ||
| 
						 | 
					e8bbc9799c | ||
| 
						 | 
					96a48b4813 | ||
| 
						 | 
					355450e82d | ||
| 
						 | 
					99307c5b0c | ||
| 
						 | 
					ace8be6514 | ||
| 
						 | 
					1b538931b1 | ||
| 
						 | 
					7ccd08ee2b | ||
| 
						 | 
					104beed594 | ||
| 
						 | 
					e8df594edb | ||
| 
						 | 
					6e922a84f8 | ||
| 
						 | 
					b74bf86277 | ||
| 
						 | 
					6cbe50c9ef | ||
| 
						 | 
					14fcca040b | ||
| 
						 | 
					7bb545cff9 | ||
| 
						 | 
					f52b1a246c | ||
| 
						 | 
					273dfd89cc | ||
| 
						 | 
					52d72d287b | ||
| 
						 | 
					e8d8fcbe69 | ||
| 
						 | 
					30c6c1afd3 | ||
| 
						 | 
					c8c8093b3a | ||
| 
						 | 
					c970b2cf2e | ||
| 
						 | 
					0815283d31 | ||
| 
						 | 
					55ee2d93b8 | ||
| 
						 | 
					c9e17ed42b | ||
| 
						 | 
					76a91b7fe0 | ||
| 
						 | 
					f9b3169b6a | ||
| 
						 | 
					0f74195255 | ||
| 
						 | 
					5ba33786ab | ||
| 
						 | 
					1fc8ee6fee | 
@@ -1,12 +1,14 @@
 | 
				
			|||||||
#  Obtainium
 | 
					#  Obtainium
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[](https://techforpalestine.org/learn-more)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Get Android App Updates Directly From the Source.
 | 
					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)
 | 
					Motivation: [Side Of Burritos - You should use this instead of F-Droid | How to use app RSS feed](https://youtu.be/FFz57zNR_M0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Wiki: [https://github.com/ImranR98/Obtainium/wiki](https://github.com/ImranR98/Obtainium/wiki)
 | 
					Read the Wiki: [https://github.com/ImranR98/Obtainium/wiki](https://github.com/ImranR98/Obtainium/wiki)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Currently supported App sources:
 | 
					Currently supported App sources:
 | 
				
			||||||
- Open Source - General:
 | 
					- Open Source - General:
 | 
				
			||||||
@@ -30,8 +32,8 @@ Currently supported App sources:
 | 
				
			|||||||
  - [Signal](https://signal.org/)
 | 
					  - [Signal](https://signal.org/)
 | 
				
			||||||
  - [VLC](https://videolan.org/)
 | 
					  - [VLC](https://videolan.org/)
 | 
				
			||||||
- Other - App-Specific:
 | 
					- Other - App-Specific:
 | 
				
			||||||
 | 
					  - [WhatsApp](https://whatsapp.com)
 | 
				
			||||||
  - [Telegram App](https://telegram.org)
 | 
					  - [Telegram App](https://telegram.org)
 | 
				
			||||||
  - [Steam Mobile Apps](https://store.steampowered.com/mobile)
 | 
					 | 
				
			||||||
  - [Neutron Code](https://neutroncode.com)
 | 
					  - [Neutron Code](https://neutroncode.com)
 | 
				
			||||||
- "HTML" (Fallback): Any other URL that returns an HTML page with links to APK files
 | 
					- "HTML" (Fallback): Any other URL that returns an HTML page with links to APK files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -96,19 +96,15 @@ repositories {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def shizuku_version = '13.1.5'
 | 
					    def shizuku_version = '13.1.5'
 | 
				
			||||||
    implementation "dev.rikka.shizuku:api:$shizuku_version"
 | 
					    implementation "dev.rikka.shizuku:api:$shizuku_version"
 | 
				
			||||||
    implementation "dev.rikka.shizuku:provider:$shizuku_version"
 | 
					    implementation "dev.rikka.shizuku:provider:$shizuku_version"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def hidden_api_version = '4.1.0'
 | 
					    def hidden_api_version = '4.3.1'
 | 
				
			||||||
    // DO NOT UPDATE Hidden API without updating the Android tools
 | 
					 | 
				
			||||||
    // and do not update Android tools without updating the whole Flutter
 | 
					 | 
				
			||||||
    // (also in android/build.gradle)
 | 
					 | 
				
			||||||
    implementation "dev.rikka.tools.refine:runtime:$hidden_api_version"
 | 
					    implementation "dev.rikka.tools.refine:runtime:$hidden_api_version"
 | 
				
			||||||
    implementation "dev.rikka.hidden:compat:$hidden_api_version"
 | 
					    implementation "dev.rikka.hidden:compat:$hidden_api_version"
 | 
				
			||||||
    compileOnly "dev.rikka.hidden:stub:$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"
 | 
					    implementation "com.github.topjohnwu.libsu:core:5.2.2"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,8 @@
 | 
				
			|||||||
        android:label="Obtainium"
 | 
					        android:label="Obtainium"
 | 
				
			||||||
        android:name="${applicationName}"
 | 
					        android:name="${applicationName}"
 | 
				
			||||||
        android:icon="@mipmap/ic_launcher"
 | 
					        android:icon="@mipmap/ic_launcher"
 | 
				
			||||||
        android:requestLegacyExternalStorage="true">
 | 
					        android:requestLegacyExternalStorage="true"
 | 
				
			||||||
 | 
					        android:usesCleartextTraffic="true">
 | 
				
			||||||
        <activity
 | 
					        <activity
 | 
				
			||||||
            android:name=".MainActivity"
 | 
					            android:name=".MainActivity"
 | 
				
			||||||
            android:exported="true"
 | 
					            android:exported="true"
 | 
				
			||||||
@@ -44,21 +45,6 @@
 | 
				
			|||||||
        <meta-data
 | 
					        <meta-data
 | 
				
			||||||
            android:name="flutterEmbedding"
 | 
					            android:name="flutterEmbedding"
 | 
				
			||||||
            android:value="2" />
 | 
					            android:value="2" />
 | 
				
			||||||
        <service
 | 
					 | 
				
			||||||
            android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmService"
 | 
					 | 
				
			||||||
            android:permission="android.permission.BIND_JOB_SERVICE"
 | 
					 | 
				
			||||||
            android:exported="false" />
 | 
					 | 
				
			||||||
        <receiver
 | 
					 | 
				
			||||||
            android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmBroadcastReceiver"
 | 
					 | 
				
			||||||
            android:exported="false" />
 | 
					 | 
				
			||||||
        <receiver
 | 
					 | 
				
			||||||
            android:name="dev.fluttercommunity.plus.androidalarmmanager.RebootBroadcastReceiver"
 | 
					 | 
				
			||||||
            android:enabled="false"
 | 
					 | 
				
			||||||
            android:exported="false">
 | 
					 | 
				
			||||||
            <intent-filter>
 | 
					 | 
				
			||||||
                <action android:name="android.intent.action.BOOT_COMPLETED" />
 | 
					 | 
				
			||||||
            </intent-filter>
 | 
					 | 
				
			||||||
        </receiver>
 | 
					 | 
				
			||||||
        <provider
 | 
					        <provider
 | 
				
			||||||
            android:name="androidx.core.content.FileProvider"
 | 
					            android:name="androidx.core.content.FileProvider"
 | 
				
			||||||
            android:authorities="dev.imranr.obtainium"
 | 
					            android:authorities="dev.imranr.obtainium"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					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"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -22,12 +22,13 @@ import io.flutter.plugin.common.MethodChannel
 | 
				
			|||||||
import io.flutter.plugin.common.MethodChannel.Result
 | 
					import io.flutter.plugin.common.MethodChannel.Result
 | 
				
			||||||
import java.io.IOException
 | 
					import java.io.IOException
 | 
				
			||||||
import java.util.concurrent.CountDownLatch
 | 
					import java.util.concurrent.CountDownLatch
 | 
				
			||||||
 | 
					import org.lsposed.hiddenapibypass.HiddenApiBypass
 | 
				
			||||||
import rikka.shizuku.Shizuku
 | 
					import rikka.shizuku.Shizuku
 | 
				
			||||||
import rikka.shizuku.Shizuku.OnRequestPermissionResultListener
 | 
					import rikka.shizuku.Shizuku.OnRequestPermissionResultListener
 | 
				
			||||||
import rikka.shizuku.ShizukuBinderWrapper
 | 
					import rikka.shizuku.ShizukuBinderWrapper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MainActivity: FlutterActivity() {
 | 
					class MainActivity: FlutterActivity() {
 | 
				
			||||||
    private var installersChannel: MethodChannel? = null
 | 
					    private var nativeChannel: MethodChannel? = null
 | 
				
			||||||
    private val SHIZUKU_PERMISSION_REQUEST_CODE = (10..200).random()
 | 
					    private val SHIZUKU_PERMISSION_REQUEST_CODE = (10..200).random()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun shizukuCheckPermission(result: Result) {
 | 
					    private fun shizukuCheckPermission(result: Result) {
 | 
				
			||||||
@@ -51,7 +52,7 @@ class MainActivity: FlutterActivity() {
 | 
				
			|||||||
            requestCode: Int, grantResult: Int ->
 | 
					            requestCode: Int, grantResult: Int ->
 | 
				
			||||||
        if (requestCode == SHIZUKU_PERMISSION_REQUEST_CODE) {
 | 
					        if (requestCode == SHIZUKU_PERMISSION_REQUEST_CODE) {
 | 
				
			||||||
            val res = if (grantResult == PackageManager.PERMISSION_GRANTED) 1 else 0
 | 
					            val res = if (grantResult == PackageManager.PERMISSION_GRANTED) 1 else 0
 | 
				
			||||||
            installersChannel!!.invokeMethod("resPermShizuku", mapOf("res" to res))
 | 
					            nativeChannel!!.invokeMethod("resPermShizuku", mapOf("res" to res))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -76,7 +77,8 @@ class MainActivity: FlutterActivity() {
 | 
				
			|||||||
            val params =
 | 
					            val params =
 | 
				
			||||||
                PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
 | 
					                PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
 | 
				
			||||||
            var installFlags: Int = PackageInstallerUtils.getInstallFlags(params)
 | 
					            var installFlags: Int = PackageInstallerUtils.getInstallFlags(params)
 | 
				
			||||||
            installFlags = installFlags or 0x00000004  // PackageManager.INSTALL_ALLOW_TEST
 | 
					            installFlags = installFlags or (0x00000002/*PackageManager.INSTALL_REPLACE_EXISTING*/
 | 
				
			||||||
 | 
					                    or 0x00000004 /*PackageManager.INSTALL_ALLOW_TEST*/)
 | 
				
			||||||
            PackageInstallerUtils.setInstallFlags(params, installFlags)
 | 
					            PackageInstallerUtils.setInstallFlags(params, installFlags)
 | 
				
			||||||
            val sessionId = packageInstaller.createSession(params)
 | 
					            val sessionId = packageInstaller.createSession(params)
 | 
				
			||||||
            val iSession = IPackageInstallerSession.Stub.asInterface(
 | 
					            val iSession = IPackageInstallerSession.Stub.asInterface(
 | 
				
			||||||
@@ -136,7 +138,7 @@ class MainActivity: FlutterActivity() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private fun rootInstallApk(apkFilePath: String, result: Result) {
 | 
					    private fun rootInstallApk(apkFilePath: String, result: Result) {
 | 
				
			||||||
        Shell.sh("pm install -R -t " + apkFilePath).submit { out ->
 | 
					        Shell.sh("pm install -r -t " + apkFilePath).submit { out ->
 | 
				
			||||||
            val builder = StringBuilder()
 | 
					            val builder = StringBuilder()
 | 
				
			||||||
            for (data in out.getOut()) { builder.append(data) }
 | 
					            for (data in out.getOut()) { builder.append(data) }
 | 
				
			||||||
            result.success(builder.toString().endsWith("Success"))
 | 
					            result.success(builder.toString().endsWith("Success"))
 | 
				
			||||||
@@ -145,12 +147,18 @@ class MainActivity: FlutterActivity() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
 | 
					    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
 | 
				
			||||||
        super.configureFlutterEngine(flutterEngine)
 | 
					        super.configureFlutterEngine(flutterEngine)
 | 
				
			||||||
 | 
					        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
 | 
				
			||||||
 | 
					            HiddenApiBypass.addHiddenApiExemptions("")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        Shizuku.addRequestPermissionResultListener(shizukuRequestPermissionResultListener)
 | 
					        Shizuku.addRequestPermissionResultListener(shizukuRequestPermissionResultListener)
 | 
				
			||||||
        installersChannel = MethodChannel(
 | 
					        nativeChannel = MethodChannel(
 | 
				
			||||||
            flutterEngine.dartExecutor.binaryMessenger, "installers")
 | 
					            flutterEngine.dartExecutor.binaryMessenger, "native")
 | 
				
			||||||
        installersChannel!!.setMethodCallHandler {
 | 
					        nativeChannel!!.setMethodCallHandler {
 | 
				
			||||||
            call, result ->
 | 
					            call, result ->
 | 
				
			||||||
            if (call.method == "checkPermissionShizuku") {
 | 
					            if (call.method == "getSystemFont") {
 | 
				
			||||||
 | 
					                val res = DefaultSystemFont().get()
 | 
				
			||||||
 | 
					                result.success(res)
 | 
				
			||||||
 | 
					            } else if (call.method == "checkPermissionShizuku") {
 | 
				
			||||||
                shizukuCheckPermission(result)
 | 
					                shizukuCheckPermission(result)
 | 
				
			||||||
            } else if (call.method == "checkPermissionRoot") {
 | 
					            } else if (call.method == "checkPermissionRoot") {
 | 
				
			||||||
                rootCheckPermission(result)
 | 
					                rootCheckPermission(result)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
buildscript {
 | 
					buildscript {
 | 
				
			||||||
    ext.kotlin_version = '1.7.10'
 | 
					    ext.kotlin_version = '1.8.10'
 | 
				
			||||||
    ext {
 | 
					    ext {
 | 
				
			||||||
        compileSdkVersion   = 34                // or latest
 | 
					        compileSdkVersion   = 34                // or latest
 | 
				
			||||||
        targetSdkVersion    = 34                // or latest
 | 
					        targetSdkVersion    = 34                // or latest
 | 
				
			||||||
@@ -11,9 +11,9 @@ buildscript {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dependencies {
 | 
					    dependencies {
 | 
				
			||||||
        classpath 'com.android.tools.build:gradle:7.2.0'
 | 
					        classpath "com.android.tools.build:gradle:7.4.2"
 | 
				
			||||||
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 | 
					        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 | 
				
			||||||
        classpath 'dev.rikka.tools.refine:gradle-plugin:4.1.0'  // Do not update!
 | 
					        classpath "dev.rikka.tools.refine:gradle-plugin:4.3.1"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Uvezi greške",
 | 
					    "importErrors": "Uvezi greške",
 | 
				
			||||||
    "importedXOfYApps": "{} od {} aplikacija uvezeno.",
 | 
					    "importedXOfYApps": "{} od {} aplikacija uvezeno.",
 | 
				
			||||||
    "followingURLsHadErrors": "Sljedeći URL-ovi su imali greške:",
 | 
					    "followingURLsHadErrors": "Sljedeći URL-ovi su imali greške:",
 | 
				
			||||||
    "okay": "Dobro",
 | 
					 | 
				
			||||||
    "selectURL": "Odaberite URL",
 | 
					    "selectURL": "Odaberite URL",
 | 
				
			||||||
    "selectURLs": "Odaberite URL-ove",
 | 
					    "selectURLs": "Odaberite URL-ove",
 | 
				
			||||||
    "pick": "Odaberi",
 | 
					    "pick": "Odaberi",
 | 
				
			||||||
@@ -283,6 +282,11 @@
 | 
				
			|||||||
    "supportFixedAPKURL": "Podržite fiksne APK URL-ove",
 | 
					    "supportFixedAPKURL": "Podržite fiksne APK URL-ove",
 | 
				
			||||||
    "selectX": "Izaberite {}",
 | 
					    "selectX": "Izaberite {}",
 | 
				
			||||||
    "parallelDownloads": "Allow parallel downloads",
 | 
					    "parallelDownloads": "Allow parallel downloads",
 | 
				
			||||||
 | 
					    "installMethod": "Installation method",
 | 
				
			||||||
 | 
					    "normal": "Normal",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizuku is not running",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Želite li ukloniti aplikaciju?",
 | 
					        "one": "Želite li ukloniti aplikaciju?",
 | 
				
			||||||
        "other": "Želite li ukloniti aplikacije?"
 | 
					        "other": "Želite li ukloniti aplikacije?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Chyba importu",
 | 
					    "importErrors": "Chyba importu",
 | 
				
			||||||
    "importedXOfYApps": "{}importováno z {} aplikací.",
 | 
					    "importedXOfYApps": "{}importováno z {} aplikací.",
 | 
				
			||||||
    "followingURLsHadErrors": "U následujících adres došlo k chybám:",
 | 
					    "followingURLsHadErrors": "U následujících adres došlo k chybám:",
 | 
				
			||||||
    "okay": "Okay",
 | 
					 | 
				
			||||||
    "selectURL": "Vybrat adresu",
 | 
					    "selectURL": "Vybrat adresu",
 | 
				
			||||||
    "selectURLs": "Select adresy",
 | 
					    "selectURLs": "Select adresy",
 | 
				
			||||||
    "pick": "Vybrat",
 | 
					    "pick": "Vybrat",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Importfehler",
 | 
					    "importErrors": "Importfehler",
 | 
				
			||||||
    "importedXOfYApps": "{} von {} Apps importiert.",
 | 
					    "importedXOfYApps": "{} von {} Apps importiert.",
 | 
				
			||||||
    "followingURLsHadErrors": "Bei folgenden URLs traten Fehler auf:",
 | 
					    "followingURLsHadErrors": "Bei folgenden URLs traten Fehler auf:",
 | 
				
			||||||
    "okay": "Okay",
 | 
					 | 
				
			||||||
    "selectURL": "URL auswählen",
 | 
					    "selectURL": "URL auswählen",
 | 
				
			||||||
    "selectURLs": "URLs auswählen",
 | 
					    "selectURLs": "URLs auswählen",
 | 
				
			||||||
    "pick": "Auswählen",
 | 
					    "pick": "Auswählen",
 | 
				
			||||||
@@ -283,6 +282,11 @@
 | 
				
			|||||||
    "supportFixedAPKURL": "neuere Version anhand der ersten dreißig Zahlen der Checksumme der APK URL erraten, wenn anderweitig nicht unterstützt",
 | 
					    "supportFixedAPKURL": "neuere Version anhand der ersten dreißig Zahlen der Checksumme der APK URL erraten, wenn anderweitig nicht unterstützt",
 | 
				
			||||||
    "selectX": "Wähle {}",
 | 
					    "selectX": "Wähle {}",
 | 
				
			||||||
    "parallelDownloads": "Erlaube parallele Downloads",
 | 
					    "parallelDownloads": "Erlaube parallele Downloads",
 | 
				
			||||||
 | 
					    "installMethod": "Installationsmethode",
 | 
				
			||||||
 | 
					    "normal": "Normal",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizuku läuft nicht",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "App entfernen?",
 | 
					        "one": "App entfernen?",
 | 
				
			||||||
        "other": "Apps entfernen?"
 | 
					        "other": "Apps entfernen?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Import Errors",
 | 
					    "importErrors": "Import Errors",
 | 
				
			||||||
    "importedXOfYApps": "{} of {} Apps imported.",
 | 
					    "importedXOfYApps": "{} of {} Apps imported.",
 | 
				
			||||||
    "followingURLsHadErrors": "The following URLs had errors:",
 | 
					    "followingURLsHadErrors": "The following URLs had errors:",
 | 
				
			||||||
    "okay": "Okay",
 | 
					 | 
				
			||||||
    "selectURL": "Select URL",
 | 
					    "selectURL": "Select URL",
 | 
				
			||||||
    "selectURLs": "Select URLs",
 | 
					    "selectURLs": "Select URLs",
 | 
				
			||||||
    "pick": "Pick",
 | 
					    "pick": "Pick",
 | 
				
			||||||
@@ -287,7 +286,9 @@
 | 
				
			|||||||
    "normal": "Normal",
 | 
					    "normal": "Normal",
 | 
				
			||||||
    "shizuku": "Shizuku",
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
    "root": "Root",
 | 
					    "root": "Root",
 | 
				
			||||||
    "shizukuBinderNotFound": "Shizuku is not running",
 | 
					    "shizukuBinderNotFound": "Сompatible Shizuku service wasn't found",
 | 
				
			||||||
 | 
					    "useSystemFont": "Use the system font",
 | 
				
			||||||
 | 
					    "systemFontError": "Error loading the system font: {}",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Remove App?",
 | 
					        "one": "Remove App?",
 | 
				
			||||||
        "other": "Remove Apps?"
 | 
					        "other": "Remove Apps?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,13 +8,13 @@
 | 
				
			|||||||
    "functionNotImplemented": "Esta clase no ha implementado esta función",
 | 
					    "functionNotImplemented": "Esta clase no ha implementado esta función",
 | 
				
			||||||
    "placeholder": "Espacio reservado",
 | 
					    "placeholder": "Espacio reservado",
 | 
				
			||||||
    "someErrors": "Han ocurrido algunos errores",
 | 
					    "someErrors": "Han ocurrido algunos errores",
 | 
				
			||||||
    "unexpectedError": "Error Inesperado",
 | 
					    "unexpectedError": "Error inesperado",
 | 
				
			||||||
    "ok": "OK",
 | 
					    "ok": "OK",
 | 
				
			||||||
    "and": "y",
 | 
					    "and": "y",
 | 
				
			||||||
    "githubPATLabel": "Token Github de Acceso Personal\n(Reduce tiempos de espera)",
 | 
					    "githubPATLabel": "Token GitHub de acceso personal\n(reduce tiempos de espera)",
 | 
				
			||||||
    "includePrereleases": "Incluir versiones preliminares",
 | 
					    "includePrereleases": "Incluir versiones preliminares",
 | 
				
			||||||
    "fallbackToOlderReleases": "Retroceder a versiones previas",
 | 
					    "fallbackToOlderReleases": "Retroceder a versiones previas",
 | 
				
			||||||
    "filterReleaseTitlesByRegEx": "Filtrar por título de version",
 | 
					    "filterReleaseTitlesByRegEx": "Filtrar por título de versión",
 | 
				
			||||||
    "invalidRegEx": "Expresión inválida",
 | 
					    "invalidRegEx": "Expresión inválida",
 | 
				
			||||||
    "noDescription": "Sin descripción",
 | 
					    "noDescription": "Sin descripción",
 | 
				
			||||||
    "cancel": "Cancelar",
 | 
					    "cancel": "Cancelar",
 | 
				
			||||||
@@ -25,11 +25,11 @@
 | 
				
			|||||||
    "githubStarredRepos": "Repositorios favoritos GitHub",
 | 
					    "githubStarredRepos": "Repositorios favoritos GitHub",
 | 
				
			||||||
    "uname": "Nombre de usuario",
 | 
					    "uname": "Nombre de usuario",
 | 
				
			||||||
    "wrongArgNum": "Número de argumentos provistos inválido",
 | 
					    "wrongArgNum": "Número de argumentos provistos inválido",
 | 
				
			||||||
    "xIsTrackOnly": "{} es de 'Solo Seguimiento'",
 | 
					    "xIsTrackOnly": "{} es de 'Sólo seguimiento'",
 | 
				
			||||||
    "source": "Origen",
 | 
					    "source": "Origen",
 | 
				
			||||||
    "app": "Aplicación",
 | 
					    "app": "Aplicación",
 | 
				
			||||||
    "appsFromSourceAreTrackOnly": "Las aplicaciones de este origen son de 'Solo Seguimiento'.",
 | 
					    "appsFromSourceAreTrackOnly": "Las aplicaciones de este origen son de 'solo seguimiento'.",
 | 
				
			||||||
    "youPickedTrackOnly": "Debe seleccionar la opción de 'Solo Seguimiento'.",
 | 
					    "youPickedTrackOnly": "Debe seleccionar la opción de 'solo seguimiento'.",
 | 
				
			||||||
    "trackOnlyAppDescription": "Se hará el seguimiento de actualizaciones para la aplicación, pero Obtainium no será capaz de descargarla o actalizarla.",
 | 
					    "trackOnlyAppDescription": "Se hará el seguimiento de actualizaciones para la aplicación, pero Obtainium no será capaz de descargarla o actalizarla.",
 | 
				
			||||||
    "cancelled": "Cancelado",
 | 
					    "cancelled": "Cancelado",
 | 
				
			||||||
    "appAlreadyAdded": "Aplicación ya añadida",
 | 
					    "appAlreadyAdded": "Aplicación ya añadida",
 | 
				
			||||||
@@ -42,7 +42,7 @@
 | 
				
			|||||||
    "search": "Buscar",
 | 
					    "search": "Buscar",
 | 
				
			||||||
    "additionalOptsFor": "Opciones Adicionales para {}",
 | 
					    "additionalOptsFor": "Opciones Adicionales para {}",
 | 
				
			||||||
    "supportedSources": "Fuentes Soportadas",
 | 
					    "supportedSources": "Fuentes Soportadas",
 | 
				
			||||||
    "trackOnlyInBrackets": "(Solo Seguimiento)",
 | 
					    "trackOnlyInBrackets": "(Solo seguimiento)",
 | 
				
			||||||
    "searchableInBrackets": "(soporta búsqueda)",
 | 
					    "searchableInBrackets": "(soporta búsqueda)",
 | 
				
			||||||
    "appsString": "Aplicaciones",
 | 
					    "appsString": "Aplicaciones",
 | 
				
			||||||
    "noApps": "Sin Aplicaciones",
 | 
					    "noApps": "Sin Aplicaciones",
 | 
				
			||||||
@@ -61,27 +61,27 @@
 | 
				
			|||||||
    "removeSelectedApps": "Eliminar Aplicaciones Seleccionadas",
 | 
					    "removeSelectedApps": "Eliminar Aplicaciones Seleccionadas",
 | 
				
			||||||
    "updateX": "Actualizar {}",
 | 
					    "updateX": "Actualizar {}",
 | 
				
			||||||
    "installX": "Instalar {}",
 | 
					    "installX": "Instalar {}",
 | 
				
			||||||
    "markXTrackOnlyAsUpdated": "Marcar {}\n(Solo Seguimiento)\ncomo Actualizada",
 | 
					    "markXTrackOnlyAsUpdated": "Marcar {}\n(Solo seguimiento)\ncomo actualizada",
 | 
				
			||||||
    "changeX": "Cambiar {}",
 | 
					    "changeX": "Cambiar {}",
 | 
				
			||||||
    "installUpdateApps": "Instalar/Actualizar Aplicaciones",
 | 
					    "installUpdateApps": "Instalar/Actualizar aplicaciones",
 | 
				
			||||||
    "installUpdateSelectedApps": "Instalar/Actualizar Aplicaciones Seleccionadas",
 | 
					    "installUpdateSelectedApps": "Instalar/Actualizar aplicaciones seleccionadas",
 | 
				
			||||||
    "markXSelectedAppsAsUpdated": "¿Marcar {} Aplicaciones Seleccionadas como Actualizadas?",
 | 
					    "markXSelectedAppsAsUpdated": "¿Marcar {} aplicaciones seleccionadas como actualizadas?",
 | 
				
			||||||
    "no": "No",
 | 
					    "no": "No",
 | 
				
			||||||
    "yes": "Sí",
 | 
					    "yes": "Sí",
 | 
				
			||||||
    "markSelectedAppsUpdated": "Marcar Aplicaciones Seleccionadas como Actualizadas",
 | 
					    "markSelectedAppsUpdated": "Marcar aplicaciones seleccionadas como actualizadas",
 | 
				
			||||||
    "pinToTop": "Fijar arriba",
 | 
					    "pinToTop": "Fijar arriba",
 | 
				
			||||||
    "unpinFromTop": "Desfijar de arriba",
 | 
					    "unpinFromTop": "Desfijar de arriba",
 | 
				
			||||||
    "resetInstallStatusForSelectedAppsQuestion": "¿Restuarar Estado de Instalación para las Aplicaciones Seleccionadas?",
 | 
					    "resetInstallStatusForSelectedAppsQuestion": "¿Restuarar estado de instalación para las aplicaciones seleccionadas?",
 | 
				
			||||||
    "installStatusOfXWillBeResetExplanation": "El estado de instalación de las aplicaciones seleccionadas será restaurado.\n\nEsto puede ser de útil cuando la versión de la aplicación mostrada en Obtainium es incorrecta por actualizaciones fallidas u otros motivos.",
 | 
					    "installStatusOfXWillBeResetExplanation": "El estado de instalación de las aplicaciones seleccionadas será restaurado.\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.",
 | 
				
			||||||
    "shareSelectedAppURLs": "Compartir URLs de las Aplicaciones Seleccionadas",
 | 
					    "shareSelectedAppURLs": "Compartir URLs de las aplicaciones seleccionadas",
 | 
				
			||||||
    "resetInstallStatus": "Restaurar Estado de Instalación",
 | 
					    "resetInstallStatus": "Restaurar Estado de Instalación",
 | 
				
			||||||
    "more": "Más",
 | 
					    "more": "Más",
 | 
				
			||||||
    "removeOutdatedFilter": "Elimiar Filtro de Aplicaciones Desactualizado",
 | 
					    "removeOutdatedFilter": "Elimiar filtro de aplicaciones desactualizado",
 | 
				
			||||||
    "showOutdatedOnly": "Mostrar solo Aplicaciones Desactualizadas",
 | 
					    "showOutdatedOnly": "Mostrar solo aplicaciones desactualizadas",
 | 
				
			||||||
    "filter": "Filtrar",
 | 
					    "filter": "Filtrar",
 | 
				
			||||||
    "filterActive": "Filtrar *",
 | 
					    "filterActive": "Filtrar *",
 | 
				
			||||||
    "filterApps": "Filtrar Actualizaciones",
 | 
					    "filterApps": "Filtrar Actualizaciones",
 | 
				
			||||||
    "appName": "Nombre de la Aplicación",
 | 
					    "appName": "Nombre de la aplicación",
 | 
				
			||||||
    "author": "Autor",
 | 
					    "author": "Autor",
 | 
				
			||||||
    "upToDateApps": "Aplicaciones Actualizadas",
 | 
					    "upToDateApps": "Aplicaciones Actualizadas",
 | 
				
			||||||
    "nonInstalledApps": "Aplicaciones No Instaladas",
 | 
					    "nonInstalledApps": "Aplicaciones No Instaladas",
 | 
				
			||||||
@@ -103,14 +103,13 @@
 | 
				
			|||||||
    "importErrors": "Errores de Importación",
 | 
					    "importErrors": "Errores de Importación",
 | 
				
			||||||
    "importedXOfYApps": "{} de {} Aplicaciones importadas.",
 | 
					    "importedXOfYApps": "{} de {} Aplicaciones importadas.",
 | 
				
			||||||
    "followingURLsHadErrors": "Las siguientes URLs han tenido problemas:",
 | 
					    "followingURLsHadErrors": "Las siguientes URLs han tenido problemas:",
 | 
				
			||||||
    "okay": "Aceptar",
 | 
					 | 
				
			||||||
    "selectURL": "Seleccionar URL",
 | 
					    "selectURL": "Seleccionar URL",
 | 
				
			||||||
    "selectURLs": "Seleccionar URLs",
 | 
					    "selectURLs": "Seleccionar URLs",
 | 
				
			||||||
    "pick": "Escoger",
 | 
					    "pick": "Escoger",
 | 
				
			||||||
    "theme": "Tema",
 | 
					    "theme": "Tema",
 | 
				
			||||||
    "dark": "Oscuro",
 | 
					    "dark": "Oscuro",
 | 
				
			||||||
    "light": "Claro",
 | 
					    "light": "Claro",
 | 
				
			||||||
    "followSystem": "Seguir al Sistema",
 | 
					    "followSystem": "Seguir al sistema",
 | 
				
			||||||
    "obtainium": "Obtainium",
 | 
					    "obtainium": "Obtainium",
 | 
				
			||||||
    "materialYou": "Material You",
 | 
					    "materialYou": "Material You",
 | 
				
			||||||
    "useBlackTheme": "Negro puro en tema Oscuro",
 | 
					    "useBlackTheme": "Negro puro en tema Oscuro",
 | 
				
			||||||
@@ -121,16 +120,16 @@
 | 
				
			|||||||
    "appSortOrder": "Orden de Clasificación",
 | 
					    "appSortOrder": "Orden de Clasificación",
 | 
				
			||||||
    "ascending": "Ascendente",
 | 
					    "ascending": "Ascendente",
 | 
				
			||||||
    "descending": "Descendente",
 | 
					    "descending": "Descendente",
 | 
				
			||||||
    "bgUpdateCheckInterval": "Intervalo de Comprobación de Actualizaciones en Segundo Plano",
 | 
					    "bgUpdateCheckInterval": "Comprobación actualizaciones en segundo plano",
 | 
				
			||||||
    "neverManualOnly": "Nunca - Solo Manual",
 | 
					    "neverManualOnly": "Nunca, solo manual",
 | 
				
			||||||
    "appearance": "Apariencia",
 | 
					    "appearance": "Apariencia",
 | 
				
			||||||
    "showWebInAppView": "Mostrar Vista de la Web de Origen",
 | 
					    "showWebInAppView": "Mostrar vista de la web de origen",
 | 
				
			||||||
    "pinUpdates": "Fijar Actualizaciones en la Parte Superior de la Vista de Aplicaciones",
 | 
					    "pinUpdates": "Fijar Actualizaciones al principio",
 | 
				
			||||||
    "updates": "Actualizaciones",
 | 
					    "updates": "Actualizaciones",
 | 
				
			||||||
    "sourceSpecific": "Fuente Específica",
 | 
					    "sourceSpecific": "Fuente Específica",
 | 
				
			||||||
    "appSource": "Fuente de la Aplicación",
 | 
					    "appSource": "Obtainium en GitHub",
 | 
				
			||||||
    "noLogs": "Sin Logs",
 | 
					    "noLogs": "Sin Logs",
 | 
				
			||||||
    "appLogs": "Logs de la Aplicación",
 | 
					    "appLogs": "Logs",
 | 
				
			||||||
    "close": "Cerrar",
 | 
					    "close": "Cerrar",
 | 
				
			||||||
    "share": "Compartir",
 | 
					    "share": "Compartir",
 | 
				
			||||||
    "appNotFound": "Aplicación no encontrada",
 | 
					    "appNotFound": "Aplicación no encontrada",
 | 
				
			||||||
@@ -214,30 +213,30 @@
 | 
				
			|||||||
    "importFromURLsInFile": "Importar URLs desde archivo (como OPML)",
 | 
					    "importFromURLsInFile": "Importar URLs desde archivo (como OPML)",
 | 
				
			||||||
    "versionDetection": "Detección de Versiones",
 | 
					    "versionDetection": "Detección de Versiones",
 | 
				
			||||||
    "standardVersionDetection": "Por versión",
 | 
					    "standardVersionDetection": "Por versión",
 | 
				
			||||||
    "groupByCategory": "Agrupar por Categoría",
 | 
					    "groupByCategory": "Agrupar por categoría",
 | 
				
			||||||
    "autoApkFilterByArch": "Filtrar APKs por arquitectura del procesador, si es posible",
 | 
					    "autoApkFilterByArch": "Filtrar APKs por arquitectura del procesador (si es posible)",
 | 
				
			||||||
    "overrideSource": "Sobrescribir Fuente",
 | 
					    "overrideSource": "Sobrescribir Fuente",
 | 
				
			||||||
    "dontShowAgain": "No mostrar de nuevo",
 | 
					    "dontShowAgain": "No mostrar de nuevo",
 | 
				
			||||||
    "dontShowTrackOnlyWarnings": "No mostrar avisos de 'Solo Seguimiento'",
 | 
					    "dontShowTrackOnlyWarnings": "No mostrar avisos sobre apps en 'solo seguimiento'",
 | 
				
			||||||
    "dontShowAPKOriginWarnings": "No mostrar avisos de las fuentes de las APKs",
 | 
					    "dontShowAPKOriginWarnings": "No mostrar avisos sobre las fuentes de las APKs",
 | 
				
			||||||
    "moveNonInstalledAppsToBottom": "Mover Apps no instaladas en la Parte Inferior de la Vista de Aplicaciones",
 | 
					    "moveNonInstalledAppsToBottom": "Mover Apps no instaladas al final",
 | 
				
			||||||
    "gitlabPATLabel": "Token GitLab de Acceso Personal\n(Habilita la Búsqueda y Mejor Detección de APKs)",
 | 
					    "gitlabPATLabel": "Token GitLab de acceso personal\n(habilita la búsqueda y mejor detección de APKs)",
 | 
				
			||||||
    "about": "Acerca",
 | 
					    "about": "Acerca",
 | 
				
			||||||
    "requiresCredentialsInSettings": "{}: Esto requiere credenciales adicionales (en Ajustes)",
 | 
					    "requiresCredentialsInSettings": "{}: Esto requiere credenciales adicionales (en ajustes)",
 | 
				
			||||||
    "checkOnStart": "Comprobar actualizaciones durante el inicio",
 | 
					    "checkOnStart": "Comprobar actualizaciones al inicio",
 | 
				
			||||||
    "tryInferAppIdFromCode": "Intentar deducir la ID de la APP por el código fuente",
 | 
					    "tryInferAppIdFromCode": "Intentar deducir la ID de la app por el código fuente",
 | 
				
			||||||
    "removeOnExternalUninstall": "Auto eliminar Apps desinstaladas externamente",
 | 
					    "removeOnExternalUninstall": "Auto eliminar apps desinstaladas externamente",
 | 
				
			||||||
    "pickHighestVersionCode": "Auto selección versión superior del código APK",
 | 
					    "pickHighestVersionCode": "Auto selección versión superior del código APK",
 | 
				
			||||||
    "checkUpdateOnDetailPage": "Comprobar actualizaciones al abrir detalles de la App",
 | 
					    "checkUpdateOnDetailPage": "Comprobar actualizaciones al abrir detalles de la app",
 | 
				
			||||||
    "disablePageTransitions": "Deshabilitar animaciones de transición de la página",
 | 
					    "disablePageTransitions": "Deshabilitar animaciones de transición",
 | 
				
			||||||
    "reversePageTransitions": "Invertir animaciones de transición de la página",
 | 
					    "reversePageTransitions": "Invertir animaciones de transición",
 | 
				
			||||||
    "minStarCount": "Número Mínimo de Estrellas",
 | 
					    "minStarCount": "Número Mínimo de Estrellas",
 | 
				
			||||||
    "addInfoBelow": "Añadir esta información debajo.",
 | 
					    "addInfoBelow": "Añadir esta información debajo.",
 | 
				
			||||||
    "addInfoInSettings": "Puede añadir esta información en Ajustes.",
 | 
					    "addInfoInSettings": "Puede añadir esta información en Ajustes.",
 | 
				
			||||||
    "githubSourceNote": "La limitación de velocidad de GitHub puede evitarse con una clave API.",
 | 
					    "githubSourceNote": "La limitación de velocidad de GitHub puede evitarse con una clave API.",
 | 
				
			||||||
    "gitlabSourceNote": "La extracción de APK de GitLab podría no funcionar sin una clave API.",
 | 
					    "gitlabSourceNote": "La extracción de APK de GitLab podría no funcionar sin una clave API.",
 | 
				
			||||||
    "sortByLastLinkSegment": "Sort by only the last segment of the link",
 | 
					    "sortByLastLinkSegment": "Sort by only the last segment of the link",
 | 
				
			||||||
    "filterReleaseNotesByRegEx": "Filtrar por notas de nersión (release notes)",
 | 
					    "filterReleaseNotesByRegEx": "Filtrar por notas de versión (release notes)",
 | 
				
			||||||
    "customLinkFilterRegex": "Filtro personalizado de Enlace APK (por defecto '.apk$')",
 | 
					    "customLinkFilterRegex": "Filtro personalizado de Enlace APK (por defecto '.apk$')",
 | 
				
			||||||
    "appsPossiblyUpdated": "Actualización de Apps intentada",
 | 
					    "appsPossiblyUpdated": "Actualización de Apps intentada",
 | 
				
			||||||
    "appsPossiblyUpdatedNotifDescription": "Notifica al usuario que las actualizaciones en segundo plano podrían haberse realizado para una o más aplicaciones",
 | 
					    "appsPossiblyUpdatedNotifDescription": "Notifica al usuario que las actualizaciones en segundo plano podrían haberse realizado para una o más aplicaciones",
 | 
				
			||||||
@@ -245,7 +244,7 @@
 | 
				
			|||||||
    "enableBackgroundUpdates": "Habilitar actualizaciones en segundo plano",
 | 
					    "enableBackgroundUpdates": "Habilitar actualizaciones en segundo plano",
 | 
				
			||||||
    "backgroundUpdateReqsExplanation": "Las actualizaciones en segundo plano pueden no estar disponibles para todas las aplicaciones.",
 | 
					    "backgroundUpdateReqsExplanation": "Las actualizaciones en segundo plano pueden no estar disponibles para todas las aplicaciones.",
 | 
				
			||||||
    "backgroundUpdateLimitsExplanation": "El éxito de las instalaciones en segundo plano solo se puede comprobar con Obtainium abierto.",
 | 
					    "backgroundUpdateLimitsExplanation": "El éxito de las instalaciones en segundo plano solo se puede comprobar con Obtainium abierto.",
 | 
				
			||||||
    "verifyLatestTag": "Comprueba la etiqueta 'Latest'",
 | 
					    "verifyLatestTag": "Comprobar la etiqueta 'Latest'",
 | 
				
			||||||
    "intermediateLinkRegex": "Filtrar por enlace 'intermedio' para visitar primero",
 | 
					    "intermediateLinkRegex": "Filtrar por enlace 'intermedio' para visitar primero",
 | 
				
			||||||
    "filterByLinkText": "Filter links by link text",
 | 
					    "filterByLinkText": "Filter links by link text",
 | 
				
			||||||
    "intermediateLinkNotFound": "Enlace intermedio no encontrado",
 | 
					    "intermediateLinkNotFound": "Enlace intermedio no encontrado",
 | 
				
			||||||
@@ -253,10 +252,10 @@
 | 
				
			|||||||
    "exemptFromBackgroundUpdates": "Exenta de actualizciones en segundo plano (si están habilitadas)",
 | 
					    "exemptFromBackgroundUpdates": "Exenta de actualizciones en segundo plano (si están habilitadas)",
 | 
				
			||||||
    "bgUpdatesOnWiFiOnly": "Deshabilitar las actualizaciones en segundo plano sin WiFi",
 | 
					    "bgUpdatesOnWiFiOnly": "Deshabilitar las actualizaciones en segundo plano sin WiFi",
 | 
				
			||||||
    "autoSelectHighestVersionCode": "Auto Selección de la versionCode APK superior",
 | 
					    "autoSelectHighestVersionCode": "Auto Selección de la versionCode APK superior",
 | 
				
			||||||
    "versionExtractionRegEx": "Versión de Extracción de RegEx",
 | 
					    "versionExtractionRegEx": "Versión de extracción regex",
 | 
				
			||||||
    "matchGroupToUse": "Coincidir en Grupo a Usar",
 | 
					    "matchGroupToUse": "Grupo a usar para versión de extracción regex",
 | 
				
			||||||
    "highlightTouchTargets": "Resaltar objetivos menos obvios",
 | 
					    "highlightTouchTargets": "Resaltar objetivos menos obvios",
 | 
				
			||||||
    "pickExportDir": "Selecciona el Directorio para Exportar",
 | 
					    "pickExportDir": "Directorio para Exportar",
 | 
				
			||||||
    "autoExportOnChanges": "Auto Exportar cuando haya cambios",
 | 
					    "autoExportOnChanges": "Auto Exportar cuando haya cambios",
 | 
				
			||||||
    "includeSettings": "Incluir ajustes",
 | 
					    "includeSettings": "Incluir ajustes",
 | 
				
			||||||
    "filterVersionsByRegEx": "Filtrar por Versiones",
 | 
					    "filterVersionsByRegEx": "Filtrar por Versiones",
 | 
				
			||||||
@@ -268,21 +267,26 @@
 | 
				
			|||||||
    "debugMenu": "Menu Depurar",
 | 
					    "debugMenu": "Menu Depurar",
 | 
				
			||||||
    "bgTaskStarted": "Iniciada tarea en segundo plano - revisa los logs.",
 | 
					    "bgTaskStarted": "Iniciada tarea en segundo plano - revisa los logs.",
 | 
				
			||||||
    "runBgCheckNow": "Ejecutar verficiación de actualizaciones en segundo plano",
 | 
					    "runBgCheckNow": "Ejecutar verficiación de actualizaciones en segundo plano",
 | 
				
			||||||
    "versionExtractWholePage": "Aplicar la Versión de Extracción Regex a la Página Entera",
 | 
					    "versionExtractWholePage": "Aplicar la versión de extracción regex a la página entera",
 | 
				
			||||||
    "installing": "Instalando",
 | 
					    "installing": "Instalando",
 | 
				
			||||||
    "skipUpdateNotifications": "Omitir de notificaciones sobre actualizaciones",
 | 
					    "skipUpdateNotifications": "No notificar sobre actualizaciones",
 | 
				
			||||||
    "updatesAvailableNotifChannel": "Actualizaciones Disponibles",
 | 
					    "updatesAvailableNotifChannel": "Actualizaciones disponibles",
 | 
				
			||||||
    "appsUpdatedNotifChannel": "Aplicaciones Actualizadas",
 | 
					    "appsUpdatedNotifChannel": "Aplicaciones actualizadas",
 | 
				
			||||||
    "appsPossiblyUpdatedNotifChannel": "Se ha Intentado Actualizar la Aplicación",
 | 
					    "appsPossiblyUpdatedNotifChannel": "Se ha intentado actualizar la aplicación",
 | 
				
			||||||
    "errorCheckingUpdatesNotifChannel": "Error Buscando Actualizaciones",
 | 
					    "errorCheckingUpdatesNotifChannel": "Error buscando actualizaciones",
 | 
				
			||||||
    "appsRemovedNotifChannel": "Aplicaciones Eliminadas",
 | 
					    "appsRemovedNotifChannel": "Aplicaciones eliminadas",
 | 
				
			||||||
    "downloadingXNotifChannel": "Descargando {}",
 | 
					    "downloadingXNotifChannel": "Descargando {}",
 | 
				
			||||||
    "completeAppInstallationNotifChannel": "Instalación Completa de la Aplicación",
 | 
					    "completeAppInstallationNotifChannel": "Instalación completada",
 | 
				
			||||||
    "checkingForUpdatesNotifChannel": "Buscando Actualizaciones",
 | 
					    "checkingForUpdatesNotifChannel": "Buscando actualizaciones",
 | 
				
			||||||
    "onlyCheckInstalledOrTrackOnlyApps": "Comprobar actualizaciones solo para apps instaladas y en seguimiento",
 | 
					    "onlyCheckInstalledOrTrackOnlyApps": "Comprobar actualizaciones solo para apps instaladas o en seguimiento",
 | 
				
			||||||
    "supportFixedAPKURL": "Soporte para URLs fijas de APK",
 | 
					    "supportFixedAPKURL": "Soporte para URLs fijas de APK",
 | 
				
			||||||
    "selectX": "Selecciona {}",
 | 
					    "selectX": "Selecciona {}",
 | 
				
			||||||
    "parallelDownloads": "Permitir descargas paralelas",
 | 
					    "parallelDownloads": "Permitir descargas paralelas",
 | 
				
			||||||
 | 
					    "installMethod": "Método de instalación",
 | 
				
			||||||
 | 
					    "normal": "Normal",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizuku no está operativo",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "¿Eliminar Aplicación?",
 | 
					        "one": "¿Eliminar Aplicación?",
 | 
				
			||||||
        "other": "¿Eliminar Aplicaciones?"
 | 
					        "other": "¿Eliminar Aplicaciones?"
 | 
				
			||||||
@@ -308,16 +312,16 @@
 | 
				
			|||||||
        "other": "{} URLs"
 | 
					        "other": "{} URLs"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "minute": {
 | 
					    "minute": {
 | 
				
			||||||
        "one": "{} Minuto",
 | 
					        "one": "{} minuto",
 | 
				
			||||||
        "other": "{} Minutos"
 | 
					        "other": "{} minutos"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "hour": {
 | 
					    "hour": {
 | 
				
			||||||
        "one": "{} Hora",
 | 
					        "one": "{} hora",
 | 
				
			||||||
        "other": "{} Horas"
 | 
					        "other": "{} horas"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "day": {
 | 
					    "day": {
 | 
				
			||||||
        "one": "{} Día",
 | 
					        "one": "{} día",
 | 
				
			||||||
        "other": "{} Días"
 | 
					        "other": "{} días"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "clearedNLogsBeforeXAfterY": {
 | 
					    "clearedNLogsBeforeXAfterY": {
 | 
				
			||||||
        "one": "Eliminado {n} log (previo a = {before}, posterior a = {after})",
 | 
					        "one": "Eliminado {n} log (previo a = {before}, posterior a = {after})",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "خطاهای وارد کردن",
 | 
					    "importErrors": "خطاهای وارد کردن",
 | 
				
			||||||
    "importedXOfYApps": "{} از {} برنامه وارد شد.",
 | 
					    "importedXOfYApps": "{} از {} برنامه وارد شد.",
 | 
				
			||||||
    "followingURLsHadErrors": "آدرس های اینترنتی زیر دارای خطا بودند:",
 | 
					    "followingURLsHadErrors": "آدرس های اینترنتی زیر دارای خطا بودند:",
 | 
				
			||||||
    "okay": "باشه",
 | 
					 | 
				
			||||||
    "selectURL": "آدرس اینترنتی انتخاب شده",
 | 
					    "selectURL": "آدرس اینترنتی انتخاب شده",
 | 
				
			||||||
    "selectURLs": "آدرس های اینترنتی انتخاب شده",
 | 
					    "selectURLs": "آدرس های اینترنتی انتخاب شده",
 | 
				
			||||||
    "pick": "انتخاب",
 | 
					    "pick": "انتخاب",
 | 
				
			||||||
@@ -283,6 +282,11 @@
 | 
				
			|||||||
    "supportFixedAPKURL": "پشتیبانی از URL های APK ثابت",
 | 
					    "supportFixedAPKURL": "پشتیبانی از URL های APK ثابت",
 | 
				
			||||||
    "selectX": "انتخاب کنید {}",
 | 
					    "selectX": "انتخاب کنید {}",
 | 
				
			||||||
    "parallelDownloads": "Allow parallel downloads",
 | 
					    "parallelDownloads": "Allow parallel downloads",
 | 
				
			||||||
 | 
					    "installMethod": "Installation method",
 | 
				
			||||||
 | 
					    "normal": "Normal",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizuku is not running",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "برنامه حذف شود؟",
 | 
					        "one": "برنامه حذف شود؟",
 | 
				
			||||||
        "other": "برنامه ها حذف شوند؟"
 | 
					        "other": "برنامه ها حذف شوند؟"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Erreurs d'importation",
 | 
					    "importErrors": "Erreurs d'importation",
 | 
				
			||||||
    "importedXOfYApps": "{} sur {} applications importées.",
 | 
					    "importedXOfYApps": "{} sur {} applications importées.",
 | 
				
			||||||
    "followingURLsHadErrors": "Les URL suivantes comportaient des erreurs :",
 | 
					    "followingURLsHadErrors": "Les URL suivantes comportaient des erreurs :",
 | 
				
			||||||
    "okay": "Okay",
 | 
					 | 
				
			||||||
    "selectURL": "Sélectionnez l'URL",
 | 
					    "selectURL": "Sélectionnez l'URL",
 | 
				
			||||||
    "selectURLs": "Sélectionnez les URLs",
 | 
					    "selectURLs": "Sélectionnez les URLs",
 | 
				
			||||||
    "pick": "Prendre",
 | 
					    "pick": "Prendre",
 | 
				
			||||||
@@ -283,6 +282,11 @@
 | 
				
			|||||||
    "supportFixedAPKURL": "Support fixed APK URLs",
 | 
					    "supportFixedAPKURL": "Support fixed APK URLs",
 | 
				
			||||||
    "selectX": "Select {}",
 | 
					    "selectX": "Select {}",
 | 
				
			||||||
    "parallelDownloads": "Allow parallel downloads",
 | 
					    "parallelDownloads": "Allow parallel downloads",
 | 
				
			||||||
 | 
					    "installMethod": "Installation method",
 | 
				
			||||||
 | 
					    "normal": "Normal",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizuku is not running",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Supprimer l'application ?",
 | 
					        "one": "Supprimer l'application ?",
 | 
				
			||||||
        "other": "Supprimer les applications ?"
 | 
					        "other": "Supprimer les applications ?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Importálási hibák",
 | 
					    "importErrors": "Importálási hibák",
 | 
				
			||||||
    "importedXOfYApps": "{}/{} app importálva.",
 | 
					    "importedXOfYApps": "{}/{} app importálva.",
 | 
				
			||||||
    "followingURLsHadErrors": "A következő URL-ek hibákat tartalmaztak:",
 | 
					    "followingURLsHadErrors": "A következő URL-ek hibákat tartalmaztak:",
 | 
				
			||||||
    "okay": "Oké",
 | 
					 | 
				
			||||||
    "selectURL": "Válassza ki az URL-t",
 | 
					    "selectURL": "Válassza ki az URL-t",
 | 
				
			||||||
    "selectURLs": "Kiválasztott URL-ek",
 | 
					    "selectURLs": "Kiválasztott URL-ek",
 | 
				
			||||||
    "pick": "Válasszon",
 | 
					    "pick": "Válasszon",
 | 
				
			||||||
@@ -283,6 +282,11 @@
 | 
				
			|||||||
    "supportFixedAPKURL": "Támogatja a rögzített APK URL-eket",
 | 
					    "supportFixedAPKURL": "Támogatja a rögzített APK URL-eket",
 | 
				
			||||||
    "selectX": "Kiválaszt {}",
 | 
					    "selectX": "Kiválaszt {}",
 | 
				
			||||||
    "parallelDownloads": "Párhuzamos letöltéseket enged",
 | 
					    "parallelDownloads": "Párhuzamos letöltéseket enged",
 | 
				
			||||||
 | 
					    "installMethod": "Installation method",
 | 
				
			||||||
 | 
					    "normal": "Normal",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizuku is not running",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Eltávolítja az alkalmazást?",
 | 
					        "one": "Eltávolítja az alkalmazást?",
 | 
				
			||||||
        "other": "Eltávolítja az alkalmazást?"
 | 
					        "other": "Eltávolítja az alkalmazást?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Errori di importazione",
 | 
					    "importErrors": "Errori di importazione",
 | 
				
			||||||
    "importedXOfYApps": "{} app di {} importate.",
 | 
					    "importedXOfYApps": "{} app di {} importate.",
 | 
				
			||||||
    "followingURLsHadErrors": "I seguenti URL contengono errori:",
 | 
					    "followingURLsHadErrors": "I seguenti URL contengono errori:",
 | 
				
			||||||
    "okay": "Va bene",
 | 
					 | 
				
			||||||
    "selectURL": "Seleziona l'URL",
 | 
					    "selectURL": "Seleziona l'URL",
 | 
				
			||||||
    "selectURLs": "Seleziona gli URL",
 | 
					    "selectURLs": "Seleziona gli URL",
 | 
				
			||||||
    "pick": "Seleziona",
 | 
					    "pick": "Seleziona",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "インポートエラー",
 | 
					    "importErrors": "インポートエラー",
 | 
				
			||||||
    "importedXOfYApps": "{} / {} アプリをインポートしました",
 | 
					    "importedXOfYApps": "{} / {} アプリをインポートしました",
 | 
				
			||||||
    "followingURLsHadErrors": "以下のURLでエラーが発生しました:",
 | 
					    "followingURLsHadErrors": "以下のURLでエラーが発生しました:",
 | 
				
			||||||
    "okay": "OK",
 | 
					 | 
				
			||||||
    "selectURL": "URLを選択",
 | 
					    "selectURL": "URLを選択",
 | 
				
			||||||
    "selectURLs": "URLを選択",
 | 
					    "selectURLs": "URLを選択",
 | 
				
			||||||
    "pick": "選択",
 | 
					    "pick": "選択",
 | 
				
			||||||
@@ -236,7 +235,7 @@
 | 
				
			|||||||
    "addInfoInSettings": "設定でこの情報を追加してください。",
 | 
					    "addInfoInSettings": "設定でこの情報を追加してください。",
 | 
				
			||||||
    "githubSourceNote": "GitHubのレート制限はAPIキーを使うことで回避できます。",
 | 
					    "githubSourceNote": "GitHubのレート制限はAPIキーを使うことで回避できます。",
 | 
				
			||||||
    "gitlabSourceNote": "GitLabのAPK抽出はAPIキーがないと動作しない場合があります。",
 | 
					    "gitlabSourceNote": "GitLabのAPK抽出はAPIキーがないと動作しない場合があります。",
 | 
				
			||||||
    "sortByLastLinkSegment": "Sort by only the last segment of the link",
 | 
					    "sortByLastLinkSegment": "リンクの最後のセグメントのみでソートする",
 | 
				
			||||||
    "filterReleaseNotesByRegEx": "正規表現でリリースノートをフィルタリングする",
 | 
					    "filterReleaseNotesByRegEx": "正規表現でリリースノートをフィルタリングする",
 | 
				
			||||||
    "customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')",
 | 
					    "customLinkFilterRegex": "正規表現によるカスタムリンクフィルター (デフォルト '.apk$')",
 | 
				
			||||||
    "appsPossiblyUpdated": "アプリのアップデートを試行",
 | 
					    "appsPossiblyUpdated": "アプリのアップデートを試行",
 | 
				
			||||||
@@ -246,10 +245,10 @@
 | 
				
			|||||||
    "backgroundUpdateReqsExplanation": "バックグラウンドアップデートは、すべてのアプリで可能とは限りません。",
 | 
					    "backgroundUpdateReqsExplanation": "バックグラウンドアップデートは、すべてのアプリで可能とは限りません。",
 | 
				
			||||||
    "backgroundUpdateLimitsExplanation": "バックグラウンドアップデートが成功したかどうかは、Obtainiumを起動したときにしか判断できません。",
 | 
					    "backgroundUpdateLimitsExplanation": "バックグラウンドアップデートが成功したかどうかは、Obtainiumを起動したときにしか判断できません。",
 | 
				
			||||||
    "verifyLatestTag": "'latest'タグを確認する",
 | 
					    "verifyLatestTag": "'latest'タグを確認する",
 | 
				
			||||||
    "intermediateLinkRegex": "Filter for an 'Intermediate' Link to Visit",
 | 
					    "intermediateLinkRegex": "訪問する「中間」リンクのフィルター",
 | 
				
			||||||
    "filterByLinkText": "Filter links by link text",
 | 
					    "filterByLinkText": "テキストでリンクをフィルタリングする",
 | 
				
			||||||
    "intermediateLinkNotFound": "中間リンクが見つかりませんでした",
 | 
					    "intermediateLinkNotFound": "中間リンクが見つかりませんでした",
 | 
				
			||||||
    "intermediateLink": "Intermediate link",
 | 
					    "intermediateLink": "中間リンク",
 | 
				
			||||||
    "exemptFromBackgroundUpdates": "バックグラウンドアップデートを行わない (有効な場合)",
 | 
					    "exemptFromBackgroundUpdates": "バックグラウンドアップデートを行わない (有効な場合)",
 | 
				
			||||||
    "bgUpdatesOnWiFiOnly": "WiFiを使用していない場合,バックグラウンドアップデートを無効にする",
 | 
					    "bgUpdatesOnWiFiOnly": "WiFiを使用していない場合,バックグラウンドアップデートを無効にする",
 | 
				
			||||||
    "autoSelectHighestVersionCode": "最も高いバージョンコードのAPKを自動で選択する",
 | 
					    "autoSelectHighestVersionCode": "最も高いバージョンコードのAPKを自動で選択する",
 | 
				
			||||||
@@ -263,8 +262,8 @@
 | 
				
			|||||||
    "trySelectingSuggestedVersionCode": "提案されたバージョンコードのAPKを選択する",
 | 
					    "trySelectingSuggestedVersionCode": "提案されたバージョンコードのAPKを選択する",
 | 
				
			||||||
    "dontSortReleasesList": "APIからのリリース順を保持する",
 | 
					    "dontSortReleasesList": "APIからのリリース順を保持する",
 | 
				
			||||||
    "reverseSort": "逆順ソート",
 | 
					    "reverseSort": "逆順ソート",
 | 
				
			||||||
    "takeFirstLink": "Take first link",
 | 
					    "takeFirstLink": "最初のリンクを取得する",
 | 
				
			||||||
    "skipSort": "Skip sorting",
 | 
					    "skipSort": "ソートをスキップする",
 | 
				
			||||||
    "debugMenu": "デバッグメニュー",
 | 
					    "debugMenu": "デバッグメニュー",
 | 
				
			||||||
    "bgTaskStarted": "バックグラウンドタスクが開始されました - ログを確認してください。",
 | 
					    "bgTaskStarted": "バックグラウンドタスクが開始されました - ログを確認してください。",
 | 
				
			||||||
    "runBgCheckNow": "今すぐバックグラウンドでのアップデート確認を開始する",
 | 
					    "runBgCheckNow": "今すぐバックグラウンドでのアップデート確認を開始する",
 | 
				
			||||||
@@ -280,9 +279,14 @@
 | 
				
			|||||||
    "completeAppInstallationNotifChannel": "アプリのインストールを完了する",
 | 
					    "completeAppInstallationNotifChannel": "アプリのインストールを完了する",
 | 
				
			||||||
    "checkingForUpdatesNotifChannel": "アップデートを確認中",
 | 
					    "checkingForUpdatesNotifChannel": "アップデートを確認中",
 | 
				
			||||||
    "onlyCheckInstalledOrTrackOnlyApps": "インストール済みのアプリと「追跡のみ」のアプリのアップデートのみを確認する",
 | 
					    "onlyCheckInstalledOrTrackOnlyApps": "インストール済みのアプリと「追跡のみ」のアプリのアップデートのみを確認する",
 | 
				
			||||||
    "supportFixedAPKURL": "Support fixed APK URLs",
 | 
					    "supportFixedAPKURL": "固定されたAPKのURLをサポートする",
 | 
				
			||||||
    "selectX": "Select {}",
 | 
					    "selectX": "{} 選択",
 | 
				
			||||||
    "parallelDownloads": "Allow parallel downloads",
 | 
					    "parallelDownloads": "並行ダウンロードを許可する",
 | 
				
			||||||
 | 
					    "installMethod": "インストール方法",
 | 
				
			||||||
 | 
					    "normal": "通常",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizukuが起動していません",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "アプリを削除しますか?",
 | 
					        "one": "アプリを削除しますか?",
 | 
				
			||||||
        "other": "アプリを削除しますか?"
 | 
					        "other": "アプリを削除しますか?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Import foutmeldingen",
 | 
					    "importErrors": "Import foutmeldingen",
 | 
				
			||||||
    "importedXOfYApps": "{} van {} apps geïmporteerd.",
 | 
					    "importedXOfYApps": "{} van {} apps geïmporteerd.",
 | 
				
			||||||
    "followingURLsHadErrors": "De volgende URL's bevatten fouten:",
 | 
					    "followingURLsHadErrors": "De volgende URL's bevatten fouten:",
 | 
				
			||||||
    "okay": "Ok",
 | 
					 | 
				
			||||||
    "selectURL": "Selecteer URL",
 | 
					    "selectURL": "Selecteer URL",
 | 
				
			||||||
    "selectURLs": "Selecteer URL's",
 | 
					    "selectURLs": "Selecteer URL's",
 | 
				
			||||||
    "pick": "Kies",
 | 
					    "pick": "Kies",
 | 
				
			||||||
@@ -283,6 +282,11 @@
 | 
				
			|||||||
    "supportFixedAPKURL": "Support fixed APK URLs",
 | 
					    "supportFixedAPKURL": "Support fixed APK URLs",
 | 
				
			||||||
    "selectX": "Select {}",
 | 
					    "selectX": "Select {}",
 | 
				
			||||||
    "parallelDownloads": "Allow parallel downloads",
 | 
					    "parallelDownloads": "Allow parallel downloads",
 | 
				
			||||||
 | 
					    "installMethod": "Installation method",
 | 
				
			||||||
 | 
					    "normal": "Normal",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizuku is not running",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "App verwijderen?",
 | 
					        "one": "App verwijderen?",
 | 
				
			||||||
        "other": "Apps verwijderen?"
 | 
					        "other": "Apps verwijderen?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Błędy importowania",
 | 
					    "importErrors": "Błędy importowania",
 | 
				
			||||||
    "importedXOfYApps": "Zaimportowano {} z {} aplikacji.",
 | 
					    "importedXOfYApps": "Zaimportowano {} z {} aplikacji.",
 | 
				
			||||||
    "followingURLsHadErrors": "Następujące adresy URL zawierały błędy:",
 | 
					    "followingURLsHadErrors": "Następujące adresy URL zawierały błędy:",
 | 
				
			||||||
    "okay": "Okej",
 | 
					 | 
				
			||||||
    "selectURL": "Wybierz adres URL",
 | 
					    "selectURL": "Wybierz adres URL",
 | 
				
			||||||
    "selectURLs": "Wybierz adresy URL",
 | 
					    "selectURLs": "Wybierz adresy URL",
 | 
				
			||||||
    "pick": "Wybierz",
 | 
					    "pick": "Wybierz",
 | 
				
			||||||
@@ -283,6 +282,11 @@
 | 
				
			|||||||
    "supportFixedAPKURL": "Obsługuj stałe adresy URL APK",
 | 
					    "supportFixedAPKURL": "Obsługuj stałe adresy URL APK",
 | 
				
			||||||
    "selectX": "Wybierz {}",
 | 
					    "selectX": "Wybierz {}",
 | 
				
			||||||
    "parallelDownloads": "Allow parallel downloads",
 | 
					    "parallelDownloads": "Allow parallel downloads",
 | 
				
			||||||
 | 
					    "installMethod": "Installation method",
 | 
				
			||||||
 | 
					    "normal": "Normal",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizuku is not running",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Usunąć aplikację?",
 | 
					        "one": "Usunąć aplikację?",
 | 
				
			||||||
        "few": "Usunąć aplikacje?",
 | 
					        "few": "Usunąć aplikacje?",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Erros de Importação",
 | 
					    "importErrors": "Erros de Importação",
 | 
				
			||||||
    "importedXOfYApps": "{} de {} Apps importados.",
 | 
					    "importedXOfYApps": "{} de {} Apps importados.",
 | 
				
			||||||
    "followingURLsHadErrors": "As seguintes URLs apresentaram erros:",
 | 
					    "followingURLsHadErrors": "As seguintes URLs apresentaram erros:",
 | 
				
			||||||
    "okay": "Ok",
 | 
					 | 
				
			||||||
    "selectURL": "Selecionar URL",
 | 
					    "selectURL": "Selecionar URL",
 | 
				
			||||||
    "selectURLs": "Selecionar URLs",
 | 
					    "selectURLs": "Selecionar URLs",
 | 
				
			||||||
    "pick": "Escolher",
 | 
					    "pick": "Escolher",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Ошибка импорта",
 | 
					    "importErrors": "Ошибка импорта",
 | 
				
			||||||
    "importedXOfYApps": "Импортировано приложений: {} из {}",
 | 
					    "importedXOfYApps": "Импортировано приложений: {} из {}",
 | 
				
			||||||
    "followingURLsHadErrors": "При импорте следующие URL-адреса содержали ошибки:",
 | 
					    "followingURLsHadErrors": "При импорте следующие URL-адреса содержали ошибки:",
 | 
				
			||||||
    "okay": "Ok",
 | 
					 | 
				
			||||||
    "selectURL": "Выбрать URL-адрес",
 | 
					    "selectURL": "Выбрать URL-адрес",
 | 
				
			||||||
    "selectURLs": "Выбрать URL-адреса",
 | 
					    "selectURLs": "Выбрать URL-адреса",
 | 
				
			||||||
    "pick": "Выбрать",
 | 
					    "pick": "Выбрать",
 | 
				
			||||||
@@ -287,7 +286,9 @@
 | 
				
			|||||||
    "normal": "Нормальный",
 | 
					    "normal": "Нормальный",
 | 
				
			||||||
    "shizuku": "Shizuku",
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
    "root": "Суперпользователь",
 | 
					    "root": "Суперпользователь",
 | 
				
			||||||
    "shizukuBinderNotFound": "Shizuku не запущен",
 | 
					    "shizukuBinderNotFound": "Совместимый сервис Shizuku не найден",
 | 
				
			||||||
 | 
					    "useSystemFont": "Использовать системный шрифт",
 | 
				
			||||||
 | 
					    "systemFontError": "Ошибка загрузки системного шрифта: {}",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Удалить приложение?",
 | 
					        "one": "Удалить приложение?",
 | 
				
			||||||
        "other": "Удалить приложения?"
 | 
					        "other": "Удалить приложения?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Importfel",
 | 
					    "importErrors": "Importfel",
 | 
				
			||||||
    "importedXOfYApps": "{} av {} Appar importerade.",
 | 
					    "importedXOfYApps": "{} av {} Appar importerade.",
 | 
				
			||||||
    "followingURLsHadErrors": "Följande URL:er hade fel:",
 | 
					    "followingURLsHadErrors": "Följande URL:er hade fel:",
 | 
				
			||||||
    "okay": "Okej",
 | 
					 | 
				
			||||||
    "selectURL": "Välj URL",
 | 
					    "selectURL": "Välj URL",
 | 
				
			||||||
    "selectURLs": "Välj URL:er",
 | 
					    "selectURLs": "Välj URL:er",
 | 
				
			||||||
    "pick": "Välj",
 | 
					    "pick": "Välj",
 | 
				
			||||||
@@ -269,6 +268,11 @@
 | 
				
			|||||||
    "bgTaskStarted": "Background task started - check logs.",
 | 
					    "bgTaskStarted": "Background task started - check logs.",
 | 
				
			||||||
    "runBgCheckNow": "Kör Bakgrundsuppdateringskoll Nu",
 | 
					    "runBgCheckNow": "Kör Bakgrundsuppdateringskoll Nu",
 | 
				
			||||||
    "parallelDownloads": "Allow parallel downloads",
 | 
					    "parallelDownloads": "Allow parallel downloads",
 | 
				
			||||||
 | 
					    "installMethod": "Installation method",
 | 
				
			||||||
 | 
					    "normal": "Normal",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizuku is not running",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Ta Bort App?",
 | 
					        "one": "Ta Bort App?",
 | 
				
			||||||
        "other": "Ta Bort Appar?"
 | 
					        "other": "Ta Bort Appar?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "İçe Aktarma Hataları",
 | 
					    "importErrors": "İçe Aktarma Hataları",
 | 
				
			||||||
    "importedXOfYApps": "{}'den {} Uygulama İçe Aktarıldı.",
 | 
					    "importedXOfYApps": "{}'den {} Uygulama İçe Aktarıldı.",
 | 
				
			||||||
    "followingURLsHadErrors": "Aşağıdaki URL'lerde hatalar oluştu:",
 | 
					    "followingURLsHadErrors": "Aşağıdaki URL'lerde hatalar oluştu:",
 | 
				
			||||||
    "okay": "Tamam",
 | 
					 | 
				
			||||||
    "selectURL": "URL Seç",
 | 
					    "selectURL": "URL Seç",
 | 
				
			||||||
    "selectURLs": "URL'leri Seç",
 | 
					    "selectURLs": "URL'leri Seç",
 | 
				
			||||||
    "pick": "Seç",
 | 
					    "pick": "Seç",
 | 
				
			||||||
@@ -283,6 +282,11 @@
 | 
				
			|||||||
    "supportFixedAPKURL": "Support fixed APK URLs",
 | 
					    "supportFixedAPKURL": "Support fixed APK URLs",
 | 
				
			||||||
    "selectX": "Select {}",
 | 
					    "selectX": "Select {}",
 | 
				
			||||||
    "parallelDownloads": "Allow parallel downloads",
 | 
					    "parallelDownloads": "Allow parallel downloads",
 | 
				
			||||||
 | 
					    "installMethod": "Installation method",
 | 
				
			||||||
 | 
					    "normal": "Normal",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizuku is not running",
 | 
				
			||||||
    "removeAppQuestion": {
 | 
					    "removeAppQuestion": {
 | 
				
			||||||
        "one": "Uygulamayı Kaldır?",
 | 
					        "one": "Uygulamayı Kaldır?",
 | 
				
			||||||
        "other": "Uygulamaları Kaldır?"
 | 
					        "other": "Uygulamaları Kaldır?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@
 | 
				
			|||||||
    "placeholder": "Giữ chỗ",
 | 
					    "placeholder": "Giữ chỗ",
 | 
				
			||||||
    "someErrors": "Đã xảy ra một số lỗi",
 | 
					    "someErrors": "Đã xảy ra một số lỗi",
 | 
				
			||||||
    "unexpectedError": "Lỗi không mong đợi",
 | 
					    "unexpectedError": "Lỗi không mong đợi",
 | 
				
			||||||
    "ok": "Ôkê",
 | 
					    "ok": "OK",
 | 
				
			||||||
    "and": "và",
 | 
					    "and": "và",
 | 
				
			||||||
    "githubPATLabel": "Mã thông báo truy cập cá nhân GitHub (Tăng tốc độ giới hạn)",
 | 
					    "githubPATLabel": "Mã thông báo truy cập cá nhân GitHub (Tăng tốc độ giới hạn)",
 | 
				
			||||||
    "includePrereleases": "Bao gồm các bản phát hành trước",
 | 
					    "includePrereleases": "Bao gồm các bản phát hành trước",
 | 
				
			||||||
@@ -17,7 +17,7 @@
 | 
				
			|||||||
    "filterReleaseTitlesByRegEx": "Lọc tiêu đề bản phát hành theo biểu thức chính quy",
 | 
					    "filterReleaseTitlesByRegEx": "Lọc tiêu đề bản phát hành theo biểu thức chính quy",
 | 
				
			||||||
    "invalidRegEx": "Biểu thức chính quy không hợp lệ",
 | 
					    "invalidRegEx": "Biểu thức chính quy không hợp lệ",
 | 
				
			||||||
    "noDescription": "Không có mô tả",
 | 
					    "noDescription": "Không có mô tả",
 | 
				
			||||||
    "cancel": "Hủy bỏ",
 | 
					    "cancel": "Hủy",
 | 
				
			||||||
    "continue": "Tiếp tục",
 | 
					    "continue": "Tiếp tục",
 | 
				
			||||||
    "requiredInBrackets": "(Yêu cầu)",
 | 
					    "requiredInBrackets": "(Yêu cầu)",
 | 
				
			||||||
    "dropdownNoOptsError": "LỖI: TẢI XUỐNG PHẢI CÓ ÍT NHẤT MỘT LỰA CHỌN",
 | 
					    "dropdownNoOptsError": "LỖI: TẢI XUỐNG PHẢI CÓ ÍT NHẤT MỘT LỰA CHỌN",
 | 
				
			||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "Lỗi nhập",
 | 
					    "importErrors": "Lỗi nhập",
 | 
				
			||||||
    "importedXOfYApps": "{} trong số {} Ứng dụng đã được nhập.",
 | 
					    "importedXOfYApps": "{} trong số {} Ứng dụng đã được nhập.",
 | 
				
			||||||
    "followingURLsHadErrors": "Các URL sau có lỗi:",
 | 
					    "followingURLsHadErrors": "Các URL sau có lỗi:",
 | 
				
			||||||
    "okay": "Ôkê",
 | 
					 | 
				
			||||||
    "selectURL": "Chọn URL",
 | 
					    "selectURL": "Chọn URL",
 | 
				
			||||||
    "selectURLs": "Chọn URL",
 | 
					    "selectURLs": "Chọn URL",
 | 
				
			||||||
    "pick": "Chọn",
 | 
					    "pick": "Chọn",
 | 
				
			||||||
@@ -113,17 +112,17 @@
 | 
				
			|||||||
    "followSystem": "Theo hệ thống",
 | 
					    "followSystem": "Theo hệ thống",
 | 
				
			||||||
    "obtainium": "Obtainium",
 | 
					    "obtainium": "Obtainium",
 | 
				
			||||||
    "materialYou": "Material You",
 | 
					    "materialYou": "Material You",
 | 
				
			||||||
    "useBlackTheme": "Sử dụng chủ đề tối màu đen thuần túy",
 | 
					    "useBlackTheme": "Nền đen",
 | 
				
			||||||
    "appSortBy": "Sắp xếp ứng dụng theo",
 | 
					    "appSortBy": "Sắp xếp ứng dụng",
 | 
				
			||||||
    "authorName": "Tác giả/Tên",
 | 
					    "authorName": "Tác giả",
 | 
				
			||||||
    "nameAuthor": "Tên/Tác giả",
 | 
					    "nameAuthor": "Tên",
 | 
				
			||||||
    "asAdded": "Như đã thêm",
 | 
					    "asAdded": "Như đã thêm",
 | 
				
			||||||
    "appSortOrder": "Thứ tự sắp xếp ứng dụng",
 | 
					    "appSortOrder": "Thứ tự sắp xếp",
 | 
				
			||||||
    "ascending": "Tăng dần",
 | 
					    "ascending": "Tăng dần",
 | 
				
			||||||
    "descending": "Giảm dần",
 | 
					    "descending": "Giảm dần",
 | 
				
			||||||
    "bgUpdateCheckInterval": "Khoảng thời gian kiểm tra cập nhật nền",
 | 
					    "bgUpdateCheckInterval": "Khoảng thời gian kiểm tra cập nhật nền",
 | 
				
			||||||
    "neverManualOnly": "Không bao giờ - Chỉ thủ công",
 | 
					    "neverManualOnly": "Không bao giờ - Chỉ thủ công",
 | 
				
			||||||
    "appearance": "Vẻ ngoài",
 | 
					    "appearance": "Hiển thị",
 | 
				
			||||||
    "showWebInAppView": "Hiển thị trang web Nguồn trong chế độ xem Ứng dụng",
 | 
					    "showWebInAppView": "Hiển thị trang web Nguồn trong chế độ xem Ứng dụng",
 | 
				
			||||||
    "pinUpdates": "Ghim nội dung cập nhật lên đầu chế độ xem Ứng dụng",
 | 
					    "pinUpdates": "Ghim nội dung cập nhật lên đầu chế độ xem Ứng dụng",
 | 
				
			||||||
    "updates": "Cập nhật",
 | 
					    "updates": "Cập nhật",
 | 
				
			||||||
@@ -229,7 +228,7 @@
 | 
				
			|||||||
    "removeOnExternalUninstall": "Tự động xóa ứng dụng đã gỡ cài đặt bên ngoài",
 | 
					    "removeOnExternalUninstall": "Tự động xóa ứng dụng đã gỡ cài đặt bên ngoài",
 | 
				
			||||||
    "pickHighestVersionCode": "Tự động chọn APK mã phiên bản cao nhất",
 | 
					    "pickHighestVersionCode": "Tự động chọn APK mã phiên bản cao nhất",
 | 
				
			||||||
    "checkUpdateOnDetailPage": "Kiểm tra các bản cập nhật khi mở trang chi tiết Ứng dụng",
 | 
					    "checkUpdateOnDetailPage": "Kiểm tra các bản cập nhật khi mở trang chi tiết Ứng dụng",
 | 
				
			||||||
    "disablePageTransitions": "Tắt hoạt ảnh chuyển trang",
 | 
					    "disablePageTransitions": "Tắt hiệu ứng chuyển trang",
 | 
				
			||||||
    "reversePageTransitions": "Hoạt ảnh chuyển đổi trang đảo ngược",
 | 
					    "reversePageTransitions": "Hoạt ảnh chuyển đổi trang đảo ngược",
 | 
				
			||||||
    "minStarCount": "Số lượng sao tối thiểu",
 | 
					    "minStarCount": "Số lượng sao tối thiểu",
 | 
				
			||||||
    "addInfoBelow": "Thêm thông tin này vào bên dưới.",
 | 
					    "addInfoBelow": "Thêm thông tin này vào bên dưới.",
 | 
				
			||||||
@@ -283,6 +282,11 @@
 | 
				
			|||||||
    "supportFixedAPKURL": "Support fixed APK URLs",
 | 
					    "supportFixedAPKURL": "Support fixed APK URLs",
 | 
				
			||||||
    "selectX": "Select {}",
 | 
					    "selectX": "Select {}",
 | 
				
			||||||
    "parallelDownloads": "Allow parallel downloads",
 | 
					    "parallelDownloads": "Allow parallel downloads",
 | 
				
			||||||
 | 
					    "installMethod": "Installation method",
 | 
				
			||||||
 | 
					    "normal": "Normal",
 | 
				
			||||||
 | 
					    "shizuku": "Shizuku",
 | 
				
			||||||
 | 
					    "root": "Root",
 | 
				
			||||||
 | 
					    "shizukuBinderNotFound": "Shizuku chưa khởi động",
 | 
				
			||||||
    "removeAppQuestion":{
 | 
					    "removeAppQuestion":{
 | 
				
			||||||
        "one": "Gỡ ứng dụng?",
 | 
					        "one": "Gỡ ứng dụng?",
 | 
				
			||||||
        "other": "Gỡ ứng dụng?"
 | 
					        "other": "Gỡ ứng dụng?"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,6 @@
 | 
				
			|||||||
    "importErrors": "导入错误",
 | 
					    "importErrors": "导入错误",
 | 
				
			||||||
    "importedXOfYApps": "已导入 {} 中的 {} 个应用。",
 | 
					    "importedXOfYApps": "已导入 {} 中的 {} 个应用。",
 | 
				
			||||||
    "followingURLsHadErrors": "下列 URL 存在错误:",
 | 
					    "followingURLsHadErrors": "下列 URL 存在错误:",
 | 
				
			||||||
    "okay": "好的",
 | 
					 | 
				
			||||||
    "selectURL": "选择 URL",
 | 
					    "selectURL": "选择 URL",
 | 
				
			||||||
    "selectURLs": "选择 URL",
 | 
					    "selectURLs": "选择 URL",
 | 
				
			||||||
    "pick": "选择",
 | 
					    "pick": "选择",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -346,6 +346,11 @@ class GitHub extends AppSource {
 | 
				
			|||||||
          continue;
 | 
					          continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        var apkUrls = getReleaseAPKUrls(releases[i]);
 | 
					        var apkUrls = getReleaseAPKUrls(releases[i]);
 | 
				
			||||||
 | 
					        if (additionalSettings['apkFilterRegEx'] != null) {
 | 
				
			||||||
 | 
					          var reg = RegExp(additionalSettings['apkFilterRegEx']);
 | 
				
			||||||
 | 
					          apkUrls =
 | 
				
			||||||
 | 
					              apkUrls.where((element) => reg.hasMatch(element.key)).toList();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) {
 | 
					        if (apkUrls.isEmpty && additionalSettings['trackOnly'] != true) {
 | 
				
			||||||
          continue;
 | 
					          continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
import 'package:easy_localization/easy_localization.dart';
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:html/parser.dart';
 | 
					import 'package:html/parser.dart';
 | 
				
			||||||
import 'package:http/http.dart';
 | 
					import 'package:http/http.dart';
 | 
				
			||||||
import 'package:obtainium/components/generated_form.dart';
 | 
					import 'package:obtainium/components/generated_form.dart';
 | 
				
			||||||
@@ -100,28 +99,6 @@ class HTML extends AppSource {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
          ])
 | 
					          ])
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    [
 | 
					 | 
				
			||||||
      GeneratedFormTextField('versionExtractionRegEx',
 | 
					 | 
				
			||||||
          label: tr('versionExtractionRegEx'),
 | 
					 | 
				
			||||||
          required: false,
 | 
					 | 
				
			||||||
          additionalValidators: [(value) => regExValidator(value)]),
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    [
 | 
					 | 
				
			||||||
      GeneratedFormTextField('matchGroupToUse',
 | 
					 | 
				
			||||||
          label: tr('matchGroupToUse'),
 | 
					 | 
				
			||||||
          required: false,
 | 
					 | 
				
			||||||
          hint: '0',
 | 
					 | 
				
			||||||
          textInputType: const TextInputType.numberWithOptions(),
 | 
					 | 
				
			||||||
          additionalValidators: [
 | 
					 | 
				
			||||||
            (value) {
 | 
					 | 
				
			||||||
              if (value?.isEmpty == true) {
 | 
					 | 
				
			||||||
                value = null;
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
              value ??= '0';
 | 
					 | 
				
			||||||
              return intValidator(value);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          ])
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    [
 | 
					    [
 | 
				
			||||||
      GeneratedFormSwitch('versionExtractWholePage',
 | 
					      GeneratedFormSwitch('versionExtractWholePage',
 | 
				
			||||||
          label: tr('versionExtractWholePage'))
 | 
					          label: tr('versionExtractWholePage'))
 | 
				
			||||||
@@ -242,9 +219,14 @@ class HTML extends AppSource {
 | 
				
			|||||||
    Map<String, dynamic> additionalSettings,
 | 
					    Map<String, dynamic> additionalSettings,
 | 
				
			||||||
  ) async {
 | 
					  ) async {
 | 
				
			||||||
    var currentUrl = standardUrl;
 | 
					    var currentUrl = standardUrl;
 | 
				
			||||||
    for (int i = 0;
 | 
					    if (additionalSettings['intermediateLink']?.isNotEmpty != true) {
 | 
				
			||||||
        i < (additionalSettings['intermediateLink']?.length ?? 0);
 | 
					      additionalSettings['intermediateLink'] = [];
 | 
				
			||||||
        i++) {
 | 
					    }
 | 
				
			||||||
 | 
					    additionalSettings['intermediateLink'] =
 | 
				
			||||||
 | 
					        additionalSettings['intermediateLink']
 | 
				
			||||||
 | 
					            .where((l) => l['customLinkFilterRegex'].isNotEmpty == true)
 | 
				
			||||||
 | 
					            .toList();
 | 
				
			||||||
 | 
					    for (int i = 0; i < (additionalSettings['intermediateLink'].length); i++) {
 | 
				
			||||||
      var intLinks = await grabLinksCommon(await sourceRequest(currentUrl),
 | 
					      var intLinks = await grabLinksCommon(await sourceRequest(currentUrl),
 | 
				
			||||||
          additionalSettings['intermediateLink'][i]);
 | 
					          additionalSettings['intermediateLink'][i]);
 | 
				
			||||||
      if (intLinks.isEmpty) {
 | 
					      if (intLinks.isEmpty) {
 | 
				
			||||||
@@ -270,26 +252,12 @@ class HTML extends AppSource {
 | 
				
			|||||||
    if (additionalSettings['supportFixedAPKURL'] != true) {
 | 
					    if (additionalSettings['supportFixedAPKURL'] != true) {
 | 
				
			||||||
      version = rel.hashCode.toString();
 | 
					      version = rel.hashCode.toString();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    var versionExtractionRegEx =
 | 
					    version = extractVersion(
 | 
				
			||||||
        additionalSettings['versionExtractionRegEx'] as String?;
 | 
					        additionalSettings['versionExtractionRegEx'] as String?,
 | 
				
			||||||
    if (versionExtractionRegEx?.isNotEmpty == true) {
 | 
					        additionalSettings['matchGroupToUse'] as String?,
 | 
				
			||||||
      var match = RegExp(versionExtractionRegEx!).allMatches(
 | 
					        additionalSettings['versionExtractWholePage'] == true
 | 
				
			||||||
          additionalSettings['versionExtractWholePage'] == true
 | 
					            ? res.body.split('\r\n').join('\n').split('\n').join('\\n')
 | 
				
			||||||
              ? res.body.split('\r\n').join('\n').split('\n').join('\\n')
 | 
					            : rel);
 | 
				
			||||||
              : rel);
 | 
					 | 
				
			||||||
      if (match.isEmpty) {
 | 
					 | 
				
			||||||
        throw NoVersionError();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      String matchGroupString =
 | 
					 | 
				
			||||||
          (additionalSettings['matchGroupToUse'] as String).trim();
 | 
					 | 
				
			||||||
      if (matchGroupString.isEmpty) {
 | 
					 | 
				
			||||||
        matchGroupString = "0";
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      version = match.last.group(int.parse(matchGroupString));
 | 
					 | 
				
			||||||
      if (version?.isEmpty == true) {
 | 
					 | 
				
			||||||
        throw NoVersionError();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    rel = ensureAbsoluteUrl(rel, uri);
 | 
					    rel = ensureAbsoluteUrl(rel, uri);
 | 
				
			||||||
    version ??= (await checkDownloadHash(rel)).toString();
 | 
					    version ??= (await checkDownloadHash(rel)).toString();
 | 
				
			||||||
    return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(),
 | 
					    return APKDetails(version, [rel].map((e) => MapEntry(e, e)).toList(),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -123,7 +123,7 @@ class GeneratedFormSubForm extends GeneratedFormItem {
 | 
				
			|||||||
  final List<List<GeneratedFormItem>> items;
 | 
					  final List<List<GeneratedFormItem>> items;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  GeneratedFormSubForm(super.key, this.items,
 | 
					  GeneratedFormSubForm(super.key, this.items,
 | 
				
			||||||
      {super.label, super.belowWidgets, super.defaultValue});
 | 
					      {super.label, super.belowWidgets, super.defaultValue = const []});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  ensureType(val) {
 | 
					  ensureType(val) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart';
 | 
				
			|||||||
// ignore: implementation_imports
 | 
					// ignore: implementation_imports
 | 
				
			||||||
import 'package:easy_localization/src/localization.dart';
 | 
					import 'package:easy_localization/src/localization.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const String currentVersion = '0.15.3';
 | 
					const String currentVersion = '0.15.5';
 | 
				
			||||||
const String currentReleaseTag =
 | 
					const String currentReleaseTag =
 | 
				
			||||||
    'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
 | 
					    'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -36,7 +36,7 @@ List<MapEntry<Locale, String>> supportedLocales = const [
 | 
				
			|||||||
  MapEntry(Locale('fr'), 'Français'),
 | 
					  MapEntry(Locale('fr'), 'Français'),
 | 
				
			||||||
  MapEntry(Locale('es'), 'Español'),
 | 
					  MapEntry(Locale('es'), 'Español'),
 | 
				
			||||||
  MapEntry(Locale('pl'), 'Polski'),
 | 
					  MapEntry(Locale('pl'), 'Polski'),
 | 
				
			||||||
  MapEntry(Locale('ru'), 'Русский язык'),
 | 
					  MapEntry(Locale('ru'), 'Русский'),
 | 
				
			||||||
  MapEntry(Locale('bs'), 'Bosanski'),
 | 
					  MapEntry(Locale('bs'), 'Bosanski'),
 | 
				
			||||||
  MapEntry(Locale('pt'), 'Brasileiro'),
 | 
					  MapEntry(Locale('pt'), 'Brasileiro'),
 | 
				
			||||||
  MapEntry(Locale('cs'), 'Česky'),
 | 
					  MapEntry(Locale('cs'), 'Česky'),
 | 
				
			||||||
@@ -236,13 +236,15 @@ class _ObtainiumState extends State<Obtainium> {
 | 
				
			|||||||
              colorScheme: settingsProvider.theme == ThemeSettings.dark
 | 
					              colorScheme: settingsProvider.theme == ThemeSettings.dark
 | 
				
			||||||
                  ? darkColorScheme
 | 
					                  ? darkColorScheme
 | 
				
			||||||
                  : lightColorScheme,
 | 
					                  : lightColorScheme,
 | 
				
			||||||
              fontFamily: 'Metropolis'),
 | 
					              fontFamily:
 | 
				
			||||||
 | 
					                  settingsProvider.useSystemFont ? 'SystemFont' : 'Metropolis'),
 | 
				
			||||||
          darkTheme: ThemeData(
 | 
					          darkTheme: ThemeData(
 | 
				
			||||||
              useMaterial3: true,
 | 
					              useMaterial3: true,
 | 
				
			||||||
              colorScheme: settingsProvider.theme == ThemeSettings.light
 | 
					              colorScheme: settingsProvider.theme == ThemeSettings.light
 | 
				
			||||||
                  ? lightColorScheme
 | 
					                  ? lightColorScheme
 | 
				
			||||||
                  : darkColorScheme,
 | 
					                  : darkColorScheme,
 | 
				
			||||||
              fontFamily: 'Metropolis'),
 | 
					              fontFamily:
 | 
				
			||||||
 | 
					                  settingsProvider.useSystemFont ? 'SystemFont' : 'Metropolis'),
 | 
				
			||||||
          home: Shortcuts(shortcuts: <LogicalKeySet, Intent>{
 | 
					          home: Shortcuts(shortcuts: <LogicalKeySet, Intent>{
 | 
				
			||||||
            LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
 | 
					            LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(),
 | 
				
			||||||
          }, child: const HomePage()));
 | 
					          }, child: const HomePage()));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@ import 'package:app_links/app_links.dart';
 | 
				
			|||||||
import 'package:easy_localization/easy_localization.dart';
 | 
					import 'package:easy_localization/easy_localization.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:flutter/services.dart';
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
 | 
					import 'package:obtainium/components/generated_form_modal.dart';
 | 
				
			||||||
import 'package:obtainium/custom_errors.dart';
 | 
					import 'package:obtainium/custom_errors.dart';
 | 
				
			||||||
import 'package:obtainium/pages/add_app.dart';
 | 
					import 'package:obtainium/pages/add_app.dart';
 | 
				
			||||||
import 'package:obtainium/pages/apps.dart';
 | 
					import 'package:obtainium/pages/apps.dart';
 | 
				
			||||||
@@ -76,14 +77,39 @@ class _HomePageState extends State<HomePage> {
 | 
				
			|||||||
      try {
 | 
					      try {
 | 
				
			||||||
        if (action == 'add') {
 | 
					        if (action == 'add') {
 | 
				
			||||||
          await goToAddApp(data);
 | 
					          await goToAddApp(data);
 | 
				
			||||||
        } else if (action == 'app') {
 | 
					        } else if (action == 'app' || action == 'apps') {
 | 
				
			||||||
          await context
 | 
					          var dataStr = Uri.decodeComponent(data);
 | 
				
			||||||
              .read<AppsProvider>()
 | 
					          if (await showDialog(
 | 
				
			||||||
              .import('{ "apps": [${Uri.decodeComponent(data)}] }');
 | 
					                  context: context,
 | 
				
			||||||
        } else if (action == 'apps') {
 | 
					                  builder: (BuildContext ctx) {
 | 
				
			||||||
          await context
 | 
					                    return GeneratedFormModal(
 | 
				
			||||||
              .read<AppsProvider>()
 | 
					                      title: tr('importX', args: [
 | 
				
			||||||
              .import('{ "apps": ${Uri.decodeComponent(data)} }');
 | 
					                        action == 'app' ? tr('app') : tr('appsString')
 | 
				
			||||||
 | 
					                      ]),
 | 
				
			||||||
 | 
					                      items: const [],
 | 
				
			||||||
 | 
					                      additionalWidgets: [
 | 
				
			||||||
 | 
					                        ExpansionTile(
 | 
				
			||||||
 | 
					                          title: const Text('Raw JSON'),
 | 
				
			||||||
 | 
					                          children: [
 | 
				
			||||||
 | 
					                            Text(
 | 
				
			||||||
 | 
					                              dataStr,
 | 
				
			||||||
 | 
					                              style: const TextStyle(fontFamily: 'monospace'),
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                          ],
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                      ],
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                  }) !=
 | 
				
			||||||
 | 
					              null) {
 | 
				
			||||||
 | 
					            // ignore: use_build_context_synchronously
 | 
				
			||||||
 | 
					            var result = await context.read<AppsProvider>().import(
 | 
				
			||||||
 | 
					                action == 'app'
 | 
				
			||||||
 | 
					                    ? '{ "apps": [$dataStr] }'
 | 
				
			||||||
 | 
					                    : '{ "apps": $dataStr }');
 | 
				
			||||||
 | 
					            // ignore: use_build_context_synchronously
 | 
				
			||||||
 | 
					            showMessage(
 | 
				
			||||||
 | 
					                tr('importedX', args: [plural('apps', result.key)]), context);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          throw ObtainiumError(tr('unknown'));
 | 
					          throw ObtainiumError(tr('unknown'));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -590,7 +590,7 @@ class _ImportErrorDialogState extends State<ImportErrorDialog> {
 | 
				
			|||||||
            onPressed: () {
 | 
					            onPressed: () {
 | 
				
			||||||
              Navigator.of(context).pop(null);
 | 
					              Navigator.of(context).pop(null);
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            child: Text(tr('okay')))
 | 
					            child: Text(tr('ok')))
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@ import 'package:obtainium/custom_errors.dart';
 | 
				
			|||||||
import 'package:obtainium/main.dart';
 | 
					import 'package:obtainium/main.dart';
 | 
				
			||||||
import 'package:obtainium/providers/apps_provider.dart';
 | 
					import 'package:obtainium/providers/apps_provider.dart';
 | 
				
			||||||
import 'package:obtainium/providers/logs_provider.dart';
 | 
					import 'package:obtainium/providers/logs_provider.dart';
 | 
				
			||||||
 | 
					import 'package:obtainium/providers/native_provider.dart';
 | 
				
			||||||
import 'package:obtainium/providers/settings_provider.dart';
 | 
					import 'package:obtainium/providers/settings_provider.dart';
 | 
				
			||||||
import 'package:obtainium/providers/source_provider.dart';
 | 
					import 'package:obtainium/providers/source_provider.dart';
 | 
				
			||||||
import 'package:provider/provider.dart';
 | 
					import 'package:provider/provider.dart';
 | 
				
			||||||
@@ -350,8 +351,6 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
				
			|||||||
                              ],
 | 
					                              ],
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
                            height16,
 | 
					                            height16,
 | 
				
			||||||
                            installMethodDropdown,
 | 
					 | 
				
			||||||
                            height16,
 | 
					 | 
				
			||||||
                            Row(
 | 
					                            Row(
 | 
				
			||||||
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
					                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
				
			||||||
                              children: [
 | 
					                              children: [
 | 
				
			||||||
@@ -364,6 +363,7 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
				
			|||||||
                                    })
 | 
					                                    })
 | 
				
			||||||
                              ],
 | 
					                              ],
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
 | 
					                            installMethodDropdown,
 | 
				
			||||||
                            height32,
 | 
					                            height32,
 | 
				
			||||||
                            Text(
 | 
					                            Text(
 | 
				
			||||||
                              tr('sourceSpecific'),
 | 
					                              tr('sourceSpecific'),
 | 
				
			||||||
@@ -408,6 +408,30 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
				
			|||||||
                            height16,
 | 
					                            height16,
 | 
				
			||||||
                            localeDropdown,
 | 
					                            localeDropdown,
 | 
				
			||||||
                            height16,
 | 
					                            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;
 | 
				
			||||||
 | 
					                                      }
 | 
				
			||||||
 | 
					                                    })
 | 
				
			||||||
 | 
					                              ],
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                            height16,
 | 
				
			||||||
                            Row(
 | 
					                            Row(
 | 
				
			||||||
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
					                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
				
			||||||
                              children: [
 | 
					                              children: [
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@ import 'package:http/http.dart';
 | 
				
			|||||||
import 'package:android_intent_plus/android_intent.dart';
 | 
					import 'package:android_intent_plus/android_intent.dart';
 | 
				
			||||||
import 'package:flutter_archive/flutter_archive.dart';
 | 
					import 'package:flutter_archive/flutter_archive.dart';
 | 
				
			||||||
import 'package:shared_storage/shared_storage.dart' as saf;
 | 
					import 'package:shared_storage/shared_storage.dart' as saf;
 | 
				
			||||||
import 'installers_provider.dart';
 | 
					import 'native_provider.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
final pm = AndroidPackageManager();
 | 
					final pm = AndroidPackageManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -522,14 +522,15 @@ class AppsProvider with ChangeNotifier {
 | 
				
			|||||||
        code = await AndroidPackageInstaller.installApk(
 | 
					        code = await AndroidPackageInstaller.installApk(
 | 
				
			||||||
            apkFilePath: file.file.path);
 | 
					            apkFilePath: file.file.path);
 | 
				
			||||||
      case InstallMethodSettings.shizuku:
 | 
					      case InstallMethodSettings.shizuku:
 | 
				
			||||||
        code = (await Installers.installWithShizuku(
 | 
					        code = (await NativeFeatures.installWithShizuku(
 | 
				
			||||||
                apkFileUri: file.file.uri.toString()))
 | 
					                apkFileUri: file.file.uri.toString()))
 | 
				
			||||||
            ? 0
 | 
					            ? 0
 | 
				
			||||||
            : 1;
 | 
					            : 1;
 | 
				
			||||||
      case InstallMethodSettings.root:
 | 
					      case InstallMethodSettings.root:
 | 
				
			||||||
        code = (await Installers.installWithRoot(apkFilePath: file.file.path))
 | 
					        code =
 | 
				
			||||||
            ? 0
 | 
					            (await NativeFeatures.installWithRoot(apkFilePath: file.file.path))
 | 
				
			||||||
            : 1;
 | 
					                ? 0
 | 
				
			||||||
 | 
					                : 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    bool installed = false;
 | 
					    bool installed = false;
 | 
				
			||||||
    if (code != null && code != 0 && code != 3) {
 | 
					    if (code != null && code != 0 && code != 3) {
 | 
				
			||||||
@@ -694,14 +695,14 @@ class AppsProvider with ChangeNotifier {
 | 
				
			|||||||
              throw ObtainiumError(tr('cancelled'));
 | 
					              throw ObtainiumError(tr('cancelled'));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          case InstallMethodSettings.shizuku:
 | 
					          case InstallMethodSettings.shizuku:
 | 
				
			||||||
            int code = await Installers.checkPermissionShizuku();
 | 
					            int code = await NativeFeatures.checkPermissionShizuku();
 | 
				
			||||||
            if (code == -1) {
 | 
					            if (code == -1) {
 | 
				
			||||||
              throw ObtainiumError(tr('shizukuBinderNotFound'));
 | 
					              throw ObtainiumError(tr('shizukuBinderNotFound'));
 | 
				
			||||||
            } else if (code == 0) {
 | 
					            } else if (code == 0) {
 | 
				
			||||||
              throw ObtainiumError(tr('cancelled'));
 | 
					              throw ObtainiumError(tr('cancelled'));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          case InstallMethodSettings.root:
 | 
					          case InstallMethodSettings.root:
 | 
				
			||||||
            if (!(await Installers.checkPermissionRoot())) {
 | 
					            if (!(await NativeFeatures.checkPermissionRoot())) {
 | 
				
			||||||
              throw ObtainiumError(tr('cancelled'));
 | 
					              throw ObtainiumError(tr('cancelled'));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -1300,6 +1301,9 @@ class AppsProvider with ChangeNotifier {
 | 
				
			|||||||
          settingsProvider.prefs?.setInt(key, value);
 | 
					          settingsProvider.prefs?.setInt(key, value);
 | 
				
			||||||
        } else if (value is bool) {
 | 
					        } else if (value is bool) {
 | 
				
			||||||
          settingsProvider.prefs?.setBool(key, value);
 | 
					          settingsProvider.prefs?.setBool(key, value);
 | 
				
			||||||
 | 
					        } else if (value is List) {
 | 
				
			||||||
 | 
					          settingsProvider.prefs
 | 
				
			||||||
 | 
					              ?.setStringList(key, value.map((e) => e as String).toList());
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          settingsProvider.prefs?.setString(key, value as String);
 | 
					          settingsProvider.prefs?.setString(key, value as String);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,26 @@
 | 
				
			|||||||
import 'dart:async';
 | 
					import 'dart:async';
 | 
				
			||||||
 | 
					import 'dart:io';
 | 
				
			||||||
import 'package:flutter/services.dart';
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Installers {
 | 
					class NativeFeatures {
 | 
				
			||||||
  static const MethodChannel _channel = MethodChannel('installers');
 | 
					  static const MethodChannel _channel = MethodChannel('native');
 | 
				
			||||||
 | 
					  static bool _systemFontLoaded = false;
 | 
				
			||||||
  static bool _callbacksApplied = false;
 | 
					  static bool _callbacksApplied = false;
 | 
				
			||||||
  static int _resPermShizuku = -2;  // not set
 | 
					  static int _resPermShizuku = -2;  // not set
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static Future waitWhile(bool Function() test,
 | 
					  static Future<ByteData> _readFileBytes(String path) async {
 | 
				
			||||||
 | 
					    var file = File(path);
 | 
				
			||||||
 | 
					    var bytes = await file.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)]) {
 | 
					      [Duration pollInterval = const Duration(milliseconds: 250)]) {
 | 
				
			||||||
    var completer = Completer();
 | 
					    var completer = Completer();
 | 
				
			||||||
    check() {
 | 
					    check() {
 | 
				
			||||||
@@ -20,20 +34,25 @@ class Installers {
 | 
				
			|||||||
    return completer.future;
 | 
					    return completer.future;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static Future handleCalls(MethodCall call) async {
 | 
					  static Future<String> loadSystemFont() async {
 | 
				
			||||||
    if (call.method == 'resPermShizuku') {
 | 
					    if (_systemFontLoaded) { return "ok"; }
 | 
				
			||||||
      _resPermShizuku = call.arguments['res'];
 | 
					    var getFontRes = await _channel.invokeMethod('getSystemFont');
 | 
				
			||||||
    }
 | 
					    if (getFontRes[0] != '/') { return getFontRes; }  // Error
 | 
				
			||||||
 | 
					    var fontLoader = FontLoader('SystemFont');
 | 
				
			||||||
 | 
					    fontLoader.addFont(_readFileBytes(getFontRes));
 | 
				
			||||||
 | 
					    await fontLoader.load();
 | 
				
			||||||
 | 
					    _systemFontLoaded = true;
 | 
				
			||||||
 | 
					    return "ok";
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static Future<int> checkPermissionShizuku() async {
 | 
					  static Future<int> checkPermissionShizuku() async {
 | 
				
			||||||
    if (!_callbacksApplied) {
 | 
					    if (!_callbacksApplied) {
 | 
				
			||||||
      _channel.setMethodCallHandler(handleCalls);
 | 
					      _channel.setMethodCallHandler(_handleCalls);
 | 
				
			||||||
      _callbacksApplied = true;
 | 
					      _callbacksApplied = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    int res = await _channel.invokeMethod('checkPermissionShizuku');
 | 
					    int res = await _channel.invokeMethod('checkPermissionShizuku');
 | 
				
			||||||
    if(res == -2) {
 | 
					    if (res == -2) {
 | 
				
			||||||
      await waitWhile(() => _resPermShizuku == -2);
 | 
					      await _waitWhile(() => _resPermShizuku == -2);
 | 
				
			||||||
      res = _resPermShizuku;
 | 
					      res = _resPermShizuku;
 | 
				
			||||||
      _resPermShizuku = -2;
 | 
					      _resPermShizuku = -2;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -51,6 +51,15 @@ class SettingsProvider with ChangeNotifier {
 | 
				
			|||||||
    notifyListeners();
 | 
					    notifyListeners();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool get useSystemFont {
 | 
				
			||||||
 | 
					    return prefs?.getBool('useSystemFont') ?? false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  set useSystemFont(bool useSystemFont) {
 | 
				
			||||||
 | 
					    prefs?.setBool('useSystemFont', useSystemFont);
 | 
				
			||||||
 | 
					    notifyListeners();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  InstallMethodSettings get installMethod {
 | 
					  InstallMethodSettings get installMethod {
 | 
				
			||||||
    return InstallMethodSettings.values[
 | 
					    return InstallMethodSettings.values[
 | 
				
			||||||
        prefs?.getInt('installMethod') ?? InstallMethodSettings.normal.index];
 | 
					        prefs?.getInt('installMethod') ?? InstallMethodSettings.normal.index];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -163,6 +163,24 @@ appJSONCompatibilityModifiers(Map<String, dynamic> json) {
 | 
				
			|||||||
        return e['customLinkFilterRegex']?.isNotEmpty == true;
 | 
					        return e['customLinkFilterRegex']?.isNotEmpty == true;
 | 
				
			||||||
      }).toList();
 | 
					      }).toList();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    // Steam source apps should be converted to HTML (#1244)
 | 
				
			||||||
 | 
					    var legacySteamSourceApps = SteamMobile().apks.keys;
 | 
				
			||||||
 | 
					    if (legacySteamSourceApps.contains(additionalSettings['app'] ?? '')) {
 | 
				
			||||||
 | 
					      json['url'] = '${json['url']}/mobile';
 | 
				
			||||||
 | 
					      var replacementAdditionalSettings = getDefaultValuesFromFormItems(
 | 
				
			||||||
 | 
					          HTML().combinedAppSpecificSettingFormItems);
 | 
				
			||||||
 | 
					      for (var s in replacementAdditionalSettings.keys) {
 | 
				
			||||||
 | 
					        if (additionalSettings.containsKey(s)) {
 | 
				
			||||||
 | 
					          replacementAdditionalSettings[s] = additionalSettings[s];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      replacementAdditionalSettings['customLinkFilterRegex'] =
 | 
				
			||||||
 | 
					          '/${additionalSettings['app']}-(([0-9]+\\.?){1,})\\.apk';
 | 
				
			||||||
 | 
					      replacementAdditionalSettings['versionExtractionRegEx'] =
 | 
				
			||||||
 | 
					          replacementAdditionalSettings['customLinkFilterRegex'];
 | 
				
			||||||
 | 
					      replacementAdditionalSettings['matchGroupToUse'] = '\$1';
 | 
				
			||||||
 | 
					      additionalSettings = replacementAdditionalSettings;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  json['additionalSettings'] = jsonEncode(additionalSettings);
 | 
					  json['additionalSettings'] = jsonEncode(additionalSettings);
 | 
				
			||||||
  // F-Droid no longer needs cloudflare exception since override can be used - migrate apps appropriately
 | 
					  // F-Droid no longer needs cloudflare exception since override can be used - migrate apps appropriately
 | 
				
			||||||
@@ -444,6 +462,16 @@ abstract class AppSource {
 | 
				
			|||||||
        label: tr('trackOnly'),
 | 
					        label: tr('trackOnly'),
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
 | 
					    [
 | 
				
			||||||
 | 
					      GeneratedFormTextField('versionExtractionRegEx',
 | 
				
			||||||
 | 
					          label: tr('versionExtractionRegEx'),
 | 
				
			||||||
 | 
					          required: false,
 | 
				
			||||||
 | 
					          additionalValidators: [(value) => regExValidator(value)]),
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    [
 | 
				
			||||||
 | 
					      GeneratedFormTextField('matchGroupToUse',
 | 
				
			||||||
 | 
					          label: tr('matchGroupToUse'), required: false, hint: '\$0')
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
    [
 | 
					    [
 | 
				
			||||||
      GeneratedFormDropdown(
 | 
					      GeneratedFormDropdown(
 | 
				
			||||||
          'versionDetection',
 | 
					          'versionDetection',
 | 
				
			||||||
@@ -580,6 +608,57 @@ bool isTempId(App app) {
 | 
				
			|||||||
  return RegExp('^[0-9]+\$').hasMatch(app.id);
 | 
					  return RegExp('^[0-9]+\$').hasMatch(app.id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					replaceMatchGroupsInString(RegExpMatch match, String matchGroupString) {
 | 
				
			||||||
 | 
					  if (RegExp('^\\d+\$').hasMatch(matchGroupString)) {
 | 
				
			||||||
 | 
					    matchGroupString = '\$$matchGroupString';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // Regular expression to match numbers in the input string
 | 
				
			||||||
 | 
					  final numberRegex = RegExp(r'\$\d+');
 | 
				
			||||||
 | 
					  // Extract all numbers from the input string
 | 
				
			||||||
 | 
					  final numbers = numberRegex.allMatches(matchGroupString);
 | 
				
			||||||
 | 
					  if (numbers.isEmpty) {
 | 
				
			||||||
 | 
					    // If no numbers found, return the original string
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // Replace numbers with corresponding match groups
 | 
				
			||||||
 | 
					  var outputString = matchGroupString;
 | 
				
			||||||
 | 
					  for (final numberMatch in numbers) {
 | 
				
			||||||
 | 
					    final number = numberMatch.group(0)!;
 | 
				
			||||||
 | 
					    final matchGroup = match.group(int.parse(number.substring(1))) ?? '';
 | 
				
			||||||
 | 
					    // Check if the number is preceded by a single backslash
 | 
				
			||||||
 | 
					    final isEscaped = outputString.contains('\\$number');
 | 
				
			||||||
 | 
					    // Replace the number with the corresponding match group
 | 
				
			||||||
 | 
					    if (!isEscaped) {
 | 
				
			||||||
 | 
					      outputString = outputString.replaceAll(number, matchGroup);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      outputString = outputString.replaceAll('\\$number', number);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return outputString;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String? extractVersion(String? versionExtractionRegEx, String? matchGroupString,
 | 
				
			||||||
 | 
					    String stringToCheck) {
 | 
				
			||||||
 | 
					  if (versionExtractionRegEx?.isNotEmpty == true) {
 | 
				
			||||||
 | 
					    String? version = stringToCheck;
 | 
				
			||||||
 | 
					    var match = RegExp(versionExtractionRegEx!).allMatches(version);
 | 
				
			||||||
 | 
					    if (match.isEmpty) {
 | 
				
			||||||
 | 
					      throw NoVersionError();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    matchGroupString = matchGroupString?.trim() ?? '';
 | 
				
			||||||
 | 
					    if (matchGroupString.isEmpty) {
 | 
				
			||||||
 | 
					      matchGroupString = "0";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    version = replaceMatchGroupsInString(match.last, matchGroupString);
 | 
				
			||||||
 | 
					    if (version?.isNotEmpty != true) {
 | 
				
			||||||
 | 
					      throw NoVersionError();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return version!;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SourceProvider {
 | 
					class SourceProvider {
 | 
				
			||||||
  // Add more source classes here so they are available via the service
 | 
					  // Add more source classes here so they are available via the service
 | 
				
			||||||
  List<AppSource> get sources => [
 | 
					  List<AppSource> get sources => [
 | 
				
			||||||
@@ -597,13 +676,11 @@ class SourceProvider {
 | 
				
			|||||||
        APKMirror(),
 | 
					        APKMirror(),
 | 
				
			||||||
        HuaweiAppGallery(),
 | 
					        HuaweiAppGallery(),
 | 
				
			||||||
        Jenkins(),
 | 
					        Jenkins(),
 | 
				
			||||||
        // APKCombo(), // Can't get past their scraping blocking yet (get 403 Forbidden)
 | 
					 | 
				
			||||||
        Mullvad(),
 | 
					        Mullvad(),
 | 
				
			||||||
        Signal(),
 | 
					        Signal(),
 | 
				
			||||||
        VLC(),
 | 
					        VLC(),
 | 
				
			||||||
        WhatsApp(), // As of 2023-03-20 this is unusable as the version on the webpage is months out of date
 | 
					        WhatsApp(),
 | 
				
			||||||
        TelegramApp(),
 | 
					        TelegramApp(),
 | 
				
			||||||
        SteamMobile(),
 | 
					 | 
				
			||||||
        NeutronCode(),
 | 
					        NeutronCode(),
 | 
				
			||||||
        HTML() // This should ALWAYS be the last option as they are tried in order
 | 
					        HTML() // This should ALWAYS be the last option as they are tried in order
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
@@ -679,6 +756,18 @@ class SourceProvider {
 | 
				
			|||||||
    String standardUrl = source.standardizeUrl(url);
 | 
					    String standardUrl = source.standardizeUrl(url);
 | 
				
			||||||
    APKDetails apk =
 | 
					    APKDetails apk =
 | 
				
			||||||
        await source.getLatestAPKDetails(standardUrl, additionalSettings);
 | 
					        await source.getLatestAPKDetails(standardUrl, additionalSettings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (source.runtimeType != HTML().runtimeType) {
 | 
				
			||||||
 | 
					      // HTML does it separately
 | 
				
			||||||
 | 
					      String? extractedVersion = extractVersion(
 | 
				
			||||||
 | 
					          additionalSettings['versionExtractionRegEx'] as String?,
 | 
				
			||||||
 | 
					          additionalSettings['matchGroupToUse'] as String?,
 | 
				
			||||||
 | 
					          apk.version);
 | 
				
			||||||
 | 
					      if (extractedVersion != null) {
 | 
				
			||||||
 | 
					        apk.version = extractedVersion;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (additionalSettings['versionDetection'] == 'releaseDateAsVersion' &&
 | 
					    if (additionalSettings['versionDetection'] == 'releaseDateAsVersion' &&
 | 
				
			||||||
        apk.releaseDate != null) {
 | 
					        apk.releaseDate != null) {
 | 
				
			||||||
      apk.version = apk.releaseDate!.microsecondsSinceEpoch.toString();
 | 
					      apk.version = apk.releaseDate!.microsecondsSinceEpoch.toString();
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										56
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								pubspec.lock
									
									
									
									
									
								
							@@ -30,10 +30,10 @@ packages:
 | 
				
			|||||||
    dependency: "direct main"
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: animations
 | 
					      name: animations
 | 
				
			||||||
      sha256: "708e4b68c23228c264b038fe7003a2f5d01ce85fc64d8cae090e86b27fcea6c5"
 | 
					      sha256: d3d6dcfb218225bbe68e87ccf6378bbb2e32a94900722c5f81611dad089911cb
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "2.0.10"
 | 
					    version: "2.0.11"
 | 
				
			||||||
  app_links:
 | 
					  app_links:
 | 
				
			||||||
    dependency: "direct main"
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@@ -46,10 +46,10 @@ packages:
 | 
				
			|||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: archive
 | 
					      name: archive
 | 
				
			||||||
      sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b"
 | 
					      sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "3.4.9"
 | 
					    version: "3.4.10"
 | 
				
			||||||
  args:
 | 
					  args:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@@ -328,10 +328,10 @@ packages:
 | 
				
			|||||||
    dependency: "direct main"
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: flutter_markdown
 | 
					      name: flutter_markdown
 | 
				
			||||||
      sha256: "35108526a233cc0755664d445f8a6b4b61e6f8fe993b3658b80b4a26827fc196"
 | 
					      sha256: "30088ce826b5b9cfbf9e8bece34c716c8a59fa54461dcae1e4ac01a94639e762"
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "0.6.18+2"
 | 
					    version: "0.6.18+3"
 | 
				
			||||||
  flutter_plugin_android_lifecycle:
 | 
					  flutter_plugin_android_lifecycle:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@@ -610,18 +610,18 @@ packages:
 | 
				
			|||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: platform
 | 
					      name: platform
 | 
				
			||||||
      sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
 | 
					      sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "3.1.3"
 | 
					    version: "3.1.4"
 | 
				
			||||||
  plugin_platform_interface:
 | 
					  plugin_platform_interface:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: plugin_platform_interface
 | 
					      name: plugin_platform_interface
 | 
				
			||||||
      sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8
 | 
					      sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "2.1.7"
 | 
					    version: "2.1.8"
 | 
				
			||||||
  pointycastle:
 | 
					  pointycastle:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@@ -831,18 +831,18 @@ packages:
 | 
				
			|||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: url_launcher_android
 | 
					      name: url_launcher_android
 | 
				
			||||||
      sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def"
 | 
					      sha256: c0766a55ab42cefaa728cabc951e82919ab41a3a4fee0aaa96176ca82da8cc51
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "6.2.0"
 | 
					    version: "6.2.1"
 | 
				
			||||||
  url_launcher_ios:
 | 
					  url_launcher_ios:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: url_launcher_ios
 | 
					      name: url_launcher_ios
 | 
				
			||||||
      sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3
 | 
					      sha256: "46b81e3109cbb2d6b81702ad3077540789a3e74e22795eb9f0b7d494dbaa72ea"
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "6.2.1"
 | 
					    version: "6.2.2"
 | 
				
			||||||
  url_launcher_linux:
 | 
					  url_launcher_linux:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@@ -863,18 +863,18 @@ packages:
 | 
				
			|||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: url_launcher_platform_interface
 | 
					      name: url_launcher_platform_interface
 | 
				
			||||||
      sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50"
 | 
					      sha256: "4aca1e060978e19b2998ee28503f40b5ba6226819c2b5e3e4d1821e8ccd92198"
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "2.2.0"
 | 
					    version: "2.3.0"
 | 
				
			||||||
  url_launcher_web:
 | 
					  url_launcher_web:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: url_launcher_web
 | 
					      name: url_launcher_web
 | 
				
			||||||
      sha256: "7286aec002c8feecc338cc33269e96b73955ab227456e9fb2a91f7fab8a358e9"
 | 
					      sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "2.2.2"
 | 
					    version: "2.2.3"
 | 
				
			||||||
  url_launcher_windows:
 | 
					  url_launcher_windows:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@@ -911,18 +911,18 @@ packages:
 | 
				
			|||||||
    dependency: "direct main"
 | 
					    dependency: "direct main"
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: webview_flutter
 | 
					      name: webview_flutter
 | 
				
			||||||
      sha256: "42393b4492e629aa3a88618530a4a00de8bb46e50e7b3993fedbfdc5352f0dbf"
 | 
					      sha256: "60e23976834e995c404c0b21d3b9db37ecd77d3303ef74f8b8d7a7b19947fc04"
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "4.4.2"
 | 
					    version: "4.4.3"
 | 
				
			||||||
  webview_flutter_android:
 | 
					  webview_flutter_android:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: webview_flutter_android
 | 
					      name: webview_flutter_android
 | 
				
			||||||
      sha256: b54c89fe14a6d26a2a46e24880da0441cdd2bf1f6d01a5b3e1d39558feb1de0b
 | 
					      sha256: "161af93c2abaf94ef2192bffb53a3658b2d721a3bf99b69aa1e47814ee18cc96"
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "3.13.1"
 | 
					    version: "3.13.2"
 | 
				
			||||||
  webview_flutter_platform_interface:
 | 
					  webview_flutter_platform_interface:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@@ -935,18 +935,18 @@ packages:
 | 
				
			|||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: webview_flutter_wkwebview
 | 
					      name: webview_flutter_wkwebview
 | 
				
			||||||
      sha256: eebfabfa8a115b535b52031b8b26f7a4b58ceceab378bc9db8762b0fb46f7b5d
 | 
					      sha256: "02d8f3ebbc842704b2b662377b3ee11c0f8f1bbaa8eab6398262f40049819160"
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "3.10.0"
 | 
					    version: "3.10.1"
 | 
				
			||||||
  win32:
 | 
					  win32:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: win32
 | 
					      name: win32
 | 
				
			||||||
      sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574
 | 
					      sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "5.1.1"
 | 
					    version: "5.2.0"
 | 
				
			||||||
  win32_registry:
 | 
					  win32_registry:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
@@ -959,10 +959,10 @@ packages:
 | 
				
			|||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
      name: xdg_directories
 | 
					      name: xdg_directories
 | 
				
			||||||
      sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
 | 
					      sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
 | 
				
			||||||
      url: "https://pub.dev"
 | 
					      url: "https://pub.dev"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "1.0.3"
 | 
					    version: "1.0.4"
 | 
				
			||||||
  xml:
 | 
					  xml:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 | 
				
			|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
					# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
				
			||||||
# In Windows, build-name is used as the major, minor, and patch parts
 | 
					# In Windows, build-name is used as the major, minor, and patch parts
 | 
				
			||||||
# of the product and file versions while build-number is used as the build suffix.
 | 
					# of the product and file versions while build-number is used as the build suffix.
 | 
				
			||||||
version: 0.15.3+239 # When changing this, update the tag in main() accordingly
 | 
					version: 0.15.5+241 # When changing this, update the tag in main() accordingly
 | 
				
			||||||
 | 
					
 | 
				
			||||||
environment:
 | 
					environment:
 | 
				
			||||||
  sdk: '>=3.0.0 <4.0.0'
 | 
					  sdk: '>=3.0.0 <4.0.0'
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user