mirror of
				https://github.com/ImranR98/Obtainium.git
				synced 2025-11-04 07:13:28 +01:00 
			
		
		
		
	Compare commits
	
		
			59 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					1e3815ca20 | ||
| 
						 | 
					0e2fa96b9f | ||
| 
						 | 
					389aebe54e | ||
| 
						 | 
					fbfeaf2a91 | ||
| 
						 | 
					485812d076 | ||
| 
						 | 
					68e98ec719 | ||
| 
						 | 
					cbe41de734 | ||
| 
						 | 
					abb8641105 | ||
| 
						 | 
					dbcb4b3c09 | ||
| 
						 | 
					b231c756e6 | ||
| 
						 | 
					3cb3f7fdd4 | ||
| 
						 | 
					9837e8e325 | ||
| 
						 | 
					73d4814f18 | ||
| 
						 | 
					0a9219c314 | ||
| 
						 | 
					56c5a73d9a | ||
| 
						 | 
					a30e063246 | ||
| 
						 | 
					bd26b6514a | ||
| 
						 | 
					3ea8c7e888 | ||
| 
						 | 
					5f2ec5ce6f | ||
| 
						 | 
					783ce9d555 | ||
| 
						 | 
					a719b2475b | ||
| 
						 | 
					84df499ea6 | ||
| 
						 | 
					0d25b74050 | ||
| 
						 | 
					0effbc3841 | ||
| 
						 | 
					7478a7af22 | ||
| 
						 | 
					0838a6d30b | ||
| 
						 | 
					8cee268d13 | ||
| 
						 | 
					a3fddc5400 | ||
| 
						 | 
					c0a2e372e5 | ||
| 
						 | 
					c633963203 | ||
| 
						 | 
					299f457938 | ||
| 
						 | 
					37e62c922b | ||
| 
						 | 
					95722ce47b | ||
| 
						 | 
					8b806b3ef1 | ||
| 
						 | 
					09221b3526 | ||
| 
						 | 
					31b6250082 | ||
| 
						 | 
					07372da91b | ||
| 
						 | 
					5c36bcfb4b | ||
| 
						 | 
					e5012b1fcb | ||
| 
						 | 
					6f951175a4 | ||
| 
						 | 
					be52ec372f | ||
| 
						 | 
					eb7126afc3 | ||
| 
						 | 
					26fc63a02a | ||
| 
						 | 
					d33ca0948f | ||
| 
						 | 
					f76637a2e1 | ||
| 
						 | 
					b7de627c7b | ||
| 
						 | 
					27fc60d437 | ||
| 
						 | 
					ec240f946e | ||
| 
						 | 
					ecd80fc371 | ||
| 
						 | 
					68fa660e6d | ||
| 
						 | 
					70f9e33d17 | ||
| 
						 | 
					2e2dffd8e2 | ||
| 
						 | 
					0b1d5bf514 | ||
| 
						 | 
					2570c8e289 | ||
| 
						 | 
					43a8ba4de1 | ||
| 
						 | 
					3f2fb1c1ed | ||
| 
						 | 
					40d303fb57 | ||
| 
						 | 
					2c1687c33d | ||
| 
						 | 
					b688e7f160 | 
							
								
								
									
										2
									
								
								.flutter
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								.flutter
									
									
									
									
									
								
							 Submodule .flutter updated: 54e66469a9...5dcb86f68f
									
								
							
							
								
								
									
										10
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								README.md
									
									
									
									
									
								
							@@ -29,15 +29,23 @@ Currently supported App sources:
 | 
			
		||||
  - [Huawei AppGallery](https://appgallery.huawei.com/)
 | 
			
		||||
  - Jenkins Jobs
 | 
			
		||||
- Open Source - App-Specific:
 | 
			
		||||
  - [Mullvad](https://mullvad.net/en/)
 | 
			
		||||
  - [Signal](https://signal.org/)
 | 
			
		||||
  - [VLC](https://videolan.org/)
 | 
			
		||||
- Other - App-Specific:
 | 
			
		||||
  - [WhatsApp](https://whatsapp.com)
 | 
			
		||||
  - [Telegram App](https://telegram.org)
 | 
			
		||||
  - [Neutron Code](https://neutroncode.com)
 | 
			
		||||
- Direct APK Link
 | 
			
		||||
- "HTML" (Fallback): Any other URL that returns an HTML page with links to APK files
 | 
			
		||||
 | 
			
		||||
## Finding App Configurations
 | 
			
		||||
 | 
			
		||||
You can find crowdsourced app configurations at [apps.obtainium.imranr.dev](https://apps.obtainium.imranr.dev).
 | 
			
		||||
 | 
			
		||||
If you can't find the configuration for an app you want, feel free to leave a request on the [discussions page](https://github.com/ImranR98/apps.obtainium.imranr.dev/discussions/new?category=app-requests).
 | 
			
		||||
 | 
			
		||||
Or, contribute some configurations to the website by creating a PR at [this repo](https://github.com/ImranR98/apps.obtainium.imranr.dev).
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
[<img src="https://github.com/machiav3lli/oandbackupx/blob/034b226cea5c1b30eb4f6a6f313e4dadcbb0ece4/badge_github.png"
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,8 @@
 | 
			
		||||
        android:name="${applicationName}"
 | 
			
		||||
        android:icon="@mipmap/ic_launcher"
 | 
			
		||||
        android:requestLegacyExternalStorage="true"
 | 
			
		||||
        android:usesCleartextTraffic="true">
 | 
			
		||||
        android:usesCleartextTraffic="true"
 | 
			
		||||
        android:localeConfig="@xml/locales_config">
 | 
			
		||||
        <activity
 | 
			
		||||
            android:name=".MainActivity"
 | 
			
		||||
            android:exported="true"
 | 
			
		||||
@@ -47,7 +48,7 @@
 | 
			
		||||
            android:value="2" />
 | 
			
		||||
        <provider
 | 
			
		||||
            android:name="androidx.core.content.FileProvider"
 | 
			
		||||
            android:authorities="dev.imranr.obtainium"
 | 
			
		||||
            android:authorities="${applicationId}"
 | 
			
		||||
            android:grantUriPermissions="true">
 | 
			
		||||
            <meta-data
 | 
			
		||||
                android:name="android.support.FILE_PROVIDER_PATHS"
 | 
			
		||||
@@ -72,4 +73,4 @@
 | 
			
		||||
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
 | 
			
		||||
        android:maxSdkVersion="29" />\
 | 
			
		||||
    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
 | 
			
		||||
</manifest>
 | 
			
		||||
</manifest>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								android/app/src/main/res/xml/locales_config.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								android/app/src/main/res/xml/locales_config.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
 | 
			
		||||
    <locale android:name="bs"/>
 | 
			
		||||
    <locale android:name="cs"/>
 | 
			
		||||
    <locale android:name="de"/>
 | 
			
		||||
    <locale android:name="en"/>
 | 
			
		||||
    <locale android:name="es"/>
 | 
			
		||||
    <locale android:name="fa"/>
 | 
			
		||||
    <locale android:name="fr"/>
 | 
			
		||||
    <locale android:name="hu"/>
 | 
			
		||||
    <locale android:name="it"/>
 | 
			
		||||
    <locale android:name="ja"/>
 | 
			
		||||
    <locale android:name="nl"/>
 | 
			
		||||
    <locale android:name="pl"/>
 | 
			
		||||
    <locale android:name="pt"/>
 | 
			
		||||
    <locale android:name="ru"/>
 | 
			
		||||
    <locale android:name="sv"/>
 | 
			
		||||
    <locale android:name="tr"/>
 | 
			
		||||
    <locale android:name="uk"/>
 | 
			
		||||
    <locale android:name="vi"/>
 | 
			
		||||
    <locale android:name="zh"/>
 | 
			
		||||
</locale-config>
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Tamna",
 | 
			
		||||
    "light": "Svijetla",
 | 
			
		||||
    "followSystem": "Pratite sistem",
 | 
			
		||||
    "followSystemThemeExplanation": "Following system theme is possible only by using third-party applications",
 | 
			
		||||
    "useBlackTheme": "Koristite čisto crnu tamnu temu",
 | 
			
		||||
    "appSortBy": "Aplikacije sortirane po",
 | 
			
		||||
    "authorName": "Autor/Ime",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "The APK could not be parsed (incompatible or partial download)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)",
 | 
			
		||||
    "appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.",
 | 
			
		||||
    "wiki": "Help/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Želite li ukloniti aplikaciju?",
 | 
			
		||||
        "other": "Želite li ukloniti aplikacije?"
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Tmavé",
 | 
			
		||||
    "light": "Světlé",
 | 
			
		||||
    "followSystem": "Jako systém",
 | 
			
		||||
    "followSystemThemeExplanation": "Sledování motivu systému je možné pouze pomocí aplikací třetích stran.",
 | 
			
		||||
    "useBlackTheme": "Použít čistě černé tmavé téma",
 | 
			
		||||
    "appSortBy": "Seřadit podle",
 | 
			
		||||
    "authorName": "Autor/Jméno",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "APK nelze analyzovat (nekompatibilní nebo částečné stažení)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Sdílení nových aplikací s aplikací AppVerifier (pokud je k dispozici)",
 | 
			
		||||
    "appVerifierInstructionToast": "Sdílejte do aplikace AppVerifier a po dokončení se sem vraťte.",
 | 
			
		||||
    "wiki": "Nápověda/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Konfigurace aplikací s využitím crowdsourcingu (použití na vlastní nebezpečí)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Odstranit Apku?",
 | 
			
		||||
        "other": "Odstranit Apky?"
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
    "colour": "Farbe",
 | 
			
		||||
    "standard": "Standard",
 | 
			
		||||
    "custom": "Benutzerdefiniert",
 | 
			
		||||
    "useMaterialYou": "Verwenden Sie Material, das Sie",
 | 
			
		||||
    "useMaterialYou": "Verwende Material You",
 | 
			
		||||
    "githubStarredRepos": "GitHub Starred Repos",
 | 
			
		||||
    "uname": "Benutzername",
 | 
			
		||||
    "wrongArgNum": "Falsche Anzahl von Argumenten (Parametern) übermittelt",
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Dunkel",
 | 
			
		||||
    "light": "Hell",
 | 
			
		||||
    "followSystem": "System folgen",
 | 
			
		||||
    "followSystemThemeExplanation": "Das Folgen des Systemthemes ist unter Android <10 nur mit Hilfe von Drittanbieteranwendungen möglich",
 | 
			
		||||
    "useBlackTheme": "Verwende Pure Black Dark Theme",
 | 
			
		||||
    "appSortBy": "App sortieren nach",
 | 
			
		||||
    "authorName": "Autor/Name",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "Die APK konnte nicht geparst werden (inkompatibler oder teilweiser Download)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Neue Apps mit AppVerifier teilen (falls verfügbar)",
 | 
			
		||||
    "appVerifierInstructionToast": "Geben Sie die Daten an AppVerifier weiter und kehren Sie dann hierher zurück, wenn Sie fertig sind.",
 | 
			
		||||
    "wiki": "Hilfe/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (Verwendung auf eigene Gefahr)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "App entfernen?",
 | 
			
		||||
        "other": "Apps entfernen?"
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Dark",
 | 
			
		||||
    "light": "Light",
 | 
			
		||||
    "followSystem": "Follow System",
 | 
			
		||||
    "followSystemThemeExplanation": "Following system theme is possible only by using third-party applications",
 | 
			
		||||
    "useBlackTheme": "Use pure black dark theme",
 | 
			
		||||
    "appSortBy": "App Sort By",
 | 
			
		||||
    "authorName": "Author/Name",
 | 
			
		||||
@@ -258,7 +259,7 @@
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "Disable background updates when not on WiFi",
 | 
			
		||||
    "autoSelectHighestVersionCode": "Auto-select highest versionCode APK",
 | 
			
		||||
    "versionExtractionRegEx": "Version String Extraction RegEx",
 | 
			
		||||
    "matchGroupToUse": "Match Group to Use for Version String Extraction Regex",
 | 
			
		||||
    "matchGroupToUse": "Match Group to Use for Version String Extraction RegEx",
 | 
			
		||||
    "highlightTouchTargets": "Highlight less obvious touch targets",
 | 
			
		||||
    "pickExportDir": "Pick Export Directory",
 | 
			
		||||
    "autoExportOnChanges": "Auto-export on changes",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "The APK could not be parsed (incompatible or partial download)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)",
 | 
			
		||||
    "appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.",
 | 
			
		||||
    "wiki": "Help/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Remove App?",
 | 
			
		||||
        "other": "Remove Apps?"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
{
 | 
			
		||||
    "invalidURLForSource": "El URL de la aplicación {} no es válido",
 | 
			
		||||
    "noReleaseFound": "No se ha podido encontrar una versión válida",
 | 
			
		||||
    "noReleaseFound": "No se ha encontrado una versión válida",
 | 
			
		||||
    "noVersionFound": "No se ha podido determinar la versión",
 | 
			
		||||
    "urlMatchesNoSource": "El URL no coincide con ninguna fuente conocida",
 | 
			
		||||
    "cantInstallOlderVersion": "No se puede instalar una versión previa de la aplicación",
 | 
			
		||||
    "appIdMismatch": "El id. del paquete descargado no coincide con la ID de la aplicación instalada",
 | 
			
		||||
    "appIdMismatch": "El ID del paquete descargado no coincide con el ID de la aplicación instalada",
 | 
			
		||||
    "functionNotImplemented": "Esta clase no ha implementado esta función",
 | 
			
		||||
    "placeholder": "Espacio reservado",
 | 
			
		||||
    "someErrors": "Han ocurrido algunos errores",
 | 
			
		||||
@@ -24,15 +24,15 @@
 | 
			
		||||
    "colour": "Color",
 | 
			
		||||
    "standard": "Estándar",
 | 
			
		||||
    "custom": "A medida",
 | 
			
		||||
    "useMaterialYou": "Utilice el material que",
 | 
			
		||||
    "useMaterialYou": "Use 'Material You'",
 | 
			
		||||
    "githubStarredRepos": "Repositorios favoritos en GitHub",
 | 
			
		||||
    "uname": "Nombre de usuario",
 | 
			
		||||
    "wrongArgNum": "Número de argumentos provistos inválido",
 | 
			
		||||
    "xIsTrackOnly": "{} es de 'sólo seguimiento'",
 | 
			
		||||
    "source": "Origen",
 | 
			
		||||
    "app": "Aplicación",
 | 
			
		||||
    "appsFromSourceAreTrackOnly": "Las aplicaciones de este origen son de 'solo seguimiento'.",
 | 
			
		||||
    "youPickedTrackOnly": "Debe seleccionar la opción de 'solo seguimiento'.",
 | 
			
		||||
    "appsFromSourceAreTrackOnly": "Las aplicaciones de este origen son solo para seguimiento.",
 | 
			
		||||
    "youPickedTrackOnly": "Debe seleccionar la opción de 'solo para seguimiento'.",
 | 
			
		||||
    "trackOnlyAppDescription": "Se hará el seguimiento de actualizaciones para la aplicación, pero Obtainium no será capaz de descargar o actualizarla.",
 | 
			
		||||
    "cancelled": "Cancelado",
 | 
			
		||||
    "appAlreadyAdded": "Aplicación añadida anteriormente",
 | 
			
		||||
@@ -45,14 +45,14 @@
 | 
			
		||||
    "search": "Buscar",
 | 
			
		||||
    "additionalOptsFor": "Opciones adicionales para {}",
 | 
			
		||||
    "supportedSources": "Fuentes admitidas",
 | 
			
		||||
    "trackOnlyInBrackets": "(Solo seguimiento)",
 | 
			
		||||
    "trackOnlyInBrackets": "(Solo para seguimiento)",
 | 
			
		||||
    "searchableInBrackets": "(permite búsqueda)",
 | 
			
		||||
    "appsString": "Aplicaciones",
 | 
			
		||||
    "noApps": "Sin Aplicaciones",
 | 
			
		||||
    "noAppsForFilter": "Sin aplicaciones para filtrar",
 | 
			
		||||
    "byX": "por: {}",
 | 
			
		||||
    "percentProgress": "Progreso: {} %",
 | 
			
		||||
    "pleaseWait": "Espere un momento",
 | 
			
		||||
    "pleaseWait": "Espere...",
 | 
			
		||||
    "updateAvailable": "Actualización disponible",
 | 
			
		||||
    "notInstalled": "No instalado",
 | 
			
		||||
    "pseudoVersion": "pseudoversión",
 | 
			
		||||
@@ -63,7 +63,7 @@
 | 
			
		||||
    "removeSelectedApps": "Eliminar aplicaciones seleccionadas",
 | 
			
		||||
    "updateX": "Actualizar {}",
 | 
			
		||||
    "installX": "Instalar {}",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "Marcar {}\n(Solo seguimiento)\ncomo actualizada",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "Marcar {}\n(solo para seguimiento)\ncomo actualizada",
 | 
			
		||||
    "changeX": "Cambiar {}",
 | 
			
		||||
    "installUpdateApps": "Instalar/actualizar aplicaciones",
 | 
			
		||||
    "installUpdateSelectedApps": "Instalar/actualizar aplicaciones seleccionadas",
 | 
			
		||||
@@ -100,7 +100,7 @@
 | 
			
		||||
    "appURLList": "Lista de URL de aplicaciones",
 | 
			
		||||
    "line": "Línea",
 | 
			
		||||
    "searchX": "Buscar {}",
 | 
			
		||||
    "noResults": "No se encontró ningún resultado",
 | 
			
		||||
    "noResults": "No se ha encontrado ningún resultado",
 | 
			
		||||
    "importX": "Importar desde {}",
 | 
			
		||||
    "importedAppsIdDisclaimer": "Las aplicaciones importadas podrían mostrarse incorrectamente como «No instalada».\nPara solucionarlo, reinstálelas a través de Obtainium.\nEsto no debería afectar a los datos de las aplicaciones.\n\nSolo afecta a los URL y a los métodos de importación mediante terceros.",
 | 
			
		||||
    "importErrors": "Errores de Importación",
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Oscuro",
 | 
			
		||||
    "light": "Claro",
 | 
			
		||||
    "followSystem": "Seguir al sistema",
 | 
			
		||||
    "followSystemThemeExplanation": "Seguir el tema del sistema sólo es posible utilizando aplicaciones de terceros",
 | 
			
		||||
    "useBlackTheme": "Negro puro en tema oscuro",
 | 
			
		||||
    "appSortBy": "Ordenar aplicaciones por",
 | 
			
		||||
    "authorName": "Autor/nombre",
 | 
			
		||||
@@ -175,9 +176,9 @@
 | 
			
		||||
    "fdroid": "Repositorio oficial F-Droid",
 | 
			
		||||
    "appIdOrName": "ID o Nombre de la Aplicación",
 | 
			
		||||
    "appId": "ID de la Aplicación",
 | 
			
		||||
    "appWithIdOrNameNotFound": "No se han encontrado aplicaciones con esa ID o nombre",
 | 
			
		||||
    "appWithIdOrNameNotFound": "No se han encontrado aplicaciones con ese ID o nombre",
 | 
			
		||||
    "reposHaveMultipleApps": "Los repositorios pueden contener varias aplicaciones",
 | 
			
		||||
    "fdroidThirdPartyRepo": "Repositorio de tercera parte F-Droid",
 | 
			
		||||
    "fdroidThirdPartyRepo": "Repositorio de terceros F-Droid",
 | 
			
		||||
    "steamMobile": "Steam para móviles",
 | 
			
		||||
    "steamChat": "Chat de Steam",
 | 
			
		||||
    "install": "Instalar",
 | 
			
		||||
@@ -190,9 +191,9 @@
 | 
			
		||||
    "downloadingX": "Descargando {}",
 | 
			
		||||
    "downloadX": "Descargar {}",
 | 
			
		||||
    "downloadedX": "Descargado {}",
 | 
			
		||||
    "releaseAsset": "Liberar activos",
 | 
			
		||||
    "releaseAsset": "Recurso publicado",
 | 
			
		||||
    "downloadNotifDescription": "Notifica al usuario del progreso de descarga de una aplicación",
 | 
			
		||||
    "noAPKFound": "No se encontró el paquete de instalación APK",
 | 
			
		||||
    "noAPKFound": "No se ha encontrado el paquete de instalación APK",
 | 
			
		||||
    "noVersionDetection": "Sin detección de versiones",
 | 
			
		||||
    "categorize": "Catogorizar",
 | 
			
		||||
    "categories": "Categorías",
 | 
			
		||||
@@ -204,7 +205,7 @@
 | 
			
		||||
    "addCategory": "Añadir categoría",
 | 
			
		||||
    "label": "Nombre",
 | 
			
		||||
    "language": "Idioma",
 | 
			
		||||
    "copiedToClipboard": "Se copió en el portapapeles",
 | 
			
		||||
    "copiedToClipboard": "Copiado en el portapapeles",
 | 
			
		||||
    "storagePermissionDenied": "Permiso de almacenamiento rechazado",
 | 
			
		||||
    "selectedCategorizeWarning": "Esto reemplazará cualquier ajuste de categoría para las aplicaciones seleccionadas.",
 | 
			
		||||
    "filterAPKsByRegEx": "Filtrar por APK",
 | 
			
		||||
@@ -221,16 +222,16 @@
 | 
			
		||||
    "standardVersionDetection": "Por versión",
 | 
			
		||||
    "groupByCategory": "Agrupar por categoría",
 | 
			
		||||
    "autoApkFilterByArch": "Filtrar APK por arquitectura del procesador (si es posible)",
 | 
			
		||||
    "overrideSource": "Anular fuente",
 | 
			
		||||
    "overrideSource": "Forzar desde la fuente",
 | 
			
		||||
    "dontShowAgain": "No mostrar de nuevo",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "No mostrar avisos sobre apps en 'solo seguimiento'",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "No mostrar avisos sobre apps 'solo para seguimiento",
 | 
			
		||||
    "dontShowAPKOriginWarnings": "No mostrar avisos sobre las fuentes de las APKs",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Mover Apps no instaladas al final",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Mover apps no instaladas al final",
 | 
			
		||||
    "gitlabPATLabel": "Token de acceso personal a GitLab",
 | 
			
		||||
    "about": "Acerca",
 | 
			
		||||
    "requiresCredentialsInSettings": "{}: Esto requiere credenciales adicionales (en ajustes)",
 | 
			
		||||
    "checkOnStart": "Comprobar actualizaciones al inicio",
 | 
			
		||||
    "tryInferAppIdFromCode": "Intentar deducir la ID de la app por el código fuente",
 | 
			
		||||
    "tryInferAppIdFromCode": "Intentar deducir el ID de la app por el código fuente",
 | 
			
		||||
    "removeOnExternalUninstall": "Auto eliminar apps desinstaladas externamente",
 | 
			
		||||
    "pickHighestVersionCode": "Auto selección de versión superior del paquete APK",
 | 
			
		||||
    "checkUpdateOnDetailPage": "Comprobar actualizaciones al abrir detalles de la app",
 | 
			
		||||
@@ -285,30 +286,32 @@
 | 
			
		||||
    "checkingForUpdatesNotifChannel": "Buscando actualizaciones",
 | 
			
		||||
    "onlyCheckInstalledOrTrackOnlyApps": "Comprobar actualizaciones solo para apps instaladas o en seguimiento",
 | 
			
		||||
    "supportFixedAPKURL": "Soporte para URLs fijas de APK",
 | 
			
		||||
    "selectX": "Selecciona {}",
 | 
			
		||||
    "selectX": "Elija {}",
 | 
			
		||||
    "parallelDownloads": "Permitir descargas paralelas",
 | 
			
		||||
    "useShizuku": "Utilice Shizuku o Sui para instalar",
 | 
			
		||||
    "useShizuku": "Use Shizuku o Sui para instalar",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku no funciona",
 | 
			
		||||
    "shizukuOld": "Versión antigua de Shizuku (<11) - actualízala",
 | 
			
		||||
    "shizukuOld": "Versión antigua de Shizuku (<11) - actualícela",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku corriendo en Android < 8.1 con ADB - actualiza Android o usa Sui en su lugar",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Establecer Google Play como fuente de instalación (si se utiliza Shizuku)",
 | 
			
		||||
    "useSystemFont": "Usar la fuente de impresión del sistema",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Establecer Google Play como fuente de instalación (si se usa Shizuku)",
 | 
			
		||||
    "useSystemFont": "Usar fuente del sistema",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Usar la versión de la aplicación como versión detectada por el sistema operativo",
 | 
			
		||||
    "requestHeader": "Encabezado de solicitud",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Usar la última carga de recursos como fecha de lanzamiento",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Usar la última carga del recurso como fecha de lanzamiento",
 | 
			
		||||
    "defaultPseudoVersioningMethod": "Método de pseudoversionado predeterminado",
 | 
			
		||||
    "partialAPKHash": "Hash de APK parcial",
 | 
			
		||||
    "APKLinkHash": "Hash de enlace APK",
 | 
			
		||||
    "directAPKLink": "Enlace APK directo",
 | 
			
		||||
    "pseudoVersionInUse": "Se está utilizando una pseudoversión",
 | 
			
		||||
    "pseudoVersionInUse": "Se está usando una pseudoversión",
 | 
			
		||||
    "installed": "Instalado",
 | 
			
		||||
    "latest": "Versión más reciente",
 | 
			
		||||
    "invertRegEx": "Invertir expresión regular",
 | 
			
		||||
    "note": "Nota",
 | 
			
		||||
    "selfHostedNote": "El desplegable «{}» puede utilizarse para acceder a instancias autoalojadas/personalizadas de cualquier fuente.",
 | 
			
		||||
    "selfHostedNote": "El desplegable «{}» puede usarse para acceder a instancias autoalojadas/personalizadas de cualquier fuente.",
 | 
			
		||||
    "badDownload": "No se ha podido analizar el APK (incompatible o descarga parcial)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Compartir nuevas aplicaciones con AppVerifier (si está disponible)",
 | 
			
		||||
    "appVerifierInstructionToast": "Comparta con AppVerifier y vuelva aquí cuando esté listo.",
 | 
			
		||||
    "wiki": "Ayuda/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (uso bajo su propia responsabilidad)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "¿Eliminar aplicación?",
 | 
			
		||||
        "other": "¿Eliminar aplicaciones?"
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "تاریک",
 | 
			
		||||
    "light": "روشن",
 | 
			
		||||
    "followSystem": "هماهنگ با سیستم",
 | 
			
		||||
    "followSystemThemeExplanation": "دنبال کردن تم سیستم فقط با استفاده از برنامه های شخص ثالث امکان پذیر است",
 | 
			
		||||
    "useBlackTheme": "استفاده از تم تیره سیاه خالص",
 | 
			
		||||
    "appSortBy": "مرتب سازی برنامه بر اساس",
 | 
			
		||||
    "authorName": "سازنده/اسم",
 | 
			
		||||
@@ -146,10 +147,10 @@
 | 
			
		||||
    "noNewUpdates": "به روز رسانی جدیدی وجود ندارد.",
 | 
			
		||||
    "xHasAnUpdate": "{} یک به روز رسانی دارد.",
 | 
			
		||||
    "appsUpdated": "برنامه ها به روز شدند",
 | 
			
		||||
    "appsNotUpdated": "Failed to update applications",
 | 
			
		||||
    "appsNotUpdated": "به روز رسانی برنامه ها ناموفق بود",
 | 
			
		||||
    "appsUpdatedNotifDescription": "به کاربر اطلاع می دهد که به روز رسانی یک یا چند برنامه در پس زمینه اعمال شده است",
 | 
			
		||||
    "xWasUpdatedToY": "{} به {} به روز شد.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Failed to update {} to {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "به روز رسانی {} به {} انجام نشد.",
 | 
			
		||||
    "errorCheckingUpdates": "خطا در بررسی بهروزرسانیها",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "اعلانی که وقتی بررسی بهروزرسانی پسزمینه ناموفق است نشان میدهد",
 | 
			
		||||
    "appsRemoved": "برنامه ها حذف شدند",
 | 
			
		||||
@@ -188,9 +189,9 @@
 | 
			
		||||
    "disableVersionDetection": "غیرفعال کردن تشخیص نسخه",
 | 
			
		||||
    "noVersionDetectionExplanation": "این گزینه فقط باید برای برنامه هایی استفاده شود که تشخیص نسخه به درستی کار نمی کند.",
 | 
			
		||||
    "downloadingX": "در حال دانلود {}",
 | 
			
		||||
    "downloadX": "Download {}",
 | 
			
		||||
    "downloadedX": "Downloaded {}",
 | 
			
		||||
    "releaseAsset": "Release Asset",
 | 
			
		||||
    "downloadX": "دانلود {}",
 | 
			
		||||
    "downloadedX": "دانلود شده {}",
 | 
			
		||||
    "releaseAsset": "انتشار دارایی",
 | 
			
		||||
    "downloadNotifDescription": "کاربر را از پیشرفت دانلود یک برنامه مطلع می کند",
 | 
			
		||||
    "noAPKFound": "APK پیدا نشد فایل",
 | 
			
		||||
    "noVersionDetection": "بدون تشخیص نسخه",
 | 
			
		||||
@@ -304,11 +305,13 @@
 | 
			
		||||
    "installed": "نصب شده است",
 | 
			
		||||
    "latest": "آخرین",
 | 
			
		||||
    "invertRegEx": "معکوس کردن عبارت منظم",
 | 
			
		||||
    "note": "Note",
 | 
			
		||||
    "selfHostedNote": "The \"{}\" dropdown can be used to reach self-hosted/custom instances of any source.",
 | 
			
		||||
    "badDownload": "The APK could not be parsed (incompatible or partial download)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Share new Apps with AppVerifier (if available)",
 | 
			
		||||
    "appVerifierInstructionToast": "Share to AppVerifier, then return here when ready.",
 | 
			
		||||
    "note": "یادداشت",
 | 
			
		||||
    "selfHostedNote": "از منوی کرکره ای \"{}\" می توان برای دسترسی به نمونه های خود میزبانی/سفارشی از هر منبعی استفاده کرد.",
 | 
			
		||||
    "badDownload": "APK قابل تجزیه نیست (دانلود ناسازگار یا جزئی)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "اشتراکگذاری برنامههای جدید با AppVerifier (در صورت وجود)",
 | 
			
		||||
    "appVerifierInstructionToast": "در AppVerifier به اشتراک بگذارید، سپس پس از آماده شدن به اینجا برگردید.",
 | 
			
		||||
    "wiki": "راهنما/ویکی",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "تنظیمات برنامه Crowdsourced (با مسئولیت خود استفاده کنید)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "برنامه حذف شود؟",
 | 
			
		||||
        "other": "برنامه ها حذف شوند؟"
 | 
			
		||||
@@ -358,8 +361,8 @@
 | 
			
		||||
        "other": "{} و {} برنامه دیگر به روز شدند."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Failed to update {} and 1 more app.",
 | 
			
		||||
        "other": "Failed to update {} and {} more apps."
 | 
			
		||||
        "one": "{} و 1 برنامه دیگر به روز نشد.",
 | 
			
		||||
        "other": "{} و {} برنامه دیگر به روز نشد."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} و 1 برنامه دیگر ممکن است به روز شده باشند.",
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Sombre",
 | 
			
		||||
    "light": "Clair",
 | 
			
		||||
    "followSystem": "Suivre le système",
 | 
			
		||||
    "followSystemThemeExplanation": "Il n'est possible de suivre le thème du système qu'en utilisant des applications tierces.",
 | 
			
		||||
    "useBlackTheme": "Utilisez le thème noir pur",
 | 
			
		||||
    "appSortBy": "Applications triées par",
 | 
			
		||||
    "authorName": "Auteur/Nom",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "L'APK n'a pas pu être analysé (téléchargement incompatible ou partiel)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Partager les nouvelles applications avec AppVerifier (si disponible)",
 | 
			
		||||
    "appVerifierInstructionToast": "Partagez avec AppVerifier, puis revenez ici lorsque vous êtes prêt.",
 | 
			
		||||
    "wiki": "Aide/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Configurations d'applications par la foule (utilisation à vos risques et périls)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Supprimer l'application ?",
 | 
			
		||||
        "other": "Supprimer les applications ?"
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Sötét",
 | 
			
		||||
    "light": "Világos",
 | 
			
		||||
    "followSystem": "Rendszer szerint",
 | 
			
		||||
    "followSystemThemeExplanation": "A következő rendszer téma csak harmadik féltől származó alkalmazások használatával lehetséges",
 | 
			
		||||
    "useBlackTheme": "Használjon teljesen fekete sötét témát",
 | 
			
		||||
    "appSortBy": "App rendezés...",
 | 
			
		||||
    "authorName": "Szerző/Név",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "Az APK-t nem lehetett elemezni (inkompatibilis vagy részleges letöltés)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Új alkalmazások megosztása az AppVerifierrel (ha elérhető)",
 | 
			
		||||
    "appVerifierInstructionToast": "Ossza meg az AppVerifierrel, majd térjen vissza ide, ha kész.",
 | 
			
		||||
    "wiki": "Súgó/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (használat saját felelősségre)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Eltávolítja az alkalmazást?",
 | 
			
		||||
        "other": "Eltávolítja az alkalmazásokat?"
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Scuro",
 | 
			
		||||
    "light": "Chiaro",
 | 
			
		||||
    "followSystem": "Segui il sistema",
 | 
			
		||||
    "followSystemThemeExplanation": "È possibile seguire il tema di sistema solo utilizzando applicazioni di terze parti.",
 | 
			
		||||
    "useBlackTheme": "Usa il tema nero puro",
 | 
			
		||||
    "appSortBy": "App ordinate per",
 | 
			
		||||
    "authorName": "Autore/Nome",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "Non è stato possibile analizzare l'APK (download incompatibile o parziale).",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Condividere le nuove applicazioni con AppVerifier (se disponibile)",
 | 
			
		||||
    "appVerifierInstructionToast": "Condividete con AppVerifier, quindi tornate qui quando siete pronti.",
 | 
			
		||||
    "wiki": "Aiuto/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Configurazioni di app in crowdsourcing (uso a proprio rischio)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Rimuovere l'app?",
 | 
			
		||||
        "other": "Rimuovere le app?"
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
    "colour": "カラー",
 | 
			
		||||
    "standard": "スタンダード",
 | 
			
		||||
    "custom": "カスタム",
 | 
			
		||||
    "useMaterialYou": "使用素材",
 | 
			
		||||
    "useMaterialYou": "Material Youを使用する",
 | 
			
		||||
    "githubStarredRepos": "Githubでスターしたリポジトリ",
 | 
			
		||||
    "uname": "ユーザー名",
 | 
			
		||||
    "wrongArgNum": "提供する引数の数が間違っています",
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "ダーク",
 | 
			
		||||
    "light": "ライト",
 | 
			
		||||
    "followSystem": "システムに従う",
 | 
			
		||||
    "followSystemThemeExplanation": "以下のシステムテーマは、サードパーティのアプリケーションを使用することによってのみ可能です。",
 | 
			
		||||
    "useBlackTheme": "ピュアブラックダークテーマを使用する",
 | 
			
		||||
    "appSortBy": "アプリの並び方",
 | 
			
		||||
    "authorName": "作者名/アプリ名",
 | 
			
		||||
@@ -287,11 +288,11 @@
 | 
			
		||||
    "supportFixedAPKURL": "固定されたAPKのURLをサポートする",
 | 
			
		||||
    "selectX": "{} 選択",
 | 
			
		||||
    "parallelDownloads": "並行ダウンロードを許可する",
 | 
			
		||||
    "useShizuku": "シズクまたはスイを使って設置する",
 | 
			
		||||
    "useShizuku": "ShizukuまたはSuiを使用してインストールする",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizukuが起動していません",
 | 
			
		||||
    "shizukuOld": "古い雫バージョン (<11) - アップデートしてください。",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "雫、Android < 8.1でADB動作 - Androidをアップデートするか、代わりにSuiを使うか",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "インストール元をGoogle Playに設定する(雫を使用する場合)",
 | 
			
		||||
    "shizukuOld": "古いShizukuのバージョン (<11) - アップデートしてください",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "ShizukuがAndroid 8.1未満でADBを使用して動作しています - Androidをアップデートするか、代わりにSuiを使用してください",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Google Playをインストール元として設定する(Shizukuを使用する場合)",
 | 
			
		||||
    "useSystemFont": "システムフォントを使用する",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "アプリのバージョンコードをOSで検出されたバージョンとして使用する",
 | 
			
		||||
    "requestHeader": "リクエストヘッダー",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "APK を解析できませんでした(互換性がないか、部分的にダウンロードされています)。",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "AppVerifierで新しいアプリを共有する(利用可能な場合)",
 | 
			
		||||
    "appVerifierInstructionToast": "AppVerifierに共有し、準備ができたらここに戻ってください。",
 | 
			
		||||
    "wiki": "ヘルプ/ウィキ",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "クラウドソーシングによるアプリの設定(利用は自己責任で)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "アプリを削除しますか?",
 | 
			
		||||
        "other": "アプリを削除しますか?"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,134 +1,135 @@
 | 
			
		||||
{
 | 
			
		||||
    "invalidURLForSource": "Geen valide {} app URL",
 | 
			
		||||
    "noReleaseFound": "Kan geen geschikte release vinden",
 | 
			
		||||
    "noVersionFound": "Kan de versie niet bepalen",
 | 
			
		||||
    "invalidURLForSource": "Ongeldige app-URL voor {}",
 | 
			
		||||
    "noReleaseFound": "Geen geschikte release gevonden",
 | 
			
		||||
    "noVersionFound": "Geen versie kunnen bepalen",
 | 
			
		||||
    "urlMatchesNoSource": "URL komt niet overeen met bekende bron",
 | 
			
		||||
    "cantInstallOlderVersion": "Kan geen oudere versie van de app installeren",
 | 
			
		||||
    "appIdMismatch": "Gedownloade pakket-ID komt niet overeen met de bestaande app-ID",
 | 
			
		||||
    "functionNotImplemented": "Deze class heeft deze functie niet geïmplementeerd.",
 | 
			
		||||
    "placeholder": "Plaatshouder",
 | 
			
		||||
    "appIdMismatch": "Gedownload pakket-ID komt niet overeen met de bestaande app-ID",
 | 
			
		||||
    "functionNotImplemented": "Deze klasse heeft deze functie niet geïmplementeerd.",
 | 
			
		||||
    "placeholder": "Dummy",
 | 
			
		||||
    "someErrors": "Er zijn enkele fouten opgetreden",
 | 
			
		||||
    "unexpectedError": "Onverwachte fout",
 | 
			
		||||
    "ok": "Ok",
 | 
			
		||||
    "ok": "Oké",
 | 
			
		||||
    "and": "en",
 | 
			
		||||
    "githubPATLabel": "GitHub Personal Access Token\n(Verhoogt limiet aantal verzoeken)",
 | 
			
		||||
    "includePrereleases": "Bevat prereleases",
 | 
			
		||||
    "includePrereleases": "Inclusief pre-releases",
 | 
			
		||||
    "fallbackToOlderReleases": "Terugvallen op oudere releases",
 | 
			
		||||
    "filterReleaseTitlesByRegEx": "Filter release-titels met reguliere expressies.",
 | 
			
		||||
    "filterReleaseTitlesByRegEx": "Release-titels filteren met reguliere expressies.",
 | 
			
		||||
    "invalidRegEx": "Ongeldige reguliere expressie",
 | 
			
		||||
    "noDescription": "Geen omschrijving",
 | 
			
		||||
    "cancel": "Annuleer",
 | 
			
		||||
    "continue": "Ga verder",
 | 
			
		||||
    "cancel": "Annuleren",
 | 
			
		||||
    "continue": "Doorgaan",
 | 
			
		||||
    "requiredInBrackets": "(Verplicht)",
 | 
			
		||||
    "dropdownNoOptsError": "FOUTMELDING: DROPDOWN MOET TENMINSTE ÉÉN OPT HEBBEN",
 | 
			
		||||
    "dropdownNoOptsError": "FOUTMELDING: UITKLAPMENU MOET TENMINSTE EEN OPT HEBBEN",
 | 
			
		||||
    "colour": "Kleur",
 | 
			
		||||
    "standard": "Standaard",
 | 
			
		||||
    "custom": "Aangepast",
 | 
			
		||||
    "useMaterialYou": "Gebruik materiaal",
 | 
			
		||||
    "useMaterialYou": "Material You gebruiken",
 | 
			
		||||
    "githubStarredRepos": "GitHub-repo's met ster",
 | 
			
		||||
    "uname": "Gebruikersnaam",
 | 
			
		||||
    "wrongArgNum": "Onjuist aantal argumenten verstrekt.",
 | 
			
		||||
    "xIsTrackOnly": "{} is alleen tracken",
 | 
			
		||||
    "wrongArgNum": "Incorrect aantal argumenten.",
 | 
			
		||||
    "xIsTrackOnly": "{} is 'Alleen volgen'",
 | 
			
		||||
    "source": "Bron",
 | 
			
		||||
    "app": "App",
 | 
			
		||||
    "appsFromSourceAreTrackOnly": "Apps van deze bron zijn 'Track-Only'.",
 | 
			
		||||
    "youPickedTrackOnly": "Je hebt de 'Track-Only' optie geselecteerd.",
 | 
			
		||||
    "appsFromSourceAreTrackOnly": "Apps van deze bron zijn 'Alleen volgen'.",
 | 
			
		||||
    "youPickedTrackOnly": "De optie 'Alleen volgen' is geselecteerd.",
 | 
			
		||||
    "trackOnlyAppDescription": "De app zal worden gevolgd voor updates, maar Obtainium zal niet in staat zijn om deze te downloaden of te installeren.",
 | 
			
		||||
    "cancelled": "Geannuleerd",
 | 
			
		||||
    "appAlreadyAdded": "App al toegevoegd",
 | 
			
		||||
    "alreadyUpToDateQuestion": "Is de app al up-to-date?",
 | 
			
		||||
    "appAlreadyAdded": "App reeds toegevoegd",
 | 
			
		||||
    "alreadyUpToDateQuestion": "App al bijgewerkt?",
 | 
			
		||||
    "addApp": "App toevoegen",
 | 
			
		||||
    "appSourceURL": "App bron URL",
 | 
			
		||||
    "appSourceURL": "App-bron URL",
 | 
			
		||||
    "error": "Foutmelding",
 | 
			
		||||
    "add": "Toevoegen",
 | 
			
		||||
    "searchSomeSourcesLabel": "Zoeken (Alleen sommige bronnen)",
 | 
			
		||||
    "searchSomeSourcesLabel": "Zoeken (sommige bronnen)",
 | 
			
		||||
    "search": "Zoeken",
 | 
			
		||||
    "additionalOptsFor": "Aanvullende opties voor {}",
 | 
			
		||||
    "supportedSources": "Ondersteunde bronnen",
 | 
			
		||||
    "trackOnlyInBrackets": "(Alleen track)",
 | 
			
		||||
    "trackOnlyInBrackets": "(Alleen volgen)",
 | 
			
		||||
    "searchableInBrackets": "(Doorzoekbaar)",
 | 
			
		||||
    "appsString": "Apps",
 | 
			
		||||
    "noApps": "Geen Apps",
 | 
			
		||||
    "noAppsForFilter": "Geen Apps voor filter",
 | 
			
		||||
    "byX": "Door {}",
 | 
			
		||||
    "percentProgress": "Vooruitgang: {}%",
 | 
			
		||||
    "percentProgress": "Voortgang: {}%",
 | 
			
		||||
    "pleaseWait": "Even geduld",
 | 
			
		||||
    "updateAvailable": "Update beschikbaar",
 | 
			
		||||
    "notInstalled": "Niet geinstalleerd",
 | 
			
		||||
    "pseudoVersion": "pseudo-versie",
 | 
			
		||||
    "selectAll": "Selecteer alles",
 | 
			
		||||
    "deselectX": "Deselecteer {}",
 | 
			
		||||
    "xWillBeRemovedButRemainInstalled": "{} zal worden verwijderd uit Obtainium, maar blijft geïnstalleerd op het apparaat.",
 | 
			
		||||
    "removeSelectedAppsQuestion": "Geselecteerde apps verwijderen??",
 | 
			
		||||
    "selectAll": "Alles selecteren",
 | 
			
		||||
    "deselectX": "Selectie opheffen {}",
 | 
			
		||||
    "xWillBeRemovedButRemainInstalled": "{} zal worden gewist uit Obtainium, maar blijft geïnstalleerd op het apparaat.",
 | 
			
		||||
    "removeSelectedAppsQuestion": "Geselecteerde apps verwijderen?",
 | 
			
		||||
    "removeSelectedApps": "Geselecteerde apps verwijderen",
 | 
			
		||||
    "updateX": "Update {}",
 | 
			
		||||
    "installX": "Installeer {}",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "Markeer {}\n(Track-Only)\nals up-to-date",
 | 
			
		||||
    "changeX": "Verander {}",
 | 
			
		||||
    "installUpdateApps": "Installeer/Update apps",
 | 
			
		||||
    "installUpdateSelectedApps": "Installeer/Update geselecteerde apps",
 | 
			
		||||
    "markXSelectedAppsAsUpdated": "{} geselecteerde apps markeren als up-to-date?",
 | 
			
		||||
    "updateX": "{} bijwerken",
 | 
			
		||||
    "installX": "{} installeren",
 | 
			
		||||
    "markXTrackOnlyAsUpdated": "{}\n(Alleen volgen)\nmarkeren als bijgewerkt",
 | 
			
		||||
    "changeX": "{} wijzigen",
 | 
			
		||||
    "installUpdateApps": "Apps installeren/bijwerken",
 | 
			
		||||
    "installUpdateSelectedApps": "Geselecteerde apps installeren/bijwerken",
 | 
			
		||||
    "markXSelectedAppsAsUpdated": "{} geselecteerde apps markeren als bijgewerkt?",
 | 
			
		||||
    "no": "Nee",
 | 
			
		||||
    "yes": "Ja",
 | 
			
		||||
    "markSelectedAppsUpdated": "Markeer geselecteerde aps als up-to-date",
 | 
			
		||||
    "pinToTop": "Vastzetten aan de bovenkant",
 | 
			
		||||
    "unpinFromTop": "Losmaken van de bovenkant",
 | 
			
		||||
    "resetInstallStatusForSelectedAppsQuestion": "Installatiestatus resetten voor geselecteerde apps?",
 | 
			
		||||
    "installStatusOfXWillBeResetExplanation": "De installatiestatus van alle geselecteerde apps zal worden gereset.\n\nDit kan helpen wanneer de versie van de app die in Obtainium wordt weergegeven onjuist is vanwege mislukte updates of andere problemen.",
 | 
			
		||||
    "customLinkMessage": "Deze links werken op apparaten waarop Obtainium is geïnstalleerd",
 | 
			
		||||
    "markSelectedAppsUpdated": "Geselecteerde apps markeren als bijgewerkt",
 | 
			
		||||
    "pinToTop": "Bovenaan plaatsen",
 | 
			
		||||
    "unpinFromTop": "Bovenaan wegnemen",
 | 
			
		||||
    "resetInstallStatusForSelectedAppsQuestion": "Installatiestatus herstellen voor geselecteerde apps?",
 | 
			
		||||
    "installStatusOfXWillBeResetExplanation": "De installatiestatus van alle geselecteerde apps zal worden hersteld.\n\nDit kan helpen wanneer de versie van de app die in Obtainium wordt weergegeven onjuist is vanwege mislukte updates of andere problemen.",
 | 
			
		||||
    "customLinkMessage": "Deze koppelingen werken op apparaten waarop Obtainium is geïnstalleerd",
 | 
			
		||||
    "shareAppConfigLinks": "App-configuratie delen als HTML-link",
 | 
			
		||||
    "shareSelectedAppURLs": "Deel geselecteerde app URL's",
 | 
			
		||||
    "resetInstallStatus": "Reset installatiestatus",
 | 
			
		||||
    "shareSelectedAppURLs": "Geselecteerde app-URL's delen",
 | 
			
		||||
    "resetInstallStatus": "Installatiestatus herstellen",
 | 
			
		||||
    "more": "Meer",
 | 
			
		||||
    "removeOutdatedFilter": "Verwijder out-of-date app filter",
 | 
			
		||||
    "showOutdatedOnly": "Toon alleen out-of-date apps",
 | 
			
		||||
    "filter": "Filter",
 | 
			
		||||
    "filterApps": "Filter apps",
 | 
			
		||||
    "appName": "App naam",
 | 
			
		||||
    "removeOutdatedFilter": "Verouderde apps-filter verwijderen",
 | 
			
		||||
    "showOutdatedOnly": "Alleen verouderde apps weergeven",
 | 
			
		||||
    "filter": "Filteren",
 | 
			
		||||
    "filterApps": "Apps filteren",
 | 
			
		||||
    "appName": "App-naam",
 | 
			
		||||
    "author": "Auteur",
 | 
			
		||||
    "upToDateApps": "Up-to-date apps",
 | 
			
		||||
    "upToDateApps": "Bijgewerkte apps",
 | 
			
		||||
    "nonInstalledApps": "Niet-geïnstalleerde apps",
 | 
			
		||||
    "importExport": "Importeren/Exporteren",
 | 
			
		||||
    "importExport": "Importeren/exporteren",
 | 
			
		||||
    "settings": "Instellingen",
 | 
			
		||||
    "exportedTo": "Geëxporteerd naar {}",
 | 
			
		||||
    "obtainiumExport": "Obtainium export",
 | 
			
		||||
    "invalidInput": "Ongeldige invoer",
 | 
			
		||||
    "importedX": "Geïmporteerd {}",
 | 
			
		||||
    "importedX": "{} geïmporteerd",
 | 
			
		||||
    "obtainiumImport": "Obtainium import",
 | 
			
		||||
    "importFromURLList": "Importeer van URL-lijsten",
 | 
			
		||||
    "importFromURLList": "Importeren van URL-lijsten",
 | 
			
		||||
    "searchQuery": "Zoekopdracht",
 | 
			
		||||
    "appURLList": "App URL-lijst",
 | 
			
		||||
    "line": "Lijn",
 | 
			
		||||
    "searchX": "Zoek {}",
 | 
			
		||||
    "line": "Regel",
 | 
			
		||||
    "searchX": "{} zoeken",
 | 
			
		||||
    "noResults": "Geen resultaten gevonden",
 | 
			
		||||
    "importX": "Importeer {}",
 | 
			
		||||
    "importedAppsIdDisclaimer": "Geïmporteerde apps kunnen mogelijk onjuist worden weergegeven als \"Niet geïnstalleerd\".\nOm dit op te lossen, herinstalleer ze via Obtainium.\nDit zou geen invloed moeten hebben op app-gegevens.\n\nDit heeft alleen invloed op URL- en importmethoden van derden.",
 | 
			
		||||
    "importErrors": "Import foutmeldingen",
 | 
			
		||||
    "importX": "{} importeren",
 | 
			
		||||
    "importedAppsIdDisclaimer": "Geïmporteerde apps kunnen mogelijk onjuist worden weergegeven als \"Niet geïnstalleerd\".\nOm dit op te lossen, installeer deze opnieuw via Obtainium.\nDit zou geen invloed moeten hebben op app-gegevens.\n\nDit heeft alleen invloed op URL- en importmethoden van derden.",
 | 
			
		||||
    "importErrors": "Fouten bij het importeren",
 | 
			
		||||
    "importedXOfYApps": "{} van {} apps geïmporteerd.",
 | 
			
		||||
    "followingURLsHadErrors": "De volgende URL's bevatten fouten:",
 | 
			
		||||
    "selectURL": "Selecteer URL",
 | 
			
		||||
    "selectURLs": "Selecteer URL's",
 | 
			
		||||
    "pick": "Kies",
 | 
			
		||||
    "selectURL": "URL selecteren",
 | 
			
		||||
    "selectURLs": "URL's selecteren",
 | 
			
		||||
    "pick": "Kiezen",
 | 
			
		||||
    "theme": "Thema",
 | 
			
		||||
    "dark": "Donker",
 | 
			
		||||
    "light": "Licht",
 | 
			
		||||
    "followSystem": "Volg systeem",
 | 
			
		||||
    "useBlackTheme": "Gebruik zwart thema",
 | 
			
		||||
    "appSortBy": "App sorteren op",
 | 
			
		||||
    "followSystem": "Systeem volgen",
 | 
			
		||||
    "followSystemThemeExplanation": "Het volgen van het systeemthema is alleen mogelijk met applicaties van derden",
 | 
			
		||||
    "useBlackTheme": "Zwart thema gebruiken",
 | 
			
		||||
    "appSortBy": "Sortering",
 | 
			
		||||
    "authorName": "Auteur/Naam",
 | 
			
		||||
    "nameAuthor": "Naam/Auteur",
 | 
			
		||||
    "asAdded": "Zoals toegevoegd",
 | 
			
		||||
    "appSortOrder": "App sorteervolgorde",
 | 
			
		||||
    "asAdded": "Datum toegevoegd",
 | 
			
		||||
    "appSortOrder": "Volgorde",
 | 
			
		||||
    "ascending": "Oplopend",
 | 
			
		||||
    "descending": "Aflopend",
 | 
			
		||||
    "bgUpdateCheckInterval": "Frequentie voor achtergrondupdatecontrole",
 | 
			
		||||
    "bgUpdateCheckInterval": "Frequentie voor achtergrond-updatecontrole",
 | 
			
		||||
    "neverManualOnly": "Nooit - Alleen handmatig",
 | 
			
		||||
    "appearance": "Weergave",
 | 
			
		||||
    "showWebInAppView": "Toon de bronwebpagina in app-weergave",
 | 
			
		||||
    "pinUpdates": "Updates bovenaan in de apps-weergave vastpinnen",
 | 
			
		||||
    "showWebInAppView": "Bron-webpagina weergeven in app-weergave",
 | 
			
		||||
    "pinUpdates": "Updates bovenaan plaatsen in de apps-weergave",
 | 
			
		||||
    "updates": "Updates",
 | 
			
		||||
    "sourceSpecific": "Bron-specifiek",
 | 
			
		||||
    "appSource": "App bron",
 | 
			
		||||
    "appSource": "App-bron",
 | 
			
		||||
    "noLogs": "Geen logs",
 | 
			
		||||
    "appLogs": "App logs",
 | 
			
		||||
    "close": "Sluiten",
 | 
			
		||||
@@ -136,13 +137,13 @@
 | 
			
		||||
    "appNotFound": "App niet gevonden",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "obtainium-export",
 | 
			
		||||
    "pickAnAPK": "Kies een APK",
 | 
			
		||||
    "appHasMoreThanOnePackage": "{} heeft meer dan één package:",
 | 
			
		||||
    "deviceSupportsXArch": "Jouw apparaat support de {} CPU-architectuur.",
 | 
			
		||||
    "deviceSupportsFollowingArchs": "Je apparaat ondersteunt de volgende CPU-architecturen:",
 | 
			
		||||
    "appHasMoreThanOnePackage": "{} biedt verschillende pakketten:",
 | 
			
		||||
    "deviceSupportsXArch": "Dit apparaat ondersteunt de {} CPU-architectuur.",
 | 
			
		||||
    "deviceSupportsFollowingArchs": "Dit apparaat ondersteunt de volgende CPU-architecturen:",
 | 
			
		||||
    "warning": "Waarschuwing",
 | 
			
		||||
    "sourceIsXButPackageFromYPrompt": "De appbron is '{}' maar de release package komt van '{}'. Doorgaan?",
 | 
			
		||||
    "sourceIsXButPackageFromYPrompt": "De app-bron is '{}' maar het release-pakket komt van '{}'. Doorgaan?",
 | 
			
		||||
    "updatesAvailable": "Updates beschikbaar",
 | 
			
		||||
    "updatesAvailableNotifDescription": "Stelt de gebruiker op de hoogte dat er updates beschikbaar zijn voor één of meer apps die worden bijgehouden door Obtainium.",
 | 
			
		||||
    "updatesAvailableNotifDescription": "Stelt de gebruiker op de hoogte dat er updates beschikbaar zijn voor een of meer apps die worden bijgehouden door Obtainium.",
 | 
			
		||||
    "noNewUpdates": "Geen nieuwe updates.",
 | 
			
		||||
    "xHasAnUpdate": "{} heeft een update.",
 | 
			
		||||
    "appsUpdated": "Apps bijgewerkt",
 | 
			
		||||
@@ -151,17 +152,17 @@
 | 
			
		||||
    "xWasUpdatedToY": "{} is bijgewerkt naar {}.",
 | 
			
		||||
    "xWasNotUpdatedToY": "Het bijwerken van {} naar {} is mislukt.",
 | 
			
		||||
    "errorCheckingUpdates": "Fout bij het controleren op updates",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Een melding die verschijnt wanneer het controleren op updates in de achtergrond mislukt",
 | 
			
		||||
    "errorCheckingUpdatesNotifDescription": "Een melding die verschijnt wanneer de achtergrondcontrole op updates mislukt",
 | 
			
		||||
    "appsRemoved": "Apps verwijderd",
 | 
			
		||||
    "appsRemovedNotifDescription": "Stelt de gebruiker op de hoogte dat één of meer apps zijn verwijderd vanwege fouten tijdens het laden ervan",
 | 
			
		||||
    "xWasRemovedDueToErrorY": "{} is verwijderd vanwege deze foutmelding: {}",
 | 
			
		||||
    "completeAppInstallation": "Complete app installatie",
 | 
			
		||||
    "appsRemovedNotifDescription": "Stelt de gebruiker op de hoogte dat een of meer apps zijn verwijderd vanwege fouten tijdens het laden",
 | 
			
		||||
    "xWasRemovedDueToErrorY": "{} is verwijderd vanwege de fout: {}",
 | 
			
		||||
    "completeAppInstallation": "App-installatie voltooien",
 | 
			
		||||
    "obtainiumMustBeOpenToInstallApps": "Obtainium moet geopend zijn om apps te installeren",
 | 
			
		||||
    "completeAppInstallationNotifDescription": "Vraagt de gebruiker om terug te keren naar Obtainium om de installatie van een app af te ronden",
 | 
			
		||||
    "checkingForUpdates": "Controleren op updates",
 | 
			
		||||
    "checkingForUpdatesNotifDescription": "Tijdelijke melding die verschijnt tijdens het controleren op updates",
 | 
			
		||||
    "pleaseAllowInstallPerm": "Sta Obtainium toe om apps te installeren",
 | 
			
		||||
    "trackOnly": "Alleen track",
 | 
			
		||||
    "pleaseAllowInstallPerm": "Toestaan dat Obtainium apps installeert",
 | 
			
		||||
    "trackOnly": "'Alleen volgen'",
 | 
			
		||||
    "errorWithHttpStatusCode": "Foutmelding {}",
 | 
			
		||||
    "versionCorrectionDisabled": "Versiecorrectie uitgeschakeld (de plug-in lijkt niet te werken)",
 | 
			
		||||
    "unknown": "Onbekend",
 | 
			
		||||
@@ -171,25 +172,25 @@
 | 
			
		||||
    "installedVersionX": "Geïnstalleerde versie: {}",
 | 
			
		||||
    "lastUpdateCheckX": "Laatste updatecontrole: {}",
 | 
			
		||||
    "remove": "Verwijderen",
 | 
			
		||||
    "yesMarkUpdated": "Ja, markeer als bijgewerkt",
 | 
			
		||||
    "fdroid": "F-Droid-ambtenaar",
 | 
			
		||||
    "appIdOrName": "App ID of naam",
 | 
			
		||||
    "yesMarkUpdated": "Ja, markeren als bijgewerkt",
 | 
			
		||||
    "fdroid": "F-Droid (Officieel)",
 | 
			
		||||
    "appIdOrName": "App-ID of naam",
 | 
			
		||||
    "appId": "App-ID",
 | 
			
		||||
    "appWithIdOrNameNotFound": "Er werd geen app gevonden met dat ID of die naam",
 | 
			
		||||
    "appWithIdOrNameNotFound": "Er is geen app gevonden met dat ID of die naam",
 | 
			
		||||
    "reposHaveMultipleApps": "Repositories kunnen meerdere apps bevatten",
 | 
			
		||||
    "fdroidThirdPartyRepo": "F-Droid Repository van derden",
 | 
			
		||||
    "steamMobile": "Stoommobiel",
 | 
			
		||||
    "steamChat": "Steamchat",
 | 
			
		||||
    "fdroidThirdPartyRepo": "F-Droid Repository voor derden",
 | 
			
		||||
    "steamMobile": "Steam Mobile",
 | 
			
		||||
    "steamChat": "Steam Chat",
 | 
			
		||||
    "install": "Installeren",
 | 
			
		||||
    "markInstalled": "Als geïnstalleerd markere",
 | 
			
		||||
    "update": "Update",
 | 
			
		||||
    "markUpdated": "Markeren als bijgewerkt",
 | 
			
		||||
    "markInstalled": "Als geïnstalleerd markeren",
 | 
			
		||||
    "update": "Bijwerken",
 | 
			
		||||
    "markUpdated": "Als bijgewerkt markeren",
 | 
			
		||||
    "additionalOptions": "Aanvullende opties",
 | 
			
		||||
    "disableVersionDetection": "Versieherkenning uitschakelen",
 | 
			
		||||
    "noVersionDetectionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt.",
 | 
			
		||||
    "downloadingX": "Downloaden {}",
 | 
			
		||||
    "downloadingX": "{} downloaden",
 | 
			
		||||
    "downloadX": "Downloaden",
 | 
			
		||||
    "downloadedX": "Gedownload {}",
 | 
			
		||||
    "downloadedX": "{} gedownload",
 | 
			
		||||
    "releaseAsset": "Release Activa",
 | 
			
		||||
    "downloadNotifDescription": "Stelt de gebruiker op de hoogte van de voortgang bij het downloaden van een app",
 | 
			
		||||
    "noAPKFound": "Geen APK gevonden",
 | 
			
		||||
@@ -202,100 +203,100 @@
 | 
			
		||||
    "deleteCategoriesQuestion": "Categorieën verwijderen?",
 | 
			
		||||
    "categoryDeleteWarning": "Alle apps in verwijderde categorieën worden teruggezet naar 'ongecategoriseerd'.",
 | 
			
		||||
    "addCategory": "Categorie toevoegen",
 | 
			
		||||
    "label": "Etiket",
 | 
			
		||||
    "label": "Label",
 | 
			
		||||
    "language": "Taal",
 | 
			
		||||
    "copiedToClipboard": "Gekopieerd naar klembord",
 | 
			
		||||
    "storagePermissionDenied": "Toegang tot opslag geweigerd",
 | 
			
		||||
    "selectedCategorizeWarning": "Dit zal eventuele bestaande categorie-instellingen voor de geselecteerde apps vervangen.",
 | 
			
		||||
    "filterAPKsByRegEx": "Filter APK's op reguliere expressie",
 | 
			
		||||
    "removeFromObtainium": "Verwijder van Obtainium",
 | 
			
		||||
    "uninstallFromDevice": "Verwijder van apparaat",
 | 
			
		||||
    "filterAPKsByRegEx": "APK's flteren met reguliere expressie",
 | 
			
		||||
    "removeFromObtainium": "Uit Obtainium verwijderen",
 | 
			
		||||
    "uninstallFromDevice": "Van apparaat verwijderen",
 | 
			
		||||
    "onlyWorksWithNonVersionDetectApps": "Werkt alleen voor apps waarbij versieherkenning is uitgeschakeld.",
 | 
			
		||||
    "releaseDateAsVersion": "Gebruik de releasedatum als versie",
 | 
			
		||||
    "releaseDateAsVersion": "Releasedatum als versie gebruiken",
 | 
			
		||||
    "releaseDateAsVersionExplanation": "Deze optie moet alleen worden gebruikt voor apps waar versieherkenning niet correct werkt, maar waar wel een releasedatum beschikbaar is.",
 | 
			
		||||
    "changes": "Veranderingen",
 | 
			
		||||
    "changes": "Aanpassingen",
 | 
			
		||||
    "releaseDate": "Releasedatum",
 | 
			
		||||
    "importFromURLsInFile": "Importeren vanaf URL's in een bestand (zoals OPML)",
 | 
			
		||||
    "versionDetectionExplanation": "Versiereeks afstemmen met versie gedetecteerd door besturingssysteem",
 | 
			
		||||
    "versionDetection": "Versieherkenning",
 | 
			
		||||
    "standardVersionDetection": "Standaard versieherkenning",
 | 
			
		||||
    "groupByCategory": "Groepeer op categorie",
 | 
			
		||||
    "autoApkFilterByArch": "Poging om APK's te filteren op CPU-architectuur indien mogelijk",
 | 
			
		||||
    "groupByCategory": "Groeperen op categorie",
 | 
			
		||||
    "autoApkFilterByArch": "Probeer APK's te filteren op CPU-architectuur, indien mogelijk",
 | 
			
		||||
    "overrideSource": "Bron overschrijven",
 | 
			
		||||
    "dontShowAgain": "Laat dit niet meer zien",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Geen waarschuwingen voor 'Track-Only' weergeven",
 | 
			
		||||
    "dontShowAPKOriginWarnings": "APK-herkomstwaarschuwingen niet weergeven",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Verplaats niet-geïnstalleerde apps naar de onderkant van de apps-weergave",
 | 
			
		||||
    "dontShowTrackOnlyWarnings": "Geen waarschuwingen weergeven voor 'Alleen volgen'",
 | 
			
		||||
    "dontShowAPKOriginWarnings": "Geen waarschuwingen weergeven voor APK-herkomst",
 | 
			
		||||
    "moveNonInstalledAppsToBottom": "Niet-geïnstalleerde apps onderaan de apps-lijst plaatsen",
 | 
			
		||||
    "gitlabPATLabel": "GitLab persoonlijk toegangskenmerk",
 | 
			
		||||
    "about": "Over",
 | 
			
		||||
    "requiresCredentialsInSettings": "{}: Dit vereist aanvullende referenties (in Instellingen)",
 | 
			
		||||
    "checkOnStart": "Controleren op updates bij opstarten",
 | 
			
		||||
    "requiresCredentialsInSettings": "{} vereist aanvullende referenties (in Instellingen)",
 | 
			
		||||
    "checkOnStart": "Bij opstarten op updates controleren",
 | 
			
		||||
    "tryInferAppIdFromCode": "Probeer de app-ID af te leiden uit de broncode",
 | 
			
		||||
    "removeOnExternalUninstall": "Automatisch extern verwijderde apps verwijderen",
 | 
			
		||||
    "pickHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren",
 | 
			
		||||
    "removeOnExternalUninstall": "Extern verwijderde apps automatisch verwijderen",
 | 
			
		||||
    "pickHighestVersionCode": "De APK met de hoogste versiecode automatisch selecteren",
 | 
			
		||||
    "checkUpdateOnDetailPage": "Controleren op updates bij het openen van een app-detailpagina",
 | 
			
		||||
    "disablePageTransitions": "Schakel overgangsanimaties tussen pagina's uit",
 | 
			
		||||
    "reversePageTransitions": "Omgekeerde overgangsanimaties tussen pagina's",
 | 
			
		||||
    "minStarCount": "Minimale Github Stars",
 | 
			
		||||
    "addInfoBelow": "Voeg deze informatie hieronder toe.",
 | 
			
		||||
    "addInfoInSettings": "Voeg deze informatie toe in de instellingen.",
 | 
			
		||||
    "disablePageTransitions": "Overgangsanimaties tussen pagina's uitschakelen",
 | 
			
		||||
    "reversePageTransitions": "Overgangsanimaties tussen pagina's herstellen",
 | 
			
		||||
    "minStarCount": "Minimum Github Stars",
 | 
			
		||||
    "addInfoBelow": "Deze informatie hieronder toevoegen.",
 | 
			
		||||
    "addInfoInSettings": "Deze informatie toevoegen in de instellingen.",
 | 
			
		||||
    "githubSourceNote": "Beperkingen van GitHub kunnen worden vermeden door het gebruik van een API-sleutel.",
 | 
			
		||||
    "sortByLastLinkSegment": "Sorteren op alleen het laatste segment van de link",
 | 
			
		||||
    "filterReleaseNotesByRegEx": "Filter release-opmerkingen met een reguliere expressie.",
 | 
			
		||||
    "customLinkFilterRegex": "Aangepaste APK-linkfilter met een reguliere expressie (Standaard '.apk$').",
 | 
			
		||||
    "appsPossiblyUpdated": "Poging tot app-updates",
 | 
			
		||||
    "sortByLastLinkSegment": "Alleen sorteren op het laatste segment van de link",
 | 
			
		||||
    "filterReleaseNotesByRegEx": "Release-opmerkingen fiteren met een reguliere expressie.",
 | 
			
		||||
    "customLinkFilterRegex": "Aangepaste APK-links filteren met een reguliere expressie (Standaard '.apk$').",
 | 
			
		||||
    "appsPossiblyUpdated": "Pogingen tot app-updates",
 | 
			
		||||
    "appsPossiblyUpdatedNotifDescription": "Stelt de gebruiker op de hoogte dat updates voor één of meer apps mogelijk in de achtergrond zijn toegepast",
 | 
			
		||||
    "xWasPossiblyUpdatedToY": "{} mogelijk bijgewerkt naar {}.",
 | 
			
		||||
    "enableBackgroundUpdates": "Achtergrondupdates inschakelen",
 | 
			
		||||
    "backgroundUpdateReqsExplanation": "Achtergrondupdates zijn mogelijk niet voor alle apps mogelijk.",
 | 
			
		||||
    "xWasPossiblyUpdatedToY": "{} kan bijgewerkt zijn naar {}.",
 | 
			
		||||
    "enableBackgroundUpdates": "Achtergrond-updates inschakelen",
 | 
			
		||||
    "backgroundUpdateReqsExplanation": "Achtergrond-updates zijn niet voor alle apps mogelijk.",
 | 
			
		||||
    "backgroundUpdateLimitsExplanation": "Het succes van een installatie in de achtergrond kan alleen worden bepaald wanneer Obtainium is geopend.",
 | 
			
		||||
    "verifyLatestTag": "Verifieer de 'Laatste'-tag",
 | 
			
		||||
    "intermediateLinkRegex": "Filter voor een 'Intermediaire' link om te bezoeken",
 | 
			
		||||
    "verifyLatestTag": "Het label 'Laatste' verifiëren",
 | 
			
		||||
    "intermediateLinkRegex": "Filteren op een 'Intermediaire' link om te bezoeken",
 | 
			
		||||
    "filterByLinkText": "Links filteren op linktekst",
 | 
			
		||||
    "intermediateLinkNotFound": "Tussenliggende link niet gevonden",
 | 
			
		||||
    "intermediateLinkNotFound": "Intermediaire link niet gevonden",
 | 
			
		||||
    "intermediateLink": "Intermediaire link",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "Vrijgesteld van achtergrondupdates (indien ingeschakeld)",
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "Achtergrondupdates uitschakelen wanneer niet verbonden met WiFi",
 | 
			
		||||
    "autoSelectHighestVersionCode": "Automatisch de APK met de hoogste versiecode selecteren",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "Vrijgesteld van achtergrond-updates (indien ingeschakeld)",
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "Achtergrond-updates uitschakelen wanneer niet verbonden met WiFi",
 | 
			
		||||
    "autoSelectHighestVersionCode": "De APK met de hoogste versiecode automatisch selecteren",
 | 
			
		||||
    "versionExtractionRegEx": "Reguliere expressie voor versie-extractie",
 | 
			
		||||
    "matchGroupToUse": "Overeenkomende groep om te gebruiken voor de reguliere expressie voor versie-extractie",
 | 
			
		||||
    "highlightTouchTargets": "Markeer minder voor de hand liggende aanraakdoelen.",
 | 
			
		||||
    "highlightTouchTargets": "Minder voor de hand liggende aanraakdoelen markeren.",
 | 
			
		||||
    "pickExportDir": "Kies de exportmap",
 | 
			
		||||
    "autoExportOnChanges": "Automatisch exporteren bij wijzigingen",
 | 
			
		||||
    "autoExportOnChanges": "Bij wijzigingen automatisch exporteren",
 | 
			
		||||
    "includeSettings": "Instellingen opnemen",
 | 
			
		||||
    "filterVersionsByRegEx": "Filter versies met een reguliere expressie",
 | 
			
		||||
    "filterVersionsByRegEx": "Versies met een reguliere expressie filteren",
 | 
			
		||||
    "trySelectingSuggestedVersionCode": "Probeer de voorgestelde versiecode APK te selecteren",
 | 
			
		||||
    "dontSortReleasesList": "Volgorde van releases behouden vanuit de API",
 | 
			
		||||
    "reverseSort": "Sortering omkeren",
 | 
			
		||||
    "reverseSort": "Omgekeerde sortering",
 | 
			
		||||
    "takeFirstLink": "Neem de eerste link",
 | 
			
		||||
    "skipSort": "Sorteren overslaan",
 | 
			
		||||
    "debugMenu": "Debug menu",
 | 
			
		||||
    "skipSort": "Sortering overslaan",
 | 
			
		||||
    "debugMenu": "Debug-menu",
 | 
			
		||||
    "bgTaskStarted": "Achtergrondtaak gestart - controleer de logs.",
 | 
			
		||||
    "runBgCheckNow": "Voer nu een achtergrondupdatecontrole uit",
 | 
			
		||||
    "runBgCheckNow": "Nu een achtergrond-updatecontrole uitvoeren",
 | 
			
		||||
    "versionExtractWholePage": "De reguliere expressie voor versie-extractie toepassen op de hele pagina",
 | 
			
		||||
    "installing": "Installeren",
 | 
			
		||||
    "skipUpdateNotifications": "Updatemeldingen overslaan",
 | 
			
		||||
    "updatesAvailableNotifChannel": "Updates beschikbaar",
 | 
			
		||||
    "appsUpdatedNotifChannel": "Apps bijgewerkt",
 | 
			
		||||
    "appsPossiblyUpdatedNotifChannel": "Poging tot app-updates",
 | 
			
		||||
    "appsPossiblyUpdatedNotifChannel": "Pogingen tot app-updates",
 | 
			
		||||
    "errorCheckingUpdatesNotifChannel": "Foutcontrole bij het zoeken naar updates",
 | 
			
		||||
    "appsRemovedNotifChannel": "Apps verwijderd",
 | 
			
		||||
    "downloadingXNotifChannel": "{} downloaden",
 | 
			
		||||
    "completeAppInstallationNotifChannel": "Voltooien van de app-installatie",
 | 
			
		||||
    "completeAppInstallationNotifChannel": "App-installatie voltooien",
 | 
			
		||||
    "checkingForUpdatesNotifChannel": "Controleren op updates",
 | 
			
		||||
    "onlyCheckInstalledOrTrackOnlyApps": "Alleen geïnstalleerde en Track-Only apps controleren op updates",
 | 
			
		||||
    "supportFixedAPKURL": "Ondersteuning vaste APK URL's",
 | 
			
		||||
    "selectX": "Selecteer {}",
 | 
			
		||||
    "onlyCheckInstalledOrTrackOnlyApps": "Alleen geïnstalleerde apps en 'Alleen volgen' controleren op updates",
 | 
			
		||||
    "supportFixedAPKURL": "Vaste APK-URL's ondersteunen",
 | 
			
		||||
    "selectX": "{} selecteren",
 | 
			
		||||
    "parallelDownloads": "Parallelle downloads toestaan",
 | 
			
		||||
    "useShizuku": "Gebruik Shizuku of Sui om te installeren",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku draait niet",
 | 
			
		||||
    "shizukuOld": "Oude Shizuku-versie (<11) - bijwerken",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku draait op Android < 8.1 met ADB - update Android of gebruik Sui in plaats daarvan",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Google Play instellen als installatiebron (als Shizuku wordt gebruikt)",
 | 
			
		||||
    "useSystemFont": "Gebruik het systeemlettertype",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "Gebruik app versieCode als door OS gedetecteerde versie",
 | 
			
		||||
    "useShizuku": "Shizuku of Sui gebruiken om te installeren",
 | 
			
		||||
    "shizukuBinderNotFound": "Shizuku is niet actief",
 | 
			
		||||
    "shizukuOld": "Verouderde Shizuku-versie (<11) - bijwerken",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "Shizuku draait op Android < 8.1 met ADB - update Android of gebruik in plaats daarvan Sui",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "Google Play instellen als installatiebron (bij Shizuku)",
 | 
			
		||||
    "useSystemFont": "Systeemlettertype gebruiken",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "App versiecode gebruiken als door OS gedetecteerde versie",
 | 
			
		||||
    "requestHeader": "Verzoekkoptekst",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Gebruik laatste upload als releasedatum",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "Laatste upload als releasedatum gebruiken",
 | 
			
		||||
    "defaultPseudoVersioningMethod": "Standaard pseudo-versiebeheermethode",
 | 
			
		||||
    "partialAPKHash": "Gedeeltelijke APK-hash",
 | 
			
		||||
    "APKLinkHash": "APK-link-hash",
 | 
			
		||||
@@ -308,22 +309,24 @@
 | 
			
		||||
    "selfHostedNote": "De \"{}\" dropdown kan gebruikt worden om zelf gehoste/aangepaste instanties van elke bron te bereiken.",
 | 
			
		||||
    "badDownload": "De APK kon niet worden verwerkt (incompatibele of gedeeltelijke download)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Nieuwe Apps delen met AppVerifier (indien beschikbaar)",
 | 
			
		||||
    "appVerifierInstructionToast": "Deel naar AppVerifier en keer hier terug als je klaar bent.",
 | 
			
		||||
    "appVerifierInstructionToast": "Deel het met AppVerifier en keer daarna hier terug.",
 | 
			
		||||
    "wiki": "Help/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App-configuraties (gebruik op eigen risico)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "App verwijderen?",
 | 
			
		||||
        "other": "Apps verwijderen?"
 | 
			
		||||
    },
 | 
			
		||||
    "tooManyRequestsTryAgainInMinutes": {
 | 
			
		||||
        "one": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuut",
 | 
			
		||||
        "other": "Te veel verzoeken (aantal beperkt) - probeer het opnieuw in {} minuten"
 | 
			
		||||
        "one": "Te veel verzoeken (aantal beperkt) - opnieuw proberen over {} minuut",
 | 
			
		||||
        "other": "Te veel verzoeken (aantal beperkt) - opnieuw proberen over {} minuten"
 | 
			
		||||
    },
 | 
			
		||||
    "bgUpdateGotErrorRetryInMinutes": {
 | 
			
		||||
        "one": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuut",
 | 
			
		||||
        "other": "Achtergrondupdatecontrole heeft een {}, zal een hercontrole plannen over {} minuten"
 | 
			
		||||
        "one": "Achtergrond-updatecontrole heeft een {}, zal een nieuwe controle plannen over {} minuut",
 | 
			
		||||
        "other": "Achtergrond-updatecontrole heeft een {}, zal een nieuwe controle plannen over {} minuten"
 | 
			
		||||
    },
 | 
			
		||||
    "bgCheckFoundUpdatesWillNotifyIfNeeded": {
 | 
			
		||||
        "one": "Achtergrondupdatecontrole heeft {} update gevonden - zal de gebruiker op de hoogte stellen indien nodig",
 | 
			
		||||
        "other": "Achtergrondupdatecontrole heeft {} updates gevonden - zal de gebruiker op de hoogte stellen indien nodig"
 | 
			
		||||
        "one": "Achtergrond-updatecontrole heeft {} update gevonden - zal de gebruiker op de hoogte stellen indien nodig",
 | 
			
		||||
        "other": "Achtergrond-updatecontrole heeft {} updates gevonden - zal de gebruiker op de hoogte stellen indien nodig"
 | 
			
		||||
    },
 | 
			
		||||
    "apps": {
 | 
			
		||||
        "one": "{} app",
 | 
			
		||||
@@ -351,19 +354,19 @@
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesAvailable": {
 | 
			
		||||
        "one": "{} en nog 1 app hebben updates.",
 | 
			
		||||
        "other": "{} en {} meer apps hebben updates."
 | 
			
		||||
        "other": "{} en nog {} apps hebben updates."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesInstalled": {
 | 
			
		||||
        "one": "{} en nog 1 app is bijgewerkt.",
 | 
			
		||||
        "other": "{} en {} meer apps zijn bijgewerkt."
 | 
			
		||||
        "other": "{} en nog {} apps zijn bijgewerkt."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "Bijwerken mislukt {} en nog 1 app.",
 | 
			
		||||
        "other": "Mislukt om {} en {} meer apps bij te werken."
 | 
			
		||||
        "one": "Bijwerken mislukt voor {} en nog 1 app.",
 | 
			
		||||
        "other": "Bijwerken mislukt voor {} en nog {} apps."
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} en nog 1 app zijn mogelijk bijgewerkt.",
 | 
			
		||||
        "other": "{} en {} meer apps zijn mogelijk bijgwerkt."
 | 
			
		||||
        "other": "{} en nog {} apps zijn mogelijk bijgwerkt."
 | 
			
		||||
    },
 | 
			
		||||
    "apk": {
 | 
			
		||||
        "one": "{} APK",
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Ciemny",
 | 
			
		||||
    "light": "Jasny",
 | 
			
		||||
    "followSystem": "Zgodny z systemem",
 | 
			
		||||
    "followSystemThemeExplanation": "Podążanie za motywem systemowym jest możliwe tylko przy użyciu aplikacji firm trzecich",
 | 
			
		||||
    "useBlackTheme": "Użyj czarnego motywu",
 | 
			
		||||
    "appSortBy": "Sortuj aplikacje według",
 | 
			
		||||
    "authorName": "Autor/Nazwa",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "Nie można przeanalizować pliku APK (niekompatybilny lub częściowo pobrany).",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Udostępnianie nowych aplikacji za pomocą AppVerifier (jeśli dostępne)",
 | 
			
		||||
    "appVerifierInstructionToast": "Udostępnij w AppVerifier, a następnie wróć tutaj, gdy będziesz gotowy.",
 | 
			
		||||
    "wiki": "Pomoc/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Konfiguracje aplikacji pochodzące z crowdsourcingu (korzystanie na własne ryzyko)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Usunąć aplikację?",
 | 
			
		||||
        "few": "Usunąć aplikacje?",
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Escuro",
 | 
			
		||||
    "light": "Claro",
 | 
			
		||||
    "followSystem": "Padrão do sistema",
 | 
			
		||||
    "followSystemThemeExplanation": "O tema do sistema seguinte só é possível através da utilização de aplicações de terceiros",
 | 
			
		||||
    "useBlackTheme": "Usar tema preto AMOLED",
 | 
			
		||||
    "appSortBy": "Classificar aplicativo por",
 | 
			
		||||
    "authorName": "Autor/Nome",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "Não foi possível analisar o APK (transferência incompatível ou parcial)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Partilhar novas aplicações com o AppVerifier (se disponível)",
 | 
			
		||||
    "appVerifierInstructionToast": "Partilhe com o AppVerifier e, em seguida, regresse aqui quando estiver pronto.",
 | 
			
		||||
    "wiki": "Ajuda/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Configurações de aplicações de crowdsourcing (utilização por sua conta e risco)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Remover aplicativo?",
 | 
			
		||||
        "other": "Remover aplicativos?"
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    "placeholder": "Заполнитель",
 | 
			
		||||
    "someErrors": "Возникли некоторые ошибки",
 | 
			
		||||
    "unexpectedError": "Неожиданная ошибка",
 | 
			
		||||
    "ok": "Ok",
 | 
			
		||||
    "ok": "Ок",
 | 
			
		||||
    "and": "и",
 | 
			
		||||
    "githubPATLabel": "Персональный токен доступа GitHub\n(увеличивает лимит запросов)",
 | 
			
		||||
    "includePrereleases": "Включить предварительные релизы",
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Тёмная",
 | 
			
		||||
    "light": "Светлая",
 | 
			
		||||
    "followSystem": "Системная",
 | 
			
		||||
    "followSystemThemeExplanation": "Следование системной теме возможно только при использовании сторонних приложений",
 | 
			
		||||
    "useBlackTheme": "Использовать чёрную тему",
 | 
			
		||||
    "appSortBy": "Сортировка приложений",
 | 
			
		||||
    "authorName": "Автор/Название",
 | 
			
		||||
@@ -134,7 +135,7 @@
 | 
			
		||||
    "close": "Закрыть",
 | 
			
		||||
    "share": "Поделиться",
 | 
			
		||||
    "appNotFound": "Приложение не найдено",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "получение-экспорт",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "экспорт-obtainium",
 | 
			
		||||
    "pickAnAPK": "Выберите APK-файл",
 | 
			
		||||
    "appHasMoreThanOnePackage": "{} имеет более одного пакета:",
 | 
			
		||||
    "deviceSupportsXArch": "Ваше устройство поддерживает архитектуру процессора {}",
 | 
			
		||||
@@ -178,8 +179,8 @@
 | 
			
		||||
    "appWithIdOrNameNotFound": "Приложение с таким ID или названием не было найдено",
 | 
			
		||||
    "reposHaveMultipleApps": "В хранилище несколько приложений",
 | 
			
		||||
    "fdroidThirdPartyRepo": "Сторонние репозитории F-Droid",
 | 
			
		||||
    "steamMobile": "Стим Мобайл",
 | 
			
		||||
    "steamChat": "Стим-чат",
 | 
			
		||||
    "steamMobile": "Приложение Steam",
 | 
			
		||||
    "steamChat": "Steam Chat",
 | 
			
		||||
    "install": "Установить",
 | 
			
		||||
    "markInstalled": "Пометить как установленное",
 | 
			
		||||
    "update": "Обновить",
 | 
			
		||||
@@ -190,7 +191,7 @@
 | 
			
		||||
    "downloadingX": "Загрузка {}",
 | 
			
		||||
    "downloadX": "Скачать {}",
 | 
			
		||||
    "downloadedX": "Загружено {}",
 | 
			
		||||
    "releaseAsset": "Освобождение актива",
 | 
			
		||||
    "releaseAsset": "Релизный объект",
 | 
			
		||||
    "downloadNotifDescription": "Уведомляет пользователя о прогрессе загрузки приложения",
 | 
			
		||||
    "noAPKFound": "APK не найден",
 | 
			
		||||
    "noVersionDetection": "Обнаружение версий отключено",
 | 
			
		||||
@@ -253,7 +254,7 @@
 | 
			
		||||
    "intermediateLinkRegex": "Фильтр для \"промежуточной\" ссылки для посещения",
 | 
			
		||||
    "filterByLinkText": "Фильтрация ссылок по тексту ссылки",
 | 
			
		||||
    "intermediateLinkNotFound": "Промежуточная ссылка не найдена",
 | 
			
		||||
    "intermediateLink": "Промежуточное звено",
 | 
			
		||||
    "intermediateLink": "Промежуточная ссылка",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "Исключить из фоновых обновлений (если включено)",
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "Отключить фоновые обновления, если нет соединения с Wi-Fi",
 | 
			
		||||
    "autoSelectHighestVersionCode": "Автоматически выбирать APK с актуальной версией кода",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "APK не удалось разобрать (несовместимая или неполная загрузка)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Поделитесь новыми приложениями с AppVerifier (если доступно)",
 | 
			
		||||
    "appVerifierInstructionToast": "Поделитесь с AppVerifier, а затем вернитесь сюда, когда будете готовы.",
 | 
			
		||||
    "wiki": "Помощь/Вики",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Конфигурации приложений на основе краудсорсинга (используйте на свой страх и риск)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Удалить приложение?",
 | 
			
		||||
        "other": "Удалить приложения?"
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Mörkt",
 | 
			
		||||
    "light": "Ljust",
 | 
			
		||||
    "followSystem": "Följ System",
 | 
			
		||||
    "followSystemThemeExplanation": "Följande systemtema är endast möjligt med hjälp av tredjepartsapplikationer",
 | 
			
		||||
    "useBlackTheme": "Använd svart tema",
 | 
			
		||||
    "appSortBy": "Sortera Appar via",
 | 
			
		||||
    "authorName": "Utvecklare/Namn",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "APK kunde inte analyseras (inkompatibel eller partiell nedladdning)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Dela nya appar med AppVerifier (om tillgängligt)",
 | 
			
		||||
    "appVerifierInstructionToast": "Dela till AppVerifier och återvänd sedan hit när du är klar.",
 | 
			
		||||
    "wiki": "Hjälp/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourcade appkonfigurationer (använd på egen risk)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Ta Bort App?",
 | 
			
		||||
        "other": "Ta Bort Appar?"
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Koyu",
 | 
			
		||||
    "light": "Aydınlık",
 | 
			
		||||
    "followSystem": "Sistemi Takip Et",
 | 
			
		||||
    "followSystemThemeExplanation": "Sistem temasını takip etmek yalnızca üçüncü taraf uygulamaları kullanarak mümkündür",
 | 
			
		||||
    "useBlackTheme": "Saf siyah koyu temasını kullan",
 | 
			
		||||
    "appSortBy": "Uygulama Sıralama Ölçütü",
 | 
			
		||||
    "authorName": "Yazar/Ad",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "APK ayrıştırılamadı (uyumsuz veya kısmi indirme)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Yeni Uygulamaları AppVerifier ile paylaşın (varsa)",
 | 
			
		||||
    "appVerifierInstructionToast": "AppVerifier ile paylaşın, hazır olduğunuzda buraya dönün.",
 | 
			
		||||
    "wiki": "Yardım/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Kitle Kaynaklı Uygulama Yapılandırmaları (riski size ait olmak üzere kullanın)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Uygulamayı Kaldır?",
 | 
			
		||||
        "other": "Uygulamaları Kaldır?"
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Темна",
 | 
			
		||||
    "light": "Світла",
 | 
			
		||||
    "followSystem": "Дотримуватися системи",
 | 
			
		||||
    "followSystemThemeExplanation": "Зміна теми системи можлива лише за допомогою сторонніх додатків",
 | 
			
		||||
    "useBlackTheme": "Використовувати чорну тему (Amoled)",
 | 
			
		||||
    "appSortBy": "Сортувати застосунки за",
 | 
			
		||||
    "authorName": "Автор/Назва",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "APK не вдалося розпарсити (несумісний або часткове завантаження)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Діліться новими додатками з AppVerifier (якщо доступно)",
 | 
			
		||||
    "appVerifierInstructionToast": "Надішліть на AppVerifier, а потім поверніться сюди, коли будете готові.",
 | 
			
		||||
    "wiki": "Довідка/Вікі",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Краудсорсингові конфігурації додатків (використовуйте на свій страх і ризик)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Видалити застосунок?",
 | 
			
		||||
        "other": "Видалити застосунки?"
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "Tối",
 | 
			
		||||
    "light": "Sáng",
 | 
			
		||||
    "followSystem": "Theo hệ thống",
 | 
			
		||||
    "followSystemThemeExplanation": "Following system theme is possible only by using third-party applications",
 | 
			
		||||
    "useBlackTheme": "Nền đen",
 | 
			
		||||
    "appSortBy": "Sắp xếp ứng dụng",
 | 
			
		||||
    "authorName": "Tác giả",
 | 
			
		||||
@@ -309,6 +310,8 @@
 | 
			
		||||
    "badDownload": "Không thể phân tích cú pháp APK (tải xuống một phần hoặc không tương thích)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "Chia sẻ ứng dụng mới với AppVerifier (nếu có)",
 | 
			
		||||
    "appVerifierInstructionToast": "Chia sẻ lên AppVerifier, sau đó quay lại đây khi sẵn sàng.",
 | 
			
		||||
    "wiki": "Help/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "Crowdsourced App Configurations (use at your own risk)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "Gỡ ứng dụng?",
 | 
			
		||||
        "other": "Gỡ ứng dụng?"
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,8 @@
 | 
			
		||||
    "and": "和",
 | 
			
		||||
    "githubPATLabel": "GitHub 个人访问令牌(提升 API 请求限额)",
 | 
			
		||||
    "includePrereleases": "包含预发行版",
 | 
			
		||||
    "fallbackToOlderReleases": "将旧发行版作为备选",
 | 
			
		||||
    "filterReleaseTitlesByRegEx": "筛选发行标题(正则表达式)",
 | 
			
		||||
    "fallbackToOlderReleases": "将过往的发行版作为备选",
 | 
			
		||||
    "filterReleaseTitlesByRegEx": "筛选发行标题的正则表达式",
 | 
			
		||||
    "invalidRegEx": "无效的正则表达式",
 | 
			
		||||
    "noDescription": "无描述",
 | 
			
		||||
    "cancel": "取消",
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
    "colour": "配色",
 | 
			
		||||
    "standard": "标准",
 | 
			
		||||
    "custom": "定制",
 | 
			
		||||
    "useMaterialYou": "使用您的材料",
 | 
			
		||||
    "useMaterialYou": "使用 Material You",
 | 
			
		||||
    "githubStarredRepos": "已星标的 GitHub 仓库",
 | 
			
		||||
    "uname": "用户名",
 | 
			
		||||
    "wrongArgNum": "参数数量错误",
 | 
			
		||||
@@ -45,8 +45,8 @@
 | 
			
		||||
    "search": "搜索",
 | 
			
		||||
    "additionalOptsFor": "{} 的更多选项",
 | 
			
		||||
    "supportedSources": "支持的来源",
 | 
			
		||||
    "trackOnlyInBrackets": "(仅追踪)",
 | 
			
		||||
    "searchableInBrackets": "(可搜索)",
 | 
			
		||||
    "trackOnlyInBrackets": "(仅追踪)",
 | 
			
		||||
    "searchableInBrackets": "(可搜索)",
 | 
			
		||||
    "appsString": "应用列表",
 | 
			
		||||
    "noApps": "无应用",
 | 
			
		||||
    "noAppsForFilter": "没有符合条件的应用",
 | 
			
		||||
@@ -75,8 +75,8 @@
 | 
			
		||||
    "unpinFromTop": "取消置顶",
 | 
			
		||||
    "resetInstallStatusForSelectedAppsQuestion": "是否重置选中应用的安装状态?",
 | 
			
		||||
    "installStatusOfXWillBeResetExplanation": "选中应用的安装状态将会被重置。\n\n当更新安装失败或其他问题导致 Obtainium 中的应用版本显示错误时,可以尝试通过此方法解决。",
 | 
			
		||||
    "customLinkMessage": "这些链接适用于安装了 Gettingium 的设备",
 | 
			
		||||
    "shareAppConfigLinks": "将应用程序配置共享为 HTML 链接",
 | 
			
		||||
    "customLinkMessage": "分享链接仅适用于已安装 Obtainium 的设备",
 | 
			
		||||
    "shareAppConfigLinks": "通过链接分享应用配置",
 | 
			
		||||
    "shareSelectedAppURLs": "分享选中应用的 URL",
 | 
			
		||||
    "resetInstallStatus": "重置安装状态",
 | 
			
		||||
    "more": "更多",
 | 
			
		||||
@@ -113,6 +113,7 @@
 | 
			
		||||
    "dark": "深色",
 | 
			
		||||
    "light": "浅色",
 | 
			
		||||
    "followSystem": "跟随系统",
 | 
			
		||||
    "followSystemThemeExplanation": "跟随系统主题仅在使用第三方应用时有效",
 | 
			
		||||
    "useBlackTheme": "使用纯黑深色主题",
 | 
			
		||||
    "appSortBy": "排序依据",
 | 
			
		||||
    "authorName": "作者 / 应用名称",
 | 
			
		||||
@@ -124,7 +125,7 @@
 | 
			
		||||
    "bgUpdateCheckInterval": "后台更新检查间隔",
 | 
			
		||||
    "neverManualOnly": "手动",
 | 
			
		||||
    "appearance": "外观",
 | 
			
		||||
    "showWebInAppView": "应用详情页显示来源网页",
 | 
			
		||||
    "showWebInAppView": "应用详情页显示来源网站内容",
 | 
			
		||||
    "pinUpdates": "将待更新应用置顶",
 | 
			
		||||
    "updates": "更新",
 | 
			
		||||
    "sourceSpecific": "来源",
 | 
			
		||||
@@ -134,7 +135,7 @@
 | 
			
		||||
    "close": "关闭",
 | 
			
		||||
    "share": "分享",
 | 
			
		||||
    "appNotFound": "未找到应用",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "获取出口",
 | 
			
		||||
    "obtainiumExportHyphenatedLowercase": "obtainium-export",
 | 
			
		||||
    "pickAnAPK": "选择一个 APK 文件",
 | 
			
		||||
    "appHasMoreThanOnePackage": "“{}”有多个架构可用:",
 | 
			
		||||
    "deviceSupportsXArch": "您的设备支持 {} 架构。",
 | 
			
		||||
@@ -146,7 +147,7 @@
 | 
			
		||||
    "noNewUpdates": "全部应用已是最新。",
 | 
			
		||||
    "xHasAnUpdate": "“{}”可以更新了。",
 | 
			
		||||
    "appsUpdated": "应用已更新",
 | 
			
		||||
    "appsNotUpdated": "更新应用程序失败",
 | 
			
		||||
    "appsNotUpdated": "更新应用失败",
 | 
			
		||||
    "appsUpdatedNotifDescription": "当应用在后台安装更新时发送通知",
 | 
			
		||||
    "xWasUpdatedToY": "“{}”已更新至 {}。",
 | 
			
		||||
    "xWasNotUpdatedToY": "未能将 {} 更新为 {}。",
 | 
			
		||||
@@ -178,8 +179,8 @@
 | 
			
		||||
    "appWithIdOrNameNotFound": "未找到符合此 ID 或名称的应用",
 | 
			
		||||
    "reposHaveMultipleApps": "存储库中可能包含多个应用",
 | 
			
		||||
    "fdroidThirdPartyRepo": "F-Droid 第三方存储库",
 | 
			
		||||
    "steamMobile": "蒸汽手机",
 | 
			
		||||
    "steamChat": "蒸汽聊天",
 | 
			
		||||
    "steamMobile": "Steam Mobile",
 | 
			
		||||
    "steamChat": "Steam Chat",
 | 
			
		||||
    "install": "安装",
 | 
			
		||||
    "markInstalled": "标记为已安装",
 | 
			
		||||
    "update": "更新",
 | 
			
		||||
@@ -190,7 +191,7 @@
 | 
			
		||||
    "downloadingX": "正在下载“{}”",
 | 
			
		||||
    "downloadX": "下载 {}",
 | 
			
		||||
    "downloadedX": "下载 {}",
 | 
			
		||||
    "releaseAsset": "释放资产",
 | 
			
		||||
    "releaseAsset": "发行版附件",
 | 
			
		||||
    "downloadNotifDescription": "提示应用的下载进度",
 | 
			
		||||
    "noAPKFound": "未找到 APK 文件",
 | 
			
		||||
    "noVersionDetection": "禁用版本检测",
 | 
			
		||||
@@ -200,14 +201,14 @@
 | 
			
		||||
    "noCategory": "无类别",
 | 
			
		||||
    "noCategories": "无类别",
 | 
			
		||||
    "deleteCategoriesQuestion": "是否删除选中的类别?",
 | 
			
		||||
    "categoryDeleteWarning": "被删除类别下的应用将恢复为未分类状态。",
 | 
			
		||||
    "categoryDeleteWarning": "被删除类别的应用将恢复为未分类状态。",
 | 
			
		||||
    "addCategory": "添加类别",
 | 
			
		||||
    "label": "标签",
 | 
			
		||||
    "language": "语言",
 | 
			
		||||
    "copiedToClipboard": "已复制至剪贴板",
 | 
			
		||||
    "storagePermissionDenied": "已拒绝授予存储权限",
 | 
			
		||||
    "selectedCategorizeWarning": "这将覆盖选中应用当前的类别设置。",
 | 
			
		||||
    "filterAPKsByRegEx": "筛选 APK 文件(正则表达式)",
 | 
			
		||||
    "filterAPKsByRegEx": "筛选 APK 文件的正则表达式",
 | 
			
		||||
    "removeFromObtainium": "从 Obtainium 中删除",
 | 
			
		||||
    "uninstallFromDevice": "从设备中卸载",
 | 
			
		||||
    "onlyWorksWithNonVersionDetectApps": "仅适用于禁用版本检测的应用。",
 | 
			
		||||
@@ -241,29 +242,29 @@
 | 
			
		||||
    "addInfoInSettings": "在“设置”中添加此凭据。",
 | 
			
		||||
    "githubSourceNote": "使用访问令牌可避免触发 GitHub 的 API 请求限制。",
 | 
			
		||||
    "sortByLastLinkSegment": "仅根据链接的末尾部分进行筛选",
 | 
			
		||||
    "filterReleaseNotesByRegEx": "筛选发行说明(正则表达式)",
 | 
			
		||||
    "filterReleaseNotesByRegEx": "筛选发行说明的正则表达式",
 | 
			
		||||
    "customLinkFilterRegex": "筛选自定义来源的 APK 文件链接\n(正则表达式,默认匹配模式为“.apk$”)",
 | 
			
		||||
    "appsPossiblyUpdated": "已尝试更新应用",
 | 
			
		||||
    "appsPossiblyUpdatedNotifDescription": "当应用已尝试在后台更新时发送通知",
 | 
			
		||||
    "xWasPossiblyUpdatedToY": "已尝试将“{}”更新至 {}。",
 | 
			
		||||
    "enableBackgroundUpdates": "启用后台更新",
 | 
			
		||||
    "enableBackgroundUpdates": "启用全局后台更新",
 | 
			
		||||
    "backgroundUpdateReqsExplanation": "后台更新未必适用于所有的应用。",
 | 
			
		||||
    "backgroundUpdateLimitsExplanation": "只有在启动 Obtainium 时才能确认安装是否成功。",
 | 
			
		||||
    "verifyLatestTag": "验证“Latest”标签",
 | 
			
		||||
    "intermediateLinkRegex": "筛选中转链接(正则表达式)",
 | 
			
		||||
    "intermediateLinkRegex": "筛选中转链接的正则表达式",
 | 
			
		||||
    "filterByLinkText": "根据链接文本进行筛选",
 | 
			
		||||
    "intermediateLinkNotFound": "未找到中转链接",
 | 
			
		||||
    "intermediateLink": "中转链接",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "禁用后台更新(如果已经全局启用)",
 | 
			
		||||
    "exemptFromBackgroundUpdates": "禁用后台更新(仅此应用生效,即使已启用全局后台更新)",
 | 
			
		||||
    "bgUpdatesOnWiFiOnly": "未连接 Wi-Fi 时禁用后台更新",
 | 
			
		||||
    "autoSelectHighestVersionCode": "自动选择内部版本号最高的 APK 文件",
 | 
			
		||||
    "versionExtractionRegEx": "版本号提取规则(正则表达式)",
 | 
			
		||||
    "matchGroupToUse": "引用的捕获组",
 | 
			
		||||
    "highlightTouchTargets": "突出展示不明显的触摸区域",
 | 
			
		||||
    "versionExtractionRegEx": "提取版本号的正则表达式",
 | 
			
		||||
    "matchGroupToUse": "从上述匹配结果中引用的捕获组",
 | 
			
		||||
    "highlightTouchTargets": "突出展示不明显的可交互区域",
 | 
			
		||||
    "pickExportDir": "选择导出文件夹",
 | 
			
		||||
    "autoExportOnChanges": "数据变更时自动导出",
 | 
			
		||||
    "includeSettings": "同时导出应用设置",
 | 
			
		||||
    "filterVersionsByRegEx": "筛选版本号(正则表达式)",
 | 
			
		||||
    "filterVersionsByRegEx": "筛选版本号的正则表达式",
 | 
			
		||||
    "trySelectingSuggestedVersionCode": "尝试选择推荐版本的 APK 文件",
 | 
			
		||||
    "dontSortReleasesList": "保持来自 API 的发行顺序",
 | 
			
		||||
    "reverseSort": "反转排序",
 | 
			
		||||
@@ -289,13 +290,13 @@
 | 
			
		||||
    "parallelDownloads": "启用并行下载",
 | 
			
		||||
    "useShizuku": "使用 Shizuku 或 Sui 安装",
 | 
			
		||||
    "shizukuBinderNotFound": "未发现兼容的 Shizuku 服务",
 | 
			
		||||
    "shizukuOld": "旧的 Shizuku 版本 (<11) - 更新它",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "使用 ADB 在 Android < 8.1 上运行 Shizuku - 更新 Android 或使用 Sui 代替",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "将 Google Play 设置为安装源(如果使用 Shizuku)",
 | 
			
		||||
    "shizukuOld": "Shizuku 版本过低(<11)- 请更新",
 | 
			
		||||
    "shizukuOldAndroidWithADB": "正在低版本 Android(<8.1)系统中以 ADB 模式运行 Shizuku - 请更新 Android 系统版本或使用 Sui 代替",
 | 
			
		||||
    "shizukuPretendToBeGooglePlay": "将安装来源伪装为 Google Play(需要使用 Shizuku)",
 | 
			
		||||
    "useSystemFont": "使用系统字体",
 | 
			
		||||
    "useVersionCodeAsOSVersion": "使用内部版本号代替应用定义的版本号",
 | 
			
		||||
    "requestHeader": "请求标头",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "使用最近文件上传时间作为发行日期",
 | 
			
		||||
    "useLatestAssetDateAsReleaseDate": "使用最新文件上传时间作为发行日期",
 | 
			
		||||
    "defaultPseudoVersioningMethod": "默认虚拟版本方案",
 | 
			
		||||
    "partialAPKHash": "APK 文件散列值片段",
 | 
			
		||||
    "APKLinkHash": "APK 文件链接散列值",
 | 
			
		||||
@@ -307,19 +308,21 @@
 | 
			
		||||
    "note": "备注",
 | 
			
		||||
    "selfHostedNote": "可以通过“{}”下拉菜单来指向任意来源的自托管/自定义实例。",
 | 
			
		||||
    "badDownload": "无法解析 APK 文件(不兼容或文件不完整)",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "与 AppVerifier 共享新应用程序(如有)",
 | 
			
		||||
    "appVerifierInstructionToast": "分享到 AppVerifier,准备就绪后返回此处。",
 | 
			
		||||
    "beforeNewInstallsShareToAppVerifier": "通过 AppVerifier 校验新应用(如果可用)",
 | 
			
		||||
    "appVerifierInstructionToast": "分享至 AppVerifier,完成后返回此处。",
 | 
			
		||||
    "wiki": "帮助/Wiki",
 | 
			
		||||
    "crowdsourcedConfigsLabel": "众包应用程序配置(使用风险自负)",
 | 
			
		||||
    "removeAppQuestion": {
 | 
			
		||||
        "one": "是否删除应用?",
 | 
			
		||||
        "other": "是否删除应用?"
 | 
			
		||||
    },
 | 
			
		||||
    "tooManyRequestsTryAgainInMinutes": {
 | 
			
		||||
        "one": "API 请求过于频繁(速率限制)- 在 {} 分钟后重试",
 | 
			
		||||
        "other": "API 请求过于频繁(速率限制)- 在 {} 分钟后重试"
 | 
			
		||||
        "one": "API 请求过于频繁(速率限制)- 请在 {} 分钟后重试",
 | 
			
		||||
        "other": "API 请求过于频繁(速率限制)- 请在 {} 分钟后重试"
 | 
			
		||||
    },
 | 
			
		||||
    "bgUpdateGotErrorRetryInMinutes": {
 | 
			
		||||
        "one": "后台更新检查遇到了“{}”问题,预定于 {} 分钟后重试",
 | 
			
		||||
        "other": "后台更新检查遇到了“{}”问题,预定于 {} 分钟后重试"
 | 
			
		||||
        "one": "后台更新检查遇到了“{}”问题,将于 {} 分钟后重试",
 | 
			
		||||
        "other": "后台更新检查遇到了“{}”问题,将于 {} 分钟后重试"
 | 
			
		||||
    },
 | 
			
		||||
    "bgCheckFoundUpdatesWillNotifyIfNeeded": {
 | 
			
		||||
        "one": "后台检查发现 {} 个应用更新 - 如有需要将发送通知",
 | 
			
		||||
@@ -358,8 +361,8 @@
 | 
			
		||||
        "other": "“{}”和另外 {} 个应用已更新。"
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesFailed": {
 | 
			
		||||
        "one": "更新 {} 和另外 1 个应用程序失败。",
 | 
			
		||||
        "other": "未能更新 {} 和 {} 更多应用程序。"
 | 
			
		||||
        "one": "{} 和另外 1 个应用更新失败。",
 | 
			
		||||
        "other": "{} 和另外 {} 个应用更新失败。"
 | 
			
		||||
    },
 | 
			
		||||
    "xAndNMoreUpdatesPossiblyInstalled": {
 | 
			
		||||
        "one": "{} 和另外 1 个应用已尝试更新。",
 | 
			
		||||
 
 | 
			
		||||
@@ -273,10 +273,11 @@ class GitHub extends AppSource {
 | 
			
		||||
 | 
			
		||||
      List<MapEntry<String, String>> getReleaseAssetUrls(dynamic release) =>
 | 
			
		||||
          (release['assets'] as List<dynamic>?)?.map((e) {
 | 
			
		||||
            return (e['name'] != null) &&
 | 
			
		||||
                    ((e['url'] ?? e['browser_download_url']) != null)
 | 
			
		||||
                ? MapEntry(e['name'] as String,
 | 
			
		||||
                    (e['url'] ?? e['browser_download_url']) as String)
 | 
			
		||||
            var url = !e['name'].toString().toLowerCase().endsWith('.apk')
 | 
			
		||||
                ? (e['browser_download_url'] ?? e['url'])
 | 
			
		||||
                : (e['url'] ?? e['browser_download_url']);
 | 
			
		||||
            return (e['name'] != null) && (url != null)
 | 
			
		||||
                ? MapEntry(e['name'] as String, url as String)
 | 
			
		||||
                : const MapEntry('', '');
 | 
			
		||||
          }).toList() ??
 | 
			
		||||
          [];
 | 
			
		||||
 
 | 
			
		||||
@@ -243,19 +243,28 @@ class HTML extends AppSource {
 | 
			
		||||
    if ((additionalSettings['customLinkFilterRegex'] as String?)?.isNotEmpty ==
 | 
			
		||||
        true) {
 | 
			
		||||
      var reg = RegExp(additionalSettings['customLinkFilterRegex']);
 | 
			
		||||
      links = allLinks
 | 
			
		||||
          .where((element) => reg.hasMatch(
 | 
			
		||||
              filterLinkByText ? element.value : Uri.decodeFull(element.key)))
 | 
			
		||||
          .toList();
 | 
			
		||||
      links = allLinks.where((element) {
 | 
			
		||||
        var link = element.key;
 | 
			
		||||
        try {
 | 
			
		||||
          link = Uri.decodeFull(element.key);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          // Some links may not have valid encoding
 | 
			
		||||
        }
 | 
			
		||||
        return reg.hasMatch(filterLinkByText ? element.value : link);
 | 
			
		||||
      }).toList();
 | 
			
		||||
    } else {
 | 
			
		||||
      links = allLinks
 | 
			
		||||
          .where((element) => Uri.parse(filterLinkByText
 | 
			
		||||
                  ? element.value
 | 
			
		||||
                  : Uri.decodeFull(element.key))
 | 
			
		||||
              .path
 | 
			
		||||
              .toLowerCase()
 | 
			
		||||
              .endsWith('.apk'))
 | 
			
		||||
          .toList();
 | 
			
		||||
      links = allLinks.where((element) {
 | 
			
		||||
        var link = element.key;
 | 
			
		||||
        try {
 | 
			
		||||
          link = Uri.decodeFull(element.key);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          // Some links may not have valid encoding
 | 
			
		||||
        }
 | 
			
		||||
        return Uri.parse(filterLinkByText ? element.value : link)
 | 
			
		||||
            .path
 | 
			
		||||
            .toLowerCase()
 | 
			
		||||
            .endsWith('.apk');
 | 
			
		||||
      }).toList();
 | 
			
		||||
    }
 | 
			
		||||
    if (!skipSort) {
 | 
			
		||||
      links.sort((a, b) => additionalSettings['sortByLastLinkSegment'] == true
 | 
			
		||||
@@ -310,13 +319,19 @@ class HTML extends AppSource {
 | 
			
		||||
      links = [MapEntry(currentUrl, currentUrl)];
 | 
			
		||||
    }
 | 
			
		||||
    var rel = links.last.key;
 | 
			
		||||
    var relDecoded = rel;
 | 
			
		||||
    try {
 | 
			
		||||
      relDecoded = Uri.decodeFull(rel);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      // Some links may not have valid encoding
 | 
			
		||||
    }
 | 
			
		||||
    String? version;
 | 
			
		||||
    version = extractVersion(
 | 
			
		||||
        additionalSettings['versionExtractionRegEx'] as String?,
 | 
			
		||||
        additionalSettings['matchGroupToUse'] as String?,
 | 
			
		||||
        additionalSettings['versionExtractWholePage'] == true
 | 
			
		||||
            ? versionExtractionWholePageString
 | 
			
		||||
            : Uri.decodeFull(rel));
 | 
			
		||||
            : relDecoded);
 | 
			
		||||
    version ??=
 | 
			
		||||
        additionalSettings['defaultPseudoVersioningMethod'] == 'APKLinkHash'
 | 
			
		||||
            ? rel.hashCode.toString()
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ import 'package:obtainium/providers/source_provider.dart';
 | 
			
		||||
class HuaweiAppGallery extends AppSource {
 | 
			
		||||
  HuaweiAppGallery() {
 | 
			
		||||
    name = 'Huawei AppGallery';
 | 
			
		||||
    hosts = ['appgallery.huawei.com'];
 | 
			
		||||
    hosts = ['appgallery.huawei.com', 'appgallery.cloud.huawei.com'];
 | 
			
		||||
    versionDetectionDisallowed = true;
 | 
			
		||||
    showReleaseDateAsVersionToggle = true;
 | 
			
		||||
  }
 | 
			
		||||
@@ -14,7 +14,7 @@ class HuaweiAppGallery extends AppSource {
 | 
			
		||||
  @override
 | 
			
		||||
  String sourceSpecificStandardizeURL(String url) {
 | 
			
		||||
    RegExp standardUrlRegEx = RegExp(
 | 
			
		||||
        '^https?://(www\\.)?${getSourceRegex(hosts)}/app/[^/]+',
 | 
			
		||||
        '^https?://(www\\.)?${getSourceRegex(hosts)}(/#)?/(app|appdl)/[^/]+',
 | 
			
		||||
        caseSensitive: false);
 | 
			
		||||
    RegExpMatch? match = standardUrlRegEx.firstMatch(url);
 | 
			
		||||
    if (match == null) {
 | 
			
		||||
@@ -24,7 +24,7 @@ class HuaweiAppGallery extends AppSource {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getDlUrl(String standardUrl) =>
 | 
			
		||||
      'https://${hosts[0].replaceAll('appgallery.', 'appgallery.cloud.')}/appdl/${standardUrl.split('/').last}';
 | 
			
		||||
      'https://${hosts[0].replaceAll('appgallery.huawei', 'appgallery.cloud.huawei')}/appdl/${standardUrl.split('/').last}';
 | 
			
		||||
 | 
			
		||||
  requestAppdlRedirect(
 | 
			
		||||
      String dlUrl, Map<String, dynamic> additionalSettings) async {
 | 
			
		||||
@@ -73,21 +73,23 @@ class HuaweiAppGallery extends AppSource {
 | 
			
		||||
      throw NoReleasesError();
 | 
			
		||||
    }
 | 
			
		||||
    String appId = appIdFromRedirectDlUrl(res.headers['location']!);
 | 
			
		||||
    if (appId.isEmpty) {
 | 
			
		||||
      throw NoReleasesError();
 | 
			
		||||
    }
 | 
			
		||||
    var relDateStr =
 | 
			
		||||
        res.headers['location']?.split('?')[0].split('.').reversed.toList()[1];
 | 
			
		||||
    var relDateStrAdj = relDateStr?.split('');
 | 
			
		||||
    var tempLen = relDateStrAdj?.length ?? 0;
 | 
			
		||||
    var i = 2;
 | 
			
		||||
    while (i < tempLen) {
 | 
			
		||||
      relDateStrAdj?.insert((i + i ~/ 2 - 1), '-');
 | 
			
		||||
      i += 2;
 | 
			
		||||
    }
 | 
			
		||||
    var relDate = relDateStrAdj == null
 | 
			
		||||
        ? null
 | 
			
		||||
        : DateFormat('yy-MM-dd-HH-mm').parse(relDateStrAdj.join(''));
 | 
			
		||||
    if (relDateStr == null) {
 | 
			
		||||
    if (relDateStr == null || relDateStr.length != 10) {
 | 
			
		||||
      throw NoVersionError();
 | 
			
		||||
    }
 | 
			
		||||
    var relDateStrAdj = relDateStr.split('');
 | 
			
		||||
    var tempLen = relDateStrAdj.length;
 | 
			
		||||
    var i = 2;
 | 
			
		||||
    while (i < tempLen) {
 | 
			
		||||
      relDateStrAdj.insert((i + i ~/ 2 - 1), '-');
 | 
			
		||||
      i += 2;
 | 
			
		||||
    }
 | 
			
		||||
    var relDate =
 | 
			
		||||
        DateFormat('yy-MM-dd-HH-mm', 'en_US').parse(relDateStrAdj.join(''));
 | 
			
		||||
    return APKDetails(
 | 
			
		||||
        relDateStr, [MapEntry('$appId.apk', dlUrl)], AppNames(name, appId),
 | 
			
		||||
        releaseDate: relDate);
 | 
			
		||||
 
 | 
			
		||||
@@ -224,7 +224,7 @@ class _ObtainiumState extends State<Obtainium> {
 | 
			
		||||
      // set the background and surface colors to pure black in the amoled theme
 | 
			
		||||
      if (settingsProvider.useBlackTheme) {
 | 
			
		||||
        darkColorScheme = darkColorScheme
 | 
			
		||||
            .copyWith(background: Colors.black, surface: Colors.black)
 | 
			
		||||
            .copyWith(surface: Colors.black)
 | 
			
		||||
            .harmonized();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -133,7 +133,7 @@ class _AppPageState extends State<AppPage> {
 | 
			
		||||
                        child: Text(
 | 
			
		||||
                          app?.app.releaseDate == null
 | 
			
		||||
                              ? tr('changes')
 | 
			
		||||
                              : app!.app.releaseDate.toString(),
 | 
			
		||||
                              : app!.app.releaseDate!.toLocal().toString(),
 | 
			
		||||
                          textAlign: TextAlign.center,
 | 
			
		||||
                          style:
 | 
			
		||||
                              Theme.of(context).textTheme.labelSmall!.copyWith(
 | 
			
		||||
@@ -175,9 +175,8 @@ class _AppPageState extends State<AppPage> {
 | 
			
		||||
                tr('downloadX', args: [tr('releaseAsset').toLowerCase()]),
 | 
			
		||||
                textAlign: TextAlign.center,
 | 
			
		||||
                style: Theme.of(context).textTheme.labelSmall!.copyWith(
 | 
			
		||||
                      decoration:
 | 
			
		||||
                          changeLogFn != null ? TextDecoration.underline : null,
 | 
			
		||||
                      fontStyle: changeLogFn != null ? FontStyle.italic : null,
 | 
			
		||||
                      decoration: TextDecoration.underline,
 | 
			
		||||
                      fontStyle: FontStyle.italic,
 | 
			
		||||
                    ),
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
@@ -287,7 +286,7 @@ class _AppPageState extends State<AppPage> {
 | 
			
		||||
        ? WebViewWidget(
 | 
			
		||||
            controller: WebViewController()
 | 
			
		||||
              ..setJavaScriptMode(JavaScriptMode.unrestricted)
 | 
			
		||||
              ..setBackgroundColor(Theme.of(context).colorScheme.background)
 | 
			
		||||
              ..setBackgroundColor(Theme.of(context).colorScheme.surface)
 | 
			
		||||
              ..setJavaScriptMode(JavaScriptMode.unrestricted)
 | 
			
		||||
              ..setNavigationDelegate(
 | 
			
		||||
                NavigationDelegate(
 | 
			
		||||
 
 | 
			
		||||
@@ -437,7 +437,7 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
              ? tr('changes')
 | 
			
		||||
              : ''
 | 
			
		||||
          : DateFormat('yyyy-MM-dd')
 | 
			
		||||
              .format(listedApps[appIndex].app.releaseDate!);
 | 
			
		||||
              .format(listedApps[appIndex].app.releaseDate!.toLocal());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getSingleAppHorizTile(int index) {
 | 
			
		||||
@@ -503,7 +503,7 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      var transparent =
 | 
			
		||||
          Theme.of(context).colorScheme.background.withAlpha(0).value;
 | 
			
		||||
          Theme.of(context).colorScheme.surface.withAlpha(0).value;
 | 
			
		||||
      List<double> stops = [
 | 
			
		||||
        ...listedApps[index].app.categories.asMap().entries.map(
 | 
			
		||||
            (e) => ((e.key / (listedApps[index].app.categories.length - 1)))),
 | 
			
		||||
@@ -882,11 +882,10 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                          onPressed: selectedAppIds.isEmpty
 | 
			
		||||
                              ? null
 | 
			
		||||
                              : () {
 | 
			
		||||
                                  String urls =
 | 
			
		||||
                                      '<p>${tr('customLinkMessage')}:</p>\n\n<ul>\n';
 | 
			
		||||
                                  String urls = '';
 | 
			
		||||
                                  for (var a in selectedApps) {
 | 
			
		||||
                                    urls +=
 | 
			
		||||
                                        '    <li><a href="obtainium://app/${Uri.encodeComponent(jsonEncode({
 | 
			
		||||
                                        'https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/${Uri.encodeComponent(jsonEncode({
 | 
			
		||||
                                          'id': a.id,
 | 
			
		||||
                                          'url': a.url,
 | 
			
		||||
                                          'author': a.author,
 | 
			
		||||
@@ -894,11 +893,10 @@ class AppsPageState extends State<AppsPage> {
 | 
			
		||||
                                          'preferredApkIndex':
 | 
			
		||||
                                              a.preferredApkIndex,
 | 
			
		||||
                                          'additionalSettings':
 | 
			
		||||
                                              jsonEncode(a.additionalSettings)
 | 
			
		||||
                                        }))}">${a.name}</a></li>\n';
 | 
			
		||||
                                              jsonEncode(a.additionalSettings),
 | 
			
		||||
                                          'overrideSource': a.overrideSource
 | 
			
		||||
                                        }))}\n\n';
 | 
			
		||||
                                  }
 | 
			
		||||
                                  urls +=
 | 
			
		||||
                                      '</ul>\n\n<p><a href="$obtainiumUrl">${tr('about')}</a></p>';
 | 
			
		||||
                                  Share.share(urls,
 | 
			
		||||
                                      subject:
 | 
			
		||||
                                          'Obtainium - ${tr('appsString')}');
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ import 'package:obtainium/pages/import_export.dart';
 | 
			
		||||
import 'package:obtainium/pages/settings.dart';
 | 
			
		||||
import 'package:obtainium/providers/apps_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/settings_provider.dart';
 | 
			
		||||
import 'package:obtainium/providers/source_provider.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
 | 
			
		||||
class HomePage extends StatefulWidget {
 | 
			
		||||
@@ -102,13 +103,22 @@ class _HomePageState extends State<HomePage> {
 | 
			
		||||
                  }) !=
 | 
			
		||||
              null) {
 | 
			
		||||
            // ignore: use_build_context_synchronously
 | 
			
		||||
            var result = await context.read<AppsProvider>().import(
 | 
			
		||||
                action == 'app'
 | 
			
		||||
                    ? '{ "apps": [$dataStr] }'
 | 
			
		||||
                    : '{ "apps": $dataStr }');
 | 
			
		||||
            var appsProvider = context.read<AppsProvider>();
 | 
			
		||||
            var result = await appsProvider.import(action == 'app'
 | 
			
		||||
                ? '{ "apps": [$dataStr] }'
 | 
			
		||||
                : '{ "apps": $dataStr }');
 | 
			
		||||
            // ignore: use_build_context_synchronously
 | 
			
		||||
            showMessage(
 | 
			
		||||
                tr('importedX', args: [plural('apps', result.key)]), context);
 | 
			
		||||
                tr('importedX', args: [plural('apps', result.key.length)]),
 | 
			
		||||
                context);
 | 
			
		||||
            await appsProvider
 | 
			
		||||
                .checkUpdates(specificIds: result.key.map((e) => e.id).toList())
 | 
			
		||||
                .catchError((e) {
 | 
			
		||||
              if (e is Map && e['errors'] is MultiAppMultiError) {
 | 
			
		||||
                showError(e['errors'].toString(), context);
 | 
			
		||||
              }
 | 
			
		||||
              return <App>[];
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          throw ObtainiumError(tr('unknown'));
 | 
			
		||||
@@ -119,7 +129,7 @@ class _HomePageState extends State<HomePage> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check initial link if app was in cold state (terminated)
 | 
			
		||||
    final appLink = await _appLinks.getInitialAppLink();
 | 
			
		||||
    final appLink = await _appLinks.getInitialLink();
 | 
			
		||||
    if (appLink != null) {
 | 
			
		||||
      await interpretLink(appLink);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
 | 
			
		||||
    var settingsProvider = context.watch<SettingsProvider>();
 | 
			
		||||
 | 
			
		||||
    var outlineButtonStyle = ButtonStyle(
 | 
			
		||||
      shape: MaterialStateProperty.all(
 | 
			
		||||
      shape: WidgetStateProperty.all(
 | 
			
		||||
        StadiumBorder(
 | 
			
		||||
          side: BorderSide(
 | 
			
		||||
            width: 1,
 | 
			
		||||
@@ -144,7 +144,7 @@ class _ImportExportPageState extends State<ImportExportPage> {
 | 
			
		||||
            appsProvider.addMissingCategories(settingsProvider);
 | 
			
		||||
            showMessage(
 | 
			
		||||
                '${tr('importedX', args: [
 | 
			
		||||
                      plural('apps', value.key)
 | 
			
		||||
                      plural('apps', value.key.length)
 | 
			
		||||
                    ])}${value.value ? ' + ${tr('settings')}' : ''}',
 | 
			
		||||
                context);
 | 
			
		||||
          });
 | 
			
		||||
 
 | 
			
		||||
@@ -26,20 +26,33 @@ class SettingsPage extends StatefulWidget {
 | 
			
		||||
 | 
			
		||||
class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
  List<int> updateIntervalNodes = [
 | 
			
		||||
    15, 30, 60, 120, 180, 360, 720, 1440, 4320, 10080, 20160, 43200];
 | 
			
		||||
    15,
 | 
			
		||||
    30,
 | 
			
		||||
    60,
 | 
			
		||||
    120,
 | 
			
		||||
    180,
 | 
			
		||||
    360,
 | 
			
		||||
    720,
 | 
			
		||||
    1440,
 | 
			
		||||
    4320,
 | 
			
		||||
    10080,
 | 
			
		||||
    20160,
 | 
			
		||||
    43200
 | 
			
		||||
  ];
 | 
			
		||||
  int updateInterval = 0;
 | 
			
		||||
  late SplineInterpolation updateIntervalInterpolator;  // 🤓
 | 
			
		||||
  late SplineInterpolation updateIntervalInterpolator; // 🤓
 | 
			
		||||
  String updateIntervalLabel = tr('neverManualOnly');
 | 
			
		||||
  bool showIntervalLabel = true;
 | 
			
		||||
  final Map<ColorSwatch<Object>, String> colorsNameMap =
 | 
			
		||||
  <ColorSwatch<Object>, String> {
 | 
			
		||||
      <ColorSwatch<Object>, String>{
 | 
			
		||||
    ColorTools.createPrimarySwatch(obtainiumThemeColor): 'Obtainium'
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  void initUpdateIntervalInterpolator() {
 | 
			
		||||
    List<InterpolationNode> nodes = [];
 | 
			
		||||
    for (final (index, element) in updateIntervalNodes.indexed) {
 | 
			
		||||
      nodes.add(InterpolationNode(x: index.toDouble()+1, y: element.toDouble()));
 | 
			
		||||
      nodes.add(
 | 
			
		||||
          InterpolationNode(x: index.toDouble() + 1, y: element.toDouble()));
 | 
			
		||||
    }
 | 
			
		||||
    updateIntervalInterpolator = SplineInterpolation(nodes: nodes);
 | 
			
		||||
  }
 | 
			
		||||
@@ -69,7 +82,7 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
      int valRounded = (valInterpolated / 30).floor() * 30;
 | 
			
		||||
      updateInterval = valRounded;
 | 
			
		||||
      updateIntervalLabel = plural('hour', valRounded / 60);
 | 
			
		||||
    } else if (valInterpolated < 7 * 24 * 60){
 | 
			
		||||
    } else if (valInterpolated < 7 * 24 * 60) {
 | 
			
		||||
      int valRounded = (valInterpolated / (12 * 60)).floor() * 12 * 60;
 | 
			
		||||
      updateInterval = valRounded;
 | 
			
		||||
      updateIntervalLabel = plural('day', valRounded / (24 * 60));
 | 
			
		||||
@@ -88,41 +101,20 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
    initUpdateIntervalInterpolator();
 | 
			
		||||
    processIntervalSliderValue(settingsProvider.updateIntervalSliderVal);
 | 
			
		||||
 | 
			
		||||
    var themeDropdown = FutureBuilder(
 | 
			
		||||
    var followSystemThemeExplanation = FutureBuilder(
 | 
			
		||||
        builder: (ctx, val) {
 | 
			
		||||
          return DropdownButtonFormField(
 | 
			
		||||
              decoration: InputDecoration(labelText: tr('theme')),
 | 
			
		||||
              value: settingsProvider.theme,
 | 
			
		||||
              items: [
 | 
			
		||||
                DropdownMenuItem(
 | 
			
		||||
                  value: ThemeSettings.light,
 | 
			
		||||
                  child: Text(tr('light')),
 | 
			
		||||
                ),
 | 
			
		||||
                DropdownMenuItem(
 | 
			
		||||
                  value: ThemeSettings.dark,
 | 
			
		||||
                  child: Text(tr('dark')),
 | 
			
		||||
                ),
 | 
			
		||||
                if ((val.data?.version.sdkInt ?? 0) >= 29) DropdownMenuItem(
 | 
			
		||||
                  value: ThemeSettings.system,
 | 
			
		||||
                  child: Text(tr('followSystem')),
 | 
			
		||||
                )
 | 
			
		||||
              ],
 | 
			
		||||
              onChanged: (value) {
 | 
			
		||||
                if (value != null) {
 | 
			
		||||
                  settingsProvider.theme = value;
 | 
			
		||||
                }
 | 
			
		||||
              });
 | 
			
		||||
          return ((val.data?.version.sdkInt ?? 30) < 29)
 | 
			
		||||
              ? Text(tr('followSystemThemeExplanation'),
 | 
			
		||||
                  style: Theme.of(context).textTheme.labelSmall)
 | 
			
		||||
              : const SizedBox.shrink();
 | 
			
		||||
        },
 | 
			
		||||
        future: DeviceInfoPlugin().androidInfo
 | 
			
		||||
    );
 | 
			
		||||
        future: DeviceInfoPlugin().androidInfo);
 | 
			
		||||
 | 
			
		||||
    Future<bool> colorPickerDialog() async {
 | 
			
		||||
      return ColorPicker(
 | 
			
		||||
        color: settingsProvider.themeColor,
 | 
			
		||||
        onColorChanged: (Color color) =>
 | 
			
		||||
            setState(() =>
 | 
			
		||||
            settingsProvider.themeColor = color
 | 
			
		||||
            ),
 | 
			
		||||
            setState(() => settingsProvider.themeColor = color),
 | 
			
		||||
        actionButtons: const ColorPickerActionButtons(
 | 
			
		||||
          okButton: true,
 | 
			
		||||
          closeButton: true,
 | 
			
		||||
@@ -155,19 +147,17 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
        showColorName: true,
 | 
			
		||||
        materialNameTextStyle: Theme.of(context).textTheme.bodySmall,
 | 
			
		||||
        colorNameTextStyle: Theme.of(context).textTheme.bodySmall,
 | 
			
		||||
        copyPasteBehavior: const ColorPickerCopyPasteBehavior(longPressMenu: true),
 | 
			
		||||
        copyPasteBehavior:
 | 
			
		||||
            const ColorPickerCopyPasteBehavior(longPressMenu: true),
 | 
			
		||||
      ).showPickerDialog(
 | 
			
		||||
        context,
 | 
			
		||||
        transitionBuilder: (BuildContext context,
 | 
			
		||||
            Animation<double> a1, Animation<double> a2, Widget widget) {
 | 
			
		||||
        transitionBuilder: (BuildContext context, Animation<double> a1,
 | 
			
		||||
            Animation<double> a2, Widget widget) {
 | 
			
		||||
          final double curvedValue = Curves.easeInCubic.transform(a1.value);
 | 
			
		||||
          return Transform(
 | 
			
		||||
            alignment: Alignment.center,
 | 
			
		||||
            transform: Matrix4.diagonal3Values(curvedValue, curvedValue, 1),
 | 
			
		||||
            child: Opacity(
 | 
			
		||||
                opacity: curvedValue,
 | 
			
		||||
                child: widget
 | 
			
		||||
            ),
 | 
			
		||||
            child: Opacity(opacity: curvedValue, child: widget),
 | 
			
		||||
          );
 | 
			
		||||
        },
 | 
			
		||||
        transitionDuration: const Duration(milliseconds: 250),
 | 
			
		||||
@@ -175,46 +165,44 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var colorPicker = ListTile(
 | 
			
		||||
      dense: true,
 | 
			
		||||
      contentPadding: EdgeInsets.zero,
 | 
			
		||||
      title: Text(tr('selectX', args: [tr('colour')])),
 | 
			
		||||
      subtitle: Text("${ColorTools.nameThatColor(settingsProvider.themeColor)} "
 | 
			
		||||
          "(${ColorTools.materialNameAndCode(settingsProvider.themeColor,
 | 
			
		||||
              colorSwatchNameMap: colorsNameMap)})"),
 | 
			
		||||
      trailing: ColorIndicator(
 | 
			
		||||
        width: 40,
 | 
			
		||||
        height: 40,
 | 
			
		||||
        borderRadius: 20,
 | 
			
		||||
        color: settingsProvider.themeColor,
 | 
			
		||||
        onSelectFocus: false,
 | 
			
		||||
        onSelect: () async {
 | 
			
		||||
          final Color colorBeforeDialog = settingsProvider.themeColor;
 | 
			
		||||
          if (!(await colorPickerDialog())) {
 | 
			
		||||
            setState(() {
 | 
			
		||||
              settingsProvider.themeColor = colorBeforeDialog;
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
        dense: true,
 | 
			
		||||
        contentPadding: EdgeInsets.zero,
 | 
			
		||||
        title: Text(tr('selectX', args: [tr('colour')])),
 | 
			
		||||
        subtitle: Text(
 | 
			
		||||
            "${ColorTools.nameThatColor(settingsProvider.themeColor)} "
 | 
			
		||||
            "(${ColorTools.materialNameAndCode(settingsProvider.themeColor, colorSwatchNameMap: colorsNameMap)})"),
 | 
			
		||||
        trailing: ColorIndicator(
 | 
			
		||||
            width: 40,
 | 
			
		||||
            height: 40,
 | 
			
		||||
            borderRadius: 20,
 | 
			
		||||
            color: settingsProvider.themeColor,
 | 
			
		||||
            onSelectFocus: false,
 | 
			
		||||
            onSelect: () async {
 | 
			
		||||
              final Color colorBeforeDialog = settingsProvider.themeColor;
 | 
			
		||||
              if (!(await colorPickerDialog())) {
 | 
			
		||||
                setState(() {
 | 
			
		||||
                  settingsProvider.themeColor = colorBeforeDialog;
 | 
			
		||||
                });
 | 
			
		||||
              }
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
    var useMaterialThemeSwitch = FutureBuilder(
 | 
			
		||||
        builder: (ctx, val) {
 | 
			
		||||
          return ((val.data?.version.sdkInt ?? 0) >= 31) ?
 | 
			
		||||
          Row(
 | 
			
		||||
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
            children: [
 | 
			
		||||
              Flexible(child: Text(tr('useMaterialYou'))),
 | 
			
		||||
              Switch(
 | 
			
		||||
                  value: settingsProvider.useMaterialYou,
 | 
			
		||||
                  onChanged: (value) {
 | 
			
		||||
                    settingsProvider.useMaterialYou = value;
 | 
			
		||||
                  })
 | 
			
		||||
            ],
 | 
			
		||||
          ) : const SizedBox.shrink();
 | 
			
		||||
          return ((val.data?.version.sdkInt ?? 0) >= 31)
 | 
			
		||||
              ? Row(
 | 
			
		||||
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                  children: [
 | 
			
		||||
                    Flexible(child: Text(tr('useMaterialYou'))),
 | 
			
		||||
                    Switch(
 | 
			
		||||
                        value: settingsProvider.useMaterialYou,
 | 
			
		||||
                        onChanged: (value) {
 | 
			
		||||
                          settingsProvider.useMaterialYou = value;
 | 
			
		||||
                        })
 | 
			
		||||
                  ],
 | 
			
		||||
                )
 | 
			
		||||
              : const SizedBox.shrink();
 | 
			
		||||
        },
 | 
			
		||||
        future: DeviceInfoPlugin().androidInfo
 | 
			
		||||
    );
 | 
			
		||||
        future: DeviceInfoPlugin().androidInfo);
 | 
			
		||||
 | 
			
		||||
    var sortDropdown = DropdownButtonFormField(
 | 
			
		||||
        isExpanded: true,
 | 
			
		||||
@@ -361,13 +349,20 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                            ),
 | 
			
		||||
                            //intervalDropdown,
 | 
			
		||||
                            height16,
 | 
			
		||||
                            if (showIntervalLabel) SizedBox(
 | 
			
		||||
                                child: Text("${tr('bgUpdateCheckInterval')}: $updateIntervalLabel")
 | 
			
		||||
                            ) else const SizedBox(height: 16),
 | 
			
		||||
                            if (showIntervalLabel)
 | 
			
		||||
                              SizedBox(
 | 
			
		||||
                                  child: Text(
 | 
			
		||||
                                      "${tr('bgUpdateCheckInterval')}: $updateIntervalLabel"))
 | 
			
		||||
                            else
 | 
			
		||||
                              const SizedBox(height: 16),
 | 
			
		||||
                            intervalSlider,
 | 
			
		||||
                            FutureBuilder(
 | 
			
		||||
                                builder: (ctx, val) {
 | 
			
		||||
                                  return ((val.data?.version.sdkInt ?? 0) >= 30) || settingsProvider.useShizuku
 | 
			
		||||
                                  return (settingsProvider.updateInterval >
 | 
			
		||||
                                              0) &&
 | 
			
		||||
                                          (((val.data?.version.sdkInt ?? 0) >=
 | 
			
		||||
                                                  30) ||
 | 
			
		||||
                                              settingsProvider.useShizuku)
 | 
			
		||||
                                      ? Column(
 | 
			
		||||
                                          crossAxisAlignment:
 | 
			
		||||
                                              CrossAxisAlignment.start,
 | 
			
		||||
@@ -509,33 +504,33 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                              children: [
 | 
			
		||||
                                Flexible(
 | 
			
		||||
                                    child: Column(
 | 
			
		||||
                                      crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                                      mainAxisSize: MainAxisSize.min,
 | 
			
		||||
                                      children: [
 | 
			
		||||
                                        Text(tr(
 | 
			
		||||
                                            'beforeNewInstallsShareToAppVerifier')),
 | 
			
		||||
                                        GestureDetector(
 | 
			
		||||
                                            onTap: () {
 | 
			
		||||
                                              launchUrlString(
 | 
			
		||||
                                                  'https://github.com/soupslurpr/AppVerifier',
 | 
			
		||||
                                                  mode: LaunchMode
 | 
			
		||||
                                                      .externalApplication);
 | 
			
		||||
                                            },
 | 
			
		||||
                                            child: Text(
 | 
			
		||||
                                              tr('about'),
 | 
			
		||||
                                              style: const TextStyle(
 | 
			
		||||
                                                  decoration:
 | 
			
		||||
                                  crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                                  mainAxisSize: MainAxisSize.min,
 | 
			
		||||
                                  children: [
 | 
			
		||||
                                    Text(tr(
 | 
			
		||||
                                        'beforeNewInstallsShareToAppVerifier')),
 | 
			
		||||
                                    GestureDetector(
 | 
			
		||||
                                        onTap: () {
 | 
			
		||||
                                          launchUrlString(
 | 
			
		||||
                                              'https://github.com/soupslurpr/AppVerifier',
 | 
			
		||||
                                              mode: LaunchMode
 | 
			
		||||
                                                  .externalApplication);
 | 
			
		||||
                                        },
 | 
			
		||||
                                        child: Text(
 | 
			
		||||
                                          tr('about'),
 | 
			
		||||
                                          style: const TextStyle(
 | 
			
		||||
                                              decoration:
 | 
			
		||||
                                                  TextDecoration.underline,
 | 
			
		||||
                                                  fontSize: 12),
 | 
			
		||||
                                            )),
 | 
			
		||||
                                      ],
 | 
			
		||||
                                    )),
 | 
			
		||||
                                              fontSize: 12),
 | 
			
		||||
                                        )),
 | 
			
		||||
                                  ],
 | 
			
		||||
                                )),
 | 
			
		||||
                                Switch(
 | 
			
		||||
                                    value: settingsProvider
 | 
			
		||||
                                        .beforeNewInstallsShareToAppVerifier,
 | 
			
		||||
                                    onChanged: (value) {
 | 
			
		||||
                                      settingsProvider
 | 
			
		||||
                                          .beforeNewInstallsShareToAppVerifier =
 | 
			
		||||
                                              .beforeNewInstallsShareToAppVerifier =
 | 
			
		||||
                                          value;
 | 
			
		||||
                                    })
 | 
			
		||||
                              ],
 | 
			
		||||
@@ -549,17 +544,31 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                                    value: settingsProvider.useShizuku,
 | 
			
		||||
                                    onChanged: (useShizuku) {
 | 
			
		||||
                                      if (useShizuku) {
 | 
			
		||||
                                        ShizukuApkInstaller.checkPermission().then((resCode) {
 | 
			
		||||
                                          settingsProvider.useShizuku = resCode!.startsWith('granted');
 | 
			
		||||
                                          switch(resCode){
 | 
			
		||||
                                        ShizukuApkInstaller.checkPermission()
 | 
			
		||||
                                            .then((resCode) {
 | 
			
		||||
                                          settingsProvider.useShizuku =
 | 
			
		||||
                                              resCode!.startsWith('granted');
 | 
			
		||||
                                          switch (resCode) {
 | 
			
		||||
                                            case 'binder_not_found':
 | 
			
		||||
                                              showError(ObtainiumError(tr('shizukuBinderNotFound')), context);
 | 
			
		||||
                                              showError(
 | 
			
		||||
                                                  ObtainiumError(tr(
 | 
			
		||||
                                                      'shizukuBinderNotFound')),
 | 
			
		||||
                                                  context);
 | 
			
		||||
                                            case 'old_shizuku':
 | 
			
		||||
                                              showError(ObtainiumError(tr('shizukuOld')), context);
 | 
			
		||||
                                              showError(
 | 
			
		||||
                                                  ObtainiumError(
 | 
			
		||||
                                                      tr('shizukuOld')),
 | 
			
		||||
                                                  context);
 | 
			
		||||
                                            case 'old_android_with_adb':
 | 
			
		||||
                                              showError(ObtainiumError(tr('shizukuOldAndroidWithADB')), context);
 | 
			
		||||
                                              showError(
 | 
			
		||||
                                                  ObtainiumError(tr(
 | 
			
		||||
                                                      'shizukuOldAndroidWithADB')),
 | 
			
		||||
                                                  context);
 | 
			
		||||
                                            case 'denied':
 | 
			
		||||
                                              showError(ObtainiumError(tr('cancelled')), context);
 | 
			
		||||
                                              showError(
 | 
			
		||||
                                                  ObtainiumError(
 | 
			
		||||
                                                      tr('cancelled')),
 | 
			
		||||
                                                  context);
 | 
			
		||||
                                          }
 | 
			
		||||
                                        });
 | 
			
		||||
                                      } else {
 | 
			
		||||
@@ -583,20 +592,47 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                                  fontWeight: FontWeight.bold,
 | 
			
		||||
                                  color: Theme.of(context).colorScheme.primary),
 | 
			
		||||
                            ),
 | 
			
		||||
                            themeDropdown,
 | 
			
		||||
                            height16,
 | 
			
		||||
                            Row(
 | 
			
		||||
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                              children: [
 | 
			
		||||
                                Flexible(child: Text(tr('useBlackTheme'))),
 | 
			
		||||
                                Switch(
 | 
			
		||||
                                    value: settingsProvider.useBlackTheme,
 | 
			
		||||
                                    onChanged: (value) {
 | 
			
		||||
                                      settingsProvider.useBlackTheme = value;
 | 
			
		||||
                                    })
 | 
			
		||||
                              ],
 | 
			
		||||
                            ),
 | 
			
		||||
                            DropdownButtonFormField(
 | 
			
		||||
                                decoration:
 | 
			
		||||
                                    InputDecoration(labelText: tr('theme')),
 | 
			
		||||
                                value: settingsProvider.theme,
 | 
			
		||||
                                items: [
 | 
			
		||||
                                  DropdownMenuItem(
 | 
			
		||||
                                    value: ThemeSettings.system,
 | 
			
		||||
                                    child: Text(tr('followSystem')),
 | 
			
		||||
                                  ),
 | 
			
		||||
                                  DropdownMenuItem(
 | 
			
		||||
                                    value: ThemeSettings.light,
 | 
			
		||||
                                    child: Text(tr('light')),
 | 
			
		||||
                                  ),
 | 
			
		||||
                                  DropdownMenuItem(
 | 
			
		||||
                                    value: ThemeSettings.dark,
 | 
			
		||||
                                    child: Text(tr('dark')),
 | 
			
		||||
                                  )
 | 
			
		||||
                                ],
 | 
			
		||||
                                onChanged: (value) {
 | 
			
		||||
                                  if (value != null) {
 | 
			
		||||
                                    settingsProvider.theme = value;
 | 
			
		||||
                                  }
 | 
			
		||||
                                }),
 | 
			
		||||
                            height8,
 | 
			
		||||
                            if (settingsProvider.theme == ThemeSettings.system)
 | 
			
		||||
                              followSystemThemeExplanation,
 | 
			
		||||
                            height16,
 | 
			
		||||
                            if (settingsProvider.theme != ThemeSettings.light)
 | 
			
		||||
                              Row(
 | 
			
		||||
                                  mainAxisAlignment:
 | 
			
		||||
                                      MainAxisAlignment.spaceBetween,
 | 
			
		||||
                                  children: [
 | 
			
		||||
                                    Flexible(child: Text(tr('useBlackTheme'))),
 | 
			
		||||
                                    Switch(
 | 
			
		||||
                                        value: settingsProvider.useBlackTheme,
 | 
			
		||||
                                        onChanged: (value) {
 | 
			
		||||
                                          settingsProvider.useBlackTheme =
 | 
			
		||||
                                              value;
 | 
			
		||||
                                        })
 | 
			
		||||
                                  ]),
 | 
			
		||||
                            height8,
 | 
			
		||||
                            useMaterialThemeSwitch,
 | 
			
		||||
                            if (!settingsProvider.useMaterialYou) colorPicker,
 | 
			
		||||
                            Row(
 | 
			
		||||
@@ -616,28 +652,39 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                                builder: (ctx, val) {
 | 
			
		||||
                                  return (val.data?.version.sdkInt ?? 0) >= 34
 | 
			
		||||
                                      ? Column(
 | 
			
		||||
                                    crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                                    children: [
 | 
			
		||||
                                      height16,
 | 
			
		||||
                                      Row(
 | 
			
		||||
                                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                                        children: [
 | 
			
		||||
                                          Flexible(child: Text(tr('useSystemFont'))),
 | 
			
		||||
                                          Switch(
 | 
			
		||||
                                              value: settingsProvider.useSystemFont,
 | 
			
		||||
                                              onChanged: (useSystemFont) {
 | 
			
		||||
                                                if (useSystemFont) {
 | 
			
		||||
                                                  NativeFeatures.loadSystemFont().then((val) {
 | 
			
		||||
                                                    settingsProvider.useSystemFont = true;
 | 
			
		||||
                                                  });
 | 
			
		||||
                                                } else {
 | 
			
		||||
                                                  settingsProvider.useSystemFont = false;
 | 
			
		||||
                                                }
 | 
			
		||||
                                              })
 | 
			
		||||
                                        ]
 | 
			
		||||
                                      )
 | 
			
		||||
                                    ]
 | 
			
		||||
                                  )
 | 
			
		||||
                                          crossAxisAlignment:
 | 
			
		||||
                                              CrossAxisAlignment.start,
 | 
			
		||||
                                          children: [
 | 
			
		||||
                                              height16,
 | 
			
		||||
                                              Row(
 | 
			
		||||
                                                  mainAxisAlignment:
 | 
			
		||||
                                                      MainAxisAlignment
 | 
			
		||||
                                                          .spaceBetween,
 | 
			
		||||
                                                  children: [
 | 
			
		||||
                                                    Flexible(
 | 
			
		||||
                                                        child: Text(tr(
 | 
			
		||||
                                                            'useSystemFont'))),
 | 
			
		||||
                                                    Switch(
 | 
			
		||||
                                                        value: settingsProvider
 | 
			
		||||
                                                            .useSystemFont,
 | 
			
		||||
                                                        onChanged:
 | 
			
		||||
                                                            (useSystemFont) {
 | 
			
		||||
                                                          if (useSystemFont) {
 | 
			
		||||
                                                            NativeFeatures
 | 
			
		||||
                                                                    .loadSystemFont()
 | 
			
		||||
                                                                .then((val) {
 | 
			
		||||
                                                              settingsProvider
 | 
			
		||||
                                                                      .useSystemFont =
 | 
			
		||||
                                                                  true;
 | 
			
		||||
                                                            });
 | 
			
		||||
                                                          } else {
 | 
			
		||||
                                                            settingsProvider
 | 
			
		||||
                                                                    .useSystemFont =
 | 
			
		||||
                                                                false;
 | 
			
		||||
                                                          }
 | 
			
		||||
                                                        })
 | 
			
		||||
                                                  ])
 | 
			
		||||
                                            ])
 | 
			
		||||
                                      : const SizedBox.shrink();
 | 
			
		||||
                                },
 | 
			
		||||
                                future: DeviceInfoPlugin().androidInfo),
 | 
			
		||||
@@ -793,17 +840,31 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                Row(
 | 
			
		||||
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
 | 
			
		||||
                  children: [
 | 
			
		||||
                    TextButton.icon(
 | 
			
		||||
                    IconButton(
 | 
			
		||||
                      onPressed: () {
 | 
			
		||||
                        launchUrlString(settingsProvider.sourceUrl,
 | 
			
		||||
                            mode: LaunchMode.externalApplication);
 | 
			
		||||
                      },
 | 
			
		||||
                      icon: const Icon(Icons.code),
 | 
			
		||||
                      label: Text(
 | 
			
		||||
                        tr('appSource'),
 | 
			
		||||
                      ),
 | 
			
		||||
                      tooltip: tr('appSource'),
 | 
			
		||||
                    ),
 | 
			
		||||
                    TextButton.icon(
 | 
			
		||||
                    IconButton(
 | 
			
		||||
                      onPressed: () {
 | 
			
		||||
                        launchUrlString('${settingsProvider.sourceUrl}/wiki',
 | 
			
		||||
                            mode: LaunchMode.externalApplication);
 | 
			
		||||
                      },
 | 
			
		||||
                      icon: const Icon(Icons.help_outline_rounded),
 | 
			
		||||
                      tooltip: tr('wiki'),
 | 
			
		||||
                    ),
 | 
			
		||||
                    IconButton(
 | 
			
		||||
                      onPressed: () {
 | 
			
		||||
                        launchUrlString('https://apps.obtainium.imranr.dev/',
 | 
			
		||||
                            mode: LaunchMode.externalApplication);
 | 
			
		||||
                      },
 | 
			
		||||
                      icon: const Icon(Icons.apps_rounded),
 | 
			
		||||
                      tooltip: tr('crowdsourcedConfigsLabel'),
 | 
			
		||||
                    ),
 | 
			
		||||
                    IconButton(
 | 
			
		||||
                        onPressed: () {
 | 
			
		||||
                          context.read<LogsProvider>().get().then((logs) {
 | 
			
		||||
                            if (logs.isEmpty) {
 | 
			
		||||
@@ -819,7 +880,7 @@ class _SettingsPageState extends State<SettingsPage> {
 | 
			
		||||
                          });
 | 
			
		||||
                        },
 | 
			
		||||
                        icon: const Icon(Icons.bug_report_outlined),
 | 
			
		||||
                        label: Text(tr('appLogs'))),
 | 
			
		||||
                        tooltip: tr('appLogs'))
 | 
			
		||||
                  ],
 | 
			
		||||
                ),
 | 
			
		||||
                const SizedBox(
 | 
			
		||||
 
 | 
			
		||||
@@ -142,19 +142,20 @@ List<MapEntry<String, int>> moveStrToEndMapEntryWithCount(
 | 
			
		||||
  return arr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Future<File> downloadFileWithRetry(
 | 
			
		||||
    String url, String fileNameNoExt, Function? onProgress, String destDir,
 | 
			
		||||
Future<File> downloadFileWithRetry(String url, String fileName,
 | 
			
		||||
    bool fileNameHasExt, Function? onProgress, String destDir,
 | 
			
		||||
    {bool useExisting = true,
 | 
			
		||||
    Map<String, String>? headers,
 | 
			
		||||
    int retries = 3}) async {
 | 
			
		||||
  try {
 | 
			
		||||
    return await downloadFile(url, fileNameNoExt, onProgress, destDir,
 | 
			
		||||
    return await downloadFile(
 | 
			
		||||
        url, fileName, fileNameHasExt, onProgress, destDir,
 | 
			
		||||
        useExisting: useExisting, headers: headers);
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    if (retries > 0 && e is ClientException) {
 | 
			
		||||
      await Future.delayed(const Duration(seconds: 5));
 | 
			
		||||
      return await downloadFileWithRetry(
 | 
			
		||||
          url, fileNameNoExt, onProgress, destDir,
 | 
			
		||||
          url, fileName, fileNameHasExt, onProgress, destDir,
 | 
			
		||||
          useExisting: useExisting, headers: headers, retries: (retries - 1));
 | 
			
		||||
    } else {
 | 
			
		||||
      rethrow;
 | 
			
		||||
@@ -201,8 +202,8 @@ Future<String> checkPartialDownloadHash(String url, int bytesToGrab,
 | 
			
		||||
  return hashListOfLists(bytes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Future<File> downloadFile(
 | 
			
		||||
    String url, String fileNameNoExt, Function? onProgress, String destDir,
 | 
			
		||||
Future<File> downloadFile(String url, String fileName, bool fileNameHasExt,
 | 
			
		||||
    Function? onProgress, String destDir,
 | 
			
		||||
    {bool useExisting = true, Map<String, String>? headers}) async {
 | 
			
		||||
  // Send the initial request but cancel it as soon as you have the headers
 | 
			
		||||
  var reqHeaders = headers ?? {};
 | 
			
		||||
@@ -222,7 +223,12 @@ Future<File> downloadFile(
 | 
			
		||||
  if (url.toLowerCase().endsWith('.apk') && ext != 'apk') {
 | 
			
		||||
    ext = 'apk';
 | 
			
		||||
  }
 | 
			
		||||
  File downloadedFile = File('$destDir/$fileNameNoExt.$ext');
 | 
			
		||||
  fileName = fileName.split('/').last; // Ensure the fileName is a file name
 | 
			
		||||
  File downloadedFile = File('$destDir/$fileName.$ext');
 | 
			
		||||
  if (fileNameHasExt) {
 | 
			
		||||
    // If the user says the filename already has an ext, ignore whatever you inferred from above
 | 
			
		||||
    downloadedFile = File('$destDir/$fileName');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool rangeFeatureEnabled = false;
 | 
			
		||||
  if (resHeaders['accept-ranges']?.isNotEmpty == true) {
 | 
			
		||||
@@ -415,7 +421,8 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<Object> downloadApp(App app, BuildContext? context,
 | 
			
		||||
      {NotificationsProvider? notificationsProvider}) async {
 | 
			
		||||
      {NotificationsProvider? notificationsProvider,
 | 
			
		||||
      bool useExisting = true}) async {
 | 
			
		||||
    var notifId = DownloadNotification(app.finalName, 0).id;
 | 
			
		||||
    if (apps[app.id] != null) {
 | 
			
		||||
      apps[app.id]!.downloadProgress = 0;
 | 
			
		||||
@@ -435,8 +442,8 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
      var headers = await source.getRequestHeaders(app.additionalSettings,
 | 
			
		||||
          forAPKDownload: true);
 | 
			
		||||
      var downloadedFile = await downloadFileWithRetry(
 | 
			
		||||
          downloadUrl, fileNameNoExt,
 | 
			
		||||
          headers: headers, (double? progress) {
 | 
			
		||||
          downloadUrl, fileNameNoExt, false, headers: headers,
 | 
			
		||||
          (double? progress) {
 | 
			
		||||
        int? prog = progress?.ceil();
 | 
			
		||||
        if (apps[app.id] != null) {
 | 
			
		||||
          apps[app.id]!.downloadProgress = progress;
 | 
			
		||||
@@ -447,7 +454,7 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
          notificationsProvider?.notify(notif);
 | 
			
		||||
        }
 | 
			
		||||
        prevProg = prog;
 | 
			
		||||
      }, APKDir.path);
 | 
			
		||||
      }, APKDir.path, useExisting: useExisting);
 | 
			
		||||
      // Set to 90 for remaining steps, will make null in 'finally'
 | 
			
		||||
      if (apps[app.id] != null) {
 | 
			
		||||
        apps[app.id]!.downloadProgress = -1;
 | 
			
		||||
@@ -525,10 +532,11 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
              ?.installingPackageName
 | 
			
		||||
          : (await pm.getInstallerPackageName(packageName: app.id));
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      return false;  // App probably not installed
 | 
			
		||||
      return false; // App probably not installed
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int? targetSDK = (await getInstalledInfo(app.id))?.applicationInfo?.targetSdkVersion;
 | 
			
		||||
    int? targetSDK =
 | 
			
		||||
        (await getInstalledInfo(app.id))?.applicationInfo?.targetSdkVersion;
 | 
			
		||||
    // The APK should target a new enough API
 | 
			
		||||
    // https://developer.android.com/reference/android/content/pm/PackageInstaller.SessionParams#setRequireUserAction(int)
 | 
			
		||||
    if (!(targetSDK != null && targetSDK >= (osInfo.version.sdkInt - 3))) {
 | 
			
		||||
@@ -571,7 +579,8 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
 | 
			
		||||
  Future<bool> installXApkDir(
 | 
			
		||||
      DownloadedXApkDir dir, BuildContext? firstTimeWithContext,
 | 
			
		||||
      {bool needsBGWorkaround = false, bool shizukuPretendToBeGooglePlay = false}) async {
 | 
			
		||||
      {bool needsBGWorkaround = false,
 | 
			
		||||
      bool shizukuPretendToBeGooglePlay = false}) async {
 | 
			
		||||
    // We don't know which APKs in an XAPK are supported by the user's device
 | 
			
		||||
    // So we try installing all of them and assume success if at least one installed
 | 
			
		||||
    // If 0 APKs installed, throw the first install error encountered
 | 
			
		||||
@@ -610,7 +619,8 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
 | 
			
		||||
  Future<bool> installApk(
 | 
			
		||||
      DownloadedApk file, BuildContext? firstTimeWithContext,
 | 
			
		||||
      {bool needsBGWorkaround = false, bool shizukuPretendToBeGooglePlay = false}) async {
 | 
			
		||||
      {bool needsBGWorkaround = false,
 | 
			
		||||
      bool shizukuPretendToBeGooglePlay = false}) async {
 | 
			
		||||
    if (firstTimeWithContext != null &&
 | 
			
		||||
        settingsProvider.beforeNewInstallsShareToAppVerifier &&
 | 
			
		||||
        (await getInstalledInfo('dev.soupslurpr.appverifier')) != null) {
 | 
			
		||||
@@ -651,7 +661,8 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
    }
 | 
			
		||||
    int? code;
 | 
			
		||||
    if (!settingsProvider.useShizuku) {
 | 
			
		||||
      code = await AndroidPackageInstaller.installApk(apkFilePath: file.file.path);
 | 
			
		||||
      code =
 | 
			
		||||
          await AndroidPackageInstaller.installApk(apkFilePath: file.file.path);
 | 
			
		||||
    } else {
 | 
			
		||||
      code = await ShizukuApkInstaller.installAPK(file.file.uri.toString(),
 | 
			
		||||
          shizukuPretendToBeGooglePlay ? "com.android.vending" : "");
 | 
			
		||||
@@ -756,7 +767,8 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
  Future<List<String>> downloadAndInstallLatestApps(
 | 
			
		||||
      List<String> appIds, BuildContext? context,
 | 
			
		||||
      {NotificationsProvider? notificationsProvider,
 | 
			
		||||
      bool forceParallelDownloads = false}) async {
 | 
			
		||||
      bool forceParallelDownloads = false,
 | 
			
		||||
      bool useExisting = true}) async {
 | 
			
		||||
    notificationsProvider =
 | 
			
		||||
        notificationsProvider ?? context?.read<NotificationsProvider>();
 | 
			
		||||
    List<String> appsToInstall = [];
 | 
			
		||||
@@ -808,27 +820,88 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
    appsToInstall =
 | 
			
		||||
        moveStrToEnd(appsToInstall, obtainiumId, strB: obtainiumTempId);
 | 
			
		||||
 | 
			
		||||
    Future<String> updateFn(String id, {bool skipInstalls = false}) async {
 | 
			
		||||
    Future<void> installFn(String id, bool willBeSilent,
 | 
			
		||||
        DownloadedApk? downloadedFile, DownloadedXApkDir? downloadedDir) async {
 | 
			
		||||
      apps[id]?.downloadProgress = -1;
 | 
			
		||||
      notifyListeners();
 | 
			
		||||
      try {
 | 
			
		||||
        bool sayInstalled = true;
 | 
			
		||||
        var contextIfNewInstall =
 | 
			
		||||
            apps[id]?.installedInfo == null ? context : null;
 | 
			
		||||
        bool needBGWorkaround =
 | 
			
		||||
            willBeSilent && context == null && !settingsProvider.useShizuku;
 | 
			
		||||
        if (downloadedFile != null) {
 | 
			
		||||
          if (needBGWorkaround) {
 | 
			
		||||
            // ignore: use_build_context_synchronously
 | 
			
		||||
            installApk(downloadedFile, contextIfNewInstall,
 | 
			
		||||
                needsBGWorkaround: true);
 | 
			
		||||
          } else {
 | 
			
		||||
            // ignore: use_build_context_synchronously
 | 
			
		||||
            sayInstalled = await installApk(downloadedFile, contextIfNewInstall,
 | 
			
		||||
                shizukuPretendToBeGooglePlay: apps[id]!
 | 
			
		||||
                        .app
 | 
			
		||||
                        .additionalSettings['shizukuPretendToBeGooglePlay'] ==
 | 
			
		||||
                    true);
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          if (needBGWorkaround) {
 | 
			
		||||
            // ignore: use_build_context_synchronously
 | 
			
		||||
            installXApkDir(downloadedDir!, contextIfNewInstall,
 | 
			
		||||
                needsBGWorkaround: true);
 | 
			
		||||
          } else {
 | 
			
		||||
            // ignore: use_build_context_synchronously
 | 
			
		||||
            sayInstalled = await installXApkDir(
 | 
			
		||||
                downloadedDir!, contextIfNewInstall,
 | 
			
		||||
                shizukuPretendToBeGooglePlay: apps[id]!
 | 
			
		||||
                        .app
 | 
			
		||||
                        .additionalSettings['shizukuPretendToBeGooglePlay'] ==
 | 
			
		||||
                    true);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (willBeSilent && context == null) {
 | 
			
		||||
          if (!settingsProvider.useShizuku) {
 | 
			
		||||
            notificationsProvider?.notify(SilentUpdateAttemptNotification(
 | 
			
		||||
                [apps[id]!.app],
 | 
			
		||||
                id: id.hashCode));
 | 
			
		||||
          } else {
 | 
			
		||||
            notificationsProvider?.notify(SilentUpdateNotification(
 | 
			
		||||
                [apps[id]!.app], sayInstalled,
 | 
			
		||||
                id: id.hashCode));
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (sayInstalled) {
 | 
			
		||||
          installedIds.add(id);
 | 
			
		||||
        }
 | 
			
		||||
      } finally {
 | 
			
		||||
        apps[id]?.downloadProgress = null;
 | 
			
		||||
        notifyListeners();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Future<Map<Object?, Object?>> downloadFn(String id,
 | 
			
		||||
        {bool skipInstalls = false}) async {
 | 
			
		||||
      bool willBeSilent = false;
 | 
			
		||||
      DownloadedApk? downloadedFile;
 | 
			
		||||
      DownloadedXApkDir? downloadedDir;
 | 
			
		||||
      try {
 | 
			
		||||
        var downloadedArtifact =
 | 
			
		||||
            // ignore: use_build_context_synchronously
 | 
			
		||||
            await downloadApp(apps[id]!.app, context,
 | 
			
		||||
                notificationsProvider: notificationsProvider);
 | 
			
		||||
        DownloadedApk? downloadedFile;
 | 
			
		||||
        DownloadedXApkDir? downloadedDir;
 | 
			
		||||
                notificationsProvider: notificationsProvider,
 | 
			
		||||
                useExisting: useExisting);
 | 
			
		||||
        if (downloadedArtifact is DownloadedApk) {
 | 
			
		||||
          downloadedFile = downloadedArtifact;
 | 
			
		||||
        } else {
 | 
			
		||||
          downloadedDir = downloadedArtifact as DownloadedXApkDir;
 | 
			
		||||
        }
 | 
			
		||||
        id = downloadedFile?.appId ?? downloadedDir!.appId;
 | 
			
		||||
        bool willBeSilent = await canInstallSilently(apps[id]!.app);
 | 
			
		||||
        willBeSilent = await canInstallSilently(apps[id]!.app);
 | 
			
		||||
        if (!settingsProvider.useShizuku) {
 | 
			
		||||
          if (!(await settingsProvider.getInstallPermission(enforce: false))) {
 | 
			
		||||
            throw ObtainiumError(tr('cancelled'));
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          switch((await ShizukuApkInstaller.checkPermission())!){
 | 
			
		||||
          switch ((await ShizukuApkInstaller.checkPermission())!) {
 | 
			
		||||
            case 'binder_not_found':
 | 
			
		||||
              throw ObtainiumError(tr('shizukuBinderNotFound'));
 | 
			
		||||
            case 'old_shizuku':
 | 
			
		||||
@@ -839,69 +912,37 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
              throw ObtainiumError(tr('cancelled'));
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (!willBeSilent && context != null) {
 | 
			
		||||
        if (!willBeSilent && context != null && !settingsProvider.useShizuku) {
 | 
			
		||||
          // ignore: use_build_context_synchronously
 | 
			
		||||
          await waitForUserToReturnToForeground(context);
 | 
			
		||||
        }
 | 
			
		||||
        apps[id]?.downloadProgress = -1;
 | 
			
		||||
        notifyListeners();
 | 
			
		||||
        try {
 | 
			
		||||
          if (!skipInstalls) {
 | 
			
		||||
            bool sayInstalled = true;
 | 
			
		||||
            var contextIfNewInstall =
 | 
			
		||||
                apps[id]?.installedInfo == null ? context : null;
 | 
			
		||||
            bool needBGWorkaround = willBeSilent && context == null && !settingsProvider.useShizuku;
 | 
			
		||||
            if (downloadedFile != null) {
 | 
			
		||||
              if (needBGWorkaround) {
 | 
			
		||||
                // ignore: use_build_context_synchronously
 | 
			
		||||
                installApk(downloadedFile, contextIfNewInstall, needsBGWorkaround: true);
 | 
			
		||||
              } else {
 | 
			
		||||
                // ignore: use_build_context_synchronously
 | 
			
		||||
                sayInstalled = await installApk(downloadedFile, contextIfNewInstall, shizukuPretendToBeGooglePlay: apps[id]!.app.additionalSettings['shizukuPretendToBeGooglePlay'] == true);
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
              if (needBGWorkaround) {
 | 
			
		||||
                // ignore: use_build_context_synchronously
 | 
			
		||||
                installXApkDir(downloadedDir!, contextIfNewInstall, needsBGWorkaround: true);
 | 
			
		||||
              } else {
 | 
			
		||||
                // ignore: use_build_context_synchronously
 | 
			
		||||
                sayInstalled = await installXApkDir(downloadedDir!, contextIfNewInstall, shizukuPretendToBeGooglePlay: apps[id]!.app.additionalSettings['shizukuPretendToBeGooglePlay'] == true);
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            if (willBeSilent && context == null) {
 | 
			
		||||
              if (!settingsProvider.useShizuku) {
 | 
			
		||||
                notificationsProvider?.notify(SilentUpdateAttemptNotification(
 | 
			
		||||
                    [apps[id]!.app], id: id.hashCode));
 | 
			
		||||
              } else {
 | 
			
		||||
                notificationsProvider?.notify(SilentUpdateNotification(
 | 
			
		||||
                    [apps[id]!.app], sayInstalled, id: id.hashCode));
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            if (sayInstalled) {
 | 
			
		||||
              installedIds.add(id);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        } finally {
 | 
			
		||||
          apps[id]?.downloadProgress = null;
 | 
			
		||||
          notifyListeners();
 | 
			
		||||
        }
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        errors.add(id, e, appName: apps[id]?.name);
 | 
			
		||||
      }
 | 
			
		||||
      return id;
 | 
			
		||||
      return {
 | 
			
		||||
        'id': id,
 | 
			
		||||
        'willBeSilent': willBeSilent,
 | 
			
		||||
        'downloadedFile': downloadedFile,
 | 
			
		||||
        'downloadedDir': downloadedDir
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    List<Map<Object?, Object?>> downloadResults = [];
 | 
			
		||||
    if (forceParallelDownloads || !settingsProvider.parallelDownloads) {
 | 
			
		||||
      for (var id in appsToInstall) {
 | 
			
		||||
        await updateFn(id);
 | 
			
		||||
        downloadResults.add(await downloadFn(id));
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      List<String> ids = await Future.wait(
 | 
			
		||||
          appsToInstall.map((id) => updateFn(id, skipInstalls: true)));
 | 
			
		||||
      for (var id in ids) {
 | 
			
		||||
        if (!errors.appIdNames.containsKey(id)) {
 | 
			
		||||
          await updateFn(id);
 | 
			
		||||
        }
 | 
			
		||||
      downloadResults = await Future.wait(
 | 
			
		||||
          appsToInstall.map((id) => downloadFn(id, skipInstalls: true)));
 | 
			
		||||
    }
 | 
			
		||||
    for (var res in downloadResults) {
 | 
			
		||||
      if (!errors.appIdNames.containsKey(res['id'])) {
 | 
			
		||||
        await installFn(
 | 
			
		||||
            res['id'] as String,
 | 
			
		||||
            res['willBeSilent'] as bool,
 | 
			
		||||
            res['downloadedFile'] as DownloadedApk?,
 | 
			
		||||
            res['downloadedDir'] as DownloadedXApkDir?);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -950,15 +991,8 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
        if (!downloadsAccessible && exportDir != null) {
 | 
			
		||||
          downloadPath = exportDir.path;
 | 
			
		||||
        }
 | 
			
		||||
        await downloadFile(
 | 
			
		||||
            fileUrl.value,
 | 
			
		||||
            fileUrl.key
 | 
			
		||||
                .split('.')
 | 
			
		||||
                .reversed
 | 
			
		||||
                .toList()
 | 
			
		||||
                .sublist(1)
 | 
			
		||||
                .reversed
 | 
			
		||||
                .join('.'), (double? progress) {
 | 
			
		||||
        await downloadFile(fileUrl.value, fileUrl.key, true,
 | 
			
		||||
            (double? progress) {
 | 
			
		||||
          notificationsProvider
 | 
			
		||||
              .notify(DownloadNotification(fileUrl.key, progress?.ceil() ?? 0));
 | 
			
		||||
        }, downloadPath,
 | 
			
		||||
@@ -1145,40 +1179,38 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
    var sp = SourceProvider();
 | 
			
		||||
    List<List<String>> errors = [];
 | 
			
		||||
    List<App?> newApps = (await getAppsDir()) // Parse Apps from JSON
 | 
			
		||||
    await Future.wait((await getAppsDir()) // Parse Apps from JSON
 | 
			
		||||
        .listSync()
 | 
			
		||||
        .where((item) => item.path.toLowerCase().endsWith('.json'))
 | 
			
		||||
        .where((item) =>
 | 
			
		||||
            singleId == null ||
 | 
			
		||||
            item.path.split('/').last.toLowerCase() ==
 | 
			
		||||
                '${singleId.toLowerCase()}.json')
 | 
			
		||||
        .map((e) {
 | 
			
		||||
      try {
 | 
			
		||||
        return App.fromJson(jsonDecode(File(e.path).readAsStringSync()));
 | 
			
		||||
      } catch (err) {
 | 
			
		||||
        if (err is FormatException) {
 | 
			
		||||
          logs.add('Corrupt JSON when loading App (will be ignored): $e');
 | 
			
		||||
          e.renameSync('${e.path}.corrupt');
 | 
			
		||||
        } else {
 | 
			
		||||
          rethrow;
 | 
			
		||||
        .map((item) async {
 | 
			
		||||
      App? app;
 | 
			
		||||
      if (item.path.toLowerCase().endsWith('.json') &&
 | 
			
		||||
          (singleId == null ||
 | 
			
		||||
              item.path.split('/').last.toLowerCase() ==
 | 
			
		||||
                  '${singleId.toLowerCase()}.json')) {
 | 
			
		||||
        try {
 | 
			
		||||
          app = App.fromJson(jsonDecode(File(item.path).readAsStringSync()));
 | 
			
		||||
        } catch (err) {
 | 
			
		||||
          if (err is FormatException) {
 | 
			
		||||
            logs.add('Corrupt JSON when loading App (will be ignored): $e');
 | 
			
		||||
            item.renameSync('${item.path}.corrupt');
 | 
			
		||||
          } else {
 | 
			
		||||
            rethrow;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }).toList();
 | 
			
		||||
    for (var app in newApps) {
 | 
			
		||||
      // Put Apps into memory to list them (fast)
 | 
			
		||||
      if (app != null) {
 | 
			
		||||
        try {
 | 
			
		||||
          sp.getSource(app.url, overrideSource: app.overrideSource);
 | 
			
		||||
          apps.update(
 | 
			
		||||
              app.id,
 | 
			
		||||
              (value) => AppInMemory(
 | 
			
		||||
                  app, value.downloadProgress, value.installedInfo, value.icon),
 | 
			
		||||
              ifAbsent: () => AppInMemory(app, null, null, null));
 | 
			
		||||
              (value) => AppInMemory(app!, value.downloadProgress,
 | 
			
		||||
                  value.installedInfo, value.icon),
 | 
			
		||||
              ifAbsent: () => AppInMemory(app!, null, null, null));
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          errors.add([app.id, app.finalName, e.toString()]);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    }));
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
    if (errors.isNotEmpty) {
 | 
			
		||||
      removeApps(errors.map((e) => e[0]).toList());
 | 
			
		||||
@@ -1186,19 +1218,17 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
          AppsRemovedNotification(errors.map((e) => [e[1], e[2]]).toList()));
 | 
			
		||||
    }
 | 
			
		||||
    // Get install status and other OS info for each App (slow)
 | 
			
		||||
    await Future.wait(apps.values.map((app) {
 | 
			
		||||
      return updateInstallStatusInMemory(app);
 | 
			
		||||
    }));
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
    // Reconcile version differences
 | 
			
		||||
    List<App> modifiedApps = [];
 | 
			
		||||
    for (var app in apps.values) {
 | 
			
		||||
    await Future.wait(apps.values.map((app) async {
 | 
			
		||||
      await updateInstallStatusInMemory(app);
 | 
			
		||||
      var moddedApp =
 | 
			
		||||
          getCorrectedInstallStatusAppIfPossible(app.app, app.installedInfo);
 | 
			
		||||
      if (moddedApp != null) {
 | 
			
		||||
        modifiedApps.add(moddedApp);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    }));
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
    // Reconcile version differences
 | 
			
		||||
    if (modifiedApps.isNotEmpty) {
 | 
			
		||||
      await saveApps(modifiedApps, attemptToCorrectInstallStatus: false);
 | 
			
		||||
      var removedAppIds = modifiedApps
 | 
			
		||||
@@ -1220,7 +1250,7 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
      {bool attemptToCorrectInstallStatus = true,
 | 
			
		||||
      bool onlyIfExists = true}) async {
 | 
			
		||||
    attemptToCorrectInstallStatus = attemptToCorrectInstallStatus;
 | 
			
		||||
    for (var a in apps) {
 | 
			
		||||
    await Future.wait(apps.map((a) async {
 | 
			
		||||
      var app = a.deepCopy();
 | 
			
		||||
      PackageInfo? info = await getInstalledInfo(app.id);
 | 
			
		||||
      var icon = await info?.applicationInfo?.getAppIcon();
 | 
			
		||||
@@ -1242,14 +1272,14 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
          rethrow;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    }));
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
    export(isAuto: true);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<void> removeApps(List<String> appIds) async {
 | 
			
		||||
    var apkFiles = APKDir.listSync();
 | 
			
		||||
    for (var appId in appIds) {
 | 
			
		||||
    await Future.wait(appIds.map((appId) async {
 | 
			
		||||
      File file = File('${(await getAppsDir()).path}/$appId.json');
 | 
			
		||||
      if (file.existsSync()) {
 | 
			
		||||
        file.deleteSync(recursive: true);
 | 
			
		||||
@@ -1263,7 +1293,7 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
      if (apps.containsKey(appId)) {
 | 
			
		||||
        apps.remove(appId);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    }));
 | 
			
		||||
    if (appIds.isNotEmpty) {
 | 
			
		||||
      notifyListeners();
 | 
			
		||||
      export(isAuto: true);
 | 
			
		||||
@@ -1498,7 +1528,7 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
    return returnPath;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Future<MapEntry<int, bool>> import(String appsJSON) async {
 | 
			
		||||
  Future<MapEntry<List<App>, bool>> import(String appsJSON) async {
 | 
			
		||||
    var decodedJSON = jsonDecode(appsJSON);
 | 
			
		||||
    var newFormat = decodedJSON is! List;
 | 
			
		||||
    List<App> importedApps =
 | 
			
		||||
@@ -1522,6 +1552,8 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
      settingsMap.forEach((key, value) {
 | 
			
		||||
        if (value is int) {
 | 
			
		||||
          settingsProvider.prefs?.setInt(key, value);
 | 
			
		||||
        } else if (value is double) {
 | 
			
		||||
          settingsProvider.prefs?.setDouble(key, value);
 | 
			
		||||
        } else if (value is bool) {
 | 
			
		||||
          settingsProvider.prefs?.setBool(key, value);
 | 
			
		||||
        } else if (value is List) {
 | 
			
		||||
@@ -1532,8 +1564,8 @@ class AppsProvider with ChangeNotifier {
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    return MapEntry<int, bool>(
 | 
			
		||||
        importedApps.length, newFormat && decodedJSON['settings'] != null);
 | 
			
		||||
    return MapEntry<List<App>, bool>(
 | 
			
		||||
        importedApps, newFormat && decodedJSON['settings'] != null);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
@@ -1909,7 +1941,8 @@ Future<void> bgUpdateCheck(String taskId, Map<String, dynamic>? params) async {
 | 
			
		||||
        await appsProvider.downloadAndInstallLatestApps(
 | 
			
		||||
            toInstall.map((e) => e.key).toList(), null,
 | 
			
		||||
            notificationsProvider: notificationsProvider,
 | 
			
		||||
            forceParallelDownloads: true);
 | 
			
		||||
            forceParallelDownloads: true,
 | 
			
		||||
            useExisting: false);
 | 
			
		||||
      } catch (e) {
 | 
			
		||||
        if (e is MultiAppMultiError) {
 | 
			
		||||
          e.idsByErrorString.forEach((key, value) {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ String obtainiumId = 'dev.imranr.obtainium';
 | 
			
		||||
String obtainiumUrl = 'https://github.com/ImranR98/Obtainium';
 | 
			
		||||
Color obtainiumThemeColor = const Color(0xFF6438B5);
 | 
			
		||||
 | 
			
		||||
enum ThemeSettings { light, dark, system }
 | 
			
		||||
enum ThemeSettings { system, light, dark }
 | 
			
		||||
 | 
			
		||||
enum SortColumnSettings { added, nameAuthor, authorName, releaseDate }
 | 
			
		||||
 | 
			
		||||
@@ -59,7 +59,7 @@ class SettingsProvider with ChangeNotifier {
 | 
			
		||||
 | 
			
		||||
  ThemeSettings get theme {
 | 
			
		||||
    return ThemeSettings
 | 
			
		||||
        .values[prefs?.getInt('theme') ?? ThemeSettings.light.index];
 | 
			
		||||
        .values[prefs?.getInt('theme') ?? ThemeSettings.system.index];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  set theme(ThemeSettings t) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										158
									
								
								pubspec.lock
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								pubspec.lock
									
									
									
									
									
								
							@@ -47,18 +47,18 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: app_links
 | 
			
		||||
      sha256: "42dc15aecf2618ace4ffb74a2e58a50e45cd1b9f2c17c8f0cafe4c297f08c815"
 | 
			
		||||
      sha256: "8c6ef5ba9e26b720d4c9073826befb87df2ab5e7a81c22b6c3145080b5e736c9"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "4.0.1"
 | 
			
		||||
    version: "6.0.2"
 | 
			
		||||
  archive:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: archive
 | 
			
		||||
      sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
 | 
			
		||||
      sha256: ecf4273855368121b1caed0d10d4513c7241dfc813f7d3c8933b36622ae9b265
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.4.10"
 | 
			
		||||
    version: "3.5.1"
 | 
			
		||||
  args:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -79,10 +79,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: background_fetch
 | 
			
		||||
      sha256: dbffec0317ccdef6e2014cb543e147f52441e29c4fcb53dfd23558c4d92ddece
 | 
			
		||||
      sha256: "2fe367c9be0e256dadb75b8b637b0b58a2a2d2317b7c8420bb1ae8b41e23fde3"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.3.2"
 | 
			
		||||
    version: "1.3.4"
 | 
			
		||||
  boolean_selector:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -135,10 +135,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: connectivity_plus
 | 
			
		||||
      sha256: ebe15d94de9dd7c31dc2ac54e42780acdf3384b1497c69290c9f3c5b0279fc57
 | 
			
		||||
      sha256: db7a4e143dc72cc3cb2044ef9b052a7ebfe729513e6a82943bc3526f784365b8
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.0.2"
 | 
			
		||||
    version: "6.0.3"
 | 
			
		||||
  connectivity_plus_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -147,14 +147,6 @@ packages:
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.0"
 | 
			
		||||
  convert:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: convert
 | 
			
		||||
      sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.1.1"
 | 
			
		||||
  cross_file:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -223,10 +215,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: easy_localization
 | 
			
		||||
      sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c
 | 
			
		||||
      sha256: fa59bcdbbb911a764aa6acf96bbb6fa7a5cf8234354fc45ec1a43a0349ef0201
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.0.5"
 | 
			
		||||
    version: "3.0.7"
 | 
			
		||||
  easy_logger:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -271,10 +263,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: file_picker
 | 
			
		||||
      sha256: b6283d7387310ad83bc4f3bc245b75d223a032ae6eba275afcd585de2b9a1476
 | 
			
		||||
      sha256: "29c90806ac5f5fb896547720b73b17ee9aed9bba540dc5d91fe29f8c5745b10a"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "8.0.1"
 | 
			
		||||
    version: "8.0.3"
 | 
			
		||||
  fixnum:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -287,18 +279,18 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: flex_color_picker
 | 
			
		||||
      sha256: "5c846437069fb7afdd7ade6bf37e628a71d2ab0787095ddcb1253bf9345d5f3a"
 | 
			
		||||
      sha256: "31b27677d8d8400e4cff5edb3f189f606dd964d608779b6ae1b7ddad37ea48c6"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.4.1"
 | 
			
		||||
    version: "3.5.0"
 | 
			
		||||
  flex_seed_scheme:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flex_seed_scheme
 | 
			
		||||
      sha256: "4cee2f1d07259f77e8b36f4ec5f35499d19e74e17c7dce5b819554914082bc01"
 | 
			
		||||
      sha256: fb66cdb8ca89084e79efcad2bc2d9deb144666875116f08cdd8d9f8238c8b3ab
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.5.0"
 | 
			
		||||
    version: "2.0.0"
 | 
			
		||||
  flutter:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description: flutter
 | 
			
		||||
@@ -332,18 +324,18 @@ packages:
 | 
			
		||||
    dependency: "direct dev"
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_lints
 | 
			
		||||
      sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
 | 
			
		||||
      sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.0.2"
 | 
			
		||||
    version: "4.0.0"
 | 
			
		||||
  flutter_local_notifications:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_local_notifications
 | 
			
		||||
      sha256: a701df4866f9a38bb8e4450a54c143bbeeb0ce2381e7df5a36e1006f3b43bb28
 | 
			
		||||
      sha256: "40e6fbd2da7dcc7ed78432c5cdab1559674b4af035fddbfb2f9a8f9c2112fcef"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "17.0.1"
 | 
			
		||||
    version: "17.1.2"
 | 
			
		||||
  flutter_local_notifications_linux:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -356,10 +348,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: flutter_local_notifications_platform_interface
 | 
			
		||||
      sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef"
 | 
			
		||||
      sha256: "340abf67df238f7f0ef58f4a26d2a83e1ab74c77ab03cd2b2d5018ac64db30b7"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "7.0.0+1"
 | 
			
		||||
    version: "7.1.0"
 | 
			
		||||
  flutter_localizations:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description: flutter
 | 
			
		||||
@@ -459,60 +451,52 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: intl
 | 
			
		||||
      sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
 | 
			
		||||
      sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.18.1"
 | 
			
		||||
  js:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: js
 | 
			
		||||
      sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.7.1"
 | 
			
		||||
    version: "0.19.0"
 | 
			
		||||
  json_annotation:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: json_annotation
 | 
			
		||||
      sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
 | 
			
		||||
      sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "4.8.1"
 | 
			
		||||
    version: "4.9.0"
 | 
			
		||||
  leak_tracker:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: leak_tracker
 | 
			
		||||
      sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
 | 
			
		||||
      sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "10.0.0"
 | 
			
		||||
    version: "10.0.4"
 | 
			
		||||
  leak_tracker_flutter_testing:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: leak_tracker_flutter_testing
 | 
			
		||||
      sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
 | 
			
		||||
      sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.1"
 | 
			
		||||
    version: "3.0.3"
 | 
			
		||||
  leak_tracker_testing:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: leak_tracker_testing
 | 
			
		||||
      sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
 | 
			
		||||
      sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.0.1"
 | 
			
		||||
    version: "3.0.1"
 | 
			
		||||
  lints:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: lints
 | 
			
		||||
      sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
 | 
			
		||||
      sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.0.0"
 | 
			
		||||
    version: "4.0.0"
 | 
			
		||||
  markdown:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: markdown
 | 
			
		||||
      sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051
 | 
			
		||||
@@ -539,10 +523,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: meta
 | 
			
		||||
      sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
 | 
			
		||||
      sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "1.11.0"
 | 
			
		||||
    version: "1.12.0"
 | 
			
		||||
  mime:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -595,10 +579,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: path_provider_foundation
 | 
			
		||||
      sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
 | 
			
		||||
      sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.3.2"
 | 
			
		||||
    version: "2.4.0"
 | 
			
		||||
  path_provider_linux:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -635,10 +619,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: permission_handler_android
 | 
			
		||||
      sha256: "1acac6bae58144b442f11e66621c062aead9c99841093c38f5bcdcc24c1c3474"
 | 
			
		||||
      sha256: "8bb852cd759488893805c3161d0b2b5db55db52f773dbb014420b304055ba2c5"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "12.0.5"
 | 
			
		||||
    version: "12.0.6"
 | 
			
		||||
  permission_handler_apple:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -695,14 +679,6 @@ packages:
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.1.8"
 | 
			
		||||
  pointycastle:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: pointycastle
 | 
			
		||||
      sha256: "79fbafed02cfdbe85ef3fd06c7f4bc2cbcba0177e61b765264853d4253b21744"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.9.0"
 | 
			
		||||
  provider:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
@@ -715,18 +691,18 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: share_plus
 | 
			
		||||
      sha256: fb5319f3aab4c5dda5ebb92dca978179ba21f8c783ee4380910ef4c1c6824f51
 | 
			
		||||
      sha256: ef3489a969683c4f3d0239010cc8b7a2a46543a8d139e111c06c558875083544
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "8.0.3"
 | 
			
		||||
    version: "9.0.0"
 | 
			
		||||
  share_plus_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: share_plus_platform_interface
 | 
			
		||||
      sha256: "251eb156a8b5fa9ce033747d73535bf53911071f8d3b6f4f0b578505ce0d4496"
 | 
			
		||||
      sha256: "0f9e4418835d1b2c3ae78fdb918251959106cefdbc4dd43526e182f80e82f6d4"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.4.0"
 | 
			
		||||
    version: "4.0.0"
 | 
			
		||||
  shared_preferences:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
@@ -747,10 +723,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: shared_preferences_foundation
 | 
			
		||||
      sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
 | 
			
		||||
      sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.3.5"
 | 
			
		||||
    version: "2.4.0"
 | 
			
		||||
  shared_preferences_linux:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -825,10 +801,10 @@ packages:
 | 
			
		||||
    dependency: "direct main"
 | 
			
		||||
    description:
 | 
			
		||||
      name: sqflite
 | 
			
		||||
      sha256: "5ce2e1a15e822c3b4bfb5400455775e421da7098eed8adc8f26298ada7c9308c"
 | 
			
		||||
      sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "2.3.3"
 | 
			
		||||
    version: "2.3.3+1"
 | 
			
		||||
  sqflite_common:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -881,18 +857,18 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: test_api
 | 
			
		||||
      sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
 | 
			
		||||
      sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.6.1"
 | 
			
		||||
    version: "0.7.0"
 | 
			
		||||
  timezone:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: timezone
 | 
			
		||||
      sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0"
 | 
			
		||||
      sha256: a6ccda4a69a442098b602c44e61a1e2b4bf6f5516e875bbf0f427d5df14745d5
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "0.9.2"
 | 
			
		||||
    version: "0.9.3"
 | 
			
		||||
  typed_data:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -921,10 +897,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: url_launcher_ios
 | 
			
		||||
      sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5"
 | 
			
		||||
      sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "6.2.5"
 | 
			
		||||
    version: "6.3.0"
 | 
			
		||||
  url_launcher_linux:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -937,10 +913,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: url_launcher_macos
 | 
			
		||||
      sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234
 | 
			
		||||
      sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.1.0"
 | 
			
		||||
    version: "3.2.0"
 | 
			
		||||
  url_launcher_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -985,10 +961,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: vm_service
 | 
			
		||||
      sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
 | 
			
		||||
      sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "13.0.0"
 | 
			
		||||
    version: "14.2.1"
 | 
			
		||||
  web:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -1009,10 +985,10 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: webview_flutter_android
 | 
			
		||||
      sha256: f038ee2fae73b509dde1bc9d2c5a50ca92054282de17631a9a3d515883740934
 | 
			
		||||
      sha256: dad3313c9ead95517bb1cae5e1c9d20ba83729d5a59e5e83c0a2d66203f27f91
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.16.0"
 | 
			
		||||
    version: "3.16.1"
 | 
			
		||||
  webview_flutter_platform_interface:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -1025,18 +1001,18 @@ packages:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: webview_flutter_wkwebview
 | 
			
		||||
      sha256: f12f8d8a99784b863e8b85e4a9a5e3cf1839d6803d2c0c3e0533a8f3c5a992a7
 | 
			
		||||
      sha256: "7affdf9d680c015b11587181171d3cad8093e449db1f7d9f0f08f4f33d24f9a0"
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.13.0"
 | 
			
		||||
    version: "3.13.1"
 | 
			
		||||
  win32:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
      name: win32
 | 
			
		||||
      sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a"
 | 
			
		||||
      sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
 | 
			
		||||
      url: "https://pub.dev"
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "5.4.0"
 | 
			
		||||
    version: "5.5.1"
 | 
			
		||||
  win32_registry:
 | 
			
		||||
    dependency: transitive
 | 
			
		||||
    description:
 | 
			
		||||
@@ -1070,5 +1046,5 @@ packages:
 | 
			
		||||
    source: hosted
 | 
			
		||||
    version: "3.1.2"
 | 
			
		||||
sdks:
 | 
			
		||||
  dart: ">=3.3.3 <4.0.0"
 | 
			
		||||
  flutter: ">=3.19.0"
 | 
			
		||||
  dart: ">=3.4.0 <4.0.0"
 | 
			
		||||
  flutter: ">=3.22.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 | 
			
		||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
 | 
			
		||||
# In Windows, build-name is used as the major, minor, and patch parts
 | 
			
		||||
# of the product and file versions while build-number is used as the build suffix.
 | 
			
		||||
version: 1.1.5+2262
 | 
			
		||||
version: 1.1.9+2266
 | 
			
		||||
 | 
			
		||||
environment:
 | 
			
		||||
  sdk: '>=3.0.0 <4.0.0'
 | 
			
		||||
@@ -56,7 +56,7 @@ dependencies:
 | 
			
		||||
      url: https://github.com/ImranR98/android_package_installer
 | 
			
		||||
      ref: main
 | 
			
		||||
  android_package_manager: ^0.7.0
 | 
			
		||||
  share_plus: ^8.0.2
 | 
			
		||||
  share_plus: ^9.0.0
 | 
			
		||||
  sqflite: ^2.2.0+3
 | 
			
		||||
  easy_localization: ^3.0.1
 | 
			
		||||
  android_intent_plus: ^5.0.1
 | 
			
		||||
@@ -66,7 +66,7 @@ dependencies:
 | 
			
		||||
  connectivity_plus: ^6.0.1
 | 
			
		||||
  shared_storage: ^0.8.0
 | 
			
		||||
  crypto: ^3.0.3
 | 
			
		||||
  app_links: ^4.0.0
 | 
			
		||||
  app_links: ^6.0.1
 | 
			
		||||
  background_fetch: ^1.2.1
 | 
			
		||||
  equations: ^5.0.2
 | 
			
		||||
  flex_color_picker: ^3.4.1
 | 
			
		||||
@@ -79,6 +79,7 @@ dependencies:
 | 
			
		||||
      url: https://github.com/re7gog/shizuku_apk_installer
 | 
			
		||||
      ref: master
 | 
			
		||||
 | 
			
		||||
  markdown: any
 | 
			
		||||
dev_dependencies:
 | 
			
		||||
  flutter_test:
 | 
			
		||||
    sdk: flutter
 | 
			
		||||
@@ -89,7 +90,7 @@ dev_dependencies:
 | 
			
		||||
  # activated in the `analysis_options.yaml` file located at the root of your
 | 
			
		||||
  # package. See that file for information about deactivating specific lint
 | 
			
		||||
  # rules and activating additional ones.
 | 
			
		||||
  flutter_lints: ^3.0.0
 | 
			
		||||
  flutter_lints: ^4.0.0
 | 
			
		||||
 | 
			
		||||
flutter_launcher_icons:
 | 
			
		||||
  android: "ic_launcher"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user