Merge branch 'main' into room-entity
This commit is contained in:
commit
22a1b09d2d
@ -6,7 +6,6 @@ insert_final_newline = true
|
|||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
[*.{kt,kts}]
|
[*.{kt,kts}]
|
||||||
ktlint_code_style = android_studio
|
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
ij_kotlin_allow_trailing_comma=true
|
ij_kotlin_allow_trailing_comma=true
|
||||||
ij_kotlin_allow_trailing_comma_on_call_site=true
|
ij_kotlin_allow_trailing_comma_on_call_site=true
|
||||||
|
77
.github/workflows/build_debug.yml
vendored
77
.github/workflows/build_debug.yml
vendored
@ -27,51 +27,48 @@ jobs:
|
|||||||
packages: write
|
packages: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repository
|
- name: Check out repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Validate Gradle Wrapper
|
- name: Validate Gradle Wrapper
|
||||||
uses: gradle/actions/setup-gradle@v4
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/wrapper-validation-action@v3
|
uses: gradle/wrapper-validation-action@v3
|
||||||
|
|
||||||
- name: Set up Java 17
|
- name: Set up Java 17
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: 17
|
java-version: 17
|
||||||
distribution: 'adopt'
|
distribution: 'adopt'
|
||||||
cache: gradle
|
cache: gradle
|
||||||
|
|
||||||
- name: Grant execution permission to Gradle Wrapper
|
- name: Grant execution permission to Gradle Wrapper
|
||||||
run: chmod +x gradlew
|
run: chmod +x gradlew
|
||||||
|
|
||||||
- name: Format Code
|
- name: Build Debug APK
|
||||||
run: ./gradlew ktlintFormat
|
run: ./gradlew assembleDebug
|
||||||
|
|
||||||
- name: Build Debug APK
|
- name: Sign Apk
|
||||||
run: ./gradlew assembleDebug
|
continue-on-error: true
|
||||||
|
id: sign_apk
|
||||||
|
uses: r0adkll/sign-android-release@v1
|
||||||
|
with:
|
||||||
|
releaseDir: app/build/outputs/apk/debug
|
||||||
|
signingKeyBase64: ${{ secrets.KEY_BASE64 }}
|
||||||
|
alias: ${{ secrets.KEY_ALIAS }}
|
||||||
|
keyStorePassword: ${{ secrets.KEYSTORE_PASS }}
|
||||||
|
keyPassword: ${{ secrets.KEYSTORE_PASS }}
|
||||||
|
|
||||||
- name: Sign Apk
|
- name: Remove file that aren't signed
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
id: sign_apk
|
run: |
|
||||||
uses: r0adkll/sign-android-release@v1
|
ls | grep 'signed\.apk$' && find . -type f -name '*.apk' ! -name '*-signed.apk' -delete
|
||||||
with:
|
|
||||||
releaseDir: app/build/outputs/apk/debug
|
|
||||||
signingKeyBase64: ${{ secrets.KEY_BASE64 }}
|
|
||||||
alias: ${{ secrets.KEY_ALIAS }}
|
|
||||||
keyStorePassword: ${{ secrets.KEYSTORE_PASS }}
|
|
||||||
keyPassword: ${{ secrets.KEYSTORE_PASS }}
|
|
||||||
|
|
||||||
- name: Remove file that aren't signed
|
- name: Upload the APK
|
||||||
continue-on-error: true
|
uses: actions/upload-artifact@v4
|
||||||
run: |
|
with:
|
||||||
ls | grep 'signed\.apk$' && find . -type f -name '*.apk' ! -name '*-signed.apk' -delete
|
name: debug
|
||||||
|
path: app/build/outputs/apk/debug/app-debug*.apk
|
||||||
- name: Upload the APK
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: debug
|
|
||||||
path: app/build/outputs/apk/debug/app-debug*.apk
|
|
||||||
|
24
.github/workflows/release_build.yml
vendored
24
.github/workflows/release_build.yml
vendored
@ -56,12 +56,34 @@ jobs:
|
|||||||
keyStorePassword: ${{ secrets.KEYSTORE_PASS }}
|
keyStorePassword: ${{ secrets.KEYSTORE_PASS }}
|
||||||
keyPassword: ${{ secrets.KEYSTORE_PASS }}
|
keyPassword: ${{ secrets.KEYSTORE_PASS }}
|
||||||
env:
|
env:
|
||||||
BUILD_TOOLS_VERSION: "34.0.0"
|
BUILD_TOOLS_VERSION: "35.0.0"
|
||||||
|
|
||||||
|
- name: Extract Version Code
|
||||||
|
id: extract_version
|
||||||
|
run: |
|
||||||
|
VERSION_CODE=$(grep -oP '(?<=versionCode=)\d+' app/build.gradle.kts) # Adjust path to your build.gradle
|
||||||
|
echo "::set-output name=version_code::$VERSION_CODE"
|
||||||
|
echo "Version Code: $VERSION_CODE"
|
||||||
|
|
||||||
|
- name: Read Changelog
|
||||||
|
id: read_changelog
|
||||||
|
run: |
|
||||||
|
CHANGELOG_PATH="metadata/en-US/changelogs/${{ steps.extract_version.outputs.version_code }}.txt"
|
||||||
|
if [[ -f "$CHANGELOG_PATH" ]]; then
|
||||||
|
CHANGELOG=$(cat "$CHANGELOG_PATH")
|
||||||
|
echo "::set-output name=changelog::$CHANGELOG"
|
||||||
|
else
|
||||||
|
echo "::set-output name=changelog::No changelog found for this version."
|
||||||
|
echo "No changelog found at: $CHANGELOG_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
- uses: softprops/action-gh-release@v2
|
- uses: softprops/action-gh-release@v2
|
||||||
name: Create Release
|
name: Create Release
|
||||||
id: publish_release
|
id: publish_release
|
||||||
with:
|
with:
|
||||||
|
body: ${{ steps.read_changelog.outputs.changelog }}
|
||||||
|
tag_name: ${{ github.ref }}
|
||||||
|
name: Release ${{ github.ref }}
|
||||||
files: ${{steps.sign_app.outputs.signedReleaseFile}}
|
files: ${{steps.sign_app.outputs.signedReleaseFile}}
|
||||||
draft: true
|
draft: true
|
||||||
prerelease: false
|
prerelease: false
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
[](https://github.com/Iamlooker/Droid-ify/releases/)
|
[](https://github.com/Iamlooker/Droid-ify/releases/)
|
||||||
[](https://github.com/Iamlooker/Droid-ify/releases/latest)
|
[](https://github.com/Iamlooker/Droid-ify/releases/latest)
|
||||||
[](https://f-droid.org/packages/com.looker.droidify)
|
[](https://f-droid.org/packages/com.looker.droidify)
|
||||||
|
</div>
|
||||||
<div align="left">
|
<div align="left">
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
@ -22,8 +22,10 @@
|
|||||||
<img src="metadata/en-US/images/phoneScreenshots/1.png" width="25%" /><img src="metadata/en-US/images/phoneScreenshots/2.png" width="25%" /><img src="metadata/en-US/images/phoneScreenshots/3.png" width="25%" /><img src="metadata/en-US/images/phoneScreenshots/4.png" width="25%" />
|
<img src="metadata/en-US/images/phoneScreenshots/1.png" width="25%" /><img src="metadata/en-US/images/phoneScreenshots/2.png" width="25%" /><img src="metadata/en-US/images/phoneScreenshots/3.png" width="25%" /><img src="metadata/en-US/images/phoneScreenshots/4.png" width="25%" />
|
||||||
|
|
||||||
## Building and Installing
|
## Building and Installing
|
||||||
|
|
||||||
1. **Install Android Studio**:
|
1. **Install Android Studio**:
|
||||||
- Download and install [Android Studio](https://developer.android.com/studio) on your computer if you haven't already.
|
- Download and install [Android Studio](https://developer.android.com/studio) on your computer
|
||||||
|
if you haven't already.
|
||||||
|
|
||||||
2. **Clone the Repository**:
|
2. **Clone the Repository**:
|
||||||
- Open Android Studio and select "Project from Version Control."
|
- Open Android Studio and select "Project from Version Control."
|
||||||
@ -48,6 +50,7 @@
|
|||||||
- Your PR will undergo review
|
- Your PR will undergo review
|
||||||
|
|
||||||
## Translations
|
## Translations
|
||||||
|
|
||||||
[](https://hosted.weblate.org/engage/droidify/?utm_source=widget)
|
[](https://hosted.weblate.org/engage/droidify/?utm_source=widget)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
@ -67,3 +70,5 @@ GNU General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@ -10,7 +10,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
val latestVersionName = "0.6.4"
|
val latestVersionName = "0.6.5"
|
||||||
namespace = "com.looker.droidify"
|
namespace = "com.looker.droidify"
|
||||||
buildToolsVersion = "35.0.0"
|
buildToolsVersion = "35.0.0"
|
||||||
compileSdk = 35
|
compileSdk = 35
|
||||||
@ -18,7 +18,7 @@ android {
|
|||||||
minSdk = 23
|
minSdk = 23
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
applicationId = "com.looker.droidify"
|
applicationId = "com.looker.droidify"
|
||||||
versionCode = 640
|
versionCode = 650
|
||||||
versionName = latestVersionName
|
versionName = latestVersionName
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
testInstrumentationRunner = "com.looker.droidify.TestRunner"
|
testInstrumentationRunner = "com.looker.droidify.TestRunner"
|
||||||
@ -32,7 +32,12 @@ android {
|
|||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "17"
|
jvmTarget = "17"
|
||||||
freeCompilerArgs = listOf("-Xcontext-receivers")
|
freeCompilerArgs = listOf(
|
||||||
|
"-opt-in=kotlin.RequiresOptIn",
|
||||||
|
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||||
|
"-opt-in=kotlinx.coroutines.FlowPreview",
|
||||||
|
"-Xcontext-receivers"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ksp {
|
ksp {
|
||||||
@ -45,11 +50,11 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
getByName("debug") {
|
debug {
|
||||||
applicationIdSuffix = ".debug"
|
applicationIdSuffix = ".debug"
|
||||||
resValue("string", "application_name", "Droid-ify-Debug")
|
resValue("string", "application_name", "Droid-ify-Debug")
|
||||||
}
|
}
|
||||||
getByName("release") {
|
release {
|
||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
isShrinkResources = true
|
isShrinkResources = true
|
||||||
resValue("string", "application_name", "Droid-ify")
|
resValue("string", "application_name", "Droid-ify")
|
||||||
@ -79,7 +84,16 @@ android {
|
|||||||
}
|
}
|
||||||
packaging {
|
packaging {
|
||||||
resources {
|
resources {
|
||||||
excludes += listOf("/DebugProbesKt.bin")
|
excludes += listOf(
|
||||||
|
"/DebugProbesKt.bin",
|
||||||
|
"/kotlin/**.kotlin_builtins",
|
||||||
|
"/kotlin/**.kotlin_metadata",
|
||||||
|
"/META-INF/**.kotlin_module",
|
||||||
|
"/META-INF/**.pro",
|
||||||
|
"/META-INF/**.version",
|
||||||
|
"/META-INF/{AL2.0,LGPL2.1,LICENSE*}",
|
||||||
|
"/META-INF/versions/9/previous-**.bin",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
@ -87,6 +101,10 @@ android {
|
|||||||
viewBinding = true
|
viewBinding = true
|
||||||
buildConfig = true
|
buildConfig = true
|
||||||
}
|
}
|
||||||
|
dependenciesInfo {
|
||||||
|
includeInApk = false
|
||||||
|
includeInBundle = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -102,7 +120,7 @@ dependencies {
|
|||||||
implementation(libs.sqlite.ktx)
|
implementation(libs.sqlite.ktx)
|
||||||
|
|
||||||
implementation(libs.image.viewer)
|
implementation(libs.image.viewer)
|
||||||
implementation(libs.coil.kt)
|
implementation(libs.bundles.coil)
|
||||||
|
|
||||||
implementation(libs.datastore.core)
|
implementation(libs.datastore.core)
|
||||||
implementation(libs.datastore.proto)
|
implementation(libs.datastore.proto)
|
||||||
|
65
app/proguard.pro
vendored
65
app/proguard.pro
vendored
@ -7,68 +7,3 @@
|
|||||||
-dontwarn kotlinx.serialization.KSerializer
|
-dontwarn kotlinx.serialization.KSerializer
|
||||||
-dontwarn kotlinx.serialization.Serializable
|
-dontwarn kotlinx.serialization.Serializable
|
||||||
-dontwarn org.slf4j.impl.StaticLoggerBinder
|
-dontwarn org.slf4j.impl.StaticLoggerBinder
|
||||||
#
|
|
||||||
#-dontwarn com.looker.core.common.BuildConfig
|
|
||||||
#-dontwarn com.looker.core.common.DeeplinkType$AddRepository
|
|
||||||
#-dontwarn com.looker.core.common.DeeplinkType$AppDetail
|
|
||||||
#-dontwarn com.looker.core.common.DeeplinkType
|
|
||||||
#-dontwarn com.looker.core.common.DeeplinksKt
|
|
||||||
#-dontwarn com.looker.core.common.Exporter
|
|
||||||
#-dontwarn com.looker.core.common.NotificationKt
|
|
||||||
#-dontwarn com.looker.core.common.PermissionsKt
|
|
||||||
#-dontwarn com.looker.core.common.Scroller
|
|
||||||
#-dontwarn com.looker.core.common.SdkCheck
|
|
||||||
#-dontwarn com.looker.core.common.Singleton
|
|
||||||
#-dontwarn com.looker.core.common.TextKt
|
|
||||||
#-dontwarn com.looker.core.common.cache.Cache
|
|
||||||
#-dontwarn com.looker.core.common.cache.Cache
|
|
||||||
#-dontwarn com.looker.core.common.device.Huawei
|
|
||||||
#-dontwarn com.looker.core.common.extension.ContextKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.CursorKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.DateTimeKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.FingerprintKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.FlowKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.InsetsKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.IntentKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.Json
|
|
||||||
#-dontwarn com.looker.core.common.extension.JsonKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.KeyToken
|
|
||||||
#-dontwarn com.looker.core.common.extension.LocaleKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.NumberKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.PackageInfoKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.SQLiteDatabaseKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.ServiceKt
|
|
||||||
#-dontwarn com.looker.core.common.extension.ViewKt
|
|
||||||
#-dontwarn com.looker.core.common.result.Result$Error
|
|
||||||
#-dontwarn com.looker.core.common.result.Result$Success
|
|
||||||
#-dontwarn com.looker.core.common.result.Result
|
|
||||||
#-dontwarn com.looker.core.common.signature.Hash
|
|
||||||
#-dontwarn com.looker.core.common.signature.HashCheckerKt
|
|
||||||
#
|
|
||||||
#-dontwarn com.looker.core.datastore.Settings
|
|
||||||
#-dontwarn com.looker.core.datastore.SettingsRepository
|
|
||||||
#-dontwarn com.looker.core.datastore.di.DatastoreModule_ProvidePreferenceDatastoreFactory
|
|
||||||
#-dontwarn com.looker.core.datastore.di.DatastoreModule_ProvideProtoDatastoreFactory
|
|
||||||
#-dontwarn com.looker.core.datastore.di.DatastoreModule_ProvideSettingsExporterFactory
|
|
||||||
#-dontwarn com.looker.core.datastore.di.DatastoreModule_ProvideSettingsRepositoryFactory
|
|
||||||
#-dontwarn com.looker.core.datastore.extension.PreferencesKt
|
|
||||||
#-dontwarn com.looker.core.datastore.model.AutoSync
|
|
||||||
#-dontwarn com.looker.core.datastore.model.InstallerType$Companion
|
|
||||||
#-dontwarn com.looker.core.datastore.model.InstallerType
|
|
||||||
#-dontwarn com.looker.core.datastore.model.ProxyPreference
|
|
||||||
#-dontwarn com.looker.core.datastore.model.ProxyType
|
|
||||||
#-dontwarn com.looker.core.datastore.model.SortOrder
|
|
||||||
#-dontwarn com.looker.core.datastore.model.Theme
|
|
||||||
#
|
|
||||||
#-dontwarn com.looker.installer.InstallManager
|
|
||||||
#-dontwarn com.looker.installer.InstallModule_ProvideRootPermissionHandlerFactory
|
|
||||||
#-dontwarn com.looker.installer.InstallModule_ProvideShizukuPermissionHandlerFactory
|
|
||||||
#-dontwarn com.looker.installer.InstallModule_ProvidesInstallerFactory
|
|
||||||
#-dontwarn com.looker.installer.installers.root.RootPermissionHandler
|
|
||||||
#-dontwarn com.looker.installer.installers.session.SessionInstallerReceiver_GeneratedInjector
|
|
||||||
#-dontwarn com.looker.installer.installers.shizuku.ShizukuPermissionHandler$State
|
|
||||||
#-dontwarn com.looker.installer.installers.shizuku.ShizukuPermissionHandler
|
|
||||||
#-dontwarn com.looker.installer.model.InstallItem
|
|
||||||
#-dontwarn com.looker.installer.model.InstallItemKt
|
|
||||||
#-dontwarn com.looker.installer.model.InstallState
|
|
||||||
#-dontwarn com.looker.installer.notification.InstallNotificationKt
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.looker.droidify.sync.common
|
package com.looker.droidify.sync.common
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import java.io.File
|
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
fun assets(name: String): InputStream {
|
fun assets(name: String): InputStream {
|
||||||
|
@ -50,7 +50,6 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SHOW_APP_INFO" />
|
<action android:name="android.intent.action.SHOW_APP_INFO" />
|
||||||
|
@ -13,10 +13,14 @@ import androidx.appcompat.app.AppCompatDelegate
|
|||||||
import androidx.hilt.work.HiltWorkerFactory
|
import androidx.hilt.work.HiltWorkerFactory
|
||||||
import androidx.work.Configuration
|
import androidx.work.Configuration
|
||||||
import androidx.work.NetworkType
|
import androidx.work.NetworkType
|
||||||
import coil.ImageLoader
|
import coil3.ImageLoader
|
||||||
import coil.ImageLoaderFactory
|
import coil3.PlatformContext
|
||||||
import coil.disk.DiskCache
|
import coil3.SingletonImageLoader
|
||||||
import coil.memory.MemoryCache
|
import coil3.asImage
|
||||||
|
import coil3.disk.DiskCache
|
||||||
|
import coil3.disk.directory
|
||||||
|
import coil3.memory.MemoryCache
|
||||||
|
import coil3.request.crossfade
|
||||||
import com.looker.droidify.content.ProductPreferences
|
import com.looker.droidify.content.ProductPreferences
|
||||||
import com.looker.droidify.database.Database
|
import com.looker.droidify.database.Database
|
||||||
import com.looker.droidify.datastore.SettingsRepository
|
import com.looker.droidify.datastore.SettingsRepository
|
||||||
@ -35,6 +39,7 @@ import com.looker.droidify.sync.toJobNetworkType
|
|||||||
import com.looker.droidify.utility.common.Constants
|
import com.looker.droidify.utility.common.Constants
|
||||||
import com.looker.droidify.utility.common.SdkCheck
|
import com.looker.droidify.utility.common.SdkCheck
|
||||||
import com.looker.droidify.utility.common.cache.Cache
|
import com.looker.droidify.utility.common.cache.Cache
|
||||||
|
import com.looker.droidify.utility.common.extension.getDrawableCompat
|
||||||
import com.looker.droidify.utility.common.extension.getInstalledPackagesCompat
|
import com.looker.droidify.utility.common.extension.getInstalledPackagesCompat
|
||||||
import com.looker.droidify.utility.common.extension.jobScheduler
|
import com.looker.droidify.utility.common.extension.jobScheduler
|
||||||
import com.looker.droidify.utility.common.log
|
import com.looker.droidify.utility.common.log
|
||||||
@ -55,7 +60,7 @@ import kotlin.time.Duration.Companion.INFINITE
|
|||||||
import kotlin.time.Duration.Companion.hours
|
import kotlin.time.Duration.Companion.hours
|
||||||
|
|
||||||
@HiltAndroidApp
|
@HiltAndroidApp
|
||||||
class Droidify : Application(), ImageLoaderFactory, Configuration.Provider {
|
class Droidify : Application(), SingletonImageLoader.Factory, Configuration.Provider {
|
||||||
|
|
||||||
private val parentJob = SupervisorJob()
|
private val parentJob = SupervisorJob()
|
||||||
private val appScope = CoroutineScope(Dispatchers.Default + parentJob)
|
private val appScope = CoroutineScope(Dispatchers.Default + parentJob)
|
||||||
@ -221,9 +226,14 @@ class Droidify : Application(), ImageLoaderFactory, Configuration.Provider {
|
|||||||
override fun onReceive(context: Context, intent: Intent) = Unit
|
override fun onReceive(context: Context, intent: Intent) = Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun newImageLoader(): ImageLoader {
|
override val workManagerConfiguration: Configuration
|
||||||
val memoryCache = MemoryCache.Builder(this)
|
get() = Configuration.Builder()
|
||||||
.maxSizePercent(0.25)
|
.setWorkerFactory(workerFactory)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
override fun newImageLoader(context: PlatformContext): ImageLoader {
|
||||||
|
val memoryCache = MemoryCache.Builder()
|
||||||
|
.maxSizePercent(context, 0.25)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val diskCache = DiskCache.Builder()
|
val diskCache = DiskCache.Builder()
|
||||||
@ -234,15 +244,10 @@ class Droidify : Application(), ImageLoaderFactory, Configuration.Provider {
|
|||||||
return ImageLoader.Builder(this)
|
return ImageLoader.Builder(this)
|
||||||
.memoryCache(memoryCache)
|
.memoryCache(memoryCache)
|
||||||
.diskCache(diskCache)
|
.diskCache(diskCache)
|
||||||
.error(R.drawable.ic_cannot_load)
|
.error(getDrawableCompat(R.drawable.ic_cannot_load).asImage())
|
||||||
.crossfade(350)
|
.crossfade(350)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val workManagerConfiguration: Configuration
|
|
||||||
get() = Configuration.Builder()
|
|
||||||
.setWorkerFactory(workerFactory)
|
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
@ -2,9 +2,9 @@ package com.looker.droidify.content
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import com.looker.core.common.extension.Json
|
import com.looker.droidify.utility.common.extension.Json
|
||||||
import com.looker.core.common.extension.parseDictionary
|
import com.looker.droidify.utility.common.extension.parseDictionary
|
||||||
import com.looker.core.common.extension.writeDictionary
|
import com.looker.droidify.utility.common.extension.writeDictionary
|
||||||
import com.looker.droidify.model.ProductPreference
|
import com.looker.droidify.model.ProductPreference
|
||||||
import com.looker.droidify.database.Database
|
import com.looker.droidify.database.Database
|
||||||
import com.looker.droidify.utility.serialization.productPreference
|
import com.looker.droidify.utility.serialization.productPreference
|
||||||
|
@ -12,28 +12,29 @@ class CursorOwner : Fragment(), LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
sealed class Request {
|
sealed class Request {
|
||||||
internal abstract val id: Int
|
internal abstract val id: Int
|
||||||
|
|
||||||
data class ProductsAvailable(
|
class Available(
|
||||||
val searchQuery: String,
|
val searchQuery: String,
|
||||||
val section: ProductItem.Section,
|
val section: ProductItem.Section,
|
||||||
val order: SortOrder
|
val order: SortOrder,
|
||||||
) : Request() {
|
) : Request() {
|
||||||
override val id: Int
|
override val id: Int
|
||||||
get() = 1
|
get() = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ProductsInstalled(
|
class Installed(
|
||||||
val searchQuery: String,
|
val searchQuery: String,
|
||||||
val section: ProductItem.Section,
|
val section: ProductItem.Section,
|
||||||
val order: SortOrder
|
val order: SortOrder,
|
||||||
) : Request() {
|
) : Request() {
|
||||||
override val id: Int
|
override val id: Int
|
||||||
get() = 2
|
get() = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ProductsUpdates(
|
class Updates(
|
||||||
val searchQuery: String,
|
val searchQuery: String,
|
||||||
val section: ProductItem.Section,
|
val section: ProductItem.Section,
|
||||||
val order: SortOrder
|
val order: SortOrder,
|
||||||
|
val skipSignatureCheck: Boolean,
|
||||||
) : Request() {
|
) : Request() {
|
||||||
override val id: Int
|
override val id: Int
|
||||||
get() = 3
|
get() = 3
|
||||||
@ -52,7 +53,7 @@ class CursorOwner : Fragment(), LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
private data class ActiveRequest(
|
private data class ActiveRequest(
|
||||||
val request: Request,
|
val request: Request,
|
||||||
val callback: Callback?,
|
val callback: Callback?,
|
||||||
val cursor: Cursor?
|
val cursor: Cursor?,
|
||||||
)
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -93,7 +94,7 @@ class CursorOwner : Fragment(), LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
val request = activeRequests[id]!!.request
|
val request = activeRequests[id]!!.request
|
||||||
return QueryLoader(requireContext()) {
|
return QueryLoader(requireContext()) {
|
||||||
when (request) {
|
when (request) {
|
||||||
is Request.ProductsAvailable ->
|
is Request.Available ->
|
||||||
Database.ProductAdapter
|
Database.ProductAdapter
|
||||||
.query(
|
.query(
|
||||||
installed = false,
|
installed = false,
|
||||||
@ -101,10 +102,10 @@ class CursorOwner : Fragment(), LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
searchQuery = request.searchQuery,
|
searchQuery = request.searchQuery,
|
||||||
section = request.section,
|
section = request.section,
|
||||||
order = request.order,
|
order = request.order,
|
||||||
signal = it
|
signal = it,
|
||||||
)
|
)
|
||||||
|
|
||||||
is Request.ProductsInstalled ->
|
is Request.Installed ->
|
||||||
Database.ProductAdapter
|
Database.ProductAdapter
|
||||||
.query(
|
.query(
|
||||||
installed = true,
|
installed = true,
|
||||||
@ -112,10 +113,10 @@ class CursorOwner : Fragment(), LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
searchQuery = request.searchQuery,
|
searchQuery = request.searchQuery,
|
||||||
section = request.section,
|
section = request.section,
|
||||||
order = request.order,
|
order = request.order,
|
||||||
signal = it
|
signal = it,
|
||||||
)
|
)
|
||||||
|
|
||||||
is Request.ProductsUpdates ->
|
is Request.Updates ->
|
||||||
Database.ProductAdapter
|
Database.ProductAdapter
|
||||||
.query(
|
.query(
|
||||||
installed = true,
|
installed = true,
|
||||||
@ -123,7 +124,8 @@ class CursorOwner : Fragment(), LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
searchQuery = request.searchQuery,
|
searchQuery = request.searchQuery,
|
||||||
section = request.section,
|
section = request.section,
|
||||||
order = request.order,
|
order = request.order,
|
||||||
signal = it
|
signal = it,
|
||||||
|
skipSignatureCheck = request.skipSignatureCheck,
|
||||||
)
|
)
|
||||||
|
|
||||||
is Request.Repositories -> Database.RepositoryAdapter.query(it)
|
is Request.Repositories -> Database.RepositoryAdapter.query(it)
|
||||||
|
@ -9,18 +9,18 @@ import android.os.CancellationSignal
|
|||||||
import androidx.core.database.sqlite.transaction
|
import androidx.core.database.sqlite.transaction
|
||||||
import com.fasterxml.jackson.core.JsonGenerator
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.looker.core.common.extension.Json
|
import com.looker.droidify.BuildConfig
|
||||||
import com.looker.droidify.utility.common.extension.asSequence
|
|
||||||
import com.looker.droidify.utility.common.extension.firstOrNull
|
|
||||||
import com.looker.core.common.extension.parseDictionary
|
|
||||||
import com.looker.core.common.extension.writeDictionary
|
|
||||||
import com.looker.droidify.utility.common.log
|
|
||||||
import com.looker.droidify.datastore.model.SortOrder
|
import com.looker.droidify.datastore.model.SortOrder
|
||||||
import com.looker.droidify.model.InstalledItem
|
import com.looker.droidify.model.InstalledItem
|
||||||
import com.looker.droidify.model.Product
|
import com.looker.droidify.model.Product
|
||||||
import com.looker.droidify.model.ProductItem
|
import com.looker.droidify.model.ProductItem
|
||||||
import com.looker.droidify.model.Repository
|
import com.looker.droidify.model.Repository
|
||||||
import com.looker.droidify.BuildConfig
|
import com.looker.droidify.utility.common.extension.Json
|
||||||
|
import com.looker.droidify.utility.common.extension.asSequence
|
||||||
|
import com.looker.droidify.utility.common.extension.firstOrNull
|
||||||
|
import com.looker.droidify.utility.common.extension.parseDictionary
|
||||||
|
import com.looker.droidify.utility.common.extension.writeDictionary
|
||||||
|
import com.looker.droidify.utility.common.log
|
||||||
import com.looker.droidify.utility.serialization.product
|
import com.looker.droidify.utility.serialization.product
|
||||||
import com.looker.droidify.utility.serialization.productItem
|
import com.looker.droidify.utility.serialization.productItem
|
||||||
import com.looker.droidify.utility.serialization.repository
|
import com.looker.droidify.utility.serialization.repository
|
||||||
@ -71,14 +71,20 @@ object Database {
|
|||||||
get() = "$databasePrefix$innerName"
|
get() = "$databasePrefix$innerName"
|
||||||
|
|
||||||
fun formatCreateTable(name: String): String {
|
fun formatCreateTable(name: String): String {
|
||||||
return "CREATE TABLE $name (${QueryBuilder.trimQuery(createTable)})"
|
return buildString(128) {
|
||||||
|
append("CREATE TABLE ")
|
||||||
|
append(name)
|
||||||
|
append(" (")
|
||||||
|
trimAndJoin(createTable)
|
||||||
|
append(")")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val createIndexPairFormatted: Pair<String, String>?
|
val createIndexPairFormatted: Pair<String, String>?
|
||||||
get() = createIndex?.let {
|
get() = createIndex?.let {
|
||||||
Pair(
|
Pair(
|
||||||
"CREATE INDEX ${innerName}_index ON $innerName ($it)",
|
"CREATE INDEX ${innerName}_index ON $innerName ($it)",
|
||||||
"CREATE INDEX ${name}_index ON $innerName ($it)"
|
"CREATE INDEX ${name}_index ON $innerName ($it)",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,7 +220,7 @@ object Database {
|
|||||||
Schema.Product,
|
Schema.Product,
|
||||||
Schema.Category,
|
Schema.Category,
|
||||||
Schema.Installed,
|
Schema.Installed,
|
||||||
Schema.Lock
|
Schema.Lock,
|
||||||
)
|
)
|
||||||
dropOldTables(db, Schema.Repository, Schema.Product, Schema.Category)
|
dropOldTables(db, Schema.Repository, Schema.Product, Schema.Category)
|
||||||
this.created = this.created || create
|
this.created = this.created || create
|
||||||
@ -227,7 +233,7 @@ object Database {
|
|||||||
val sql = db.query(
|
val sql = db.query(
|
||||||
"${table.databasePrefix}sqlite_master",
|
"${table.databasePrefix}sqlite_master",
|
||||||
columns = arrayOf("sql"),
|
columns = arrayOf("sql"),
|
||||||
selection = Pair("type = ? AND name = ?", arrayOf("table", table.innerName))
|
selection = Pair("type = ? AND name = ?", arrayOf("table", table.innerName)),
|
||||||
).use { it.firstOrNull()?.getString(0) }.orEmpty()
|
).use { it.firstOrNull()?.getString(0) }.orEmpty()
|
||||||
table.formatCreateTable(table.innerName) != sql
|
table.formatCreateTable(table.innerName) != sql
|
||||||
}
|
}
|
||||||
@ -261,7 +267,7 @@ object Database {
|
|||||||
val sqls = db.query(
|
val sqls = db.query(
|
||||||
"${table.databasePrefix}sqlite_master",
|
"${table.databasePrefix}sqlite_master",
|
||||||
columns = arrayOf("name", "sql"),
|
columns = arrayOf("name", "sql"),
|
||||||
selection = Pair("type = ? AND tbl_name = ?", arrayOf("index", table.innerName))
|
selection = Pair("type = ? AND tbl_name = ?", arrayOf("index", table.innerName)),
|
||||||
)
|
)
|
||||||
.use { cursor ->
|
.use { cursor ->
|
||||||
cursor.asSequence()
|
cursor.asSequence()
|
||||||
@ -289,7 +295,7 @@ object Database {
|
|||||||
val tables = db.query(
|
val tables = db.query(
|
||||||
"sqlite_master",
|
"sqlite_master",
|
||||||
columns = arrayOf("name"),
|
columns = arrayOf("name"),
|
||||||
selection = Pair("type = ?", arrayOf("table"))
|
selection = Pair("type = ?", arrayOf("table")),
|
||||||
)
|
)
|
||||||
.use { cursor -> cursor.asSequence().mapNotNull { it.getString(0) }.toList() }
|
.use { cursor -> cursor.asSequence().mapNotNull { it.getString(0) }.toList() }
|
||||||
.filter { !it.startsWith("sqlite_") && !it.startsWith("android_") }
|
.filter { !it.startsWith("sqlite_") && !it.startsWith("android_") }
|
||||||
@ -345,7 +351,7 @@ object Database {
|
|||||||
private fun SQLiteDatabase.insertOrReplace(
|
private fun SQLiteDatabase.insertOrReplace(
|
||||||
replace: Boolean,
|
replace: Boolean,
|
||||||
table: String,
|
table: String,
|
||||||
contentValues: ContentValues
|
contentValues: ContentValues,
|
||||||
): Long {
|
): Long {
|
||||||
return if (replace) {
|
return if (replace) {
|
||||||
replace(table, null, contentValues)
|
replace(table, null, contentValues)
|
||||||
@ -353,7 +359,7 @@ object Database {
|
|||||||
insert(
|
insert(
|
||||||
table,
|
table,
|
||||||
null,
|
null,
|
||||||
contentValues
|
contentValues,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -363,7 +369,7 @@ object Database {
|
|||||||
columns: Array<String>? = null,
|
columns: Array<String>? = null,
|
||||||
selection: Pair<String, Array<String>>? = null,
|
selection: Pair<String, Array<String>>? = null,
|
||||||
orderBy: String? = null,
|
orderBy: String? = null,
|
||||||
signal: CancellationSignal? = null
|
signal: CancellationSignal? = null,
|
||||||
): Cursor {
|
): Cursor {
|
||||||
return query(
|
return query(
|
||||||
false,
|
false,
|
||||||
@ -375,7 +381,7 @@ object Database {
|
|||||||
null,
|
null,
|
||||||
orderBy,
|
orderBy,
|
||||||
null,
|
null,
|
||||||
signal
|
signal,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +403,7 @@ object Database {
|
|||||||
internal fun putWithoutNotification(
|
internal fun putWithoutNotification(
|
||||||
repository: Repository,
|
repository: Repository,
|
||||||
shouldReplace: Boolean,
|
shouldReplace: Boolean,
|
||||||
database: SQLiteDatabase
|
database: SQLiteDatabase,
|
||||||
): Long {
|
): Long {
|
||||||
return database.insertOrReplace(
|
return database.insertOrReplace(
|
||||||
shouldReplace,
|
shouldReplace,
|
||||||
@ -409,7 +415,7 @@ object Database {
|
|||||||
put(Schema.Repository.ROW_ENABLED, if (repository.enabled) 1 else 0)
|
put(Schema.Repository.ROW_ENABLED, if (repository.enabled) 1 else 0)
|
||||||
put(Schema.Repository.ROW_DELETED, 0)
|
put(Schema.Repository.ROW_DELETED, 0)
|
||||||
put(Schema.Repository.ROW_DATA, jsonGenerate(repository::serialize))
|
put(Schema.Repository.ROW_DATA, jsonGenerate(repository::serialize))
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,8 +448,8 @@ object Database {
|
|||||||
Schema.Repository.name,
|
Schema.Repository.name,
|
||||||
selection = Pair(
|
selection = Pair(
|
||||||
"${Schema.Repository.ROW_ID} = ? AND ${Schema.Repository.ROW_DELETED} == 0",
|
"${Schema.Repository.ROW_ID} = ? AND ${Schema.Repository.ROW_DELETED} == 0",
|
||||||
arrayOf(id.toString())
|
arrayOf(id.toString()),
|
||||||
)
|
),
|
||||||
).use { it.firstOrNull()?.let(::transform) }
|
).use { it.firstOrNull()?.let(::transform) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,9 +469,9 @@ object Database {
|
|||||||
selection = Pair(
|
selection = Pair(
|
||||||
"${Schema.Repository.ROW_ENABLED} != 0 AND " +
|
"${Schema.Repository.ROW_ENABLED} != 0 AND " +
|
||||||
"${Schema.Repository.ROW_DELETED} == 0",
|
"${Schema.Repository.ROW_DELETED} == 0",
|
||||||
emptyArray()
|
emptyArray(),
|
||||||
),
|
),
|
||||||
signal = null
|
signal = null,
|
||||||
).use { it.asSequence().map(::transform).toList() }
|
).use { it.asSequence().map(::transform).toList() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,7 +479,7 @@ object Database {
|
|||||||
return db.query(
|
return db.query(
|
||||||
Schema.Repository.name,
|
Schema.Repository.name,
|
||||||
selection = Pair("${Schema.Repository.ROW_DELETED} == 0", emptyArray()),
|
selection = Pair("${Schema.Repository.ROW_DELETED} == 0", emptyArray()),
|
||||||
signal = null
|
signal = null,
|
||||||
).use { it.asSequence().map(::transform).toList() }
|
).use { it.asSequence().map(::transform).toList() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,9 +495,9 @@ object Database {
|
|||||||
selection = Pair(
|
selection = Pair(
|
||||||
"${Schema.Repository.ROW_ENABLED} == 0 OR " +
|
"${Schema.Repository.ROW_ENABLED} == 0 OR " +
|
||||||
"${Schema.Repository.ROW_DELETED} != 0",
|
"${Schema.Repository.ROW_DELETED} != 0",
|
||||||
emptyArray()
|
emptyArray(),
|
||||||
),
|
),
|
||||||
signal = null
|
signal = null,
|
||||||
).use { parentCursor ->
|
).use { parentCursor ->
|
||||||
parentCursor.asSequence().associate {
|
parentCursor.asSequence().associate {
|
||||||
val idIndex = it.getColumnIndexOrThrow(Schema.Repository.ROW_ID)
|
val idIndex = it.getColumnIndexOrThrow(Schema.Repository.ROW_ID)
|
||||||
@ -508,7 +514,7 @@ object Database {
|
|||||||
put(Schema.Repository.ROW_DELETED, 1)
|
put(Schema.Repository.ROW_DELETED, 1)
|
||||||
},
|
},
|
||||||
"${Schema.Repository.ROW_ID} = ?",
|
"${Schema.Repository.ROW_ID} = ?",
|
||||||
arrayOf(id.toString())
|
arrayOf(id.toString()),
|
||||||
)
|
)
|
||||||
notifyChanged(Subject.Repositories, Subject.Repository(id), Subject.Products)
|
notifyChanged(Subject.Repositories, Subject.Repository(id), Subject.Products)
|
||||||
}
|
}
|
||||||
@ -519,18 +525,18 @@ object Database {
|
|||||||
val productsCount = db.delete(
|
val productsCount = db.delete(
|
||||||
Schema.Product.name,
|
Schema.Product.name,
|
||||||
"${Schema.Product.ROW_REPOSITORY_ID} IN ($idsString)",
|
"${Schema.Product.ROW_REPOSITORY_ID} IN ($idsString)",
|
||||||
null
|
null,
|
||||||
)
|
)
|
||||||
val categoriesCount = db.delete(
|
val categoriesCount = db.delete(
|
||||||
Schema.Category.name,
|
Schema.Category.name,
|
||||||
"${Schema.Category.ROW_REPOSITORY_ID} IN ($idsString)",
|
"${Schema.Category.ROW_REPOSITORY_ID} IN ($idsString)",
|
||||||
null
|
null,
|
||||||
)
|
)
|
||||||
if (isDeleted) {
|
if (isDeleted) {
|
||||||
db.delete(
|
db.delete(
|
||||||
Schema.Repository.name,
|
Schema.Repository.name,
|
||||||
"${Schema.Repository.ROW_ID} IN ($id)",
|
"${Schema.Repository.ROW_ID} IN ($id)",
|
||||||
null
|
null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
productsCount != 0 || categoriesCount != 0
|
productsCount != 0 || categoriesCount != 0
|
||||||
@ -555,7 +561,7 @@ object Database {
|
|||||||
Schema.Repository.name,
|
Schema.Repository.name,
|
||||||
selection = Pair("${Schema.Repository.ROW_DELETED} == 0", emptyArray()),
|
selection = Pair("${Schema.Repository.ROW_DELETED} == 0", emptyArray()),
|
||||||
orderBy = "${Schema.Repository.ROW_ENABLED} DESC",
|
orderBy = "${Schema.Repository.ROW_ENABLED} DESC",
|
||||||
signal = signal
|
signal = signal,
|
||||||
).observable(Subject.Repositories)
|
).observable(Subject.Repositories)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -577,26 +583,28 @@ object Database {
|
|||||||
.map { get(packageName, null) }
|
.map { get(packageName, null) }
|
||||||
.flowOn(Dispatchers.IO)
|
.flowOn(Dispatchers.IO)
|
||||||
|
|
||||||
suspend fun getUpdates(): List<ProductItem> = withContext(Dispatchers.IO) {
|
suspend fun getUpdates(skipSignatureCheck: Boolean): List<ProductItem> =
|
||||||
query(
|
withContext(Dispatchers.IO) {
|
||||||
installed = true,
|
query(
|
||||||
updates = true,
|
installed = true,
|
||||||
searchQuery = "",
|
updates = true,
|
||||||
section = ProductItem.Section.All,
|
searchQuery = "",
|
||||||
order = SortOrder.NAME,
|
skipSignatureCheck = skipSignatureCheck,
|
||||||
signal = null
|
section = ProductItem.Section.All,
|
||||||
).use {
|
order = SortOrder.NAME,
|
||||||
it.asSequence()
|
signal = null,
|
||||||
.map(ProductAdapter::transformItem)
|
).use {
|
||||||
.toList()
|
it.asSequence()
|
||||||
|
.map(ProductAdapter::transformItem)
|
||||||
|
.toList()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun getUpdatesStream(): Flow<List<ProductItem>> = flowOf(Unit)
|
fun getUpdatesStream(skipSignatureCheck: Boolean): Flow<List<ProductItem>> = flowOf(Unit)
|
||||||
.onCompletion { if (it == null) emitAll(flowCollection(Subject.Products)) }
|
.onCompletion { if (it == null) emitAll(flowCollection(Subject.Products)) }
|
||||||
// Crashes due to immediate retrieval of data?
|
// Crashes due to immediate retrieval of data?
|
||||||
.onEach { delay(50) }
|
.onEach { delay(50) }
|
||||||
.map { getUpdates() }
|
.map { getUpdates(skipSignatureCheck) }
|
||||||
.flowOn(Dispatchers.IO)
|
.flowOn(Dispatchers.IO)
|
||||||
|
|
||||||
fun getAll(): List<Product> {
|
fun getAll(): List<Product> {
|
||||||
@ -618,10 +626,10 @@ object Database {
|
|||||||
columns = arrayOf(
|
columns = arrayOf(
|
||||||
Schema.Product.ROW_REPOSITORY_ID,
|
Schema.Product.ROW_REPOSITORY_ID,
|
||||||
Schema.Product.ROW_DESCRIPTION,
|
Schema.Product.ROW_DESCRIPTION,
|
||||||
Schema.Product.ROW_DATA
|
Schema.Product.ROW_DATA,
|
||||||
),
|
),
|
||||||
selection = Pair("${Schema.Product.ROW_PACKAGE_NAME} = ?", arrayOf(packageName)),
|
selection = Pair("${Schema.Product.ROW_PACKAGE_NAME} = ?", arrayOf(packageName)),
|
||||||
signal = signal
|
signal = signal,
|
||||||
).use { it.asSequence().map(::transform).toList() }
|
).use { it.asSequence().map(::transform).toList() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,24 +644,26 @@ object Database {
|
|||||||
columns = arrayOf("COUNT (*)"),
|
columns = arrayOf("COUNT (*)"),
|
||||||
selection = Pair(
|
selection = Pair(
|
||||||
"${Schema.Product.ROW_REPOSITORY_ID} = ?",
|
"${Schema.Product.ROW_REPOSITORY_ID} = ?",
|
||||||
arrayOf(repositoryId.toString())
|
arrayOf(repositoryId.toString()),
|
||||||
)
|
),
|
||||||
).use { it.firstOrNull()?.getInt(0) ?: 0 }
|
).use { it.firstOrNull()?.getInt(0) ?: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun query(
|
fun query(
|
||||||
installed: Boolean,
|
installed: Boolean,
|
||||||
updates: Boolean,
|
updates: Boolean,
|
||||||
|
skipSignatureCheck: Boolean = false,
|
||||||
searchQuery: String,
|
searchQuery: String,
|
||||||
section: ProductItem.Section,
|
section: ProductItem.Section,
|
||||||
order: SortOrder,
|
order: SortOrder,
|
||||||
signal: CancellationSignal?
|
signal: CancellationSignal?,
|
||||||
): Cursor {
|
): Cursor {
|
||||||
val builder = QueryBuilder()
|
val builder = QueryBuilder()
|
||||||
|
|
||||||
val signatureMatches = """installed.${Schema.Installed.ROW_SIGNATURE} IS NOT NULL AND
|
val signatureMatches = if (skipSignatureCheck) "1"
|
||||||
product.${Schema.Product.ROW_SIGNATURES} LIKE ('%.' || installed.${Schema.Installed.ROW_SIGNATURE} || '.%') AND
|
else """installed.${Schema.Installed.ROW_SIGNATURE} IS NOT NULL AND
|
||||||
product.${Schema.Product.ROW_SIGNATURES} != ''"""
|
product.${Schema.Product.ROW_SIGNATURES} LIKE ('%.' || installed.${Schema.Installed.ROW_SIGNATURE} || '.%') AND
|
||||||
|
product.${Schema.Product.ROW_SIGNATURES} != ''"""
|
||||||
|
|
||||||
builder += """SELECT product.rowid AS _id, product.${Schema.Product.ROW_REPOSITORY_ID},
|
builder += """SELECT product.rowid AS _id, product.${Schema.Product.ROW_REPOSITORY_ID},
|
||||||
product.${Schema.Product.ROW_PACKAGE_NAME}, product.${Schema.Product.ROW_NAME},
|
product.${Schema.Product.ROW_PACKAGE_NAME}, product.${Schema.Product.ROW_NAME},
|
||||||
@ -741,6 +751,10 @@ object Database {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun transformPackageName(cursor: Cursor): String {
|
||||||
|
return cursor.getString(cursor.getColumnIndexOrThrow(Schema.Product.ROW_PACKAGE_NAME))
|
||||||
|
}
|
||||||
|
|
||||||
fun transformItem(cursor: Cursor): ProductItem {
|
fun transformItem(cursor: Cursor): ProductItem {
|
||||||
return cursor.getBlob(cursor.getColumnIndexOrThrow(Schema.Product.ROW_DATA_ITEM))
|
return cursor.getBlob(cursor.getColumnIndexOrThrow(Schema.Product.ROW_DATA_ITEM))
|
||||||
.jsonParse {
|
.jsonParse {
|
||||||
@ -806,10 +820,10 @@ object Database {
|
|||||||
Schema.Installed.ROW_PACKAGE_NAME,
|
Schema.Installed.ROW_PACKAGE_NAME,
|
||||||
Schema.Installed.ROW_VERSION,
|
Schema.Installed.ROW_VERSION,
|
||||||
Schema.Installed.ROW_VERSION_CODE,
|
Schema.Installed.ROW_VERSION_CODE,
|
||||||
Schema.Installed.ROW_SIGNATURE
|
Schema.Installed.ROW_SIGNATURE,
|
||||||
),
|
),
|
||||||
selection = Pair("${Schema.Installed.ROW_PACKAGE_NAME} = ?", arrayOf(packageName)),
|
selection = Pair("${Schema.Installed.ROW_PACKAGE_NAME} = ?", arrayOf(packageName)),
|
||||||
signal = signal
|
signal = signal,
|
||||||
).use { it.firstOrNull()?.let(::transform) }
|
).use { it.firstOrNull()?.let(::transform) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -822,7 +836,7 @@ object Database {
|
|||||||
put(Schema.Installed.ROW_VERSION, installedItem.version)
|
put(Schema.Installed.ROW_VERSION, installedItem.version)
|
||||||
put(Schema.Installed.ROW_VERSION_CODE, installedItem.versionCode)
|
put(Schema.Installed.ROW_VERSION_CODE, installedItem.versionCode)
|
||||||
put(Schema.Installed.ROW_SIGNATURE, installedItem.signature)
|
put(Schema.Installed.ROW_SIGNATURE, installedItem.signature)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
if (notify) {
|
if (notify) {
|
||||||
notifyChanged(Subject.Products)
|
notifyChanged(Subject.Products)
|
||||||
@ -842,7 +856,7 @@ object Database {
|
|||||||
val count = db.delete(
|
val count = db.delete(
|
||||||
Schema.Installed.name,
|
Schema.Installed.name,
|
||||||
"${Schema.Installed.ROW_PACKAGE_NAME} = ?",
|
"${Schema.Installed.ROW_PACKAGE_NAME} = ?",
|
||||||
arrayOf(packageName)
|
arrayOf(packageName),
|
||||||
)
|
)
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
notifyChanged(Subject.Products)
|
notifyChanged(Subject.Products)
|
||||||
@ -854,7 +868,7 @@ object Database {
|
|||||||
cursor.getString(cursor.getColumnIndexOrThrow(Schema.Installed.ROW_PACKAGE_NAME)),
|
cursor.getString(cursor.getColumnIndexOrThrow(Schema.Installed.ROW_PACKAGE_NAME)),
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(Schema.Installed.ROW_VERSION)),
|
cursor.getString(cursor.getColumnIndexOrThrow(Schema.Installed.ROW_VERSION)),
|
||||||
cursor.getLong(cursor.getColumnIndexOrThrow(Schema.Installed.ROW_VERSION_CODE)),
|
cursor.getLong(cursor.getColumnIndexOrThrow(Schema.Installed.ROW_VERSION_CODE)),
|
||||||
cursor.getString(cursor.getColumnIndexOrThrow(Schema.Installed.ROW_SIGNATURE))
|
cursor.getString(cursor.getColumnIndexOrThrow(Schema.Installed.ROW_SIGNATURE)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -867,7 +881,7 @@ object Database {
|
|||||||
ContentValues().apply {
|
ContentValues().apply {
|
||||||
put(Schema.Lock.ROW_PACKAGE_NAME, lock.first)
|
put(Schema.Lock.ROW_PACKAGE_NAME, lock.first)
|
||||||
put(Schema.Lock.ROW_VERSION_CODE, lock.second)
|
put(Schema.Lock.ROW_VERSION_CODE, lock.second)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
if (notify) {
|
if (notify) {
|
||||||
notifyChanged(Subject.Products)
|
notifyChanged(Subject.Products)
|
||||||
@ -923,9 +937,9 @@ object Database {
|
|||||||
put(Schema.Product.ROW_DATA, jsonGenerate(product::serialize))
|
put(Schema.Product.ROW_DATA, jsonGenerate(product::serialize))
|
||||||
put(
|
put(
|
||||||
Schema.Product.ROW_DATA_ITEM,
|
Schema.Product.ROW_DATA_ITEM,
|
||||||
jsonGenerate(product.item()::serialize)
|
jsonGenerate(product.item()::serialize),
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
for (category in product.categories) {
|
for (category in product.categories) {
|
||||||
db.insertOrReplace(
|
db.insertOrReplace(
|
||||||
@ -935,7 +949,7 @@ object Database {
|
|||||||
put(Schema.Category.ROW_REPOSITORY_ID, product.repositoryId)
|
put(Schema.Category.ROW_REPOSITORY_ID, product.repositoryId)
|
||||||
put(Schema.Category.ROW_PACKAGE_NAME, product.packageName)
|
put(Schema.Category.ROW_PACKAGE_NAME, product.packageName)
|
||||||
put(Schema.Category.ROW_NAME, category)
|
put(Schema.Category.ROW_NAME, category)
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -948,20 +962,20 @@ object Database {
|
|||||||
db.delete(
|
db.delete(
|
||||||
Schema.Product.name,
|
Schema.Product.name,
|
||||||
"${Schema.Product.ROW_REPOSITORY_ID} = ?",
|
"${Schema.Product.ROW_REPOSITORY_ID} = ?",
|
||||||
arrayOf(repository.id.toString())
|
arrayOf(repository.id.toString()),
|
||||||
)
|
)
|
||||||
db.delete(
|
db.delete(
|
||||||
Schema.Category.name,
|
Schema.Category.name,
|
||||||
"${Schema.Category.ROW_REPOSITORY_ID} = ?",
|
"${Schema.Category.ROW_REPOSITORY_ID} = ?",
|
||||||
arrayOf(repository.id.toString())
|
arrayOf(repository.id.toString()),
|
||||||
)
|
)
|
||||||
db.execSQL(
|
db.execSQL(
|
||||||
"INSERT INTO ${Schema.Product.name} SELECT * " +
|
"INSERT INTO ${Schema.Product.name} SELECT * " +
|
||||||
"FROM ${Schema.Product.temporaryName}"
|
"FROM ${Schema.Product.temporaryName}",
|
||||||
)
|
)
|
||||||
db.execSQL(
|
db.execSQL(
|
||||||
"INSERT INTO ${Schema.Category.name} SELECT * " +
|
"INSERT INTO ${Schema.Category.name} SELECT * " +
|
||||||
"FROM ${Schema.Category.temporaryName}"
|
"FROM ${Schema.Category.temporaryName}",
|
||||||
)
|
)
|
||||||
RepositoryAdapter.putWithoutNotification(repository, true, db)
|
RepositoryAdapter.putWithoutNotification(repository, true, db)
|
||||||
db.execSQL("DROP TABLE IF EXISTS ${Schema.Product.temporaryName}")
|
db.execSQL("DROP TABLE IF EXISTS ${Schema.Product.temporaryName}")
|
||||||
@ -970,7 +984,7 @@ object Database {
|
|||||||
notifyChanged(
|
notifyChanged(
|
||||||
Subject.Repositories,
|
Subject.Repositories,
|
||||||
Subject.Repository(repository.id),
|
Subject.Repository(repository.id),
|
||||||
Subject.Products
|
Subject.Products,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
db.execSQL("DROP TABLE IF EXISTS ${Schema.Product.temporaryName}")
|
db.execSQL("DROP TABLE IF EXISTS ${Schema.Product.temporaryName}")
|
||||||
|
@ -3,26 +3,20 @@ package com.looker.droidify.database
|
|||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.database.sqlite.SQLiteDatabase
|
import android.database.sqlite.SQLiteDatabase
|
||||||
import android.os.CancellationSignal
|
import android.os.CancellationSignal
|
||||||
|
import com.looker.droidify.BuildConfig
|
||||||
import com.looker.droidify.utility.common.extension.asSequence
|
import com.looker.droidify.utility.common.extension.asSequence
|
||||||
import com.looker.droidify.utility.common.log
|
import com.looker.droidify.utility.common.log
|
||||||
import com.looker.droidify.BuildConfig
|
|
||||||
|
|
||||||
class QueryBuilder {
|
class QueryBuilder {
|
||||||
companion object {
|
|
||||||
fun trimQuery(query: String): String {
|
|
||||||
return query.lines().map { it.trim() }.filter { it.isNotEmpty() }
|
|
||||||
.joinToString(separator = " ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val builder = StringBuilder()
|
private val builder = StringBuilder(256)
|
||||||
private val arguments = mutableListOf<String>()
|
private val arguments = mutableListOf<String>()
|
||||||
|
|
||||||
operator fun plusAssign(query: String) {
|
operator fun plusAssign(query: String) {
|
||||||
if (builder.isNotEmpty()) {
|
if (builder.isNotEmpty()) {
|
||||||
builder.append(" ")
|
builder.append(" ")
|
||||||
}
|
}
|
||||||
builder.append(trimQuery(query))
|
builder.trimAndJoin(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun remAssign(argument: String) {
|
operator fun remAssign(argument: String) {
|
||||||
@ -48,3 +42,53 @@ class QueryBuilder {
|
|||||||
return db.rawQuery(query, arguments, signal)
|
return db.rawQuery(query, arguments, signal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun StringBuilder.trimAndJoin(
|
||||||
|
input: String,
|
||||||
|
) {
|
||||||
|
var isFirstLine = true
|
||||||
|
var startOfLine = 0
|
||||||
|
for (i in input.indices) {
|
||||||
|
val char = input[i]
|
||||||
|
when {
|
||||||
|
char == '\n' -> {
|
||||||
|
trimAndAppendLine(input, startOfLine, i, this, isFirstLine)
|
||||||
|
isFirstLine = false
|
||||||
|
startOfLine = i + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
if (i == input.lastIndex) {
|
||||||
|
trimAndAppendLine(input, startOfLine, i + 1, this, isFirstLine)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun trimAndAppendLine(
|
||||||
|
input: String,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
builder: StringBuilder,
|
||||||
|
isFirstLine: Boolean,
|
||||||
|
) {
|
||||||
|
var lineStart = start
|
||||||
|
var lineEnd = end - 1
|
||||||
|
|
||||||
|
while (lineStart <= lineEnd && input[lineStart].isWhitespace()) {
|
||||||
|
lineStart++
|
||||||
|
}
|
||||||
|
|
||||||
|
while (lineEnd >= lineStart && input[lineEnd].isWhitespace()) {
|
||||||
|
lineEnd--
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineStart <= lineEnd) {
|
||||||
|
if (!isFirstLine) {
|
||||||
|
builder.append(' ')
|
||||||
|
}
|
||||||
|
builder.append(input, lineStart, lineEnd + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -4,12 +4,12 @@ import android.content.Context
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.fasterxml.jackson.core.JsonToken
|
import com.fasterxml.jackson.core.JsonToken
|
||||||
import com.looker.droidify.utility.common.Exporter
|
import com.looker.droidify.utility.common.Exporter
|
||||||
import com.looker.core.common.extension.Json
|
import com.looker.droidify.utility.common.extension.Json
|
||||||
import com.looker.core.common.extension.forEach
|
import com.looker.droidify.utility.common.extension.forEach
|
||||||
import com.looker.core.common.extension.forEachKey
|
import com.looker.droidify.utility.common.extension.forEachKey
|
||||||
import com.looker.core.common.extension.parseDictionary
|
import com.looker.droidify.utility.common.extension.parseDictionary
|
||||||
import com.looker.core.common.extension.writeArray
|
import com.looker.droidify.utility.common.extension.writeArray
|
||||||
import com.looker.core.common.extension.writeDictionary
|
import com.looker.droidify.utility.common.extension.writeDictionary
|
||||||
import com.looker.droidify.di.ApplicationScope
|
import com.looker.droidify.di.ApplicationScope
|
||||||
import com.looker.droidify.di.IoDispatcher
|
import com.looker.droidify.di.IoDispatcher
|
||||||
import com.looker.droidify.model.Repository
|
import com.looker.droidify.model.Repository
|
||||||
|
@ -14,6 +14,7 @@ import androidx.datastore.preferences.core.stringPreferencesKey
|
|||||||
import androidx.datastore.preferences.core.stringSetPreferencesKey
|
import androidx.datastore.preferences.core.stringSetPreferencesKey
|
||||||
import com.looker.droidify.datastore.model.AutoSync
|
import com.looker.droidify.datastore.model.AutoSync
|
||||||
import com.looker.droidify.datastore.model.InstallerType
|
import com.looker.droidify.datastore.model.InstallerType
|
||||||
|
import com.looker.droidify.datastore.model.LegacyInstallerComponent
|
||||||
import com.looker.droidify.datastore.model.ProxyPreference
|
import com.looker.droidify.datastore.model.ProxyPreference
|
||||||
import com.looker.droidify.datastore.model.ProxyType
|
import com.looker.droidify.datastore.model.ProxyType
|
||||||
import com.looker.droidify.datastore.model.SortOrder
|
import com.looker.droidify.datastore.model.SortOrder
|
||||||
@ -85,6 +86,31 @@ class PreferenceSettingsRepository(
|
|||||||
override suspend fun setInstallerType(installerType: InstallerType) =
|
override suspend fun setInstallerType(installerType: InstallerType) =
|
||||||
INSTALLER_TYPE.update(installerType.name)
|
INSTALLER_TYPE.update(installerType.name)
|
||||||
|
|
||||||
|
override suspend fun setLegacyInstallerComponent(component: LegacyInstallerComponent?) {
|
||||||
|
when (component) {
|
||||||
|
null -> {
|
||||||
|
LEGACY_INSTALLER_COMPONENT_TYPE.update("")
|
||||||
|
LEGACY_INSTALLER_COMPONENT_CLASS.update("")
|
||||||
|
LEGACY_INSTALLER_COMPONENT_ACTIVITY.update("")
|
||||||
|
}
|
||||||
|
is LegacyInstallerComponent.Component -> {
|
||||||
|
LEGACY_INSTALLER_COMPONENT_TYPE.update("component")
|
||||||
|
LEGACY_INSTALLER_COMPONENT_CLASS.update(component.clazz)
|
||||||
|
LEGACY_INSTALLER_COMPONENT_ACTIVITY.update(component.activity)
|
||||||
|
}
|
||||||
|
LegacyInstallerComponent.Unspecified -> {
|
||||||
|
LEGACY_INSTALLER_COMPONENT_TYPE.update("unspecified")
|
||||||
|
LEGACY_INSTALLER_COMPONENT_CLASS.update("")
|
||||||
|
LEGACY_INSTALLER_COMPONENT_ACTIVITY.update("")
|
||||||
|
}
|
||||||
|
LegacyInstallerComponent.AlwaysChoose -> {
|
||||||
|
LEGACY_INSTALLER_COMPONENT_TYPE.update("always_choose")
|
||||||
|
LEGACY_INSTALLER_COMPONENT_CLASS.update("")
|
||||||
|
LEGACY_INSTALLER_COMPONENT_ACTIVITY.update("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun setAutoUpdate(allow: Boolean) =
|
override suspend fun setAutoUpdate(allow: Boolean) =
|
||||||
AUTO_UPDATE.update(allow)
|
AUTO_UPDATE.update(allow)
|
||||||
|
|
||||||
@ -125,6 +151,18 @@ class PreferenceSettingsRepository(
|
|||||||
private fun mapSettings(preferences: Preferences): Settings {
|
private fun mapSettings(preferences: Preferences): Settings {
|
||||||
val installerType =
|
val installerType =
|
||||||
InstallerType.valueOf(preferences[INSTALLER_TYPE] ?: InstallerType.Default.name)
|
InstallerType.valueOf(preferences[INSTALLER_TYPE] ?: InstallerType.Default.name)
|
||||||
|
val legacyInstallerComponent = when (preferences[LEGACY_INSTALLER_COMPONENT_TYPE]) {
|
||||||
|
"component" -> {
|
||||||
|
preferences[LEGACY_INSTALLER_COMPONENT_CLASS]?.takeIf { it.isNotBlank() }?.let { cls ->
|
||||||
|
preferences[LEGACY_INSTALLER_COMPONENT_ACTIVITY]?.takeIf { it.isNotBlank() }?.let { act ->
|
||||||
|
LegacyInstallerComponent.Component(cls, act)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"unspecified" -> LegacyInstallerComponent.Unspecified
|
||||||
|
"always_choose" -> LegacyInstallerComponent.AlwaysChoose
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
val language = preferences[LANGUAGE] ?: "system"
|
val language = preferences[LANGUAGE] ?: "system"
|
||||||
val incompatibleVersions = preferences[INCOMPATIBLE_VERSIONS] ?: false
|
val incompatibleVersions = preferences[INCOMPATIBLE_VERSIONS] ?: false
|
||||||
@ -154,6 +192,7 @@ class PreferenceSettingsRepository(
|
|||||||
theme = theme,
|
theme = theme,
|
||||||
dynamicTheme = dynamicTheme,
|
dynamicTheme = dynamicTheme,
|
||||||
installerType = installerType,
|
installerType = installerType,
|
||||||
|
legacyInstallerComponent = legacyInstallerComponent,
|
||||||
autoUpdate = autoUpdate,
|
autoUpdate = autoUpdate,
|
||||||
autoSync = autoSync,
|
autoSync = autoSync,
|
||||||
sortOrder = sortOrder,
|
sortOrder = sortOrder,
|
||||||
@ -185,6 +224,9 @@ class PreferenceSettingsRepository(
|
|||||||
val LAST_CLEAN_UP = longPreferencesKey("key_last_clean_up_time")
|
val LAST_CLEAN_UP = longPreferencesKey("key_last_clean_up_time")
|
||||||
val FAVOURITE_APPS = stringSetPreferencesKey("key_favourite_apps")
|
val FAVOURITE_APPS = stringSetPreferencesKey("key_favourite_apps")
|
||||||
val HOME_SCREEN_SWIPING = booleanPreferencesKey("key_home_swiping")
|
val HOME_SCREEN_SWIPING = booleanPreferencesKey("key_home_swiping")
|
||||||
|
val LEGACY_INSTALLER_COMPONENT_CLASS = stringPreferencesKey("key_legacy_installer_component_class")
|
||||||
|
val LEGACY_INSTALLER_COMPONENT_ACTIVITY = stringPreferencesKey("key_legacy_installer_component_activity")
|
||||||
|
val LEGACY_INSTALLER_COMPONENT_TYPE = stringPreferencesKey("key_legacy_installer_component_type")
|
||||||
|
|
||||||
// Enums
|
// Enums
|
||||||
val THEME = stringPreferencesKey("key_theme")
|
val THEME = stringPreferencesKey("key_theme")
|
||||||
@ -200,6 +242,28 @@ class PreferenceSettingsRepository(
|
|||||||
set(UNSTABLE_UPDATES, settings.unstableUpdate)
|
set(UNSTABLE_UPDATES, settings.unstableUpdate)
|
||||||
set(THEME, settings.theme.name)
|
set(THEME, settings.theme.name)
|
||||||
set(DYNAMIC_THEME, settings.dynamicTheme)
|
set(DYNAMIC_THEME, settings.dynamicTheme)
|
||||||
|
when (settings.legacyInstallerComponent) {
|
||||||
|
is LegacyInstallerComponent.Component -> {
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_TYPE, "component")
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_CLASS, settings.legacyInstallerComponent.clazz)
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_ACTIVITY, settings.legacyInstallerComponent.activity)
|
||||||
|
}
|
||||||
|
LegacyInstallerComponent.Unspecified -> {
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_TYPE, "unspecified")
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_CLASS, "")
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_ACTIVITY, "")
|
||||||
|
}
|
||||||
|
LegacyInstallerComponent.AlwaysChoose -> {
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_TYPE, "always_choose")
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_CLASS, "")
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_ACTIVITY, "")
|
||||||
|
}
|
||||||
|
null -> {
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_TYPE, "")
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_CLASS, "")
|
||||||
|
set(LEGACY_INSTALLER_COMPONENT_ACTIVITY, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
set(INSTALLER_TYPE, settings.installerType.name)
|
set(INSTALLER_TYPE, settings.installerType.name)
|
||||||
set(AUTO_UPDATE, settings.autoUpdate)
|
set(AUTO_UPDATE, settings.autoUpdate)
|
||||||
set(AUTO_SYNC, settings.autoSync.name)
|
set(AUTO_SYNC, settings.autoSync.name)
|
||||||
|
@ -3,6 +3,7 @@ package com.looker.droidify.datastore
|
|||||||
import androidx.datastore.core.Serializer
|
import androidx.datastore.core.Serializer
|
||||||
import com.looker.droidify.datastore.model.AutoSync
|
import com.looker.droidify.datastore.model.AutoSync
|
||||||
import com.looker.droidify.datastore.model.InstallerType
|
import com.looker.droidify.datastore.model.InstallerType
|
||||||
|
import com.looker.droidify.datastore.model.LegacyInstallerComponent
|
||||||
import com.looker.droidify.datastore.model.ProxyPreference
|
import com.looker.droidify.datastore.model.ProxyPreference
|
||||||
import com.looker.droidify.datastore.model.SortOrder
|
import com.looker.droidify.datastore.model.SortOrder
|
||||||
import com.looker.droidify.datastore.model.Theme
|
import com.looker.droidify.datastore.model.Theme
|
||||||
@ -29,6 +30,7 @@ data class Settings(
|
|||||||
val theme: Theme = Theme.SYSTEM,
|
val theme: Theme = Theme.SYSTEM,
|
||||||
val dynamicTheme: Boolean = false,
|
val dynamicTheme: Boolean = false,
|
||||||
val installerType: InstallerType = InstallerType.Default,
|
val installerType: InstallerType = InstallerType.Default,
|
||||||
|
val legacyInstallerComponent: LegacyInstallerComponent? = null,
|
||||||
val autoUpdate: Boolean = false,
|
val autoUpdate: Boolean = false,
|
||||||
val autoSync: AutoSync = AutoSync.WIFI_ONLY,
|
val autoSync: AutoSync = AutoSync.WIFI_ONLY,
|
||||||
val sortOrder: SortOrder = SortOrder.UPDATED,
|
val sortOrder: SortOrder = SortOrder.UPDATED,
|
||||||
|
@ -3,6 +3,7 @@ package com.looker.droidify.datastore
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.looker.droidify.datastore.model.AutoSync
|
import com.looker.droidify.datastore.model.AutoSync
|
||||||
import com.looker.droidify.datastore.model.InstallerType
|
import com.looker.droidify.datastore.model.InstallerType
|
||||||
|
import com.looker.droidify.datastore.model.LegacyInstallerComponent
|
||||||
import com.looker.droidify.datastore.model.ProxyType
|
import com.looker.droidify.datastore.model.ProxyType
|
||||||
import com.looker.droidify.datastore.model.SortOrder
|
import com.looker.droidify.datastore.model.SortOrder
|
||||||
import com.looker.droidify.datastore.model.Theme
|
import com.looker.droidify.datastore.model.Theme
|
||||||
@ -37,6 +38,8 @@ interface SettingsRepository {
|
|||||||
|
|
||||||
suspend fun setInstallerType(installerType: InstallerType)
|
suspend fun setInstallerType(installerType: InstallerType)
|
||||||
|
|
||||||
|
suspend fun setLegacyInstallerComponent(component: LegacyInstallerComponent?)
|
||||||
|
|
||||||
suspend fun setAutoUpdate(allow: Boolean)
|
suspend fun setAutoUpdate(allow: Boolean)
|
||||||
|
|
||||||
suspend fun setAutoSync(autoSync: AutoSync)
|
suspend fun setAutoSync(autoSync: AutoSync)
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.looker.droidify.datastore.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
sealed class LegacyInstallerComponent {
|
||||||
|
@Serializable
|
||||||
|
object Unspecified : LegacyInstallerComponent()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
object AlwaysChoose : LegacyInstallerComponent()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Component(
|
||||||
|
val clazz: String,
|
||||||
|
val activity: String,
|
||||||
|
) : LegacyInstallerComponent() {
|
||||||
|
fun update(
|
||||||
|
newClazz: String? = null,
|
||||||
|
newActivity: String? = null,
|
||||||
|
): Component = copy(
|
||||||
|
clazz = newClazz ?: clazz,
|
||||||
|
activity = newActivity ?: activity
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,3 @@
|
|||||||
@file:Suppress("unused")
|
|
||||||
|
|
||||||
package com.looker.droidify.di
|
package com.looker.droidify.di
|
||||||
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
|
@ -22,9 +22,6 @@ data class Repo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val String.isOnion: Boolean
|
|
||||||
get() = endsWith(".onion")
|
|
||||||
|
|
||||||
data class AntiFeature(
|
data class AntiFeature(
|
||||||
val id: Long,
|
val id: Long,
|
||||||
val name: String,
|
val name: String,
|
||||||
|
@ -51,7 +51,6 @@ open class DrawableWrapper(val drawable: Drawable) : Drawable() {
|
|||||||
drawable.colorFilter = colorFilter
|
drawable.colorFilter = colorFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Deprecated in Java")
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
override fun getOpacity(): Int = drawable.opacity
|
override fun getOpacity(): Int = drawable.opacity
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,10 @@ package com.looker.droidify.index
|
|||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.database.sqlite.SQLiteDatabase
|
import android.database.sqlite.SQLiteDatabase
|
||||||
import com.fasterxml.jackson.core.JsonToken
|
import com.fasterxml.jackson.core.JsonToken
|
||||||
import com.looker.core.common.extension.Json
|
import com.looker.droidify.utility.common.extension.Json
|
||||||
import com.looker.droidify.utility.common.extension.asSequence
|
import com.looker.droidify.utility.common.extension.asSequence
|
||||||
import com.looker.core.common.extension.collectNotNull
|
import com.looker.droidify.utility.common.extension.collectNotNull
|
||||||
import com.looker.core.common.extension.writeDictionary
|
import com.looker.droidify.utility.common.extension.writeDictionary
|
||||||
import com.looker.droidify.model.Product
|
import com.looker.droidify.model.Product
|
||||||
import com.looker.droidify.model.Release
|
import com.looker.droidify.model.Release
|
||||||
import com.looker.droidify.utility.serialization.product
|
import com.looker.droidify.utility.serialization.product
|
||||||
@ -82,9 +82,9 @@ class IndexMerger(file: File) : Closeable {
|
|||||||
closeTransaction()
|
closeTransaction()
|
||||||
db.rawQuery(
|
db.rawQuery(
|
||||||
"""SELECT product.description, product.data AS pd, releases.data AS rd FROM product
|
"""SELECT product.description, product.data AS pd, releases.data AS rd FROM product
|
||||||
LEFT JOIN releases ON product.package_name = releases.package_name""",
|
LEFT JOIN releases ON product.package_name = releases.package_name""",
|
||||||
null
|
null
|
||||||
)?.use { cursor ->
|
).use { cursor ->
|
||||||
cursor.asSequence().map { currentCursor ->
|
cursor.asSequence().map { currentCursor ->
|
||||||
val description = currentCursor.getString(0)
|
val description = currentCursor.getString(0)
|
||||||
val product = Json.factory.createParser(currentCursor.getBlob(1)).use {
|
val product = Json.factory.createParser(currentCursor.getBlob(1)).use {
|
||||||
|
@ -5,16 +5,27 @@ import androidx.core.os.ConfigurationCompat.getLocales
|
|||||||
import androidx.core.os.LocaleListCompat
|
import androidx.core.os.LocaleListCompat
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.fasterxml.jackson.core.JsonToken
|
import com.fasterxml.jackson.core.JsonToken
|
||||||
import com.looker.droidify.utility.common.SdkCheck
|
import com.looker.droidify.utility.common.extension.Json
|
||||||
import com.looker.core.common.extension.Json
|
import com.looker.droidify.utility.common.extension.collectDistinctNotEmptyStrings
|
||||||
import com.looker.core.common.extension.collectDistinctNotEmptyStrings
|
import com.looker.droidify.utility.common.extension.collectNotNull
|
||||||
import com.looker.core.common.extension.collectNotNull
|
import com.looker.droidify.utility.common.extension.forEach
|
||||||
import com.looker.core.common.extension.forEach
|
import com.looker.droidify.utility.common.extension.forEachKey
|
||||||
import com.looker.core.common.extension.forEachKey
|
import com.looker.droidify.utility.common.extension.illegal
|
||||||
import com.looker.core.common.extension.illegal
|
|
||||||
import com.looker.droidify.utility.common.nullIfEmpty
|
|
||||||
import com.looker.droidify.model.Product
|
import com.looker.droidify.model.Product
|
||||||
|
import com.looker.droidify.model.Product.Donate.Bitcoin
|
||||||
|
import com.looker.droidify.model.Product.Donate.Liberapay
|
||||||
|
import com.looker.droidify.model.Product.Donate.Litecoin
|
||||||
|
import com.looker.droidify.model.Product.Donate.OpenCollective
|
||||||
|
import com.looker.droidify.model.Product.Donate.Regular
|
||||||
|
import com.looker.droidify.model.Product.Screenshot.Type.LARGE_TABLET
|
||||||
|
import com.looker.droidify.model.Product.Screenshot.Type.PHONE
|
||||||
|
import com.looker.droidify.model.Product.Screenshot.Type.SMALL_TABLET
|
||||||
|
import com.looker.droidify.model.Product.Screenshot.Type.TV
|
||||||
|
import com.looker.droidify.model.Product.Screenshot.Type.VIDEO
|
||||||
|
import com.looker.droidify.model.Product.Screenshot.Type.WEAR
|
||||||
import com.looker.droidify.model.Release
|
import com.looker.droidify.model.Release
|
||||||
|
import com.looker.droidify.utility.common.SdkCheck
|
||||||
|
import com.looker.droidify.utility.common.nullIfEmpty
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
object IndexV1Parser {
|
object IndexV1Parser {
|
||||||
@ -32,9 +43,12 @@ object IndexV1Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class Screenshots(
|
private class Screenshots(
|
||||||
|
val video: List<String>,
|
||||||
val phone: List<String>,
|
val phone: List<String>,
|
||||||
val smallTablet: List<String>,
|
val smallTablet: List<String>,
|
||||||
val largeTablet: List<String>
|
val largeTablet: List<String>,
|
||||||
|
val wear: List<String>,
|
||||||
|
val tv: List<String>,
|
||||||
)
|
)
|
||||||
|
|
||||||
private class Localized(
|
private class Localized(
|
||||||
@ -90,10 +104,9 @@ object IndexV1Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> Map<String, Localized>.find(callback: (String, Localized) -> T?): T? {
|
private fun <T> Map<String, Localized>.find(callback: (String, Localized) -> T?): T? {
|
||||||
return getAndCall("en-US", callback) ?: getAndCall("en_US", callback) ?: getAndCall(
|
return getAndCall("en-US", callback)
|
||||||
"en",
|
?: getAndCall("en_US", callback)
|
||||||
callback
|
?: getAndCall("en", callback)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> Map<String, Localized>.findLocalized(callback: (Localized) -> T?): T? {
|
private fun <T> Map<String, Localized>.findLocalized(callback: (Localized) -> T?): T? {
|
||||||
@ -122,12 +135,11 @@ object IndexV1Parser {
|
|||||||
|
|
||||||
internal object DonateComparator : Comparator<Product.Donate> {
|
internal object DonateComparator : Comparator<Product.Donate> {
|
||||||
private val classes = listOf(
|
private val classes = listOf(
|
||||||
Product.Donate.Regular::class,
|
Regular::class,
|
||||||
Product.Donate.Bitcoin::class,
|
Bitcoin::class,
|
||||||
Product.Donate.Litecoin::class,
|
Litecoin::class,
|
||||||
Product.Donate.Flattr::class,
|
Liberapay::class,
|
||||||
Product.Donate.Liberapay::class,
|
OpenCollective::class
|
||||||
Product.Donate.OpenCollective::class
|
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun compare(donate1: Product.Donate, donate2: Product.Donate): Int {
|
override fun compare(donate1: Product.Donate, donate2: Product.Donate): Int {
|
||||||
@ -236,14 +248,17 @@ object IndexV1Parser {
|
|||||||
private const val KEY_PRODUCT_LICENSE = "license"
|
private const val KEY_PRODUCT_LICENSE = "license"
|
||||||
private const val KEY_PRODUCT_DONATE = "donate"
|
private const val KEY_PRODUCT_DONATE = "donate"
|
||||||
private const val KEY_PRODUCT_BITCOIN = "bitcoin"
|
private const val KEY_PRODUCT_BITCOIN = "bitcoin"
|
||||||
private const val KEY_PRODUCT_FLATTRID = "flattrID"
|
private const val KEY_PRODUCT_LIBERAPAYID = "liberapay"
|
||||||
private const val KEY_PRODUCT_LIBERAPAYID = "liberapayID"
|
private const val KEY_PRODUCT_LITECOIN = "litecoin"
|
||||||
private const val KEY_PRODUCT_OPENCOLLECTIVE = "openCollective"
|
private const val KEY_PRODUCT_OPENCOLLECTIVE = "openCollective"
|
||||||
private const val KEY_PRODUCT_LOCALIZED = "localized"
|
private const val KEY_PRODUCT_LOCALIZED = "localized"
|
||||||
private const val KEY_PRODUCT_WHATSNEW = "whatsNew"
|
private const val KEY_PRODUCT_WHATSNEW = "whatsNew"
|
||||||
private const val KEY_PRODUCT_PHONESCREENSHOTS = "phoneScreenshots"
|
private const val KEY_PRODUCT_PHONE_SCREENSHOTS = "phoneScreenshots"
|
||||||
private const val KEY_PRODUCT_SEVENINCHSCREENSHOTS = "sevenInchScreenshots"
|
private const val KEY_PRODUCT_SEVEN_INCH_SCREENSHOTS = "sevenInchScreenshots"
|
||||||
private const val KEY_PRODUCT_TENINCHSCREENSHOTS = "tenInchScreenshots"
|
private const val KEY_PRODUCT_TEN_INCH_SCREENSHOTS = "tenInchScreenshots"
|
||||||
|
private const val KEY_PRODUCT_WEAR_SCREENSHOTS = "wearScreenshots"
|
||||||
|
private const val KEY_PRODUCT_TV_SCREENSHOTS = "tvScreenshots"
|
||||||
|
private const val KEY_PRODUCT_VIDEO = "video"
|
||||||
|
|
||||||
private fun JsonParser.parseProduct(repositoryId: Long): Product {
|
private fun JsonParser.parseProduct(repositoryId: Long): Product {
|
||||||
var packageName = ""
|
var packageName = ""
|
||||||
@ -293,16 +308,11 @@ object IndexV1Parser {
|
|||||||
key.string(KEY_PRODUCT_LICENSE) -> licenses += valueAsString.split(',')
|
key.string(KEY_PRODUCT_LICENSE) -> licenses += valueAsString.split(',')
|
||||||
.filter { it.isNotEmpty() }
|
.filter { it.isNotEmpty() }
|
||||||
|
|
||||||
key.string(KEY_PRODUCT_DONATE) -> donates += Product.Donate.Regular(valueAsString)
|
key.string(KEY_PRODUCT_DONATE) -> donates += Regular(valueAsString)
|
||||||
key.string(KEY_PRODUCT_BITCOIN) -> donates += Product.Donate.Bitcoin(valueAsString)
|
key.string(KEY_PRODUCT_BITCOIN) -> donates += Bitcoin(valueAsString)
|
||||||
key.string(KEY_PRODUCT_FLATTRID) -> donates += Product.Donate.Flattr(valueAsString)
|
key.string(KEY_PRODUCT_LIBERAPAYID) -> donates += Liberapay(valueAsString)
|
||||||
key.string(KEY_PRODUCT_LIBERAPAYID) -> donates += Product.Donate.Liberapay(
|
key.string(KEY_PRODUCT_LITECOIN) -> donates += Litecoin(valueAsString)
|
||||||
valueAsString
|
key.string(KEY_PRODUCT_OPENCOLLECTIVE) -> donates += OpenCollective(valueAsString)
|
||||||
)
|
|
||||||
|
|
||||||
key.string(KEY_PRODUCT_OPENCOLLECTIVE) -> donates += Product.Donate.OpenCollective(
|
|
||||||
valueAsString
|
|
||||||
)
|
|
||||||
|
|
||||||
key.dictionary(KEY_PRODUCT_LOCALIZED) -> forEachKey { localizedKey ->
|
key.dictionary(KEY_PRODUCT_LOCALIZED) -> forEachKey { localizedKey ->
|
||||||
if (localizedKey.token == JsonToken.START_OBJECT) {
|
if (localizedKey.token == JsonToken.START_OBJECT) {
|
||||||
@ -315,6 +325,9 @@ object IndexV1Parser {
|
|||||||
var phone = emptyList<String>()
|
var phone = emptyList<String>()
|
||||||
var smallTablet = emptyList<String>()
|
var smallTablet = emptyList<String>()
|
||||||
var largeTablet = emptyList<String>()
|
var largeTablet = emptyList<String>()
|
||||||
|
var wear = emptyList<String>()
|
||||||
|
var tv = emptyList<String>()
|
||||||
|
var video = emptyList<String>()
|
||||||
forEachKey {
|
forEachKey {
|
||||||
when {
|
when {
|
||||||
it.string(KEY_PRODUCT_NAME) -> name = valueAsString
|
it.string(KEY_PRODUCT_NAME) -> name = valueAsString
|
||||||
@ -322,39 +335,42 @@ object IndexV1Parser {
|
|||||||
it.string(KEY_PRODUCT_DESCRIPTION) -> description = valueAsString
|
it.string(KEY_PRODUCT_DESCRIPTION) -> description = valueAsString
|
||||||
it.string(KEY_PRODUCT_WHATSNEW) -> whatsNew = valueAsString
|
it.string(KEY_PRODUCT_WHATSNEW) -> whatsNew = valueAsString
|
||||||
it.string(KEY_PRODUCT_ICON) -> metadataIcon = valueAsString
|
it.string(KEY_PRODUCT_ICON) -> metadataIcon = valueAsString
|
||||||
it.array(KEY_PRODUCT_PHONESCREENSHOTS) ->
|
it.string(KEY_PRODUCT_VIDEO) -> video = listOf(valueAsString)
|
||||||
phone =
|
it.array(KEY_PRODUCT_PHONE_SCREENSHOTS) ->
|
||||||
collectDistinctNotEmptyStrings()
|
phone = collectDistinctNotEmptyStrings()
|
||||||
|
|
||||||
it.array(KEY_PRODUCT_SEVENINCHSCREENSHOTS) ->
|
it.array(KEY_PRODUCT_SEVEN_INCH_SCREENSHOTS) ->
|
||||||
smallTablet =
|
smallTablet = collectDistinctNotEmptyStrings()
|
||||||
collectDistinctNotEmptyStrings()
|
|
||||||
|
|
||||||
it.array(KEY_PRODUCT_TENINCHSCREENSHOTS) ->
|
it.array(KEY_PRODUCT_TEN_INCH_SCREENSHOTS) ->
|
||||||
largeTablet =
|
largeTablet = collectDistinctNotEmptyStrings()
|
||||||
collectDistinctNotEmptyStrings()
|
|
||||||
|
it.array(KEY_PRODUCT_WEAR_SCREENSHOTS) ->
|
||||||
|
wear = collectDistinctNotEmptyStrings()
|
||||||
|
|
||||||
|
it.array(KEY_PRODUCT_TV_SCREENSHOTS) ->
|
||||||
|
tv = collectDistinctNotEmptyStrings()
|
||||||
|
|
||||||
else -> skipChildren()
|
else -> skipChildren()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val isScreenshotEmpty =
|
||||||
|
arrayOf(video, phone, smallTablet, largeTablet, wear, tv)
|
||||||
|
.any { it.isNotEmpty() }
|
||||||
val screenshots =
|
val screenshots =
|
||||||
if (sequenceOf(
|
if (isScreenshotEmpty) {
|
||||||
phone,
|
Screenshots(video, phone, smallTablet, largeTablet, wear, tv)
|
||||||
smallTablet,
|
|
||||||
largeTablet
|
|
||||||
).any { it.isNotEmpty() }
|
|
||||||
) {
|
|
||||||
Screenshots(phone, smallTablet, largeTablet)
|
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
localizedMap[locale] = Localized(
|
localizedMap[locale] = Localized(
|
||||||
name,
|
name = name,
|
||||||
summary,
|
summary = summary,
|
||||||
description,
|
description = description,
|
||||||
whatsNew,
|
whatsNew = whatsNew,
|
||||||
metadataIcon.nullIfEmpty()?.let { "$locale/$it" }.orEmpty(),
|
metadataIcon = metadataIcon.nullIfEmpty()?.let { "$locale/$it" }
|
||||||
screenshots
|
.orEmpty(),
|
||||||
|
screenshots = screenshots,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
skipChildren()
|
skipChildren()
|
||||||
@ -377,28 +393,14 @@ object IndexV1Parser {
|
|||||||
}
|
}
|
||||||
val screenshotPairs =
|
val screenshotPairs =
|
||||||
localizedMap.find { key, localized -> localized.screenshots?.let { Pair(key, it) } }
|
localizedMap.find { key, localized -> localized.screenshots?.let { Pair(key, it) } }
|
||||||
val screenshots = screenshotPairs
|
val screenshots = screenshotPairs?.let { (key, screenshots) ->
|
||||||
?.let { (key, screenshots) ->
|
screenshots.video.map { Product.Screenshot(key, VIDEO, it) } +
|
||||||
screenshots.phone.asSequence()
|
screenshots.phone.map { Product.Screenshot(key, PHONE, it) } +
|
||||||
.map { Product.Screenshot(key, Product.Screenshot.Type.PHONE, it) } +
|
screenshots.smallTablet.map { Product.Screenshot(key, SMALL_TABLET, it) } +
|
||||||
screenshots.smallTablet.asSequence()
|
screenshots.largeTablet.map { Product.Screenshot(key, LARGE_TABLET, it) } +
|
||||||
.map {
|
screenshots.wear.map { Product.Screenshot(key, WEAR, it) } +
|
||||||
Product.Screenshot(
|
screenshots.tv.map { Product.Screenshot(key, TV, it) }
|
||||||
key,
|
}.orEmpty()
|
||||||
Product.Screenshot.Type.SMALL_TABLET,
|
|
||||||
it
|
|
||||||
)
|
|
||||||
} +
|
|
||||||
screenshots.largeTablet.asSequence()
|
|
||||||
.map {
|
|
||||||
Product.Screenshot(
|
|
||||||
key,
|
|
||||||
Product.Screenshot.Type.LARGE_TABLET,
|
|
||||||
it
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.orEmpty().toList()
|
|
||||||
return Product(
|
return Product(
|
||||||
repositoryId = repositoryId,
|
repositoryId = repositoryId,
|
||||||
packageName = packageName,
|
packageName = packageName,
|
||||||
|
@ -16,6 +16,8 @@ import com.looker.droidify.installer.installers.session.SessionInstaller
|
|||||||
import com.looker.droidify.installer.installers.shizuku.ShizukuInstaller
|
import com.looker.droidify.installer.installers.shizuku.ShizukuInstaller
|
||||||
import com.looker.droidify.installer.model.InstallItem
|
import com.looker.droidify.installer.model.InstallItem
|
||||||
import com.looker.droidify.installer.model.InstallState
|
import com.looker.droidify.installer.model.InstallState
|
||||||
|
import com.looker.droidify.installer.notification.createInstallNotification
|
||||||
|
import com.looker.droidify.installer.notification.installNotification
|
||||||
import com.looker.droidify.installer.notification.removeInstallNotification
|
import com.looker.droidify.installer.notification.removeInstallNotification
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
@ -30,7 +32,7 @@ import kotlinx.coroutines.sync.withLock
|
|||||||
|
|
||||||
class InstallManager(
|
class InstallManager(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
settingsRepository: SettingsRepository
|
private val settingsRepository: SettingsRepository
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val installItems = Channel<InstallItem>()
|
private val installItems = Channel<InstallItem>()
|
||||||
@ -87,6 +89,13 @@ class InstallManager(
|
|||||||
}.consumeEach { item ->
|
}.consumeEach { item ->
|
||||||
if (state.value.containsKey(item.packageName)) {
|
if (state.value.containsKey(item.packageName)) {
|
||||||
updateState { put(item.packageName, InstallState.Installing) }
|
updateState { put(item.packageName, InstallState.Installing) }
|
||||||
|
context.notificationManager?.installNotification(
|
||||||
|
packageName = item.packageName.name,
|
||||||
|
notification = context.createInstallNotification(
|
||||||
|
appName = item.packageName.name,
|
||||||
|
state = InstallState.Installing,
|
||||||
|
)
|
||||||
|
)
|
||||||
val success = installer.use {
|
val success = installer.use {
|
||||||
it.install(item)
|
it.install(item)
|
||||||
}
|
}
|
||||||
@ -106,7 +115,7 @@ class InstallManager(
|
|||||||
private suspend fun setInstaller(installerType: InstallerType) {
|
private suspend fun setInstaller(installerType: InstallerType) {
|
||||||
lock.withLock {
|
lock.withLock {
|
||||||
_installer = when (installerType) {
|
_installer = when (installerType) {
|
||||||
InstallerType.LEGACY -> LegacyInstaller(context)
|
InstallerType.LEGACY -> LegacyInstaller(context, settingsRepository)
|
||||||
InstallerType.SESSION -> SessionInstaller(context)
|
InstallerType.SESSION -> SessionInstaller(context)
|
||||||
InstallerType.SHIZUKU -> ShizukuInstaller(context)
|
InstallerType.SHIZUKU -> ShizukuInstaller(context)
|
||||||
InstallerType.ROOT -> RootInstaller(context)
|
InstallerType.ROOT -> RootInstaller(context)
|
||||||
|
@ -1,49 +1,80 @@
|
|||||||
package com.looker.droidify.installer.installers
|
package com.looker.droidify.installer.installers
|
||||||
|
|
||||||
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.util.AndroidRuntimeException
|
import android.util.AndroidRuntimeException
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.looker.droidify.utility.common.SdkCheck
|
import com.looker.droidify.R
|
||||||
import com.looker.droidify.utility.common.cache.Cache
|
import com.looker.droidify.datastore.SettingsRepository
|
||||||
|
import com.looker.droidify.datastore.get
|
||||||
|
import com.looker.droidify.datastore.model.LegacyInstallerComponent
|
||||||
import com.looker.droidify.domain.model.PackageName
|
import com.looker.droidify.domain.model.PackageName
|
||||||
import com.looker.droidify.installer.model.InstallItem
|
import com.looker.droidify.installer.model.InstallItem
|
||||||
import com.looker.droidify.installer.model.InstallState
|
import com.looker.droidify.installer.model.InstallState
|
||||||
import kotlin.coroutines.resume
|
import com.looker.droidify.utility.common.SdkCheck
|
||||||
|
import com.looker.droidify.utility.common.cache.Cache
|
||||||
|
import com.looker.droidify.utility.common.extension.intent
|
||||||
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
internal class LegacyInstaller(private val context: Context) : Installer {
|
class LegacyInstaller(
|
||||||
|
private val context: Context,
|
||||||
|
private val settingsRepository: SettingsRepository
|
||||||
|
) : Installer {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val APK_MIME = "application/vnd.android.package-archive"
|
private const val APK_MIME = "application/vnd.android.package-archive"
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun install(
|
override suspend fun install(
|
||||||
installItem: InstallItem
|
installItem: InstallItem,
|
||||||
): InstallState = suspendCancellableCoroutine { cont ->
|
): InstallState {
|
||||||
val (uri, flags) = if (SdkCheck.isNougat) {
|
val installFlag = if (SdkCheck.isNougat) Intent.FLAG_GRANT_READ_URI_PERMISSION else 0
|
||||||
Cache.getReleaseUri(
|
val fileUri = if (SdkCheck.isNougat) {
|
||||||
context,
|
Cache.getReleaseUri(context, installItem.installFileName)
|
||||||
installItem.installFileName
|
|
||||||
) to Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
||||||
} else {
|
} else {
|
||||||
val file = Cache.getReleaseFile(context, installItem.installFileName)
|
Cache.getReleaseFile(context, installItem.installFileName).toUri()
|
||||||
file.toUri() to 0
|
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
context.startActivity(
|
val comp = settingsRepository.get { legacyInstallerComponent }.firstOrNull()
|
||||||
Intent(Intent.ACTION_INSTALL_PACKAGE).setDataAndType(uri, APK_MIME).setFlags(flags)
|
|
||||||
)
|
return suspendCancellableCoroutine { cont ->
|
||||||
cont.resume(InstallState.Installed)
|
val intent = Intent(Intent.ACTION_INSTALL_PACKAGE).apply {
|
||||||
} catch (e: AndroidRuntimeException) {
|
setDataAndType(fileUri, APK_MIME)
|
||||||
context.startActivity(
|
flags = installFlag
|
||||||
Intent(Intent.ACTION_INSTALL_PACKAGE).setDataAndType(uri, APK_MIME)
|
when (comp) {
|
||||||
.setFlags(flags or Intent.FLAG_ACTIVITY_NEW_TASK)
|
is LegacyInstallerComponent.Component -> {
|
||||||
)
|
component = ComponentName(comp.clazz, comp.activity)
|
||||||
cont.resume(InstallState.Installed)
|
}
|
||||||
} catch (e: Exception) {
|
else -> {
|
||||||
cont.resume(InstallState.Failed)
|
// For Unspecified and AlwaysChoose, don't set component
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val installIntent = when (comp) {
|
||||||
|
LegacyInstallerComponent.AlwaysChoose -> Intent.createChooser(intent, context.getString(
|
||||||
|
R.string.select_installer))
|
||||||
|
else -> intent
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
context.startActivity(installIntent)
|
||||||
|
cont.resume(InstallState.Installed)
|
||||||
|
} catch (e: AndroidRuntimeException) {
|
||||||
|
installIntent.flags = installFlag or Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
try {
|
||||||
|
context.startActivity(installIntent)
|
||||||
|
cont.resume(InstallState.Installed)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
cont.resume(InstallState.Failed)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
cont.resume(InstallState.Failed)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,14 +84,14 @@ internal class LegacyInstaller(private val context: Context) : Installer {
|
|||||||
override fun close() {}
|
override fun close() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal suspend fun Context.uninstallPackage(packageName: PackageName) =
|
suspend fun Context.uninstallPackage(packageName: PackageName) =
|
||||||
suspendCancellableCoroutine { cont ->
|
suspendCancellableCoroutine { cont ->
|
||||||
try {
|
try {
|
||||||
startActivity(
|
startActivity(
|
||||||
Intent(
|
intent(Intent.ACTION_UNINSTALL_PACKAGE) {
|
||||||
Intent.ACTION_UNINSTALL_PACKAGE,
|
data = "package:${packageName.name}".toUri()
|
||||||
"package:${packageName.name}".toUri()
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
}
|
||||||
)
|
)
|
||||||
cont.resume(Unit)
|
cont.resume(Unit)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -1,70 +1,34 @@
|
|||||||
package com.looker.droidify.installer.installers.root
|
package com.looker.droidify.installer.installers.root
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.looker.droidify.utility.common.SdkCheck
|
|
||||||
import com.looker.droidify.utility.common.cache.Cache
|
|
||||||
import com.looker.droidify.domain.model.PackageName
|
import com.looker.droidify.domain.model.PackageName
|
||||||
import com.looker.droidify.installer.installers.Installer
|
import com.looker.droidify.installer.installers.Installer
|
||||||
import com.looker.droidify.installer.installers.uninstallPackage
|
import com.looker.droidify.installer.installers.uninstallPackage
|
||||||
import com.looker.droidify.installer.model.InstallItem
|
import com.looker.droidify.installer.model.InstallItem
|
||||||
import com.looker.droidify.installer.model.InstallState
|
import com.looker.droidify.installer.model.InstallState
|
||||||
|
import com.looker.droidify.utility.common.SdkCheck
|
||||||
|
import com.looker.droidify.utility.common.cache.Cache
|
||||||
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import java.io.File
|
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
internal class RootInstaller(private val context: Context) : Installer {
|
class RootInstaller(private val context: Context) : Installer {
|
||||||
|
|
||||||
private companion object {
|
|
||||||
const val ROOT_INSTALL_PACKAGE = "cat %s | pm install --user %s -t -r -S %s"
|
|
||||||
const val DELETE_PACKAGE = "%s rm %s"
|
|
||||||
|
|
||||||
val getCurrentUserState: String
|
|
||||||
get() = if (SdkCheck.isOreo) {
|
|
||||||
com.topjohnwu.superuser.Shell.cmd("am get-current-user").exec().out[0]
|
|
||||||
} else {
|
|
||||||
com.topjohnwu.superuser.Shell.cmd("dumpsys activity | grep -E \"mUserLru\"")
|
|
||||||
.exec().out[0].trim()
|
|
||||||
.removePrefix("mUserLru: [").removeSuffix("]")
|
|
||||||
}
|
|
||||||
|
|
||||||
val String.quote
|
|
||||||
get() = "\"${this.replace(Regex("""[\\$"`]""")) { c -> "\\${c.value}" }}\""
|
|
||||||
|
|
||||||
val getUtilBoxPath: String
|
|
||||||
get() {
|
|
||||||
listOf("toybox", "busybox").forEach {
|
|
||||||
val shellResult = com.topjohnwu.superuser.Shell.cmd("which $it").exec()
|
|
||||||
if (shellResult.out.isNotEmpty()) {
|
|
||||||
val utilBoxPath = shellResult.out.joinToString("")
|
|
||||||
if (utilBoxPath.isNotEmpty()) return utilBoxPath.quote
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
fun installCmd(file: File): String = String.format(
|
|
||||||
ROOT_INSTALL_PACKAGE,
|
|
||||||
file.absolutePath,
|
|
||||||
getCurrentUserState,
|
|
||||||
file.length()
|
|
||||||
)
|
|
||||||
|
|
||||||
fun deleteCmd(file: File): String = String.format(
|
|
||||||
DELETE_PACKAGE,
|
|
||||||
getUtilBoxPath,
|
|
||||||
file.absolutePath.quote
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun install(
|
override suspend fun install(
|
||||||
installItem: InstallItem
|
installItem: InstallItem,
|
||||||
): InstallState = suspendCancellableCoroutine { cont ->
|
): InstallState = suspendCancellableCoroutine { cont ->
|
||||||
val releaseFile = Cache.getReleaseFile(context, installItem.installFileName)
|
val releaseFile = Cache.getReleaseFile(context, installItem.installFileName)
|
||||||
com.topjohnwu.superuser.Shell.cmd(installCmd(releaseFile)).submit { shellResult ->
|
val installCommand = INSTALL_COMMAND.format(
|
||||||
|
releaseFile.absolutePath,
|
||||||
|
currentUser(),
|
||||||
|
releaseFile.length(),
|
||||||
|
)
|
||||||
|
Shell.cmd(installCommand).submit { shellResult ->
|
||||||
val result = if (shellResult.isSuccess) InstallState.Installed
|
val result = if (shellResult.isSuccess) InstallState.Installed
|
||||||
else InstallState.Failed
|
else InstallState.Failed
|
||||||
cont.resume(result)
|
cont.resume(result)
|
||||||
com.topjohnwu.superuser.Shell.cmd(deleteCmd(releaseFile)).submit()
|
val deleteCommand = DELETE_COMMAND.format(utilBox(), releaseFile.absolutePath)
|
||||||
|
Shell.cmd(deleteCommand).submit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,4 +36,34 @@ internal class RootInstaller(private val context: Context) : Installer {
|
|||||||
context.uninstallPackage(packageName)
|
context.uninstallPackage(packageName)
|
||||||
|
|
||||||
override fun close() {}
|
override fun close() {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val INSTALL_COMMAND = "cat %s | pm install --user %s -t -r -S %s"
|
||||||
|
private const val DELETE_COMMAND = "%s rm %s"
|
||||||
|
|
||||||
|
/** Returns the path of either toybox or busybox, or empty string if not found. */
|
||||||
|
private fun utilBox(): String {
|
||||||
|
listOf("toybox", "busybox").forEach {
|
||||||
|
// Returns the path of the requested [command], or empty string if not found
|
||||||
|
val out = Shell.cmd("which $it").exec().out
|
||||||
|
if (out.isEmpty()) return ""
|
||||||
|
if (out.first().contains("not found")) return ""
|
||||||
|
return out.first()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the current user of the device. */
|
||||||
|
private fun currentUser() = if (SdkCheck.isOreo) {
|
||||||
|
Shell.cmd("am get-current-user")
|
||||||
|
.exec()
|
||||||
|
.out[0]
|
||||||
|
} else {
|
||||||
|
Shell.cmd("dumpsys activity | grep -E \"mUserLru\"")
|
||||||
|
.exec()
|
||||||
|
.out[0]
|
||||||
|
.trim()
|
||||||
|
.removePrefix("mUserLru: [")
|
||||||
|
.removeSuffix("]")
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ import com.looker.droidify.installer.model.InstallState
|
|||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
internal class SessionInstaller(private val context: Context) : Installer {
|
class SessionInstaller(private val context: Context) : Installer {
|
||||||
|
|
||||||
private val installer = context.packageManager.packageInstaller
|
private val installer = context.packageManager.packageInstaller
|
||||||
private val intent = Intent(context, SessionInstallerReceiver::class.java)
|
private val intent = Intent(context, SessionInstallerReceiver::class.java)
|
||||||
|
@ -14,7 +14,7 @@ import java.io.BufferedReader
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
internal class ShizukuInstaller(private val context: Context) : Installer {
|
class ShizukuInstaller(private val context: Context) : Installer {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val SESSION_ID_REGEX = Regex("(?<=\\[).+?(?=])")
|
private val SESSION_ID_REGEX = Regex("(?<=\\[).+?(?=])")
|
||||||
|
@ -3,7 +3,7 @@ package com.looker.droidify.installer.model
|
|||||||
import com.looker.droidify.domain.model.PackageName
|
import com.looker.droidify.domain.model.PackageName
|
||||||
import com.looker.droidify.domain.model.toPackageName
|
import com.looker.droidify.domain.model.toPackageName
|
||||||
|
|
||||||
data class InstallItem(
|
class InstallItem(
|
||||||
val packageName: PackageName,
|
val packageName: PackageName,
|
||||||
val installFileName: String
|
val installFileName: String
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package com.looker.droidify.model
|
package com.looker.droidify.model
|
||||||
|
|
||||||
import com.looker.droidify.domain.model.Donation
|
import android.content.Context
|
||||||
import com.looker.droidify.domain.model.Screenshots
|
import com.looker.droidify.utility.common.extension.getColorFromAttr
|
||||||
|
import com.looker.droidify.utility.common.extension.videoPlaceHolder
|
||||||
|
import com.google.android.material.R as MaterialR
|
||||||
|
|
||||||
data class Product(
|
data class Product(
|
||||||
var repositoryId: Long,
|
var repositoryId: Long,
|
||||||
@ -33,29 +35,38 @@ data class Product(
|
|||||||
data class Regular(val url: String) : Donate()
|
data class Regular(val url: String) : Donate()
|
||||||
data class Bitcoin(val address: String) : Donate()
|
data class Bitcoin(val address: String) : Donate()
|
||||||
data class Litecoin(val address: String) : Donate()
|
data class Litecoin(val address: String) : Donate()
|
||||||
data class Flattr(val id: String) : Donate()
|
|
||||||
data class Liberapay(val id: String) : Donate()
|
data class Liberapay(val id: String) : Donate()
|
||||||
data class OpenCollective(val id: String) : Donate()
|
data class OpenCollective(val id: String) : Donate()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Screenshot(val locale: String, val type: Type, val path: String) {
|
class Screenshot(val locale: String, val type: Type, val path: String) {
|
||||||
enum class Type(val jsonName: String) {
|
enum class Type(val jsonName: String) {
|
||||||
|
VIDEO("video"),
|
||||||
PHONE("phone"),
|
PHONE("phone"),
|
||||||
SMALL_TABLET("smallTablet"),
|
SMALL_TABLET("smallTablet"),
|
||||||
LARGE_TABLET("largeTablet")
|
LARGE_TABLET("largeTablet"),
|
||||||
|
WEAR("wear"),
|
||||||
|
TV("tv")
|
||||||
}
|
}
|
||||||
|
|
||||||
val identifier: String
|
val identifier: String
|
||||||
get() = "$locale.${type.name}.$path"
|
get() = "$locale.${type.name}.$path"
|
||||||
|
|
||||||
fun url(
|
fun url(
|
||||||
|
context: Context,
|
||||||
repository: Repository,
|
repository: Repository,
|
||||||
packageName: String
|
packageName: String
|
||||||
): String {
|
): Any {
|
||||||
|
if (type == Type.VIDEO) return context.videoPlaceHolder.apply {
|
||||||
|
setTintList(context.getColorFromAttr(MaterialR.attr.colorOnSurfaceInverse))
|
||||||
|
}
|
||||||
val phoneType = when (type) {
|
val phoneType = when (type) {
|
||||||
Type.PHONE -> "phoneScreenshots"
|
Type.PHONE -> "phoneScreenshots"
|
||||||
Type.SMALL_TABLET -> "sevenInchScreenshots"
|
Type.SMALL_TABLET -> "sevenInchScreenshots"
|
||||||
Type.LARGE_TABLET -> "tenInchScreenshots"
|
Type.LARGE_TABLET -> "tenInchScreenshots"
|
||||||
|
Type.WEAR -> "wearScreenshots"
|
||||||
|
Type.TV -> "tvScreenshots"
|
||||||
|
else -> error("Should not be here, video url already returned")
|
||||||
}
|
}
|
||||||
return "${repository.address}/$packageName/$locale/$phoneType/$path"
|
return "${repository.address}/$packageName/$locale/$phoneType/$path"
|
||||||
}
|
}
|
||||||
@ -115,48 +126,3 @@ fun List<Pair<Product, Repository>>.findSuggested(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
//
|
|
||||||
//fun App.toProduct() = Product(
|
|
||||||
// packageName = metadata.packageName.name,
|
|
||||||
// name = metadata.name,
|
|
||||||
// summary = metadata.summary,
|
|
||||||
// description = metadata.description,
|
|
||||||
// whatsNew = metadata.whatsNew,
|
|
||||||
// icon = metadata.icon,
|
|
||||||
// metadataIcon = "",
|
|
||||||
// author = Product.Author(
|
|
||||||
// name = author.name,
|
|
||||||
// email = author.email,
|
|
||||||
// web = author.web,
|
|
||||||
// ),
|
|
||||||
// source = links.sourceCode,
|
|
||||||
// changelog = links.changelog,
|
|
||||||
// web = links.webSite,
|
|
||||||
// tracker = links.issueTracker,
|
|
||||||
// added = metadata.added,
|
|
||||||
// updated = metadata.lastUpdated,
|
|
||||||
// suggestedVersionCode = metadata.suggestedVersionCode,
|
|
||||||
// categories = categories,
|
|
||||||
// antiFeatures = metadata.antiFeatures,
|
|
||||||
// licenses = listOf(metadata.license),
|
|
||||||
// donates = donation.toLegacy(),
|
|
||||||
// screenshots = screenshots.toLegacy(),
|
|
||||||
// releases = packages
|
|
||||||
//)
|
|
||||||
|
|
||||||
fun Donation.toLegacy() = buildList {
|
|
||||||
regularUrl?.let { it.forEach { add(Product.Donate.Regular(it)) } }
|
|
||||||
bitcoinAddress?.let { add(Product.Donate.Bitcoin(it)) }
|
|
||||||
flattrId?.let { add(Product.Donate.Flattr(it)) }
|
|
||||||
litecoinAddress?.let { add(Product.Donate.Litecoin(it)) }
|
|
||||||
openCollectiveId?.let { add(Product.Donate.OpenCollective(it)) }
|
|
||||||
liberapayId?.let { add(Product.Donate.Liberapay(it)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Screenshots.toLegacy() = buildList {
|
|
||||||
phone.forEach { add(Product.Screenshot("en-US", Product.Screenshot.Type.PHONE, it)) }
|
|
||||||
sevenInch.forEach { add(Product.Screenshot("en-US", Product.Screenshot.Type.SMALL_TABLET, it)) }
|
|
||||||
tenInch.forEach { add(Product.Screenshot("en-US", Product.Screenshot.Type.LARGE_TABLET, it)) }
|
|
||||||
tv.forEach { add(Product.Screenshot("en-US", Product.Screenshot.Type.PHONE, it)) }
|
|
||||||
wear.forEach { add(Product.Screenshot("en-US", Product.Screenshot.Type.PHONE, it)) }
|
|
||||||
}
|
|
||||||
|
@ -18,16 +18,16 @@ data class ProductItem(
|
|||||||
var canUpdate: Boolean,
|
var canUpdate: Boolean,
|
||||||
var matchRank: Int
|
var matchRank: Int
|
||||||
) {
|
) {
|
||||||
sealed class Section : Parcelable {
|
sealed interface Section : Parcelable {
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data object All : Section()
|
object All : Section
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class Category(val name: String) : Section()
|
class Category(val name: String) : Section
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class Repository(val id: Long, val name: String) : Section()
|
class Repository(val id: Long, val name: String) : Section
|
||||||
}
|
}
|
||||||
|
|
||||||
private val supportedDpi = intArrayOf(120, 160, 240, 320, 480, 640)
|
private val supportedDpi = intArrayOf(120, 160, 240, 320, 480, 640)
|
||||||
|
@ -31,7 +31,7 @@ data class Release(
|
|||||||
object MinSdk : Incompatibility()
|
object MinSdk : Incompatibility()
|
||||||
object MaxSdk : Incompatibility()
|
object MaxSdk : Incompatibility()
|
||||||
object Platform : Incompatibility()
|
object Platform : Incompatibility()
|
||||||
data class Feature(val feature: String) : Incompatibility()
|
class Feature(val feature: String) : Incompatibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
val identifier: String
|
val identifier: String
|
||||||
|
@ -15,7 +15,7 @@ data class Repository(
|
|||||||
val entityTag: String,
|
val entityTag: String,
|
||||||
val updated: Long,
|
val updated: Long,
|
||||||
val timestamp: Long,
|
val timestamp: Long,
|
||||||
val authentication: String
|
val authentication: String,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun edit(address: String, fingerprint: String, authentication: String): Repository {
|
fun edit(address: String, fingerprint: String, authentication: String): Repository {
|
||||||
@ -38,7 +38,7 @@ data class Repository(
|
|||||||
version: Int,
|
version: Int,
|
||||||
lastModified: String,
|
lastModified: String,
|
||||||
entityTag: String,
|
entityTag: String,
|
||||||
timestamp: Long
|
timestamp: Long,
|
||||||
): Repository {
|
): Repository {
|
||||||
return copy(
|
return copy(
|
||||||
mirrors = mirrors,
|
mirrors = mirrors,
|
||||||
@ -62,7 +62,7 @@ data class Repository(
|
|||||||
fun newRepository(
|
fun newRepository(
|
||||||
address: String,
|
address: String,
|
||||||
fingerprint: String,
|
fingerprint: String,
|
||||||
authentication: String
|
authentication: String,
|
||||||
): Repository {
|
): Repository {
|
||||||
val name = try {
|
val name = try {
|
||||||
URL(address).let { "${it.host}${it.path}" }
|
URL(address).let { "${it.host}${it.path}" }
|
||||||
@ -79,7 +79,7 @@ data class Repository(
|
|||||||
version: Int = 21,
|
version: Int = 21,
|
||||||
enabled: Boolean = false,
|
enabled: Boolean = false,
|
||||||
fingerprint: String,
|
fingerprint: String,
|
||||||
authentication: String = ""
|
authentication: String = "",
|
||||||
): Repository {
|
): Repository {
|
||||||
return Repository(
|
return Repository(
|
||||||
-1, address, emptyList(), name, description, version, enabled,
|
-1, address, emptyList(), name, description, version, enabled,
|
||||||
@ -150,14 +150,6 @@ data class Repository(
|
|||||||
" by Netsyms Technologies.",
|
" by Netsyms Technologies.",
|
||||||
fingerprint = "2581BA7B32D3AB443180C4087CAB6A7E8FB258D3A6E98870ECB3C675E4D64489"
|
fingerprint = "2581BA7B32D3AB443180C4087CAB6A7E8FB258D3A6E98870ECB3C675E4D64489"
|
||||||
),
|
),
|
||||||
defaultRepository(
|
|
||||||
address = "https://fdroid.bromite.org/fdroid/repo",
|
|
||||||
name = "Bromite",
|
|
||||||
description = "The official repository for Bromite. " +
|
|
||||||
"Bromite is a Chromium with ad blocking and enhanced p" +
|
|
||||||
"rivacy.",
|
|
||||||
fingerprint = "E1EE5CD076D7B0DC84CB2B45FB78B86DF2EB39A3B6C56BA3DC292A5E0C3B9504"
|
|
||||||
),
|
|
||||||
defaultRepository(
|
defaultRepository(
|
||||||
address = "https://molly.im/fdroid/foss/fdroid/repo",
|
address = "https://molly.im/fdroid/foss/fdroid/repo",
|
||||||
name = "Molly",
|
name = "Molly",
|
||||||
@ -217,7 +209,7 @@ data class Repository(
|
|||||||
name = "Kali Nethunter",
|
name = "Kali Nethunter",
|
||||||
description = "Kali Nethunter's official selection of original b" +
|
description = "Kali Nethunter's official selection of original b" +
|
||||||
"inaries.",
|
"inaries.",
|
||||||
fingerprint = "7E418D34C3AD4F3C37D7E6B0FACE13332364459C862134EB099A3BDA2CCF4494"
|
fingerprint = "FE7A23DFC003A1CF2D2ADD2469B9C0C49B206BA5DC9EDD6563B3B7EB6A8F5FAB"
|
||||||
),
|
),
|
||||||
defaultRepository(
|
defaultRepository(
|
||||||
address = "https://secfirst.org/fdroid/repo",
|
address = "https://secfirst.org/fdroid/repo",
|
||||||
@ -265,14 +257,14 @@ data class Repository(
|
|||||||
name = "Threema Libre",
|
name = "Threema Libre",
|
||||||
description = "The official repository for Threema Libre. R" +
|
description = "The official repository for Threema Libre. R" +
|
||||||
"equires Threema Shop license. Threema Libre is an open" +
|
"equires Threema Shop license. Threema Libre is an open" +
|
||||||
"-source messanger focused on security and privacy.",
|
"-source messenger focused on security and privacy.",
|
||||||
fingerprint = "5734E753899B25775D90FE85362A49866E05AC4F83C05BEF5A92880D2910639E"
|
fingerprint = "5734E753899B25775D90FE85362A49866E05AC4F83C05BEF5A92880D2910639E"
|
||||||
),
|
),
|
||||||
defaultRepository(
|
defaultRepository(
|
||||||
address = "https://fdroid.getsession.org/fdroid/repo",
|
address = "https://fdroid.getsession.org/fdroid/repo",
|
||||||
name = "Session",
|
name = "Session",
|
||||||
description = "The official repository for Session. Session" +
|
description = "The official repository for Session. Session" +
|
||||||
" is an open-source messanger focused on security and privacy.",
|
" is an open-source messenger focused on security and privacy.",
|
||||||
fingerprint = "DB0E5297EB65CC22D6BD93C869943BDCFCB6A07DC69A48A0DD8C7BA698EC04E6"
|
fingerprint = "DB0E5297EB65CC22D6BD93C869943BDCFCB6A07DC69A48A0DD8C7BA698EC04E6"
|
||||||
),
|
),
|
||||||
defaultRepository(
|
defaultRepository(
|
||||||
@ -398,7 +390,7 @@ data class Repository(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
val newlyAdded = listOf<Repository>(
|
val newlyAdded: List<Repository> = listOf(
|
||||||
defaultRepository(
|
defaultRepository(
|
||||||
address = "https://fdroid.ironfoxoss.org/fdroid/repo",
|
address = "https://fdroid.ironfoxoss.org/fdroid/repo",
|
||||||
name = "IronFox",
|
name = "IronFox",
|
||||||
@ -412,6 +404,14 @@ data class Repository(
|
|||||||
description = "The official repository for Total Commander",
|
description = "The official repository for Total Commander",
|
||||||
fingerprint = "3576596CECDD70488D61CFD90799A49B7FFD26A81A8FEF1BADEC88D069FA72C1"
|
fingerprint = "3576596CECDD70488D61CFD90799A49B7FFD26A81A8FEF1BADEC88D069FA72C1"
|
||||||
),
|
),
|
||||||
|
defaultRepository(
|
||||||
|
address = "https://www.cromite.org/fdroid/repo",
|
||||||
|
name = "Cromite",
|
||||||
|
description = "The official repository for Cromite. " +
|
||||||
|
"Cromite is a Chromium fork based on Bromite with " +
|
||||||
|
"built-in support for ad blocking and an eye for privacy.",
|
||||||
|
fingerprint = "49F37E74DEE483DCA2B991334FB5A0200787430D0B5F9A783DD5F13695E9517B"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ internal class KtorDownloader(
|
|||||||
|
|
||||||
private const val CONNECTION_TIMEOUT = 30_000L
|
private const val CONNECTION_TIMEOUT = 30_000L
|
||||||
private const val SOCKET_TIMEOUT = 15_000L
|
private const val SOCKET_TIMEOUT = 15_000L
|
||||||
private const val USER_AGENT = "Droid-ify, ${BuildConfig.VERSION_NAME}"
|
private const val USER_AGENT = "Droid-ify/${BuildConfig.VERSION_NAME}-${BuildConfig.BUILD_TYPE}"
|
||||||
|
|
||||||
private fun HttpClientConfig<*>.userAgentConfig() = install(UserAgent) {
|
private fun HttpClientConfig<*>.userAgentConfig() = install(UserAgent) {
|
||||||
agent = USER_AGENT
|
agent = USER_AGENT
|
||||||
|
@ -22,7 +22,6 @@ import com.looker.droidify.utility.common.extension.getColorFromAttr
|
|||||||
import com.looker.droidify.utility.common.extension.notificationManager
|
import com.looker.droidify.utility.common.extension.notificationManager
|
||||||
import com.looker.droidify.utility.common.extension.startServiceCompat
|
import com.looker.droidify.utility.common.extension.startServiceCompat
|
||||||
import com.looker.droidify.utility.common.extension.stopForegroundCompat
|
import com.looker.droidify.utility.common.extension.stopForegroundCompat
|
||||||
import com.looker.droidify.utility.common.log
|
|
||||||
import com.looker.droidify.utility.common.result.Result
|
import com.looker.droidify.utility.common.result.Result
|
||||||
import com.looker.droidify.utility.common.sdkAbove
|
import com.looker.droidify.utility.common.sdkAbove
|
||||||
import com.looker.droidify.datastore.SettingsRepository
|
import com.looker.droidify.datastore.SettingsRepository
|
||||||
@ -53,6 +52,8 @@ import kotlinx.coroutines.withContext
|
|||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
|
import kotlinx.coroutines.FlowPreview
|
||||||
|
import kotlin.math.roundToInt
|
||||||
import android.R as AndroidR
|
import android.R as AndroidR
|
||||||
import com.looker.droidify.R.string as stringRes
|
import com.looker.droidify.R.string as stringRes
|
||||||
import com.looker.droidify.R.style as styleRes
|
import com.looker.droidify.R.style as styleRes
|
||||||
@ -69,15 +70,16 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
private const val MAX_UPDATE_NOTIFICATION = 5
|
private const val MAX_UPDATE_NOTIFICATION = 5
|
||||||
private const val ACTION_CANCEL = "${BuildConfig.APPLICATION_ID}.intent.action.CANCEL"
|
private const val ACTION_CANCEL = "${BuildConfig.APPLICATION_ID}.intent.action.CANCEL"
|
||||||
|
|
||||||
private val syncState = MutableSharedFlow<State>()
|
val syncState = MutableSharedFlow<State>()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var settingsRepository: SettingsRepository
|
lateinit var settingsRepository: SettingsRepository
|
||||||
|
|
||||||
sealed class State(val name: String) {
|
sealed class State(val name: String) {
|
||||||
data class Connecting(val appName: String) : State(appName)
|
class Connecting(appName: String) : State(appName)
|
||||||
data class Syncing(
|
|
||||||
|
class Syncing(
|
||||||
val appName: String,
|
val appName: String,
|
||||||
val stage: RepositoryUpdater.Stage,
|
val stage: RepositoryUpdater.Stage,
|
||||||
val read: DataSize,
|
val read: DataSize,
|
||||||
@ -85,6 +87,18 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
) : State(appName)
|
) : State(appName)
|
||||||
|
|
||||||
data object Finish : State("")
|
data object Finish : State("")
|
||||||
|
|
||||||
|
val progress: Int
|
||||||
|
get() = when (this) {
|
||||||
|
is Connecting -> Int.MIN_VALUE
|
||||||
|
Finish -> Int.MAX_VALUE
|
||||||
|
is Syncing -> when(stage) {
|
||||||
|
RepositoryUpdater.Stage.DOWNLOAD -> ((read percentBy total) * 0.4F).roundToInt()
|
||||||
|
RepositoryUpdater.Stage.PROCESS -> 50
|
||||||
|
RepositoryUpdater.Stage.MERGE -> 75
|
||||||
|
RepositoryUpdater.Stage.COMMIT -> 90
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Task(val repositoryId: Long, val manual: Boolean)
|
private class Task(val repositoryId: Long, val manual: Boolean)
|
||||||
@ -145,7 +159,8 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun updateAllApps() {
|
suspend fun updateAllApps() {
|
||||||
updateAllAppsInternal()
|
val skipSignature = settingsRepository.getInitial().ignoreSignature
|
||||||
|
updateAllAppsInternal(skipSignature)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setUpdateNotificationBlocker(fragment: Fragment?) {
|
fun setUpdateNotificationBlocker(fragment: Fragment?) {
|
||||||
@ -198,6 +213,7 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
private val binder = Binder()
|
private val binder = Binder()
|
||||||
override fun onBind(intent: Intent): Binder = binder
|
override fun onBind(intent: Intent): Binder = binder
|
||||||
|
|
||||||
|
@OptIn(FlowPreview::class)
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
@ -389,7 +405,8 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
handleUpdates(
|
handleUpdates(
|
||||||
hasUpdates = hasUpdates,
|
hasUpdates = hasUpdates,
|
||||||
notifyUpdates = setting.notifyUpdate,
|
notifyUpdates = setting.notifyUpdate,
|
||||||
autoUpdate = setting.autoUpdate
|
autoUpdate = setting.autoUpdate,
|
||||||
|
skipSignature = setting.ignoreSignature,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,7 +487,8 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
private suspend fun handleUpdates(
|
private suspend fun handleUpdates(
|
||||||
hasUpdates: Boolean,
|
hasUpdates: Boolean,
|
||||||
notifyUpdates: Boolean,
|
notifyUpdates: Boolean,
|
||||||
autoUpdate: Boolean
|
autoUpdate: Boolean,
|
||||||
|
skipSignature: Boolean,
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if (!hasUpdates) {
|
if (!hasUpdates) {
|
||||||
@ -481,15 +499,16 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val blocked = updateNotificationBlockerFragment?.get()?.isAdded == true
|
val blocked = updateNotificationBlockerFragment?.get()?.isAdded == true
|
||||||
val updates = Database.ProductAdapter.getUpdates()
|
val updates = Database.ProductAdapter.getUpdates(skipSignature)
|
||||||
if (!blocked && updates.isNotEmpty()) {
|
if (!blocked && updates.isNotEmpty()) {
|
||||||
if (notifyUpdates) displayUpdatesNotification(updates)
|
if (notifyUpdates) displayUpdatesNotification(updates)
|
||||||
if (autoUpdate) updateAllAppsInternal()
|
if (autoUpdate) updateAllAppsInternal(skipSignature)
|
||||||
}
|
}
|
||||||
handleUpdates(
|
handleUpdates(
|
||||||
hasUpdates = false,
|
hasUpdates = false,
|
||||||
notifyUpdates = notifyUpdates,
|
notifyUpdates = notifyUpdates,
|
||||||
autoUpdate = autoUpdate
|
autoUpdate = autoUpdate,
|
||||||
|
skipSignature = skipSignature,
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
withContext(NonCancellable) {
|
withContext(NonCancellable) {
|
||||||
@ -499,10 +518,9 @@ class SyncService : ConnectionService<SyncService.Binder>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun updateAllAppsInternal() {
|
private suspend fun updateAllAppsInternal(skipSignature: Boolean) {
|
||||||
log("Check Running", "Syncing")
|
|
||||||
Database.ProductAdapter
|
Database.ProductAdapter
|
||||||
.getUpdates()
|
.getUpdates(skipSignature)
|
||||||
// Update Droid-ify the last
|
// Update Droid-ify the last
|
||||||
.sortedBy { if (it.packageName == packageName) 1 else -1 }
|
.sortedBy { if (it.packageName == packageName) 1 else -1 }
|
||||||
.map {
|
.map {
|
||||||
|
@ -40,7 +40,7 @@ import androidx.core.text.util.LinkifyCompat
|
|||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.load
|
import coil3.load
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.google.android.material.imageview.ShapeableImageView
|
import com.google.android.material.imageview.ShapeableImageView
|
||||||
@ -56,6 +56,7 @@ import com.looker.droidify.model.Release
|
|||||||
import com.looker.droidify.model.Repository
|
import com.looker.droidify.model.Repository
|
||||||
import com.looker.droidify.model.findSuggested
|
import com.looker.droidify.model.findSuggested
|
||||||
import com.looker.droidify.network.DataSize
|
import com.looker.droidify.network.DataSize
|
||||||
|
import com.looker.droidify.network.percentBy
|
||||||
import com.looker.droidify.utility.PackageItemResolver
|
import com.looker.droidify.utility.PackageItemResolver
|
||||||
import com.looker.droidify.utility.common.extension.authentication
|
import com.looker.droidify.utility.common.extension.authentication
|
||||||
import com.looker.droidify.utility.common.extension.copyToClipboard
|
import com.looker.droidify.utility.common.extension.copyToClipboard
|
||||||
@ -69,6 +70,7 @@ import com.looker.droidify.utility.common.extension.inflate
|
|||||||
import com.looker.droidify.utility.common.extension.open
|
import com.looker.droidify.utility.common.extension.open
|
||||||
import com.looker.droidify.utility.common.extension.setTextSizeScaled
|
import com.looker.droidify.utility.common.extension.setTextSizeScaled
|
||||||
import com.looker.droidify.utility.common.nullIfEmpty
|
import com.looker.droidify.utility.common.nullIfEmpty
|
||||||
|
import com.looker.droidify.utility.common.sdkName
|
||||||
import com.looker.droidify.utility.extension.android.Android
|
import com.looker.droidify.utility.extension.android.Android
|
||||||
import com.looker.droidify.utility.extension.resources.TypefaceExtra
|
import com.looker.droidify.utility.extension.resources.TypefaceExtra
|
||||||
import com.looker.droidify.utility.extension.resources.sizeScaled
|
import com.looker.droidify.utility.extension.resources.sizeScaled
|
||||||
@ -101,7 +103,7 @@ class AppDetailAdapter(private val callbacks: Callbacks) :
|
|||||||
fun onFavouriteClicked()
|
fun onFavouriteClicked()
|
||||||
fun onPreferenceChanged(preference: ProductPreference)
|
fun onPreferenceChanged(preference: ProductPreference)
|
||||||
fun onPermissionsClick(group: String?, permissions: List<String>)
|
fun onPermissionsClick(group: String?, permissions: List<String>)
|
||||||
fun onScreenshotClick(screenshot: Product.Screenshot, parentView: ImageView)
|
fun onScreenshotClick(position: Int)
|
||||||
fun onReleaseClick(release: Release)
|
fun onReleaseClick(release: Release)
|
||||||
fun onRequestAddRepository(address: String)
|
fun onRequestAddRepository(address: String)
|
||||||
fun onUriClick(uri: Uri, shouldConfirm: Boolean): Boolean
|
fun onUriClick(uri: Uri, shouldConfirm: Boolean): Boolean
|
||||||
@ -313,7 +315,6 @@ class AppDetailAdapter(private val callbacks: Callbacks) :
|
|||||||
is Product.Donate.Regular -> drawableRes.ic_donate
|
is Product.Donate.Regular -> drawableRes.ic_donate
|
||||||
is Product.Donate.Bitcoin -> drawableRes.ic_donate_bitcoin
|
is Product.Donate.Bitcoin -> drawableRes.ic_donate_bitcoin
|
||||||
is Product.Donate.Litecoin -> drawableRes.ic_donate_litecoin
|
is Product.Donate.Litecoin -> drawableRes.ic_donate_litecoin
|
||||||
is Product.Donate.Flattr -> drawableRes.ic_donate_flattr
|
|
||||||
is Product.Donate.Liberapay -> drawableRes.ic_donate_liberapay
|
is Product.Donate.Liberapay -> drawableRes.ic_donate_liberapay
|
||||||
is Product.Donate.OpenCollective -> drawableRes.ic_donate_opencollective
|
is Product.Donate.OpenCollective -> drawableRes.ic_donate_opencollective
|
||||||
}
|
}
|
||||||
@ -322,7 +323,6 @@ class AppDetailAdapter(private val callbacks: Callbacks) :
|
|||||||
is Product.Donate.Regular -> context.getString(stringRes.website)
|
is Product.Donate.Regular -> context.getString(stringRes.website)
|
||||||
is Product.Donate.Bitcoin -> "Bitcoin"
|
is Product.Donate.Bitcoin -> "Bitcoin"
|
||||||
is Product.Donate.Litecoin -> "Litecoin"
|
is Product.Donate.Litecoin -> "Litecoin"
|
||||||
is Product.Donate.Flattr -> "Flattr"
|
|
||||||
is Product.Donate.Liberapay -> "Liberapay"
|
is Product.Donate.Liberapay -> "Liberapay"
|
||||||
is Product.Donate.OpenCollective -> "Open Collective"
|
is Product.Donate.OpenCollective -> "Open Collective"
|
||||||
}
|
}
|
||||||
@ -331,12 +331,8 @@ class AppDetailAdapter(private val callbacks: Callbacks) :
|
|||||||
is Product.Donate.Regular -> Uri.parse(donate.url)
|
is Product.Donate.Regular -> Uri.parse(donate.url)
|
||||||
is Product.Donate.Bitcoin -> Uri.parse("bitcoin:${donate.address}")
|
is Product.Donate.Bitcoin -> Uri.parse("bitcoin:${donate.address}")
|
||||||
is Product.Donate.Litecoin -> Uri.parse("litecoin:${donate.address}")
|
is Product.Donate.Litecoin -> Uri.parse("litecoin:${donate.address}")
|
||||||
is Product.Donate.Flattr -> Uri.parse(
|
|
||||||
"https://flattr.com/thing/${donate.id}"
|
|
||||||
)
|
|
||||||
|
|
||||||
is Product.Donate.Liberapay -> Uri.parse(
|
is Product.Donate.Liberapay -> Uri.parse(
|
||||||
"https://liberapay.com/~${donate.id}"
|
"https://liberapay.com/${donate.id}"
|
||||||
)
|
)
|
||||||
|
|
||||||
is Product.Donate.OpenCollective -> Uri.parse(
|
is Product.Donate.OpenCollective -> Uri.parse(
|
||||||
@ -561,6 +557,7 @@ class AppDetailAdapter(private val callbacks: Callbacks) :
|
|||||||
val size = itemView.findViewById<TextView>(R.id.size)!!
|
val size = itemView.findViewById<TextView>(R.id.size)!!
|
||||||
val signature = itemView.findViewById<TextView>(R.id.signature)!!
|
val signature = itemView.findViewById<TextView>(R.id.signature)!!
|
||||||
val compatibility = itemView.findViewById<TextView>(R.id.compatibility)!!
|
val compatibility = itemView.findViewById<TextView>(R.id.compatibility)!!
|
||||||
|
val sdkVer = itemView.findViewById<TextView>(R.id.sdk_ver)!!
|
||||||
|
|
||||||
val statefulViews: Sequence<View>
|
val statefulViews: Sequence<View>
|
||||||
get() = sequenceOf(
|
get() = sequenceOf(
|
||||||
@ -571,7 +568,8 @@ class AppDetailAdapter(private val callbacks: Callbacks) :
|
|||||||
added,
|
added,
|
||||||
size,
|
size,
|
||||||
signature,
|
signature,
|
||||||
compatibility
|
compatibility,
|
||||||
|
sdkVer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1365,12 +1363,10 @@ class AppDetailAdapter(private val callbacks: Callbacks) :
|
|||||||
)
|
)
|
||||||
holder.progress.isIndeterminate = status.total == null
|
holder.progress.isIndeterminate = status.total == null
|
||||||
if (status.total != null) {
|
if (status.total != null) {
|
||||||
holder.progress.progress =
|
holder.progress.setProgressCompat(
|
||||||
(
|
status.read.value percentBy status.total.value,
|
||||||
holder.progress.max.toFloat() *
|
true
|
||||||
status.read.value /
|
)
|
||||||
status.total.value
|
|
||||||
).roundToInt()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1430,17 +1426,15 @@ class AppDetailAdapter(private val callbacks: Callbacks) :
|
|||||||
holder as ScreenShotViewHolder
|
holder as ScreenShotViewHolder
|
||||||
item as Item.ScreenshotItem
|
item as Item.ScreenshotItem
|
||||||
holder.screenshotsRecycler.run {
|
holder.screenshotsRecycler.run {
|
||||||
|
setHasFixedSize(true)
|
||||||
isNestedScrollingEnabled = false
|
isNestedScrollingEnabled = false
|
||||||
clipToPadding = false
|
clipToPadding = false
|
||||||
setPadding(8.dp, 8.dp, 8.dp, 8.dp)
|
setPadding(8.dp, 8.dp, 8.dp, 8.dp)
|
||||||
layoutManager =
|
layoutManager =
|
||||||
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||||
adapter =
|
adapter = ScreenshotsAdapter(callbacks::onScreenshotClick).apply {
|
||||||
ScreenshotsAdapter { screenshot, view ->
|
setScreenshots(item.repository, item.packageName, item.screenshots)
|
||||||
callbacks.onScreenshotClick(screenshot, view)
|
}
|
||||||
}.apply {
|
|
||||||
setScreenshots(item.repository, item.packageName, item.screenshots)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1626,7 +1620,7 @@ class AppDetailAdapter(private val callbacks: Callbacks) :
|
|||||||
holder.version.text =
|
holder.version.text =
|
||||||
context.getString(stringRes.version_FORMAT, item.release.version)
|
context.getString(stringRes.version_FORMAT, item.release.version)
|
||||||
|
|
||||||
holder.status.apply {
|
with(holder.status) {
|
||||||
isVisible = installed || suggested
|
isVisible = installed || suggested
|
||||||
setText(
|
setText(
|
||||||
when {
|
when {
|
||||||
@ -1637,14 +1631,15 @@ class AppDetailAdapter(private val callbacks: Callbacks) :
|
|||||||
)
|
)
|
||||||
background = context.corneredBackground
|
background = context.corneredBackground
|
||||||
setPadding(15, 15, 15, 15)
|
setPadding(15, 15, 15, 15)
|
||||||
val (background, foreground) = if (installed) {
|
if (installed) {
|
||||||
MaterialR.attr.colorSecondaryContainer to MaterialR.attr.colorOnSecondaryContainer
|
backgroundTintList =
|
||||||
|
context.getColorFromAttr(MaterialR.attr.colorSecondaryContainer)
|
||||||
|
setTextColor(context.getColorFromAttr(MaterialR.attr.colorOnSecondaryContainer))
|
||||||
} else {
|
} else {
|
||||||
MaterialR.attr.colorPrimaryContainer to MaterialR.attr.colorOnPrimaryContainer
|
backgroundTintList =
|
||||||
|
context.getColorFromAttr(MaterialR.attr.colorPrimaryContainer)
|
||||||
|
setTextColor(context.getColorFromAttr(MaterialR.attr.colorOnPrimaryContainer))
|
||||||
}
|
}
|
||||||
backgroundTintList =
|
|
||||||
context.getColorFromAttr(background)
|
|
||||||
setTextColor(context.getColorFromAttr(foreground))
|
|
||||||
}
|
}
|
||||||
holder.source.text =
|
holder.source.text =
|
||||||
context.getString(stringRes.provided_by_FORMAT, item.repository.name)
|
context.getString(stringRes.provided_by_FORMAT, item.repository.name)
|
||||||
@ -1688,35 +1683,51 @@ class AppDetailAdapter(private val callbacks: Callbacks) :
|
|||||||
}
|
}
|
||||||
holder.signature.text = builder
|
holder.signature.text = builder
|
||||||
}
|
}
|
||||||
holder.compatibility.isVisible = incompatibility != null || singlePlatform != null
|
with(holder.compatibility) {
|
||||||
if (incompatibility != null) {
|
isVisible = incompatibility != null || singlePlatform != null
|
||||||
holder.compatibility.setTextColor(
|
if (incompatibility != null) {
|
||||||
context.getColorFromAttr(MaterialR.attr.colorError)
|
setTextColor(context.getColorFromAttr(MaterialR.attr.colorError))
|
||||||
)
|
text = when (incompatibility) {
|
||||||
holder.compatibility.text = when (incompatibility) {
|
is Release.Incompatibility.MinSdk,
|
||||||
is Release.Incompatibility.MinSdk,
|
is Release.Incompatibility.MaxSdk -> context.getString(
|
||||||
is Release.Incompatibility.MaxSdk
|
stringRes.incompatible_with_FORMAT,
|
||||||
-> context.getString(
|
Android.name
|
||||||
stringRes.incompatible_with_FORMAT,
|
)
|
||||||
Android.name
|
|
||||||
)
|
|
||||||
|
|
||||||
is Release.Incompatibility.Platform -> context.getString(
|
is Release.Incompatibility.Platform -> context.getString(
|
||||||
stringRes.incompatible_with_FORMAT,
|
stringRes.incompatible_with_FORMAT,
|
||||||
Android.primaryPlatform ?: context.getString(stringRes.unknown)
|
Android.primaryPlatform ?: context.getString(stringRes.unknown)
|
||||||
)
|
)
|
||||||
|
|
||||||
is Release.Incompatibility.Feature -> context.getString(
|
is Release.Incompatibility.Feature -> context.getString(
|
||||||
stringRes.requires_FORMAT,
|
stringRes.requires_FORMAT,
|
||||||
incompatibility.feature
|
incompatibility.feature
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if (singlePlatform != null) {
|
||||||
|
setTextColor(context.getColorFromAttr(android.R.attr.textColorSecondary))
|
||||||
|
text = context.getString(
|
||||||
|
stringRes.only_compatible_with_FORMAT,
|
||||||
|
singlePlatform,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if (singlePlatform != null) {
|
}
|
||||||
holder.compatibility.setTextColor(
|
with(holder.sdkVer) {
|
||||||
context.getColorFromAttr(android.R.attr.textColorSecondary)
|
val targetSdkVersion = sdkName.getOrDefault(
|
||||||
|
item.release.targetSdkVersion,
|
||||||
|
context.getString(
|
||||||
|
stringRes.label_unknown_sdk,
|
||||||
|
item.release.targetSdkVersion,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
holder.compatibility.text =
|
val minSdkVersion = sdkName.getOrDefault(
|
||||||
context.getString(stringRes.only_compatible_with_FORMAT, singlePlatform)
|
item.release.minSdkVersion,
|
||||||
|
context.getString(
|
||||||
|
stringRes.label_unknown_sdk,
|
||||||
|
item.release.minSdkVersion,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
text = context.getString(stringRes.label_sdk_version, targetSdkVersion, minSdkVersion)
|
||||||
}
|
}
|
||||||
val enabled = status == Status.Idle
|
val enabled = status == Status.Idle
|
||||||
holder.statefulViews.forEach { it.isEnabled = enabled }
|
holder.statefulViews.forEach { it.isEnabled = enabled }
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.looker.droidify.ui.appDetail
|
package com.looker.droidify.ui.appDetail
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@ -8,7 +9,6 @@ import android.os.Bundle
|
|||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
@ -20,16 +20,13 @@ import androidx.lifecycle.repeatOnLifecycle
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||||
import coil.load
|
import coil3.load
|
||||||
|
import coil3.request.allowHardware
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.looker.droidify.utility.common.cache.Cache
|
|
||||||
import com.looker.droidify.utility.common.extension.getLauncherActivities
|
|
||||||
import com.looker.droidify.utility.common.extension.getMutatedIcon
|
|
||||||
import com.looker.droidify.utility.common.extension.isFirstItemVisible
|
|
||||||
import com.looker.droidify.utility.common.extension.isSystemApplication
|
|
||||||
import com.looker.droidify.utility.common.extension.systemBarsPadding
|
|
||||||
import com.looker.droidify.utility.common.extension.updateAsMutable
|
|
||||||
import com.looker.droidify.content.ProductPreferences
|
import com.looker.droidify.content.ProductPreferences
|
||||||
|
import com.looker.droidify.installer.installers.launchShizuku
|
||||||
|
import com.looker.droidify.installer.model.InstallState
|
||||||
|
import com.looker.droidify.installer.model.isCancellable
|
||||||
import com.looker.droidify.model.InstalledItem
|
import com.looker.droidify.model.InstalledItem
|
||||||
import com.looker.droidify.model.Product
|
import com.looker.droidify.model.Product
|
||||||
import com.looker.droidify.model.ProductPreference
|
import com.looker.droidify.model.ProductPreference
|
||||||
@ -43,11 +40,15 @@ import com.looker.droidify.ui.MessageDialog
|
|||||||
import com.looker.droidify.ui.ScreenFragment
|
import com.looker.droidify.ui.ScreenFragment
|
||||||
import com.looker.droidify.ui.appDetail.AppDetailViewModel.Companion.ARG_PACKAGE_NAME
|
import com.looker.droidify.ui.appDetail.AppDetailViewModel.Companion.ARG_PACKAGE_NAME
|
||||||
import com.looker.droidify.ui.appDetail.AppDetailViewModel.Companion.ARG_REPO_ADDRESS
|
import com.looker.droidify.ui.appDetail.AppDetailViewModel.Companion.ARG_REPO_ADDRESS
|
||||||
import com.looker.droidify.utility.extension.screenActivity
|
import com.looker.droidify.utility.common.cache.Cache
|
||||||
|
import com.looker.droidify.utility.common.extension.getLauncherActivities
|
||||||
|
import com.looker.droidify.utility.common.extension.getMutatedIcon
|
||||||
|
import com.looker.droidify.utility.common.extension.isFirstItemVisible
|
||||||
|
import com.looker.droidify.utility.common.extension.isSystemApplication
|
||||||
|
import com.looker.droidify.utility.common.extension.systemBarsPadding
|
||||||
|
import com.looker.droidify.utility.common.extension.updateAsMutable
|
||||||
|
import com.looker.droidify.utility.extension.mainActivity
|
||||||
import com.looker.droidify.utility.extension.startUpdate
|
import com.looker.droidify.utility.extension.startUpdate
|
||||||
import com.looker.droidify.installer.installers.launchShizuku
|
|
||||||
import com.looker.droidify.installer.model.InstallState
|
|
||||||
import com.looker.droidify.installer.model.isCancellable
|
|
||||||
import com.stfalcon.imageviewer.StfalconImageViewer
|
import com.stfalcon.imageviewer.StfalconImageViewer
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@ -89,6 +90,7 @@ class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
|
|||||||
|
|
||||||
private val viewModel: AppDetailViewModel by viewModels()
|
private val viewModel: AppDetailViewModel by viewModels()
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
private var layoutManagerState: LinearLayoutManager.SavedState? = null
|
private var layoutManagerState: LinearLayoutManager.SavedState? = null
|
||||||
|
|
||||||
private var actions = Pair(emptySet<Action>(), null as Action?)
|
private var actions = Pair(emptySet<Action>(), null as Action?)
|
||||||
@ -99,6 +101,7 @@ class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
|
|||||||
|
|
||||||
private var recyclerView: RecyclerView? = null
|
private var recyclerView: RecyclerView? = null
|
||||||
private var detailAdapter: AppDetailAdapter? = null
|
private var detailAdapter: AppDetailAdapter? = null
|
||||||
|
private var imageViewer: StfalconImageViewer.Builder<Product.Screenshot>? = null
|
||||||
|
|
||||||
private val downloadConnection = Connection(
|
private val downloadConnection = Connection(
|
||||||
serviceClass = DownloadService::class.java,
|
serviceClass = DownloadService::class.java,
|
||||||
@ -109,11 +112,12 @@ class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
detailAdapter = AppDetailAdapter(this@AppDetailFragment)
|
detailAdapter = AppDetailAdapter(this@AppDetailFragment)
|
||||||
screenActivity.onToolbarCreated(toolbar)
|
mainActivity.onToolbarCreated(toolbar)
|
||||||
toolbar.menu.apply {
|
toolbar.menu.apply {
|
||||||
Action.entries.forEach { action ->
|
Action.entries.forEach { action ->
|
||||||
add(0, action.id, 0, action.adapterAction.titleResId)
|
add(0, action.id, 0, action.adapterAction.titleResId)
|
||||||
@ -205,10 +209,12 @@ class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
|
|||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
recyclerView = null
|
recyclerView = null
|
||||||
detailAdapter = null
|
detailAdapter = null
|
||||||
|
imageViewer = null
|
||||||
|
|
||||||
downloadConnection.unbind(requireContext())
|
downloadConnection.unbind(requireContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
|
|
||||||
@ -446,20 +452,27 @@ class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
|
|||||||
.show(childFragmentManager)
|
.show(childFragmentManager)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onScreenshotClick(screenshot: Product.Screenshot, parentView: ImageView) {
|
override fun onScreenshotClick(position: Int) {
|
||||||
val product = products
|
if (imageViewer == null) {
|
||||||
.firstOrNull { (product, _) ->
|
val productRepository = products.findSuggested(installed?.installedItem) ?: return
|
||||||
product.screenshots.find { it === screenshot }?.identifier != null
|
val screenshots = productRepository.first.screenshots.mapNotNull {
|
||||||
|
if (it.type == Product.Screenshot.Type.VIDEO) null
|
||||||
|
else it
|
||||||
}
|
}
|
||||||
?: return
|
imageViewer = StfalconImageViewer
|
||||||
val screenshots = product.first.screenshots
|
.Builder(context, screenshots) { view, current ->
|
||||||
val position = screenshots.indexOfFirst { screenshot.identifier == it.identifier }
|
val screenshotUrl = current.url(
|
||||||
StfalconImageViewer
|
context = requireContext(),
|
||||||
.Builder(context, screenshots) { view, current ->
|
repository = productRepository.second,
|
||||||
view.load(current.url(product.second, viewModel.packageName))
|
packageName = viewModel.packageName
|
||||||
}
|
)
|
||||||
.withStartPosition(position)
|
view.load(screenshotUrl) {
|
||||||
.show()
|
allowHardware(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageViewer?.withStartPosition(position)
|
||||||
|
imageViewer?.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReleaseClick(release: Release) {
|
override fun onReleaseClick(release: Release) {
|
||||||
@ -517,7 +530,7 @@ class AppDetailFragment() : ScreenFragment(), AppDetailAdapter.Callbacks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onRequestAddRepository(address: String) {
|
override fun onRequestAddRepository(address: String) {
|
||||||
screenActivity.navigateAddRepository(address)
|
mainActivity.navigateAddRepository(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUriClick(uri: Uri, shouldConfirm: Boolean): Boolean {
|
override fun onUriClick(uri: Uri, shouldConfirm: Boolean): Boolean {
|
||||||
|
@ -5,55 +5,71 @@ import android.graphics.drawable.Drawable
|
|||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.ImageView
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.dispose
|
import coil3.asImage
|
||||||
import coil.load
|
import coil3.dispose
|
||||||
import coil.size.Dimension
|
import coil3.load
|
||||||
import coil.size.Scale
|
import coil3.request.placeholder
|
||||||
|
import coil3.size.Scale
|
||||||
import com.google.android.material.imageview.ShapeableImageView
|
import com.google.android.material.imageview.ShapeableImageView
|
||||||
|
import com.looker.droidify.databinding.VideoButtonBinding
|
||||||
|
import com.looker.droidify.graphics.PaddingDrawable
|
||||||
|
import com.looker.droidify.model.Product
|
||||||
|
import com.looker.droidify.model.Repository
|
||||||
import com.looker.droidify.utility.common.extension.aspectRatio
|
import com.looker.droidify.utility.common.extension.aspectRatio
|
||||||
import com.looker.droidify.utility.common.extension.authentication
|
import com.looker.droidify.utility.common.extension.authentication
|
||||||
import com.looker.droidify.utility.common.extension.camera
|
import com.looker.droidify.utility.common.extension.camera
|
||||||
import com.looker.droidify.utility.common.extension.dp
|
import com.looker.droidify.utility.common.extension.dp
|
||||||
import com.looker.droidify.utility.common.extension.dpToPx
|
|
||||||
import com.looker.droidify.utility.common.extension.getColorFromAttr
|
import com.looker.droidify.utility.common.extension.getColorFromAttr
|
||||||
|
import com.looker.droidify.utility.common.extension.layoutInflater
|
||||||
|
import com.looker.droidify.utility.common.extension.openLink
|
||||||
import com.looker.droidify.utility.common.extension.selectableBackground
|
import com.looker.droidify.utility.common.extension.selectableBackground
|
||||||
import com.looker.droidify.graphics.PaddingDrawable
|
|
||||||
import com.looker.droidify.model.Product
|
|
||||||
import com.looker.droidify.model.Repository
|
|
||||||
import com.looker.droidify.widget.StableRecyclerAdapter
|
import com.looker.droidify.widget.StableRecyclerAdapter
|
||||||
import com.google.android.material.R as MaterialR
|
import com.google.android.material.R as MaterialR
|
||||||
import com.looker.droidify.R.dimen as dimenRes
|
import com.looker.droidify.R.dimen as dimenRes
|
||||||
|
|
||||||
class ScreenshotsAdapter(private val onClick: (Product.Screenshot, ImageView) -> Unit) :
|
class ScreenshotsAdapter(private val onClick: (position: Int) -> Unit) :
|
||||||
StableRecyclerAdapter<ScreenshotsAdapter.ViewType, RecyclerView.ViewHolder>() {
|
StableRecyclerAdapter<ScreenshotsAdapter.ViewType, RecyclerView.ViewHolder>() {
|
||||||
enum class ViewType { SCREENSHOT }
|
enum class ViewType { SCREENSHOT, VIDEO }
|
||||||
|
|
||||||
private val items = mutableListOf<Item.ScreenshotItem>()
|
private val items = mutableListOf<Item>()
|
||||||
|
|
||||||
private class ViewHolder(context: Context) :
|
private inner class VideoViewHolder(
|
||||||
RecyclerView.ViewHolder(FrameLayout(context)) {
|
binding: VideoButtonBinding,
|
||||||
val image: ShapeableImageView = object : ShapeableImageView(context) {
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
val button = binding.videoButton
|
||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
|
||||||
setMeasuredDimension(measuredWidth, measuredHeight)
|
init {
|
||||||
|
with(button) {
|
||||||
|
layoutParams = RecyclerView.LayoutParams(
|
||||||
|
RecyclerView.LayoutParams.WRAP_CONTENT,
|
||||||
|
150.dp,
|
||||||
|
)
|
||||||
|
setOnClickListener {
|
||||||
|
val item = items[absoluteAdapterPosition] as Item.VideoItem
|
||||||
|
it.context?.openLink(item.videoUrl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private inner class ScreenshotViewHolder(
|
||||||
|
context: Context,
|
||||||
|
) : RecyclerView.ViewHolder(FrameLayout(context)) {
|
||||||
|
val image = ShapeableImageView(context)
|
||||||
val placeholderColor = context.getColorFromAttr(MaterialR.attr.colorPrimaryContainer)
|
val placeholderColor = context.getColorFromAttr(MaterialR.attr.colorPrimaryContainer)
|
||||||
val radius = context.resources.getDimension(dimenRes.shape_small_corner)
|
val radius = context.resources.getDimension(dimenRes.shape_small_corner)
|
||||||
|
|
||||||
val imageShapeModel = image.shapeAppearanceModel.toBuilder()
|
val imageShapeModel = image.shapeAppearanceModel.toBuilder()
|
||||||
.setAllCornerSizes(radius)
|
.setAllCornerSizes(radius)
|
||||||
.build()
|
.build()
|
||||||
val cameraIcon = context.camera
|
val cameraIcon = context.camera.apply { setTintList(placeholderColor) }
|
||||||
.apply { setTintList(placeholderColor) }
|
|
||||||
val placeholder: Drawable = PaddingDrawable(cameraIcon, 3f, context.aspectRatio)
|
val placeholder: Drawable = PaddingDrawable(cameraIcon, 3f, context.aspectRatio)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
with(image) {
|
with(image) {
|
||||||
layout(0, 0, 0, 0)
|
layout(0, 0, 0, 0)
|
||||||
adjustViewBounds = true
|
|
||||||
shapeAppearanceModel = imageShapeModel
|
shapeAppearanceModel = imageShapeModel
|
||||||
background = context.selectableBackground
|
background = context.selectableBackground
|
||||||
isFocusable = true
|
isFocusable = true
|
||||||
@ -68,6 +84,14 @@ class ScreenshotsAdapter(private val onClick: (Product.Screenshot, ImageView) ->
|
|||||||
marginEnd = radius.toInt()
|
marginEnd = radius.toInt()
|
||||||
}
|
}
|
||||||
foregroundGravity = Gravity.CENTER
|
foregroundGravity = Gravity.CENTER
|
||||||
|
setOnClickListener {
|
||||||
|
val position = if (items.any { it.viewType == ViewType.VIDEO }) {
|
||||||
|
absoluteAdapterPosition - 1
|
||||||
|
} else {
|
||||||
|
absoluteAdapterPosition
|
||||||
|
}
|
||||||
|
onClick(position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,67 +99,73 @@ class ScreenshotsAdapter(private val onClick: (Product.Screenshot, ImageView) ->
|
|||||||
fun setScreenshots(
|
fun setScreenshots(
|
||||||
repository: Repository,
|
repository: Repository,
|
||||||
packageName: String,
|
packageName: String,
|
||||||
screenshots: List<Product.Screenshot>
|
screenshots: List<Product.Screenshot>,
|
||||||
) {
|
) {
|
||||||
items.clear()
|
items.clear()
|
||||||
items += screenshots.map { Item.ScreenshotItem(repository, packageName, it) }
|
items += screenshots.map {
|
||||||
|
if (it.type == Product.Screenshot.Type.VIDEO) Item.VideoItem(it.path)
|
||||||
|
else Item.ScreenshotItem(repository, packageName, it)
|
||||||
|
}
|
||||||
notifyItemRangeInserted(0, screenshots.size)
|
notifyItemRangeInserted(0, screenshots.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val viewTypeClass: Class<ViewType>
|
override val viewTypeClass: Class<ViewType> get() = ViewType::class.java
|
||||||
get() = ViewType::class.java
|
override fun getItemCount(): Int = items.size
|
||||||
|
override fun getItemEnumViewType(position: Int) = items[position].viewType
|
||||||
override fun getItemEnumViewType(position: Int): ViewType {
|
override fun getItemDescriptor(position: Int): String = items[position].descriptor
|
||||||
return ViewType.SCREENSHOT
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(
|
override fun onCreateViewHolder(
|
||||||
parent: ViewGroup,
|
parent: ViewGroup,
|
||||||
viewType: ViewType
|
viewType: ViewType,
|
||||||
): RecyclerView.ViewHolder {
|
): RecyclerView.ViewHolder {
|
||||||
return ViewHolder(parent.context).apply {
|
return when (viewType) {
|
||||||
image.setOnClickListener {
|
ViewType.VIDEO -> VideoViewHolder(VideoButtonBinding.inflate(parent.context.layoutInflater))
|
||||||
onClick(
|
ViewType.SCREENSHOT -> ScreenshotViewHolder(parent.context)
|
||||||
items[absoluteAdapterPosition].screenshot,
|
|
||||||
it as ImageView
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemDescriptor(position: Int): String = items[position].descriptor
|
|
||||||
override fun getItemCount(): Int = items.size
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
holder as ViewHolder
|
when (getItemEnumViewType(position)) {
|
||||||
val item = items[position]
|
ViewType.SCREENSHOT -> {
|
||||||
with(holder.image) {
|
holder as ScreenshotViewHolder
|
||||||
load(item.screenshot.url(item.repository, item.packageName)) {
|
val item = items[position] as Item.ScreenshotItem
|
||||||
size(Dimension.Undefined, Dimension(150.dp.dpToPx.toInt()))
|
with(holder.image) {
|
||||||
scale(Scale.FIT)
|
load(item.screenshot.url(context, item.repository, item.packageName)) {
|
||||||
placeholder(holder.placeholder)
|
authentication(item.repository.authentication)
|
||||||
error(holder.placeholder)
|
scale(Scale.FILL)
|
||||||
authentication(item.repository.authentication)
|
placeholder(holder.placeholder)
|
||||||
|
error(holder.placeholder.asImage())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ViewType.VIDEO -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
|
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
|
||||||
super.onViewRecycled(holder)
|
super.onViewRecycled(holder)
|
||||||
holder as ViewHolder
|
if (holder is ScreenshotViewHolder) holder.image.dispose()
|
||||||
holder.image.dispose()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed class Item {
|
private sealed interface Item {
|
||||||
abstract val descriptor: String
|
|
||||||
|
val descriptor: String
|
||||||
|
val viewType: ViewType
|
||||||
|
|
||||||
class ScreenshotItem(
|
class ScreenshotItem(
|
||||||
val repository: Repository,
|
val repository: Repository,
|
||||||
val packageName: String,
|
val packageName: String,
|
||||||
val screenshot: Product.Screenshot
|
val screenshot: Product.Screenshot,
|
||||||
) : Item() {
|
) : Item {
|
||||||
|
override val viewType: ViewType get() = ViewType.SCREENSHOT
|
||||||
override val descriptor: String
|
override val descriptor: String
|
||||||
get() = "screenshot.${repository.id}.${screenshot.identifier}"
|
get() = "screenshot.${repository.id}.${screenshot.identifier}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VideoItem(val videoUrl: String) : Item {
|
||||||
|
override val viewType: ViewType get() = ViewType.VIDEO
|
||||||
|
override val descriptor: String get() = "video"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.looker.droidify.ui.appList
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.res.ColorStateList
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -9,7 +10,7 @@ import android.widget.FrameLayout
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.load
|
import coil3.load
|
||||||
import com.google.android.material.imageview.ShapeableImageView
|
import com.google.android.material.imageview.ShapeableImageView
|
||||||
import com.google.android.material.progressindicator.CircularProgressIndicator
|
import com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
@ -22,23 +23,31 @@ import com.looker.droidify.utility.common.extension.dp
|
|||||||
import com.looker.droidify.utility.common.extension.getColorFromAttr
|
import com.looker.droidify.utility.common.extension.getColorFromAttr
|
||||||
import com.looker.droidify.utility.common.extension.inflate
|
import com.looker.droidify.utility.common.extension.inflate
|
||||||
import com.looker.droidify.utility.common.extension.setTextSizeScaled
|
import com.looker.droidify.utility.common.extension.setTextSizeScaled
|
||||||
|
import com.looker.droidify.utility.common.log
|
||||||
import com.looker.droidify.utility.common.nullIfEmpty
|
import com.looker.droidify.utility.common.nullIfEmpty
|
||||||
import com.looker.droidify.utility.extension.resources.TypefaceExtra
|
import com.looker.droidify.utility.extension.resources.TypefaceExtra
|
||||||
import com.looker.droidify.widget.CursorRecyclerAdapter
|
import com.looker.droidify.widget.CursorRecyclerAdapter
|
||||||
|
import kotlin.system.measureTimeMillis
|
||||||
import com.google.android.material.R as MaterialR
|
import com.google.android.material.R as MaterialR
|
||||||
|
|
||||||
class AppListAdapter(
|
class AppListAdapter(
|
||||||
private val source: AppListFragment.Source,
|
private val source: AppListFragment.Source,
|
||||||
private val onClick: (ProductItem) -> Unit
|
private val onClick: (packageName: String) -> Unit,
|
||||||
) : CursorRecyclerAdapter<AppListAdapter.ViewType, RecyclerView.ViewHolder>() {
|
) : CursorRecyclerAdapter<AppListAdapter.ViewType, RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
enum class ViewType { PRODUCT, LOADING, EMPTY }
|
enum class ViewType { PRODUCT, LOADING, EMPTY }
|
||||||
|
|
||||||
private class ProductViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
private inner class ProductViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
val name = itemView.findViewById<TextView>(R.id.name)!!
|
val name = itemView.findViewById<TextView>(R.id.name)!!
|
||||||
val status = itemView.findViewById<TextView>(R.id.status)!!
|
val status = itemView.findViewById<TextView>(R.id.status)!!
|
||||||
val summary = itemView.findViewById<TextView>(R.id.summary)!!
|
val summary = itemView.findViewById<TextView>(R.id.summary)!!
|
||||||
val icon = itemView.findViewById<ShapeableImageView>(R.id.icon)!!
|
val icon = itemView.findViewById<ShapeableImageView>(R.id.icon)!!
|
||||||
|
|
||||||
|
init {
|
||||||
|
itemView.setOnClickListener {
|
||||||
|
log(measureTimeMillis { onClick(getPackageName(absoluteAdapterPosition)) }, "Bench")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LoadingViewHolder(context: Context) :
|
private class LoadingViewHolder(context: Context) :
|
||||||
@ -82,12 +91,14 @@ class AppListAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var repositories: Map<Long, Repository> = emptyMap()
|
private val repositories: HashMap<Long, Repository> = HashMap()
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
|
||||||
set(value) {
|
fun updateRepos(repos: List<Repository>) {
|
||||||
field = value
|
repos.forEach {
|
||||||
notifyDataSetChanged()
|
repositories[it.id] = it
|
||||||
}
|
}
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
var emptyText: String = ""
|
var emptyText: String = ""
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
@ -117,24 +128,31 @@ class AppListAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getPackageName(position: Int): String {
|
||||||
|
return Database.ProductAdapter.transformPackageName(moveTo(position.coerceAtLeast(0)))
|
||||||
|
}
|
||||||
|
|
||||||
private fun getProductItem(position: Int): ProductItem {
|
private fun getProductItem(position: Int): ProductItem {
|
||||||
return Database.ProductAdapter.transformItem(moveTo(position.coerceAtLeast(0)))
|
return Database.ProductAdapter.transformItem(moveTo(position.coerceAtLeast(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(
|
override fun onCreateViewHolder(
|
||||||
parent: ViewGroup,
|
parent: ViewGroup,
|
||||||
viewType: ViewType
|
viewType: ViewType,
|
||||||
): RecyclerView.ViewHolder {
|
): RecyclerView.ViewHolder {
|
||||||
return when (viewType) {
|
return when (viewType) {
|
||||||
ViewType.PRODUCT -> ProductViewHolder(parent.inflate(R.layout.product_item)).apply {
|
ViewType.PRODUCT -> ProductViewHolder(parent.inflate(R.layout.product_item))
|
||||||
itemView.setOnClickListener { onClick(getProductItem(absoluteAdapterPosition)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewType.LOADING -> LoadingViewHolder(parent.context)
|
ViewType.LOADING -> LoadingViewHolder(parent.context)
|
||||||
ViewType.EMPTY -> EmptyViewHolder(parent.context)
|
ViewType.EMPTY -> EmptyViewHolder(parent.context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var updateBackground: ColorStateList? = null
|
||||||
|
private var updateForeground: ColorStateList? = null
|
||||||
|
private var installedBackground: ColorStateList? = null
|
||||||
|
private var installedForeground: ColorStateList? = null
|
||||||
|
private var defaultForeground: ColorStateList? = null
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
when (getItemEnumViewType(position)) {
|
when (getItemEnumViewType(position)) {
|
||||||
ViewType.PRODUCT -> {
|
ViewType.PRODUCT -> {
|
||||||
@ -142,9 +160,9 @@ class AppListAdapter(
|
|||||||
val productItem = getProductItem(position)
|
val productItem = getProductItem(position)
|
||||||
holder.name.text = productItem.name
|
holder.name.text = productItem.name
|
||||||
holder.summary.text = productItem.summary
|
holder.summary.text = productItem.summary
|
||||||
holder.summary.isVisible =
|
holder.summary.isVisible = productItem.summary.isNotEmpty()
|
||||||
productItem.summary.isNotEmpty() && productItem.name != productItem.summary
|
&& productItem.name != productItem.summary
|
||||||
val repository: Repository? = repositories[productItem.repositoryId]
|
val repository = repositories[productItem.repositoryId]
|
||||||
if (repository != null) {
|
if (repository != null) {
|
||||||
val iconUrl = productItem.icon(view = holder.icon, repository = repository)
|
val iconUrl = productItem.icon(view = holder.icon, repository = repository)
|
||||||
holder.icon.load(iconUrl) {
|
holder.icon.load(iconUrl) {
|
||||||
@ -161,28 +179,38 @@ class AppListAdapter(
|
|||||||
val isInstalled = productItem.installedVersion.nullIfEmpty() != null
|
val isInstalled = productItem.installedVersion.nullIfEmpty() != null
|
||||||
when {
|
when {
|
||||||
productItem.canUpdate -> {
|
productItem.canUpdate -> {
|
||||||
backgroundTintList =
|
if (updateBackground == null) {
|
||||||
context.getColorFromAttr(MaterialR.attr.colorTertiaryContainer)
|
updateBackground =
|
||||||
setTextColor(
|
context.getColorFromAttr(MaterialR.attr.colorTertiaryContainer)
|
||||||
context.getColorFromAttr(MaterialR.attr.colorOnTertiaryContainer)
|
}
|
||||||
)
|
if (updateForeground == null) {
|
||||||
|
updateForeground =
|
||||||
|
context.getColorFromAttr(MaterialR.attr.colorOnTertiaryContainer)
|
||||||
|
}
|
||||||
|
backgroundTintList = updateBackground
|
||||||
|
setTextColor(updateForeground)
|
||||||
}
|
}
|
||||||
|
|
||||||
isInstalled -> {
|
isInstalled -> {
|
||||||
backgroundTintList =
|
if (installedBackground == null) {
|
||||||
context.getColorFromAttr(MaterialR.attr.colorSecondaryContainer)
|
installedBackground =
|
||||||
setTextColor(
|
context.getColorFromAttr(MaterialR.attr.colorSecondaryContainer)
|
||||||
context.getColorFromAttr(MaterialR.attr.colorOnSecondaryContainer)
|
}
|
||||||
)
|
if (installedForeground == null) {
|
||||||
|
installedForeground =
|
||||||
|
context.getColorFromAttr(MaterialR.attr.colorOnSecondaryContainer)
|
||||||
|
}
|
||||||
|
backgroundTintList = installedBackground
|
||||||
|
setTextColor(installedForeground)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
setPadding(0, 0, 0, 0)
|
setPadding(0, 0, 0, 0)
|
||||||
setTextColor(
|
if (defaultForeground == null) {
|
||||||
holder.status.context.getColorFromAttr(
|
defaultForeground =
|
||||||
MaterialR.attr.colorOnBackground
|
context.getColorFromAttr(MaterialR.attr.colorOnBackground)
|
||||||
)
|
}
|
||||||
)
|
setTextColor(defaultForeground)
|
||||||
background = null
|
background = null
|
||||||
return@with
|
return@with
|
||||||
}
|
}
|
||||||
@ -191,9 +219,9 @@ class AppListAdapter(
|
|||||||
6.dp.let { setPadding(it, it, it, it) }
|
6.dp.let { setPadding(it, it, it, it) }
|
||||||
}
|
}
|
||||||
val enabled = productItem.compatible || productItem.installedVersion.isNotEmpty()
|
val enabled = productItem.compatible || productItem.installedVersion.isNotEmpty()
|
||||||
sequenceOf(holder.name, holder.status, holder.summary).forEach {
|
holder.name.isEnabled = enabled
|
||||||
it.isEnabled = enabled
|
holder.status.isEnabled = enabled
|
||||||
}
|
holder.summary.isEnabled = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewType.LOADING -> {
|
ViewType.LOADING -> {
|
||||||
@ -204,6 +232,6 @@ class AppListAdapter(
|
|||||||
holder as EmptyViewHolder
|
holder as EmptyViewHolder
|
||||||
holder.text.text = emptyText
|
holder.text.text = emptyText
|
||||||
}
|
}
|
||||||
}::class
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,19 +14,19 @@ import androidx.lifecycle.lifecycleScope
|
|||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.looker.droidify.utility.common.Scroller
|
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
import com.looker.droidify.R.string as stringRes
|
import com.looker.droidify.database.CursorOwner
|
||||||
|
import com.looker.droidify.databinding.RecyclerViewWithFabBinding
|
||||||
|
import com.looker.droidify.model.ProductItem
|
||||||
|
import com.looker.droidify.utility.common.Scroller
|
||||||
import com.looker.droidify.utility.common.extension.dp
|
import com.looker.droidify.utility.common.extension.dp
|
||||||
import com.looker.droidify.utility.common.extension.isFirstItemVisible
|
import com.looker.droidify.utility.common.extension.isFirstItemVisible
|
||||||
import com.looker.droidify.utility.common.extension.systemBarsMargin
|
import com.looker.droidify.utility.common.extension.systemBarsMargin
|
||||||
import com.looker.droidify.utility.common.extension.systemBarsPadding
|
import com.looker.droidify.utility.common.extension.systemBarsPadding
|
||||||
import com.looker.droidify.model.ProductItem
|
import com.looker.droidify.utility.extension.mainActivity
|
||||||
import com.looker.droidify.database.CursorOwner
|
|
||||||
import com.looker.droidify.databinding.RecyclerViewWithFabBinding
|
|
||||||
import com.looker.droidify.utility.extension.screenActivity
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import com.looker.droidify.R.string as stringRes
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class AppListFragment() : Fragment(), CursorOwner.Callback {
|
class AppListFragment() : Fragment(), CursorOwner.Callback {
|
||||||
@ -46,7 +46,7 @@ class AppListFragment() : Fragment(), CursorOwner.Callback {
|
|||||||
val titleResId: Int,
|
val titleResId: Int,
|
||||||
val sections: Boolean,
|
val sections: Boolean,
|
||||||
val order: Boolean,
|
val order: Boolean,
|
||||||
val updateAll: Boolean
|
val updateAll: Boolean,
|
||||||
) {
|
) {
|
||||||
AVAILABLE(stringRes.available, true, true, false),
|
AVAILABLE(stringRes.available, true, true, false),
|
||||||
INSTALLED(stringRes.installed, false, true, false),
|
INSTALLED(stringRes.installed, false, true, false),
|
||||||
@ -63,14 +63,15 @@ class AppListFragment() : Fragment(), CursorOwner.Callback {
|
|||||||
get() = requireArguments().getString(EXTRA_SOURCE)!!.let(Source::valueOf)
|
get() = requireArguments().getString(EXTRA_SOURCE)!!.let(Source::valueOf)
|
||||||
|
|
||||||
private lateinit var recyclerView: RecyclerView
|
private lateinit var recyclerView: RecyclerView
|
||||||
private lateinit var recyclerViewAdapter: AppListAdapter
|
private lateinit var appListAdapter: AppListAdapter
|
||||||
|
private var scroller: Scroller? = null
|
||||||
private var shortAnimationDuration: Int = 0
|
private var shortAnimationDuration: Int = 0
|
||||||
private var layoutManagerState: Parcelable? = null
|
private var layoutManagerState: Parcelable? = null
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?,
|
||||||
): View {
|
): View {
|
||||||
_binding = RecyclerViewWithFabBinding.inflate(inflater, container, false)
|
_binding = RecyclerViewWithFabBinding.inflate(inflater, container, false)
|
||||||
|
|
||||||
@ -83,10 +84,8 @@ class AppListFragment() : Fragment(), CursorOwner.Callback {
|
|||||||
isMotionEventSplittingEnabled = false
|
isMotionEventSplittingEnabled = false
|
||||||
setHasFixedSize(true)
|
setHasFixedSize(true)
|
||||||
recycledViewPool.setMaxRecycledViews(AppListAdapter.ViewType.PRODUCT.ordinal, 30)
|
recycledViewPool.setMaxRecycledViews(AppListAdapter.ViewType.PRODUCT.ordinal, 30)
|
||||||
recyclerViewAdapter = AppListAdapter(source) {
|
appListAdapter = AppListAdapter(source, mainActivity::navigateProduct)
|
||||||
screenActivity.navigateProduct(it.packageName)
|
adapter = appListAdapter
|
||||||
}
|
|
||||||
adapter = recyclerViewAdapter
|
|
||||||
systemBarsPadding()
|
systemBarsPadding()
|
||||||
}
|
}
|
||||||
val fab = binding.scrollUp
|
val fab = binding.scrollUp
|
||||||
@ -103,11 +102,13 @@ class AppListFragment() : Fragment(), CursorOwner.Callback {
|
|||||||
}
|
}
|
||||||
systemBarsMargin(16.dp)
|
systemBarsMargin(16.dp)
|
||||||
} else {
|
} else {
|
||||||
text = ""
|
text = null
|
||||||
setIconResource(R.drawable.arrow_up)
|
setIconResource(R.drawable.arrow_up)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
val scroller = Scroller(requireContext())
|
if (scroller == null) {
|
||||||
scroller.targetPosition = 0
|
scroller = Scroller(requireContext())
|
||||||
|
}
|
||||||
|
scroller!!.targetPosition = 0
|
||||||
recyclerView.layoutManager?.startSmoothScroll(scroller)
|
recyclerView.layoutManager?.startSmoothScroll(scroller)
|
||||||
}
|
}
|
||||||
alpha = 0f
|
alpha = 0f
|
||||||
@ -138,7 +139,7 @@ class AppListFragment() : Fragment(), CursorOwner.Callback {
|
|||||||
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
launch {
|
launch {
|
||||||
viewModel.reposStream.collect { repos ->
|
viewModel.reposStream.collect { repos ->
|
||||||
recyclerViewAdapter.repositories = repos.associateBy { it.id }
|
appListAdapter.updateRepos(repos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
launch {
|
launch {
|
||||||
@ -160,12 +161,13 @@ class AppListFragment() : Fragment(), CursorOwner.Callback {
|
|||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
viewModel.syncConnection.unbind(requireContext())
|
viewModel.syncConnection.unbind(requireContext())
|
||||||
_binding = null
|
_binding = null
|
||||||
screenActivity.cursorOwner.detach(this)
|
scroller = null
|
||||||
|
mainActivity.cursorOwner.detach(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCursorData(request: CursorOwner.Request, cursor: Cursor?) {
|
override fun onCursorData(request: CursorOwner.Request, cursor: Cursor?) {
|
||||||
recyclerViewAdapter.cursor = cursor
|
appListAdapter.cursor = cursor
|
||||||
recyclerViewAdapter.emptyText = when {
|
appListAdapter.emptyText = when {
|
||||||
cursor == null -> ""
|
cursor == null -> ""
|
||||||
viewModel.searchQuery.value.isNotEmpty() -> {
|
viewModel.searchQuery.value.isNotEmpty() -> {
|
||||||
getString(stringRes.no_matching_applications_found)
|
getString(stringRes.no_matching_applications_found)
|
||||||
@ -197,7 +199,7 @@ class AppListFragment() : Fragment(), CursorOwner.Callback {
|
|||||||
|
|
||||||
private fun updateRequest() {
|
private fun updateRequest() {
|
||||||
if (view != null) {
|
if (view != null) {
|
||||||
screenActivity.cursorOwner.attach(this, viewModel.request(source))
|
mainActivity.cursorOwner.attach(this, viewModel.request(source))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,40 +2,52 @@ package com.looker.droidify.ui.appList
|
|||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.looker.droidify.utility.common.extension.asStateFlow
|
import com.looker.droidify.database.CursorOwner
|
||||||
|
import com.looker.droidify.database.CursorOwner.Request.Available
|
||||||
|
import com.looker.droidify.database.CursorOwner.Request.Installed
|
||||||
|
import com.looker.droidify.database.CursorOwner.Request.Updates
|
||||||
|
import com.looker.droidify.database.Database
|
||||||
import com.looker.droidify.datastore.SettingsRepository
|
import com.looker.droidify.datastore.SettingsRepository
|
||||||
import com.looker.droidify.datastore.get
|
import com.looker.droidify.datastore.get
|
||||||
import com.looker.droidify.datastore.model.SortOrder
|
import com.looker.droidify.datastore.model.SortOrder
|
||||||
import com.looker.droidify.model.ProductItem
|
import com.looker.droidify.model.ProductItem
|
||||||
import com.looker.droidify.model.ProductItem.Section.All
|
import com.looker.droidify.model.ProductItem.Section.All
|
||||||
import com.looker.droidify.database.CursorOwner
|
|
||||||
import com.looker.droidify.database.Database
|
|
||||||
import com.looker.droidify.service.Connection
|
import com.looker.droidify.service.Connection
|
||||||
import com.looker.droidify.service.SyncService
|
import com.looker.droidify.service.SyncService
|
||||||
|
import com.looker.droidify.utility.common.extension.asStateFlow
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import javax.inject.Inject
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.flatMapConcat
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class AppListViewModel
|
class AppListViewModel
|
||||||
@Inject constructor(
|
@Inject constructor(
|
||||||
settingsRepository: SettingsRepository
|
settingsRepository: SettingsRepository,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
|
private val skipSignatureStream = settingsRepository
|
||||||
|
.get { ignoreSignature }
|
||||||
|
.asStateFlow(false)
|
||||||
|
|
||||||
|
val sortOrderFlow = settingsRepository
|
||||||
|
.get { sortOrder }
|
||||||
|
.asStateFlow(SortOrder.UPDATED)
|
||||||
|
|
||||||
val reposStream = Database.RepositoryAdapter
|
val reposStream = Database.RepositoryAdapter
|
||||||
.getAllStream()
|
.getAllStream()
|
||||||
.asStateFlow(emptyList())
|
.asStateFlow(emptyList())
|
||||||
|
|
||||||
val showUpdateAllButton = Database.ProductAdapter
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
.getUpdatesStream()
|
val showUpdateAllButton = skipSignatureStream.flatMapConcat { skip ->
|
||||||
.map { it.isNotEmpty() }
|
Database.ProductAdapter
|
||||||
.asStateFlow(false)
|
.getUpdatesStream(skip)
|
||||||
|
.map { it.isNotEmpty() }
|
||||||
val sortOrderFlow = settingsRepository.get { sortOrder }
|
}.asStateFlow(false)
|
||||||
.asStateFlow(SortOrder.UPDATED)
|
|
||||||
|
|
||||||
private val sections = MutableStateFlow<ProductItem.Section>(All)
|
private val sections = MutableStateFlow<ProductItem.Section>(All)
|
||||||
|
|
||||||
@ -51,22 +63,23 @@ class AppListViewModel
|
|||||||
|
|
||||||
fun request(source: AppListFragment.Source): CursorOwner.Request {
|
fun request(source: AppListFragment.Source): CursorOwner.Request {
|
||||||
return when (source) {
|
return when (source) {
|
||||||
AppListFragment.Source.AVAILABLE -> CursorOwner.Request.ProductsAvailable(
|
AppListFragment.Source.AVAILABLE -> Available(
|
||||||
searchQuery.value,
|
searchQuery = searchQuery.value,
|
||||||
sections.value,
|
section = sections.value,
|
||||||
sortOrderFlow.value
|
order = sortOrderFlow.value,
|
||||||
)
|
)
|
||||||
|
|
||||||
AppListFragment.Source.INSTALLED -> CursorOwner.Request.ProductsInstalled(
|
AppListFragment.Source.INSTALLED -> Installed(
|
||||||
searchQuery.value,
|
searchQuery = searchQuery.value,
|
||||||
sections.value,
|
section = sections.value,
|
||||||
sortOrderFlow.value
|
order = sortOrderFlow.value,
|
||||||
)
|
)
|
||||||
|
|
||||||
AppListFragment.Source.UPDATES -> CursorOwner.Request.ProductsUpdates(
|
AppListFragment.Source.UPDATES -> Updates(
|
||||||
searchQuery.value,
|
searchQuery = searchQuery.value,
|
||||||
sections.value,
|
section = sections.value,
|
||||||
sortOrderFlow.value
|
order = sortOrderFlow.value,
|
||||||
|
skipSignatureCheck = skipSignatureStream.value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import android.view.LayoutInflater
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.load
|
import coil3.load
|
||||||
import com.looker.droidify.databinding.ProductItemBinding
|
import com.looker.droidify.databinding.ProductItemBinding
|
||||||
import com.looker.droidify.model.Product
|
import com.looker.droidify.model.Product
|
||||||
import com.looker.droidify.model.Repository
|
import com.looker.droidify.model.Repository
|
||||||
|
@ -15,7 +15,7 @@ import com.looker.droidify.R
|
|||||||
import com.looker.droidify.utility.common.extension.systemBarsPadding
|
import com.looker.droidify.utility.common.extension.systemBarsPadding
|
||||||
import com.looker.droidify.database.Database
|
import com.looker.droidify.database.Database
|
||||||
import com.looker.droidify.ui.ScreenFragment
|
import com.looker.droidify.ui.ScreenFragment
|
||||||
import com.looker.droidify.utility.extension.screenActivity
|
import com.looker.droidify.utility.extension.mainActivity
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -43,7 +43,7 @@ class FavouritesFragment : ScreenFragment() {
|
|||||||
isVerticalScrollBarEnabled = false
|
isVerticalScrollBarEnabled = false
|
||||||
setHasFixedSize(true)
|
setHasFixedSize(true)
|
||||||
recyclerViewAdapter =
|
recyclerViewAdapter =
|
||||||
FavouriteFragmentAdapter { screenActivity.navigateProduct(it) }
|
FavouriteFragmentAdapter { mainActivity.navigateProduct(it) }
|
||||||
this.adapter = recyclerViewAdapter
|
this.adapter = recyclerViewAdapter
|
||||||
systemBarsPadding(includeFab = false)
|
systemBarsPadding(includeFab = false)
|
||||||
recyclerView = this
|
recyclerView = this
|
||||||
@ -74,6 +74,6 @@ class FavouritesFragment : ScreenFragment() {
|
|||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
screenActivity.onToolbarCreated(toolbar)
|
mainActivity.onToolbarCreated(toolbar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
package com.looker.droidify.ui.favourites
|
package com.looker.droidify.ui.favourites
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import com.looker.droidify.database.Database
|
||||||
import com.looker.droidify.utility.common.extension.asStateFlow
|
|
||||||
import com.looker.droidify.datastore.SettingsRepository
|
import com.looker.droidify.datastore.SettingsRepository
|
||||||
import com.looker.droidify.datastore.get
|
import com.looker.droidify.datastore.get
|
||||||
import com.looker.droidify.model.Product
|
import com.looker.droidify.model.Product
|
||||||
import com.looker.droidify.database.Database
|
import com.looker.droidify.utility.common.extension.asStateFlow
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import javax.inject.Inject
|
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.launch
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class FavouritesViewModel @Inject constructor(
|
class FavouritesViewModel @Inject constructor(
|
||||||
private val settingsRepository: SettingsRepository
|
settingsRepository: SettingsRepository,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val favouriteApps: StateFlow<List<List<Product>>> =
|
val favouriteApps: StateFlow<List<List<Product>>> =
|
||||||
@ -27,9 +25,4 @@ class FavouritesViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}.asStateFlow(emptyList())
|
}.asStateFlow(emptyList())
|
||||||
|
|
||||||
fun updateFavourites(packageName: String) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
settingsRepository.toggleFavourites(packageName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,26 +15,25 @@ import androidx.fragment.app.DialogFragment
|
|||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.looker.droidify.utility.common.extension.clipboardManager
|
import com.looker.droidify.R
|
||||||
import com.looker.droidify.utility.common.extension.get
|
|
||||||
import com.looker.droidify.utility.common.extension.getMutatedIcon
|
|
||||||
import com.looker.droidify.utility.common.nullIfEmpty
|
|
||||||
import com.looker.droidify.model.Repository
|
|
||||||
import com.looker.droidify.database.Database
|
import com.looker.droidify.database.Database
|
||||||
import com.looker.droidify.databinding.EditRepositoryBinding
|
import com.looker.droidify.databinding.EditRepositoryBinding
|
||||||
|
import com.looker.droidify.model.Repository
|
||||||
|
import com.looker.droidify.network.Downloader
|
||||||
|
import com.looker.droidify.network.NetworkResponse
|
||||||
import com.looker.droidify.service.Connection
|
import com.looker.droidify.service.Connection
|
||||||
import com.looker.droidify.service.SyncService
|
import com.looker.droidify.service.SyncService
|
||||||
import com.looker.droidify.ui.Message
|
import com.looker.droidify.ui.Message
|
||||||
import com.looker.droidify.ui.MessageDialog
|
import com.looker.droidify.ui.MessageDialog
|
||||||
import com.looker.droidify.ui.ScreenFragment
|
import com.looker.droidify.ui.ScreenFragment
|
||||||
import com.looker.droidify.utility.extension.screenActivity
|
import com.looker.droidify.utility.common.extension.clipboardManager
|
||||||
import com.looker.droidify.network.Downloader
|
import com.looker.droidify.utility.common.extension.get
|
||||||
import com.looker.droidify.network.NetworkResponse
|
import com.looker.droidify.utility.common.extension.getMutatedIcon
|
||||||
|
import com.looker.droidify.utility.common.nullIfEmpty
|
||||||
|
import com.looker.droidify.utility.extension.mainActivity
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.awaitAll
|
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
@ -44,7 +43,6 @@ import java.nio.charset.Charset
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import com.looker.droidify.R
|
|
||||||
import com.looker.droidify.R.string as stringRes
|
import com.looker.droidify.R.string as stringRes
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -82,11 +80,9 @@ class EditRepositoryFragment() : ScreenFragment() {
|
|||||||
|
|
||||||
syncConnection.bind(requireContext())
|
syncConnection.bind(requireContext())
|
||||||
|
|
||||||
screenActivity.onToolbarCreated(toolbar)
|
mainActivity.onToolbarCreated(toolbar)
|
||||||
toolbar.title =
|
toolbar.title =
|
||||||
getString(
|
getString(if (repoId != null) stringRes.edit_repository else stringRes.add_repository)
|
||||||
if (repoId != null) stringRes.edit_repository else stringRes.add_repository
|
|
||||||
)
|
|
||||||
|
|
||||||
saveMenuItem = toolbar.menu.add(stringRes.save)
|
saveMenuItem = toolbar.menu.add(stringRes.save)
|
||||||
.setIcon(toolbar.context.getMutatedIcon(R.drawable.ic_save))
|
.setIcon(toolbar.context.getMutatedIcon(R.drawable.ic_save))
|
||||||
@ -240,6 +236,8 @@ class EditRepositoryFragment() : ScreenFragment() {
|
|||||||
|
|
||||||
saveMenuItem = null
|
saveMenuItem = null
|
||||||
syncConnection.unbind(requireContext())
|
syncConnection.unbind(requireContext())
|
||||||
|
checkJob?.cancel()
|
||||||
|
checkJob = null
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,22 +392,22 @@ class EditRepositoryFragment() : ScreenFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun checkAddress(
|
private suspend fun checkAddress(
|
||||||
address: String,
|
rawAddress: String,
|
||||||
authentication: String
|
authentication: String
|
||||||
): String? = coroutineScope {
|
): String? = coroutineScope {
|
||||||
checkInProgress = true
|
checkInProgress = true
|
||||||
invalidateState()
|
invalidateState()
|
||||||
val allAddresses = addressSuffixes.map { "$address/$it" } + address
|
val allAddresses = addressSuffixes.map { "$rawAddress/$it" } + rawAddress
|
||||||
val pathCheck = allAddresses.map {
|
allAddresses
|
||||||
async {
|
.sortedBy { it.length }
|
||||||
downloader.headCall(
|
.forEach { address ->
|
||||||
url = "$it/index-v1.jar",
|
val response = downloader.headCall(
|
||||||
|
url = "$address/index-v1.jar",
|
||||||
headers = { authentication(authentication) }
|
headers = { authentication(authentication) }
|
||||||
) is NetworkResponse.Success
|
)
|
||||||
|
if (response is NetworkResponse.Success) return@coroutineScope address
|
||||||
}
|
}
|
||||||
}
|
null
|
||||||
val indexOfValidAddress = pathCheck.awaitAll().indexOf(true)
|
|
||||||
allAddresses[indexOfValidAddress].nullIfEmpty()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onSaveRepositoryProceedInvalidate(
|
private fun onSaveRepositoryProceedInvalidate(
|
||||||
@ -431,7 +429,7 @@ class EditRepositoryFragment() : ScreenFragment() {
|
|||||||
if (repositoryId == null && changedRepository.enabled) {
|
if (repositoryId == null && changedRepository.enabled) {
|
||||||
binder.sync(changedRepository)
|
binder.sync(changedRepository)
|
||||||
}
|
}
|
||||||
screenActivity.onBackPressedDispatcher.onBackPressed()
|
mainActivity.onBackPressedDispatcher.onBackPressed()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
invalidateState()
|
invalidateState()
|
||||||
@ -470,6 +468,6 @@ class EditRepositoryFragment() : ScreenFragment() {
|
|||||||
const val EXTRA_REPOSITORY_ID = "repositoryId"
|
const val EXTRA_REPOSITORY_ID = "repositoryId"
|
||||||
const val EXTRA_REPOSITORY_ADDRESS = "repositoryAddress"
|
const val EXTRA_REPOSITORY_ADDRESS = "repositoryAddress"
|
||||||
|
|
||||||
val addressSuffixes = listOf("fdroid/repo", "repo")
|
val addressSuffixes = arrayOf("fdroid/repo", "repo")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import com.looker.droidify.databinding.RecyclerViewWithFabBinding
|
|||||||
import com.looker.droidify.service.Connection
|
import com.looker.droidify.service.Connection
|
||||||
import com.looker.droidify.service.SyncService
|
import com.looker.droidify.service.SyncService
|
||||||
import com.looker.droidify.ui.ScreenFragment
|
import com.looker.droidify.ui.ScreenFragment
|
||||||
import com.looker.droidify.utility.extension.screenActivity
|
import com.looker.droidify.utility.extension.mainActivity
|
||||||
import com.looker.droidify.widget.addDivider
|
import com.looker.droidify.widget.addDivider
|
||||||
|
|
||||||
class RepositoriesFragment : ScreenFragment(), CursorOwner.Callback {
|
class RepositoriesFragment : ScreenFragment(), CursorOwner.Callback {
|
||||||
@ -36,7 +36,7 @@ class RepositoriesFragment : ScreenFragment(), CursorOwner.Callback {
|
|||||||
binding.scrollUp.apply {
|
binding.scrollUp.apply {
|
||||||
setIconResource(R.drawable.ic_add)
|
setIconResource(R.drawable.ic_add)
|
||||||
setText(R.string.add_repository)
|
setText(R.string.add_repository)
|
||||||
setOnClickListener { screenActivity.navigateAddRepository() }
|
setOnClickListener { mainActivity.navigateAddRepository() }
|
||||||
systemBarsMargin(16.dp)
|
systemBarsMargin(16.dp)
|
||||||
}
|
}
|
||||||
binding.recyclerView.apply {
|
binding.recyclerView.apply {
|
||||||
@ -44,7 +44,7 @@ class RepositoriesFragment : ScreenFragment(), CursorOwner.Callback {
|
|||||||
isMotionEventSplittingEnabled = false
|
isMotionEventSplittingEnabled = false
|
||||||
setHasFixedSize(true)
|
setHasFixedSize(true)
|
||||||
adapter = RepositoriesAdapter(
|
adapter = RepositoriesAdapter(
|
||||||
navigate = { screenActivity.navigateRepository(it.id) }
|
navigate = { mainActivity.navigateRepository(it.id) }
|
||||||
) { repository, isEnabled ->
|
) { repository, isEnabled ->
|
||||||
repository.enabled != isEnabled &&
|
repository.enabled != isEnabled &&
|
||||||
syncConnection.binder?.setEnabled(repository, isEnabled) == true
|
syncConnection.binder?.setEnabled(repository, isEnabled) == true
|
||||||
@ -79,8 +79,8 @@ class RepositoriesFragment : ScreenFragment(), CursorOwner.Callback {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
syncConnection.bind(requireContext())
|
syncConnection.bind(requireContext())
|
||||||
screenActivity.cursorOwner.attach(this, CursorOwner.Request.Repositories)
|
mainActivity.cursorOwner.attach(this, CursorOwner.Request.Repositories)
|
||||||
screenActivity.onToolbarCreated(toolbar)
|
mainActivity.onToolbarCreated(toolbar)
|
||||||
toolbar.title = getString(R.string.repositories)
|
toolbar.title = getString(R.string.repositories)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ class RepositoriesFragment : ScreenFragment(), CursorOwner.Callback {
|
|||||||
|
|
||||||
_binding = null
|
_binding = null
|
||||||
syncConnection.unbind(requireContext())
|
syncConnection.unbind(requireContext())
|
||||||
screenActivity.cursorOwner.detach(this)
|
mainActivity.cursorOwner.detach(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCursorData(request: CursorOwner.Request, cursor: Cursor?) {
|
override fun onCursorData(request: CursorOwner.Request, cursor: Cursor?) {
|
||||||
|
@ -22,7 +22,7 @@ import com.looker.droidify.databinding.RepositoryPageBinding
|
|||||||
import com.looker.droidify.ui.Message
|
import com.looker.droidify.ui.Message
|
||||||
import com.looker.droidify.ui.MessageDialog
|
import com.looker.droidify.ui.MessageDialog
|
||||||
import com.looker.droidify.ui.ScreenFragment
|
import com.looker.droidify.ui.ScreenFragment
|
||||||
import com.looker.droidify.utility.extension.screenActivity
|
import com.looker.droidify.utility.extension.mainActivity
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -53,7 +53,7 @@ class RepositoryFragment() : ScreenFragment() {
|
|||||||
super.onCreateView(inflater, container, savedInstanceState)
|
super.onCreateView(inflater, container, savedInstanceState)
|
||||||
_binding = RepositoryPageBinding.inflate(inflater, container, false)
|
_binding = RepositoryPageBinding.inflate(inflater, container, false)
|
||||||
viewModel.bindService(requireContext())
|
viewModel.bindService(requireContext())
|
||||||
screenActivity.onToolbarCreated(toolbar)
|
mainActivity.onToolbarCreated(toolbar)
|
||||||
toolbar.title = getString(stringRes.repository)
|
toolbar.title = getString(stringRes.repository)
|
||||||
val scroll = NestedScrollView(binding.root.context)
|
val scroll = NestedScrollView(binding.root.context)
|
||||||
scroll.addView(binding.root)
|
scroll.addView(binding.root)
|
||||||
@ -149,7 +149,7 @@ class RepositoryFragment() : ScreenFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
editRepoButton.setOnClickListener {
|
editRepoButton.setOnClickListener {
|
||||||
screenActivity.navigateEditRepository(viewModel.id)
|
mainActivity.navigateEditRepository(viewModel.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteRepoButton.setOnClickListener {
|
deleteRepoButton.setOnClickListener {
|
||||||
|
@ -2,6 +2,7 @@ package com.looker.droidify.ui.settings
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -23,13 +24,11 @@ import androidx.lifecycle.repeatOnLifecycle
|
|||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
import com.google.android.material.textfield.TextInputEditText
|
||||||
import com.looker.droidify.utility.common.SdkCheck
|
import com.looker.droidify.BuildConfig
|
||||||
import com.looker.droidify.utility.common.extension.getColorFromAttr
|
import com.looker.droidify.R
|
||||||
import com.looker.droidify.utility.common.extension.homeAsUp
|
import com.looker.droidify.databinding.EnumTypeBinding
|
||||||
import com.looker.droidify.utility.common.extension.systemBarsPadding
|
import com.looker.droidify.databinding.SettingsPageBinding
|
||||||
import com.looker.droidify.utility.common.extension.updateAsMutable
|
import com.looker.droidify.databinding.SwitchTypeBinding
|
||||||
import com.looker.droidify.utility.common.isIgnoreBatteryEnabled
|
|
||||||
import com.looker.droidify.utility.common.requestBatteryFreedom
|
|
||||||
import com.looker.droidify.datastore.Settings
|
import com.looker.droidify.datastore.Settings
|
||||||
import com.looker.droidify.datastore.extension.autoSyncName
|
import com.looker.droidify.datastore.extension.autoSyncName
|
||||||
import com.looker.droidify.datastore.extension.installerName
|
import com.looker.droidify.datastore.extension.installerName
|
||||||
@ -38,22 +37,25 @@ import com.looker.droidify.datastore.extension.themeName
|
|||||||
import com.looker.droidify.datastore.extension.toTime
|
import com.looker.droidify.datastore.extension.toTime
|
||||||
import com.looker.droidify.datastore.model.AutoSync
|
import com.looker.droidify.datastore.model.AutoSync
|
||||||
import com.looker.droidify.datastore.model.InstallerType
|
import com.looker.droidify.datastore.model.InstallerType
|
||||||
|
import com.looker.droidify.datastore.model.LegacyInstallerComponent
|
||||||
import com.looker.droidify.datastore.model.ProxyType
|
import com.looker.droidify.datastore.model.ProxyType
|
||||||
import com.looker.droidify.datastore.model.Theme
|
import com.looker.droidify.datastore.model.Theme
|
||||||
import com.looker.droidify.BuildConfig
|
import com.looker.droidify.utility.common.SdkCheck
|
||||||
import com.looker.droidify.databinding.EnumTypeBinding
|
import com.looker.droidify.utility.common.extension.getColorFromAttr
|
||||||
import com.looker.droidify.databinding.SettingsPageBinding
|
import com.looker.droidify.utility.common.extension.homeAsUp
|
||||||
import com.looker.droidify.databinding.SwitchTypeBinding
|
import com.looker.droidify.utility.common.extension.systemBarsPadding
|
||||||
|
import com.looker.droidify.utility.common.extension.updateAsMutable
|
||||||
|
import com.looker.droidify.utility.common.isIgnoreBatteryEnabled
|
||||||
|
import com.looker.droidify.utility.common.requestBatteryFreedom
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.first
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import kotlin.time.Duration.Companion.days
|
import kotlin.time.Duration.Companion.days
|
||||||
import kotlin.time.Duration.Companion.hours
|
import kotlin.time.Duration.Companion.hours
|
||||||
import com.google.android.material.R as MaterialR
|
import com.google.android.material.R as MaterialR
|
||||||
import com.looker.droidify.R
|
import androidx.core.net.toUri
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class SettingsFragment : Fragment() {
|
class SettingsFragment : Fragment() {
|
||||||
@ -119,9 +121,7 @@ class SettingsFragment : Fragment() {
|
|||||||
): View {
|
): View {
|
||||||
_binding = SettingsPageBinding.inflate(inflater, container, false)
|
_binding = SettingsPageBinding.inflate(inflater, container, false)
|
||||||
binding.nestedScrollView.systemBarsPadding()
|
binding.nestedScrollView.systemBarsPadding()
|
||||||
if (requireContext().isIgnoreBatteryEnabled()) {
|
viewModel.toggleBackgroundAccess(requireContext().isIgnoreBatteryEnabled())
|
||||||
viewModel.allowBackground()
|
|
||||||
}
|
|
||||||
val toolbar = binding.toolbar
|
val toolbar = binding.toolbar
|
||||||
toolbar.navigationIcon = toolbar.context.homeAsUp
|
toolbar.navigationIcon = toolbar.context.homeAsUp
|
||||||
toolbar.setNavigationOnClickListener { activity?.onBackPressedDispatcher?.onBackPressed() }
|
toolbar.setNavigationOnClickListener { activity?.onBackPressedDispatcher?.onBackPressed() }
|
||||||
@ -233,6 +233,56 @@ class SettingsFragment : Fragment() {
|
|||||||
onClick = { viewModel.setInstaller(requireContext(), it) }
|
onClick = { viewModel.setInstaller(requireContext(), it) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
val pm = requireContext().packageManager
|
||||||
|
legacyInstallerComponent.connect(
|
||||||
|
titleText = getString(R.string.legacyInstallerComponent),
|
||||||
|
setting = viewModel.getSetting { legacyInstallerComponent },
|
||||||
|
map = {
|
||||||
|
when (it) {
|
||||||
|
is LegacyInstallerComponent.Component -> {
|
||||||
|
val component = it
|
||||||
|
val appLabel = runCatching {
|
||||||
|
val info = pm.getApplicationInfo(component.clazz, 0)
|
||||||
|
pm.getApplicationLabel(info).toString()
|
||||||
|
}.getOrElse { component.clazz }
|
||||||
|
"$appLabel (${component.activity})"
|
||||||
|
}
|
||||||
|
LegacyInstallerComponent.Unspecified -> getString(R.string.unspecified)
|
||||||
|
LegacyInstallerComponent.AlwaysChoose -> getString(R.string.always_choose)
|
||||||
|
null -> getString(R.string.unspecified)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) { component, valueToString ->
|
||||||
|
val installerOptions = run {
|
||||||
|
var contentProtocol = "content://"
|
||||||
|
val intent = Intent(Intent.ACTION_INSTALL_PACKAGE).apply {
|
||||||
|
setDataAndType(contentProtocol.toUri(), "application/vnd.android.package-archive")
|
||||||
|
}
|
||||||
|
val activities = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
|
||||||
|
listOf(
|
||||||
|
LegacyInstallerComponent.Unspecified,
|
||||||
|
LegacyInstallerComponent.AlwaysChoose
|
||||||
|
) + activities.map {
|
||||||
|
LegacyInstallerComponent.Component(
|
||||||
|
clazz = it.activityInfo.packageName,
|
||||||
|
activity = it.activityInfo.name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addSingleCorrectDialog(
|
||||||
|
initialValue = component ?: LegacyInstallerComponent.Unspecified,
|
||||||
|
values = installerOptions,
|
||||||
|
title = R.string.legacyInstallerComponent,
|
||||||
|
iconRes = R.drawable.ic_apk_install,
|
||||||
|
valueToString = valueToString,
|
||||||
|
onClick = { viewModel.setLegacyInstallerComponentComponent(it) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
incompatibleUpdates.connect(
|
||||||
|
titleText = getString(R.string.incompatible_versions),
|
||||||
|
contentText = getString(R.string.incompatible_versions_summary),
|
||||||
|
setting = viewModel.getInitialSetting { incompatibleVersions },
|
||||||
|
)
|
||||||
proxyType.connect(
|
proxyType.connect(
|
||||||
titleText = getString(R.string.proxy_type),
|
titleText = getString(R.string.proxy_type),
|
||||||
setting = viewModel.getSetting { proxy.type },
|
setting = viewModel.getSetting { proxy.type },
|
||||||
@ -283,6 +333,7 @@ class SettingsFragment : Fragment() {
|
|||||||
exportRepos.title.text = getString(R.string.export_repos_title)
|
exportRepos.title.text = getString(R.string.export_repos_title)
|
||||||
exportRepos.content.text = getString(R.string.export_repos_DESC)
|
exportRepos.content.text = getString(R.string.export_repos_DESC)
|
||||||
|
|
||||||
|
allowBackgroundWork.root.isVisible = false
|
||||||
allowBackgroundWork.title.text = getString(R.string.require_background_access)
|
allowBackgroundWork.title.text = getString(R.string.require_background_access)
|
||||||
allowBackgroundWork.content.text =
|
allowBackgroundWork.content.text =
|
||||||
getString(R.string.require_background_access_DESC)
|
getString(R.string.require_background_access_DESC)
|
||||||
@ -315,8 +366,8 @@ class SettingsFragment : Fragment() {
|
|||||||
launch {
|
launch {
|
||||||
viewModel.settingsFlow.collect { setting ->
|
viewModel.settingsFlow.collect { setting ->
|
||||||
updateSettings(setting)
|
updateSettings(setting)
|
||||||
binding.allowBackgroundWork.root.isVisible = !viewModel.backgroundTask.first()
|
binding.allowBackgroundWork.root.isVisible =
|
||||||
&& setting.autoSync != AutoSync.NEVER
|
!viewModel.isBackgroundAllowed && setting.autoSync != AutoSync.NEVER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,9 +377,7 @@ class SettingsFragment : Fragment() {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
if (requireContext().isIgnoreBatteryEnabled()) {
|
viewModel.toggleBackgroundAccess(requireContext().isIgnoreBatteryEnabled())
|
||||||
viewModel.allowBackground()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
@ -376,9 +425,7 @@ class SettingsFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
allowBackgroundWork.root.setOnClickListener {
|
allowBackgroundWork.root.setOnClickListener {
|
||||||
requireContext().requestBatteryFreedom()
|
requireContext().requestBatteryFreedom()
|
||||||
if (requireContext().isIgnoreBatteryEnabled()) {
|
viewModel.toggleBackgroundAccess(requireContext().isIgnoreBatteryEnabled())
|
||||||
viewModel.allowBackground()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
creditFoxy.root.setOnClickListener {
|
creditFoxy.root.setOnClickListener {
|
||||||
openLink(FOXY_DROID_URL)
|
openLink(FOXY_DROID_URL)
|
||||||
@ -395,6 +442,9 @@ class SettingsFragment : Fragment() {
|
|||||||
proxyHost.root.isVisible = allowProxies
|
proxyHost.root.isVisible = allowProxies
|
||||||
proxyPort.root.isVisible = allowProxies
|
proxyPort.root.isVisible = allowProxies
|
||||||
forceCleanUp.root.isVisible = settings.cleanUpInterval == Duration.INFINITE
|
forceCleanUp.root.isVisible = settings.cleanUpInterval == Duration.INFINITE
|
||||||
|
|
||||||
|
val useLegacyInstaller = settings.installerType == InstallerType.LEGACY
|
||||||
|
legacyInstallerComponent.root.isVisible = useLegacyInstaller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,35 +7,35 @@ import androidx.appcompat.app.AppCompatDelegate
|
|||||||
import androidx.core.os.LocaleListCompat
|
import androidx.core.os.LocaleListCompat
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.looker.droidify.R
|
||||||
|
import com.looker.droidify.database.Database
|
||||||
|
import com.looker.droidify.database.RepositoryExporter
|
||||||
import com.looker.droidify.datastore.Settings
|
import com.looker.droidify.datastore.Settings
|
||||||
import com.looker.droidify.datastore.SettingsRepository
|
import com.looker.droidify.datastore.SettingsRepository
|
||||||
import com.looker.droidify.datastore.get
|
import com.looker.droidify.datastore.get
|
||||||
import com.looker.droidify.datastore.model.AutoSync
|
import com.looker.droidify.datastore.model.AutoSync
|
||||||
import com.looker.droidify.datastore.model.InstallerType
|
import com.looker.droidify.datastore.model.InstallerType
|
||||||
import com.looker.droidify.datastore.model.InstallerType.*
|
import com.looker.droidify.datastore.model.InstallerType.ROOT
|
||||||
|
import com.looker.droidify.datastore.model.InstallerType.SHIZUKU
|
||||||
|
import com.looker.droidify.datastore.model.LegacyInstallerComponent
|
||||||
import com.looker.droidify.datastore.model.ProxyType
|
import com.looker.droidify.datastore.model.ProxyType
|
||||||
import com.looker.droidify.datastore.model.Theme
|
import com.looker.droidify.datastore.model.Theme
|
||||||
import com.looker.droidify.database.Database
|
|
||||||
import com.looker.droidify.database.RepositoryExporter
|
|
||||||
import com.looker.droidify.work.CleanUpWorker
|
|
||||||
import com.looker.droidify.installer.installers.isMagiskGranted
|
import com.looker.droidify.installer.installers.isMagiskGranted
|
||||||
import com.looker.droidify.installer.installers.isShizukuAlive
|
import com.looker.droidify.installer.installers.isShizukuAlive
|
||||||
import com.looker.droidify.installer.installers.isShizukuGranted
|
import com.looker.droidify.installer.installers.isShizukuGranted
|
||||||
import com.looker.droidify.installer.installers.isShizukuInstalled
|
import com.looker.droidify.installer.installers.isShizukuInstalled
|
||||||
import com.looker.droidify.installer.installers.requestPermissionListener
|
import com.looker.droidify.installer.installers.requestPermissionListener
|
||||||
|
import com.looker.droidify.work.CleanUpWorker
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import com.looker.droidify.R
|
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class SettingsViewModel
|
class SettingsViewModel
|
||||||
@ -49,8 +49,8 @@ class SettingsViewModel
|
|||||||
}
|
}
|
||||||
val settingsFlow get() = settingsRepository.data
|
val settingsFlow get() = settingsRepository.data
|
||||||
|
|
||||||
private val _backgroundTask = MutableStateFlow(false)
|
var isBackgroundAllowed = true
|
||||||
val backgroundTask = _backgroundTask.asStateFlow()
|
private set
|
||||||
|
|
||||||
private val _snackbarStringId = MutableSharedFlow<Int>()
|
private val _snackbarStringId = MutableSharedFlow<Int>()
|
||||||
val snackbarStringId = _snackbarStringId.asSharedFlow()
|
val snackbarStringId = _snackbarStringId.asSharedFlow()
|
||||||
@ -59,10 +59,8 @@ class SettingsViewModel
|
|||||||
|
|
||||||
fun <T> getInitialSetting(block: Settings.() -> T): Flow<T> = initialSetting.map { it.block() }
|
fun <T> getInitialSetting(block: Settings.() -> T): Flow<T> = initialSetting.map { it.block() }
|
||||||
|
|
||||||
fun allowBackground() {
|
fun toggleBackgroundAccess(enable: Boolean) {
|
||||||
viewModelScope.launch {
|
isBackgroundAllowed = enable
|
||||||
_backgroundTask.emit(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setLanguage(language: String) {
|
fun setLanguage(language: String) {
|
||||||
@ -172,7 +170,7 @@ class SettingsViewModel
|
|||||||
} else if (isShizukuGranted()) {
|
} else if (isShizukuGranted()) {
|
||||||
settingsRepository.setInstallerType(installerType)
|
settingsRepository.setInstallerType(installerType)
|
||||||
} else if (!isShizukuGranted()) {
|
} else if (!isShizukuGranted()) {
|
||||||
if(requestPermissionListener()) {
|
if (requestPermissionListener()) {
|
||||||
settingsRepository.setInstallerType(installerType)
|
settingsRepository.setInstallerType(installerType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,6 +192,12 @@ class SettingsViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setLegacyInstallerComponentComponent(component: LegacyInstallerComponent?) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
settingsRepository.setLegacyInstallerComponent(component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun exportSettings(file: Uri) {
|
fun exportSettings(file: Uri) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
settingsRepository.export(file)
|
settingsRepository.export(file)
|
||||||
|
@ -14,6 +14,7 @@ import android.widget.FrameLayout
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
@ -28,24 +29,24 @@ import com.google.android.material.elevation.SurfaceColors
|
|||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import com.google.android.material.shape.ShapeAppearanceModel
|
import com.google.android.material.shape.ShapeAppearanceModel
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
import com.looker.droidify.R
|
||||||
|
import com.looker.droidify.databinding.TabsToolbarBinding
|
||||||
|
import com.looker.droidify.datastore.model.supportedSortOrders
|
||||||
|
import com.looker.droidify.datastore.extension.sortOrderName
|
||||||
|
import com.looker.droidify.datastore.model.SortOrder
|
||||||
|
import com.looker.droidify.model.ProductItem
|
||||||
|
import com.looker.droidify.service.Connection
|
||||||
|
import com.looker.droidify.service.SyncService
|
||||||
|
import com.looker.droidify.ui.ScreenFragment
|
||||||
|
import com.looker.droidify.ui.appList.AppListFragment
|
||||||
import com.looker.droidify.utility.common.device.Huawei
|
import com.looker.droidify.utility.common.device.Huawei
|
||||||
import com.looker.droidify.utility.common.extension.dp
|
import com.looker.droidify.utility.common.extension.dp
|
||||||
import com.looker.droidify.utility.common.extension.getMutatedIcon
|
import com.looker.droidify.utility.common.extension.getMutatedIcon
|
||||||
import com.looker.droidify.utility.common.extension.selectableBackground
|
import com.looker.droidify.utility.common.extension.selectableBackground
|
||||||
import com.looker.droidify.utility.common.extension.systemBarsPadding
|
import com.looker.droidify.utility.common.extension.systemBarsPadding
|
||||||
import com.looker.droidify.utility.common.sdkAbove
|
import com.looker.droidify.utility.common.sdkAbove
|
||||||
import com.looker.droidify.datastore.extension.sortOrderName
|
|
||||||
import com.looker.droidify.datastore.model.SortOrder
|
|
||||||
import com.looker.droidify.R
|
|
||||||
import com.looker.droidify.databinding.TabsToolbarBinding
|
|
||||||
import com.looker.droidify.datastore.model.supportedSortOrders
|
|
||||||
import com.looker.droidify.model.ProductItem
|
|
||||||
import com.looker.droidify.service.Connection
|
|
||||||
import com.looker.droidify.service.SyncService
|
|
||||||
import com.looker.droidify.ui.ScreenFragment
|
|
||||||
import com.looker.droidify.ui.appList.AppListFragment
|
|
||||||
import com.looker.droidify.utility.extension.resources.sizeScaled
|
import com.looker.droidify.utility.extension.resources.sizeScaled
|
||||||
import com.looker.droidify.utility.extension.screenActivity
|
import com.looker.droidify.utility.extension.mainActivity
|
||||||
import com.looker.droidify.widget.DividerConfiguration
|
import com.looker.droidify.widget.DividerConfiguration
|
||||||
import com.looker.droidify.widget.FocusSearchView
|
import com.looker.droidify.widget.FocusSearchView
|
||||||
import com.looker.droidify.widget.StableRecyclerAdapter
|
import com.looker.droidify.widget.StableRecyclerAdapter
|
||||||
@ -152,7 +153,7 @@ class TabsFragment : ScreenFragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
screenActivity.onToolbarCreated(toolbar)
|
mainActivity.onToolbarCreated(toolbar)
|
||||||
toolbar.title = getString(R.string.application_name)
|
toolbar.title = getString(R.string.application_name)
|
||||||
// Move focus from SearchView to Toolbar
|
// Move focus from SearchView to Toolbar
|
||||||
toolbar.isFocusable = true
|
toolbar.isFocusable = true
|
||||||
@ -204,7 +205,7 @@ class TabsFragment : ScreenFragment() {
|
|||||||
syncRepositoriesMenuItem = add(0, 0, 0, stringRes.sync_repositories)
|
syncRepositoriesMenuItem = add(0, 0, 0, stringRes.sync_repositories)
|
||||||
.setIcon(toolbar.context.getMutatedIcon(R.drawable.ic_sync))
|
.setIcon(toolbar.context.getMutatedIcon(R.drawable.ic_sync))
|
||||||
.setOnMenuItemClickListener {
|
.setOnMenuItemClickListener {
|
||||||
viewModel.sync()
|
syncConnection.binder?.sync(SyncService.SyncRequest.MANUAL)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,19 +227,19 @@ class TabsFragment : ScreenFragment() {
|
|||||||
favouritesItem = add(1, 0, 0, stringRes.favourites)
|
favouritesItem = add(1, 0, 0, stringRes.favourites)
|
||||||
.setIcon(toolbar.context.getMutatedIcon(R.drawable.ic_favourite_checked))
|
.setIcon(toolbar.context.getMutatedIcon(R.drawable.ic_favourite_checked))
|
||||||
.setOnMenuItemClickListener {
|
.setOnMenuItemClickListener {
|
||||||
view.post { screenActivity.navigateFavourites() }
|
view.post { mainActivity.navigateFavourites() }
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
add(1, 0, 0, stringRes.repositories)
|
add(1, 0, 0, stringRes.repositories)
|
||||||
.setOnMenuItemClickListener {
|
.setOnMenuItemClickListener {
|
||||||
view.post { screenActivity.navigateRepositories() }
|
view.post { mainActivity.navigateRepositories() }
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
add(1, 0, 0, stringRes.settings)
|
add(1, 0, 0, stringRes.settings)
|
||||||
.setOnMenuItemClickListener {
|
.setOnMenuItemClickListener {
|
||||||
view.post { screenActivity.navigatePreferences() }
|
view.post { mainActivity.navigatePreferences() }
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,6 +296,25 @@ class TabsFragment : ScreenFragment() {
|
|||||||
onBackPressedCallback?.isEnabled = it != BackAction.None
|
onBackPressedCallback?.isEnabled = it != BackAction.None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
launch {
|
||||||
|
SyncService.syncState.collect {
|
||||||
|
when (it) {
|
||||||
|
is SyncService.State.Connecting -> {
|
||||||
|
tabsBinding.syncState.isVisible = true
|
||||||
|
tabsBinding.syncState.isIndeterminate = true
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncService.State.Finish -> {
|
||||||
|
tabsBinding.syncState.isGone = true
|
||||||
|
}
|
||||||
|
|
||||||
|
is SyncService.State.Syncing -> {
|
||||||
|
tabsBinding.syncState.isVisible = true
|
||||||
|
tabsBinding.syncState.setProgressCompat(it.progress, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,17 +3,12 @@ package com.looker.droidify.ui.tabsFragment
|
|||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.looker.droidify.data.local.dao.IndexDao
|
|
||||||
import com.looker.droidify.data.local.model.RepoEntity
|
|
||||||
import com.looker.droidify.data.local.model.toRepo
|
|
||||||
import com.looker.droidify.database.Database
|
import com.looker.droidify.database.Database
|
||||||
import com.looker.droidify.datastore.SettingsRepository
|
import com.looker.droidify.datastore.SettingsRepository
|
||||||
import com.looker.droidify.datastore.get
|
import com.looker.droidify.datastore.get
|
||||||
import com.looker.droidify.datastore.model.SortOrder
|
import com.looker.droidify.datastore.model.SortOrder
|
||||||
import com.looker.droidify.domain.model.Fingerprint
|
import com.looker.droidify.domain.model.Fingerprint
|
||||||
import com.looker.droidify.model.ProductItem
|
import com.looker.droidify.model.ProductItem
|
||||||
import com.looker.droidify.sync.Syncable
|
|
||||||
import com.looker.droidify.sync.v2.model.IndexV2
|
|
||||||
import com.looker.droidify.ui.tabsFragment.TabsFragment.BackAction
|
import com.looker.droidify.ui.tabsFragment.TabsFragment.BackAction
|
||||||
import com.looker.droidify.utility.common.extension.asStateFlow
|
import com.looker.droidify.utility.common.extension.asStateFlow
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
@ -68,9 +63,15 @@ class TabsViewModel @Inject constructor(
|
|||||||
val backAction = combine(
|
val backAction = combine(
|
||||||
currentSection,
|
currentSection,
|
||||||
isSearchActionItemExpanded,
|
isSearchActionItemExpanded,
|
||||||
showSections,
|
showSections
|
||||||
::calcBackAction,
|
) { currentSection, isSearchActionItemExpanded, showSections ->
|
||||||
).asStateFlow(BackAction.None)
|
when {
|
||||||
|
currentSection != ProductItem.Section.All -> BackAction.ProductAll
|
||||||
|
isSearchActionItemExpanded -> BackAction.CollapseSearchView
|
||||||
|
showSections -> BackAction.HideSections
|
||||||
|
else -> BackAction.None
|
||||||
|
}
|
||||||
|
}.asStateFlow(BackAction.None)
|
||||||
|
|
||||||
fun setSection(section: ProductItem.Section) {
|
fun setSection(section: ProductItem.Section) {
|
||||||
savedStateHandle[STATE_SECTION] = section
|
savedStateHandle[STATE_SECTION] = section
|
||||||
@ -82,33 +83,6 @@ class TabsViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sync() {
|
|
||||||
viewModelScope.launch {
|
|
||||||
val repo = RepoEntity(
|
|
||||||
id = 1,
|
|
||||||
address = "https://apt.izzysoft.de/fdroid/repo",
|
|
||||||
name = mapOf("en-US" to "IzzyOnDroid F-Droid Repo"),
|
|
||||||
description = emptyMap(),
|
|
||||||
fingerprint = Fingerprint("3BF0D6ABFEAE2F401707B6D966BE743BF0EEE49C2561B9BA39073711F628937A"),
|
|
||||||
timestamp = 0L,
|
|
||||||
icon = emptyMap(),
|
|
||||||
)
|
|
||||||
val (_, index) = syncable.sync(
|
|
||||||
repo.toRepo(
|
|
||||||
locale = "en-US",
|
|
||||||
mirrors = emptyList(),
|
|
||||||
enabled = true,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
requireNotNull(index)
|
|
||||||
indexDao.insertIndex(
|
|
||||||
fingerprint = repo.fingerprint,
|
|
||||||
index = index,
|
|
||||||
expectedRepoId = repo.id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun calcBackAction(
|
private fun calcBackAction(
|
||||||
currentSection: ProductItem.Section,
|
currentSection: ProductItem.Section,
|
||||||
isSearchActionItemExpanded: Boolean,
|
isSearchActionItemExpanded: Boolean,
|
||||||
|
@ -12,7 +12,7 @@ private val supportedExternalHosts = arrayOf(
|
|||||||
"f-droid.org",
|
"f-droid.org",
|
||||||
"www.f-droid.org",
|
"www.f-droid.org",
|
||||||
"staging.f-droid.org",
|
"staging.f-droid.org",
|
||||||
"apt.izzysoft.de"
|
"apt.izzysoft.de",
|
||||||
)
|
)
|
||||||
|
|
||||||
val Intent.deeplinkType: DeeplinkType?
|
val Intent.deeplinkType: DeeplinkType?
|
||||||
@ -77,7 +77,7 @@ private inline fun invalidDeeplink(message: String): Nothing = throw InvalidDeep
|
|||||||
|
|
||||||
sealed interface DeeplinkType {
|
sealed interface DeeplinkType {
|
||||||
|
|
||||||
data class AddRepository(val address: String) : DeeplinkType
|
class AddRepository(val address: String) : DeeplinkType
|
||||||
|
|
||||||
data class AppDetail(val packageName: String, val repoAddress: String? = null) : DeeplinkType
|
class AppDetail(val packageName: String, val repoAddress: String? = null) : DeeplinkType
|
||||||
}
|
}
|
||||||
|
@ -33,3 +33,28 @@ object SdkCheck {
|
|||||||
@get:ChecksSdkIntAtLeast(api = Build.VERSION_CODES.N)
|
@get:ChecksSdkIntAtLeast(api = Build.VERSION_CODES.N)
|
||||||
val isNougat: Boolean get() = sdk >= Build.VERSION_CODES.N
|
val isNougat: Boolean get() = sdk >= Build.VERSION_CODES.N
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val sdkName by lazy {
|
||||||
|
mapOf(
|
||||||
|
16 to "4.1",
|
||||||
|
17 to "4.2",
|
||||||
|
18 to "4.3",
|
||||||
|
19 to "4.4",
|
||||||
|
21 to "5.0",
|
||||||
|
22 to "5.1",
|
||||||
|
23 to "6",
|
||||||
|
24 to "7.0",
|
||||||
|
25 to "7.1",
|
||||||
|
26 to "8.0",
|
||||||
|
27 to "8.1",
|
||||||
|
28 to "9",
|
||||||
|
29 to "10",
|
||||||
|
30 to "11",
|
||||||
|
31 to "12",
|
||||||
|
32 to "12L",
|
||||||
|
33 to "13",
|
||||||
|
34 to "14",
|
||||||
|
35 to "15",
|
||||||
|
36 to "16",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -46,13 +46,6 @@ object Cache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun subPath(dir: File, file: File): String {
|
|
||||||
val dirPath = "${dir.path}/"
|
|
||||||
val filePath = file.path
|
|
||||||
filePath.startsWith(dirPath) || throw RuntimeException()
|
|
||||||
return filePath.substring(dirPath.length)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getEmptySpace(context: Context): Long {
|
fun getEmptySpace(context: Context): Long {
|
||||||
val dir = context.cacheDir
|
val dir = context.cacheDir
|
||||||
return min(dir.usableSpace, dir.freeSpace)
|
return min(dir.usableSpace, dir.freeSpace)
|
||||||
@ -187,7 +180,7 @@ object Cache {
|
|||||||
projection: Array<String>?,
|
projection: Array<String>?,
|
||||||
selection: String?,
|
selection: String?,
|
||||||
selectionArgs: Array<out String>?,
|
selectionArgs: Array<out String>?,
|
||||||
sortOrder: String?
|
sortOrder: String?,
|
||||||
): Cursor {
|
): Cursor {
|
||||||
val file = getFileAndTypeForUri(uri).first
|
val file = getFileAndTypeForUri(uri).first
|
||||||
val columns = (projection ?: defaultColumns).mapNotNull {
|
val columns = (projection ?: defaultColumns).mapNotNull {
|
||||||
@ -217,7 +210,7 @@ object Cache {
|
|||||||
uri: Uri,
|
uri: Uri,
|
||||||
contentValues: ContentValues?,
|
contentValues: ContentValues?,
|
||||||
selection: String?,
|
selection: String?,
|
||||||
selectionArgs: Array<out String>?
|
selectionArgs: Array<out String>?,
|
||||||
): Int = unsupported
|
): Int = unsupported
|
||||||
|
|
||||||
override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? {
|
override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? {
|
||||||
|
@ -5,9 +5,9 @@ import android.app.job.JobScheduler
|
|||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.net.ConnectivityManager
|
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
@ -15,14 +15,12 @@ import androidx.annotation.DrawableRes
|
|||||||
import androidx.appcompat.content.res.AppCompatResources
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
|
import androidx.core.net.toUri
|
||||||
import com.looker.droidify.R
|
import com.looker.droidify.R
|
||||||
|
|
||||||
inline val Context.clipboardManager: ClipboardManager?
|
inline val Context.clipboardManager: ClipboardManager?
|
||||||
get() = getSystemService()
|
get() = getSystemService()
|
||||||
|
|
||||||
inline val Context.connectivityManager: ConnectivityManager?
|
|
||||||
get() = getSystemService()
|
|
||||||
|
|
||||||
inline val Context.inputManager: InputMethodManager?
|
inline val Context.inputManager: InputMethodManager?
|
||||||
get() = getSystemService()
|
get() = getSystemService()
|
||||||
|
|
||||||
@ -39,6 +37,13 @@ fun Context.copyToClipboard(clip: String) {
|
|||||||
clipboardManager?.setPrimaryClip(ClipData.newPlainText(null, clip))
|
clipboardManager?.setPrimaryClip(ClipData.newPlainText(null, clip))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.openLink(url: String) {
|
||||||
|
val intent = intent(Intent.ACTION_VIEW) {
|
||||||
|
setData(url.toUri())
|
||||||
|
}
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
val Context.corneredBackground: Drawable
|
val Context.corneredBackground: Drawable
|
||||||
get() = getDrawableCompat(R.drawable.background_border)
|
get() = getDrawableCompat(R.drawable.background_border)
|
||||||
|
|
||||||
@ -57,6 +62,9 @@ val Context.selectableBackground: Drawable
|
|||||||
val Context.camera: Drawable
|
val Context.camera: Drawable
|
||||||
get() = getDrawableCompat(R.drawable.ic_image)
|
get() = getDrawableCompat(R.drawable.ic_image)
|
||||||
|
|
||||||
|
val Context.videoPlaceHolder: Drawable
|
||||||
|
get() = getDrawableCompat(R.drawable.ic_video)
|
||||||
|
|
||||||
val Context.aspectRatio: Float
|
val Context.aspectRatio: Float
|
||||||
get() = with(resources.displayMetrics) {
|
get() = with(resources.displayMetrics) {
|
||||||
(heightPixels / widthPixels).toFloat()
|
(heightPixels / widthPixels).toFloat()
|
||||||
@ -75,14 +83,21 @@ private fun Context.getDrawableFromAttr(attrResId: Int): Drawable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Context.getDrawableCompat(@DrawableRes resId: Int = R.drawable.background_border): Drawable =
|
fun Context.getDrawableCompat(@DrawableRes resId: Int = R.drawable.background_border): Drawable =
|
||||||
requireNotNull(AppCompatResources.getDrawable(this, resId)) { "Cannot find drawable, ID: $resId" }
|
requireNotNull(
|
||||||
|
AppCompatResources.getDrawable(
|
||||||
|
this,
|
||||||
|
resId
|
||||||
|
)
|
||||||
|
) { "Cannot find drawable, ID: $resId" }
|
||||||
|
|
||||||
fun Context.getColorFromAttr(@AttrRes attrResId: Int): ColorStateList {
|
fun Context.getColorFromAttr(@AttrRes attrResId: Int): ColorStateList {
|
||||||
val typedArray = obtainStyledAttributes(intArrayOf(attrResId))
|
val typedArray = obtainStyledAttributes(intArrayOf(attrResId))
|
||||||
val (colorStateList, resId) = try {
|
return try {
|
||||||
Pair(typedArray.getColorStateList(0), typedArray.getResourceId(0, 0))
|
typedArray.getColorStateList(0) ?: run {
|
||||||
|
val resourceId = typedArray.getResourceId(0, 0)
|
||||||
|
ContextCompat.getColorStateList(this, resourceId)!!
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
typedArray.recycle()
|
typedArray.recycle()
|
||||||
}
|
}
|
||||||
return colorStateList ?: ContextCompat.getColorStateList(this, resId)!!
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.looker.core.common.extension
|
package com.looker.droidify.utility.common.extension
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonFactory
|
import com.fasterxml.jackson.core.JsonFactory
|
||||||
import com.fasterxml.jackson.core.JsonGenerator
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
|
@ -74,7 +74,6 @@ fun PackageManager.getApplicationInfoCompat(
|
|||||||
PackageManager.ApplicationInfoFlags.of(0L)
|
PackageManager.ApplicationInfoFlags.of(0L)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
getApplicationInfo(filePath, 0)
|
getApplicationInfo(filePath, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +97,6 @@ fun PackageManager.getPackageInfoCompat(
|
|||||||
PackageManager.PackageInfoFlags.of(signatureFlag.toLong())
|
PackageManager.PackageInfoFlags.of(signatureFlag.toLong())
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
getPackageInfo(packageName, signatureFlag)
|
getPackageInfo(packageName, signatureFlag)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -131,7 +129,6 @@ fun PackageManager.getPackageArchiveInfoCompat(
|
|||||||
PackageManager.PackageInfoFlags.of(signatureFlag.toLong())
|
PackageManager.PackageInfoFlags.of(signatureFlag.toLong())
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
getPackageArchiveInfo(filePath, signatureFlag)
|
getPackageArchiveInfo(filePath, signatureFlag)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -144,7 +141,6 @@ fun PackageManager.getInstalledPackagesCompat(
|
|||||||
if (SdkCheck.isTiramisu) {
|
if (SdkCheck.isTiramisu) {
|
||||||
getInstalledPackages(PackageManager.PackageInfoFlags.of(signatureFlag.toLong()))
|
getInstalledPackages(PackageManager.PackageInfoFlags.of(signatureFlag.toLong()))
|
||||||
} else {
|
} else {
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
getInstalledPackages(signatureFlag)
|
getInstalledPackages(signatureFlag)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.looker.droidify.utility.common.extension
|
package com.looker.droidify.utility.common.extension
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -7,7 +8,9 @@ import android.view.ViewGroup
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.request.ImageRequest
|
import coil3.network.NetworkHeaders
|
||||||
|
import coil3.network.httpHeaders
|
||||||
|
import coil3.request.ImageRequest
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
@ -17,8 +20,13 @@ import kotlinx.coroutines.flow.map
|
|||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
private val networkHeader by lazy { NetworkHeaders.Builder() }
|
||||||
|
|
||||||
fun ImageRequest.Builder.authentication(base64: String) {
|
fun ImageRequest.Builder.authentication(base64: String) {
|
||||||
addHeader("Authorization", base64)
|
if (base64.isNotEmpty()) {
|
||||||
|
networkHeader["Authorization"] = base64
|
||||||
|
httpHeaders(networkHeader.build())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun TextView.setTextSizeScaled(size: Int) {
|
fun TextView.setTextSizeScaled(size: Int) {
|
||||||
@ -26,6 +34,9 @@ fun TextView.setTextSizeScaled(size: Int) {
|
|||||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, realSize.toFloat())
|
setTextSize(TypedValue.COMPLEX_UNIT_PX, realSize.toFloat())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val Context.layoutInflater: LayoutInflater
|
||||||
|
get() = LayoutInflater.from(this)
|
||||||
|
|
||||||
fun ViewGroup.inflate(layoutResId: Int): View {
|
fun ViewGroup.inflate(layoutResId: Int): View {
|
||||||
return LayoutInflater.from(context).inflate(layoutResId, this, false)
|
return LayoutInflater.from(context).inflate(layoutResId, this, false)
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ suspend fun File.calculateHash(hashType: String): String? {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun MessageDigest.readBytesFrom(
|
private suspend fun MessageDigest.readBytesFrom(
|
||||||
file: File
|
file: File,
|
||||||
): ByteArray? = withContext(Dispatchers.IO) {
|
): ByteArray? = withContext(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
if (file.length() < DIRECT_READ_LIMIT) return@withContext digest(file.readBytes())
|
if (file.length() < DIRECT_READ_LIMIT) return@withContext digest(file.readBytes())
|
||||||
@ -57,16 +57,9 @@ private suspend fun MessageDigest.readBytesFrom(
|
|||||||
// 25 MB
|
// 25 MB
|
||||||
private const val DIRECT_READ_LIMIT = 25 * 1024 * 1024
|
private const val DIRECT_READ_LIMIT = 25 * 1024 * 1024
|
||||||
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
data class Hash(
|
data class Hash(
|
||||||
val type: String,
|
val type: String,
|
||||||
val hash: String
|
val hash: String,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun SHA256(hash: String) = Hash(type = "sha256", hash)
|
|
||||||
fun MD5(hash: String) = Hash(type = "md5", hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isValid(): Boolean = type.isNotBlank() && hash.isNotBlank()
|
fun isValid(): Boolean = type.isNotBlank() && hash.isNotBlank()
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,5 @@ package com.looker.droidify.utility.extension
|
|||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.looker.droidify.MainActivity
|
import com.looker.droidify.MainActivity
|
||||||
|
|
||||||
inline val Fragment.screenActivity: MainActivity
|
inline val Fragment.mainActivity: MainActivity
|
||||||
get() = requireActivity() as MainActivity
|
get() = requireActivity() as MainActivity
|
||||||
|
@ -2,7 +2,7 @@ package com.looker.droidify.utility.serialization
|
|||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.looker.core.common.extension.forEachKey
|
import com.looker.droidify.utility.common.extension.forEachKey
|
||||||
import com.looker.droidify.model.ProductItem
|
import com.looker.droidify.model.ProductItem
|
||||||
|
|
||||||
fun ProductItem.serialize(generator: JsonGenerator) {
|
fun ProductItem.serialize(generator: JsonGenerator) {
|
||||||
|
@ -2,7 +2,7 @@ package com.looker.droidify.utility.serialization
|
|||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.looker.core.common.extension.forEachKey
|
import com.looker.droidify.utility.common.extension.forEachKey
|
||||||
import com.looker.droidify.model.ProductPreference
|
import com.looker.droidify.model.ProductPreference
|
||||||
|
|
||||||
fun ProductPreference.serialize(generator: JsonGenerator) {
|
fun ProductPreference.serialize(generator: JsonGenerator) {
|
||||||
|
@ -3,11 +3,11 @@ package com.looker.droidify.utility.serialization
|
|||||||
import com.fasterxml.jackson.core.JsonGenerator
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.fasterxml.jackson.core.JsonToken
|
import com.fasterxml.jackson.core.JsonToken
|
||||||
import com.looker.core.common.extension.collectNotNull
|
import com.looker.droidify.utility.common.extension.collectNotNull
|
||||||
import com.looker.core.common.extension.collectNotNullStrings
|
import com.looker.droidify.utility.common.extension.collectNotNullStrings
|
||||||
import com.looker.core.common.extension.forEachKey
|
import com.looker.droidify.utility.common.extension.forEachKey
|
||||||
import com.looker.core.common.extension.writeArray
|
import com.looker.droidify.utility.common.extension.writeArray
|
||||||
import com.looker.core.common.extension.writeDictionary
|
import com.looker.droidify.utility.common.extension.writeDictionary
|
||||||
import com.looker.droidify.model.Product
|
import com.looker.droidify.model.Product
|
||||||
import com.looker.droidify.model.Release
|
import com.looker.droidify.model.Release
|
||||||
|
|
||||||
@ -53,11 +53,6 @@ fun Product.serialize(generator: JsonGenerator) {
|
|||||||
writeStringField(ADDRESS, it.address)
|
writeStringField(ADDRESS, it.address)
|
||||||
}
|
}
|
||||||
|
|
||||||
is Product.Donate.Flattr -> {
|
|
||||||
writeStringField(TYPE, DONATION_FLATTR)
|
|
||||||
writeStringField(ID, it.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
is Product.Donate.Liberapay -> {
|
is Product.Donate.Liberapay -> {
|
||||||
writeStringField(TYPE, DONATION_LIBERAPAY)
|
writeStringField(TYPE, DONATION_LIBERAPAY)
|
||||||
writeStringField(ID, it.id)
|
writeStringField(ID, it.id)
|
||||||
@ -149,7 +144,6 @@ fun JsonParser.product(): Product {
|
|||||||
DONATION_EMPTY -> Product.Donate.Regular(url)
|
DONATION_EMPTY -> Product.Donate.Regular(url)
|
||||||
DONATION_BITCOIN -> Product.Donate.Bitcoin(address)
|
DONATION_BITCOIN -> Product.Donate.Bitcoin(address)
|
||||||
DONATION_LITECOIN -> Product.Donate.Litecoin(address)
|
DONATION_LITECOIN -> Product.Donate.Litecoin(address)
|
||||||
DONATION_FLATTR -> Product.Donate.Flattr(id)
|
|
||||||
DONATION_LIBERAPAY -> Product.Donate.Liberapay(id)
|
DONATION_LIBERAPAY -> Product.Donate.Liberapay(id)
|
||||||
DONATION_OPENCOLLECTIVE -> Product.Donate.OpenCollective(id)
|
DONATION_OPENCOLLECTIVE -> Product.Donate.OpenCollective(id)
|
||||||
else -> null
|
else -> null
|
||||||
@ -243,6 +237,5 @@ private const val KEY_EMPTY = ""
|
|||||||
private const val DONATION_EMPTY = ""
|
private const val DONATION_EMPTY = ""
|
||||||
private const val DONATION_BITCOIN = "bitcoin"
|
private const val DONATION_BITCOIN = "bitcoin"
|
||||||
private const val DONATION_LITECOIN = "litecoin"
|
private const val DONATION_LITECOIN = "litecoin"
|
||||||
private const val DONATION_FLATTR = "flattr"
|
|
||||||
private const val DONATION_LIBERAPAY = "liberapay"
|
private const val DONATION_LIBERAPAY = "liberapay"
|
||||||
private const val DONATION_OPENCOLLECTIVE = "openCollective"
|
private const val DONATION_OPENCOLLECTIVE = "openCollective"
|
||||||
|
@ -3,11 +3,11 @@ package com.looker.droidify.utility.serialization
|
|||||||
import com.fasterxml.jackson.core.JsonGenerator
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.fasterxml.jackson.core.JsonToken
|
import com.fasterxml.jackson.core.JsonToken
|
||||||
import com.looker.core.common.extension.collectNotNull
|
import com.looker.droidify.utility.common.extension.collectNotNull
|
||||||
import com.looker.core.common.extension.collectNotNullStrings
|
import com.looker.droidify.utility.common.extension.collectNotNullStrings
|
||||||
import com.looker.core.common.extension.forEachKey
|
import com.looker.droidify.utility.common.extension.forEachKey
|
||||||
import com.looker.core.common.extension.writeArray
|
import com.looker.droidify.utility.common.extension.writeArray
|
||||||
import com.looker.core.common.extension.writeDictionary
|
import com.looker.droidify.utility.common.extension.writeDictionary
|
||||||
import com.looker.droidify.model.Release
|
import com.looker.droidify.model.Release
|
||||||
|
|
||||||
fun Release.serialize(generator: JsonGenerator) {
|
fun Release.serialize(generator: JsonGenerator) {
|
||||||
|
@ -2,9 +2,9 @@ package com.looker.droidify.utility.serialization
|
|||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
import com.looker.core.common.extension.collectNotNullStrings
|
import com.looker.droidify.utility.common.extension.collectNotNullStrings
|
||||||
import com.looker.core.common.extension.forEachKey
|
import com.looker.droidify.utility.common.extension.forEachKey
|
||||||
import com.looker.core.common.extension.writeArray
|
import com.looker.droidify.utility.common.extension.writeArray
|
||||||
import com.looker.droidify.model.Repository
|
import com.looker.droidify.model.Repository
|
||||||
|
|
||||||
fun Repository.serialize(generator: JsonGenerator) {
|
fun Repository.serialize(generator: JsonGenerator) {
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:color="?attr/colorOnSurfaceInverse" android:state_enabled="false" />
|
|
||||||
<item android:color="?attr/colorPrimary" android:state_checked="true" />
|
|
||||||
<item android:color="?attr/colorOutline" />
|
|
||||||
</selector>
|
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:alpha="@dimen/material_emphasis_disabled_background" android:color="?attr/colorOnSurface" android:state_enabled="false" />
|
|
||||||
<item android:color="?attr/colorPrimaryContainer" android:state_checked="true" />
|
|
||||||
<item android:color="?attr/colorSurfaceVariant" />
|
|
||||||
</selector>
|
|
@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:tint="?attr/colorOnSurface"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
|
|
||||||
<path
|
|
||||||
android:fillColor="@android:color/white"
|
|
||||||
android:pathData="M9.461 3C5.183 3 3 5.464 3 10.064v3.213 6.438L7.19 15.52v-4.902c0-1.906 .505-3.118 2.199-3.391
|
|
||||||
.592-.116 1.824-.075 2.607-.075v2.911c0 .027 .004 .074 .01 .098 .033 .118 .139 .204 .266 .204 .071 0 .138-.037
|
|
||||||
.207-.105l7.262-7.259-4.875-.001zM21 4.285L16.81 8.48v4.902c0 1.906-.505 3.118-2.199 3.391-.592 .116-1.824 .075
|
|
||||||
-2.607 .075v-2.911c0-.026-.004-.074-.01-.098-.033-.118-.139-.204-.266-.204-.071 0-.138 .037-.207 .105L4.258 20.999
|
|
||||||
9.133 21H14.539C18.817 21 21 18.536 21 13.936v-3.214z" />
|
|
||||||
|
|
||||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="512"
|
|
||||||
android:viewportHeight="512">
|
|
||||||
<path
|
|
||||||
android:fillColor="?android:textColor"
|
|
||||||
android:pathData="M494.07,281.6l-25.18,-78.08a11,11 0,0 0,-0.61 -2.1L417.78,44.48a20.08,20.08 0,0 0,-19.17 -13.82A19.77,19.77 0,0 0,379.66 44.6L331.52,194.15h-152L131.34,44.59a19.76,19.76 0,0 0,-18.86 -13.94h-0.11a20.15,20.15 0,0 0,-19.12 14L42.7,201.73c0,0.14 -0.11,0.26 -0.16,0.4L16.91,281.61a29.15,29.15 0,0 0,10.44 32.46L248.79,476.48a11.25,11.25 0,0 0,13.38 -0.07L483.65,314.07a29.13,29.13 0,0 0,10.42 -32.47m-331,-64.51L224.8,408.85 76.63,217.09m209.64,191.8 l59.19,-183.84 2.55,-8h86.52L300.47,390.44M398.8,59.31l43.37,134.83H355.35M324.16,217l-43,133.58L255.5,430.14 186.94,217M112.27,59.31l43.46,134.83H69M40.68,295.58a6.19,6.19 0,0 1,-2.21 -6.9l19,-59L197.08,410.27M470.34,295.58 L313.92,410.22l0.52,-0.69L453.5,229.64l19,59a6.2,6.2 0,0 1,-2.19 6.92" />
|
|
||||||
</vector>
|
|
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="?android:textColor"
|
|
||||||
android:pathData="M13.8521,0.7714C12.3162,0.2228 11.0572,0.3718 9.89,0.7524L9.9406,16.1462c0.8343,0.7743 3.0648,0.8543 3.8984,0.0768V9.216l5.2569,7.0811c0.9244,0.5188 4.1768,0.2319 4.162,-1.317L17.873,8.196 23.352,1.146C22.8842,0.3544 19.6824,0.1619 18.7887,1.003L13.84,7.22ZM4.834,4.005C4.7874,4.0099 4.744,4.0307 4.711,4.064L3.145,5.63C3.0793,5.696 3.0669,5.7982 3.115,5.878L4.949,8.9C4.6205,9.4525 4.3613,10.0432 4.177,10.659l-3.367,0.7c-0.0944,0.0195 -0.1621,0.1026 -0.162,0.199v2.215c0,0.093 0.064,0.174 0.155,0.196l3.268,0.8c0.1709,0.7107 0.4405,1.394 0.801,2.03L2.98,19.683c-0.0521,0.0804 -0.0408,0.1863 0.027,0.254l1.566,1.567c0.0663,0.0659 0.1689,0.0782 0.249,0.03l2.964,-1.8c0.582,0.336 1.21,0.6 1.874,0.78l0.692,3.325C10.372,23.933 10.454,24 10.55,24h2.215c0.0937,0.0003 0.1752,-0.0639 0.197,-0.155l0.815,-3.332c0.6758,-0.1827 1.3239,-0.4555 1.927,-0.811l2.922,1.915c0.08,0.053 0.186,0.042 0.254,-0.026l1.567,-1.566c0.0661,-0.0658 0.0784,-0.1683 0.03,-0.248L19.41,18.019C18.9297,17.2055 18.038,15.026 17.371,15.8 15.3819,19.6985 10.1369,20.4613 7.1197,17.291 4.1025,14.1206 5.1238,8.9198 9.116,7.126 9.5319,6.8182 7.957,5.999 7.957,5.999L7.956,5.997 4.966,4.037C4.9271,4.0111 4.8805,3.9995 4.834,4.004Z" />
|
|
||||||
</vector>
|
|
10
app/src/main/res/drawable/ic_video.xml
Normal file
10
app/src/main/res/drawable/ic_video.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M380,660L660,480L380,300L380,660ZM160,800Q127,800 103.5,776.5Q80,753 80,720L80,240Q80,207 103.5,183.5Q127,160 160,160L800,160Q833,160 856.5,183.5Q880,207 880,240L880,720Q880,753 856.5,776.5Q833,800 800,800L160,800ZM160,720L800,720Q800,720 800,720Q800,720 800,720L800,240Q800,240 800,240Q800,240 800,240L160,240Q160,240 160,240Q160,240 160,240L160,720Q160,720 160,720Q160,720 160,720ZM160,720Q160,720 160,720Q160,720 160,720L160,240Q160,240 160,240Q160,240 160,240L160,240Q160,240 160,240Q160,240 160,240L160,720Q160,720 160,720Q160,720 160,720Z"/>
|
||||||
|
</vector>
|
@ -90,7 +90,6 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.divider.MaterialDivider
|
<com.google.android.material.divider.MaterialDivider
|
||||||
android:id="@+id/divider1"
|
|
||||||
android:layout_width="2dp"
|
android:layout_width="2dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginVertical="12dp" />
|
android:layout_marginVertical="12dp" />
|
||||||
@ -120,7 +119,6 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.divider.MaterialDivider
|
<com.google.android.material.divider.MaterialDivider
|
||||||
android:id="@+id/divider2"
|
|
||||||
android:layout_width="2dp"
|
android:layout_width="2dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginVertical="12dp" />
|
android:layout_marginVertical="12dp" />
|
||||||
|
@ -10,77 +10,68 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<LinearLayout
|
||||||
style="?materialCardViewElevatedStyle"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="12dp"
|
android:orientation="vertical"
|
||||||
android:layout_marginTop="12dp">
|
android:paddingHorizontal="12dp"
|
||||||
|
android:paddingTop="4dp"
|
||||||
|
android:paddingBottom="12dp">
|
||||||
|
|
||||||
<LinearLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/address_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:hint="@string/address"
|
||||||
android:paddingHorizontal="12dp"
|
android:paddingVertical="12dp">
|
||||||
android:paddingTop="4dp"
|
|
||||||
android:paddingBottom="12dp">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/address_container"
|
android:id="@+id/address"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:hint="@string/address"
|
android:inputType="textNoSuggestions|textVisiblePassword" />
|
||||||
android:paddingVertical="12dp">
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/address"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:hint="@string/fingerprint"
|
||||||
android:inputType="textNoSuggestions|textVisiblePassword" />
|
android:paddingVertical="12dp">
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/fingerprint"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent" />
|
||||||
android:hint="@string/fingerprint"
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
android:paddingVertical="12dp">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/fingerprint"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="match_parent" />
|
android:hint="@string/username"
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
android:paddingVertical="12dp">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/username"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:hint="@string/username"
|
android:autofillHints="username" />
|
||||||
android:paddingVertical="12dp">
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/username"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:hint="@string/password"
|
||||||
android:autofillHints="username" />
|
android:paddingVertical="12dp">
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/password"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:hint="@string/password"
|
android:autofillHints="password"
|
||||||
android:paddingVertical="12dp">
|
android:inputType="textNoSuggestions|textVisiblePassword" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:id="@+id/password"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:autofillHints="password"
|
|
||||||
android:inputType="textNoSuggestions|textVisiblePassword" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@ -90,6 +81,7 @@
|
|||||||
android:background="?android:attr/colorBackground"
|
android:background="?android:attr/colorBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:ignore="KeyboardInaccessibleWidget">
|
tools:ignore="KeyboardInaccessibleWidget">
|
||||||
|
|
||||||
|
@ -19,4 +19,4 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?textAppearanceBodyMedium"
|
android:textAppearance="?textAppearanceBodyMedium"
|
||||||
android:textColor="?colorOutline" />
|
android:textColor="?colorOutline" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -19,4 +19,4 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
@ -96,6 +96,13 @@
|
|||||||
android:textColor="?android:attr/textColorSecondary"
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sdk_ver"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textSize="14sp" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="20dp">
|
||||||
|
|
||||||
<com.google.android.material.materialswitch.MaterialSwitch
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
android:id="@+id/repo_switch"
|
android:id="@+id/repo_switch"
|
||||||
@ -65,9 +66,4 @@
|
|||||||
android:text="@string/delete"
|
android:text="@string/delete"
|
||||||
android:textColor="?colorOnError" />
|
android:textColor="?colorOnError" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="20dp"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -145,6 +145,9 @@
|
|||||||
<include
|
<include
|
||||||
android:id="@+id/installer"
|
android:id="@+id/installer"
|
||||||
layout="@layout/enum_type" />
|
layout="@layout/enum_type" />
|
||||||
|
<include
|
||||||
|
android:id="@+id/legacy_installer_component"
|
||||||
|
layout="@layout/enum_type" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -44,8 +44,12 @@
|
|||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
android:src="@drawable/ic_arrow_down"
|
android:src="@drawable/ic_arrow_down"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</LinearLayout>
|
|
||||||
|
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
|
android:id="@+id/sync_state"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</LinearLayout>
|
||||||
|
14
app/src/main/res/layout/video_button.xml
Normal file
14
app/src/main/res/layout/video_button.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Button xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/video_button"
|
||||||
|
style="?materialIconButtonFilledTonalStyle"
|
||||||
|
android:text="@string/label_open_video"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="150dp"
|
||||||
|
android:paddingHorizontal="24dp"
|
||||||
|
app:icon="@drawable/ic_video"
|
||||||
|
app:iconGravity="textTop"
|
||||||
|
app:iconPadding="6dp"
|
||||||
|
app:iconSize="24dp" />
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:id="@+id/exploreTab"
|
|
||||||
android:icon="@drawable/ic_public"
|
|
||||||
android:title="@string/explore" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/latestTab"
|
|
||||||
android:icon="@drawable/ic_new_releases"
|
|
||||||
android:title="@string/latest" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/installedTab"
|
|
||||||
android:icon="@drawable/ic_launch"
|
|
||||||
android:title="@string/installed" />
|
|
||||||
</menu>
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.5 KiB |
@ -6,17 +6,13 @@
|
|||||||
<string name="description">الوصف</string>
|
<string name="description">الوصف</string>
|
||||||
<string name="incompatible_api_min_DESC_FORMAT">الحد الأدنى لإصدار واجهة برمجة التطبيقات هو %d.</string>
|
<string name="incompatible_api_min_DESC_FORMAT">الحد الأدنى لإصدار واجهة برمجة التطبيقات هو %d.</string>
|
||||||
<string name="light">فاتح</string>
|
<string name="light">فاتح</string>
|
||||||
<string name="list_animation">تحريكات القائمة</string>
|
|
||||||
<string name="ok">حسنًا</string>
|
<string name="ok">حسنًا</string>
|
||||||
<string name="repository_unsigned_DESC">ليس موقعًا. تعذر التحقق من قائمة التطبيقات. كن حذرًا عند تنزيل التطبيقات من مستودعات غير موقعة.</string>
|
<string name="repository_unsigned_DESC">ليس موقعًا. تعذر التحقق من قائمة التطبيقات. كن حذرًا عند تنزيل التطبيقات من مستودعات غير موقعة.</string>
|
||||||
<string name="sync_repositories">زامن المستودعات</string>
|
<string name="sync_repositories">زامن المستودعات</string>
|
||||||
<string name="syncing">جاري المزامنة</string>
|
<string name="syncing">جاري المزامنة</string>
|
||||||
<string name="unknown_FORMAT">غير معروف: %s</string>
|
<string name="unknown_FORMAT">غير معروف: %s</string>
|
||||||
<string name="unsigned">لم يُوقع</string>
|
|
||||||
<string name="unstable_updates">تحديثات غير مستقرة</string>
|
<string name="unstable_updates">تحديثات غير مستقرة</string>
|
||||||
<string name="show_less">اعرض أقل</string>
|
<string name="show_less">اعرض أقل</string>
|
||||||
<string name="latest">الأحدث</string>
|
|
||||||
<string name="explore">استكشف</string>
|
|
||||||
<string name="action_failed">فشل الإجراء</string>
|
<string name="action_failed">فشل الإجراء</string>
|
||||||
<string name="add_repository">أضف مستودعًا</string>
|
<string name="add_repository">أضف مستودعًا</string>
|
||||||
<string name="all_applications">كل التطبيقات</string>
|
<string name="all_applications">كل التطبيقات</string>
|
||||||
@ -90,7 +86,6 @@
|
|||||||
<string name="license_FORMAT">رخصة %s</string>
|
<string name="license_FORMAT">رخصة %s</string>
|
||||||
<string name="link_copied_to_clipboard">تم نسخ الرابط</string>
|
<string name="link_copied_to_clipboard">تم نسخ الرابط</string>
|
||||||
<string name="links">الروابط</string>
|
<string name="links">الروابط</string>
|
||||||
<string name="list_animation_description">أظهر تحريكات القائمة على الصفحة الرئيسة</string>
|
|
||||||
<string name="merging_FORMAT">جاري الدمج %s</string>
|
<string name="merging_FORMAT">جاري الدمج %s</string>
|
||||||
<string name="name">الاسم</string>
|
<string name="name">الاسم</string>
|
||||||
<string name="network_error_DESC">خطأ في الشبكة</string>
|
<string name="network_error_DESC">خطأ في الشبكة</string>
|
||||||
@ -135,12 +130,8 @@
|
|||||||
<string name="requires_FORMAT">يتطلب %s</string>
|
<string name="requires_FORMAT">يتطلب %s</string>
|
||||||
<string name="repositories">المستودعات</string>
|
<string name="repositories">المستودعات</string>
|
||||||
<string name="repository">المستودع</string>
|
<string name="repository">المستودع</string>
|
||||||
<string name="repository_not_used_DESC">هذا المستودع لم يُستخدم بعد. مكنه لعرض التطبيقات التي يحتويها.</string>
|
|
||||||
<string name="root_permission">تثبيت صامت</string>
|
|
||||||
<string name="root_permission_description">اسمح لصلاحية الجذر لتمكين التثبيت الصامت</string>
|
|
||||||
<string name="save">احفظ</string>
|
<string name="save">احفظ</string>
|
||||||
<string name="saving_details">جارٍ حفظ التفاصيل…</string>
|
<string name="saving_details">جارٍ حفظ التفاصيل…</string>
|
||||||
<string name="screenshots">لقطات الشاشة</string>
|
|
||||||
<string name="search">ابحث</string>
|
<string name="search">ابحث</string>
|
||||||
<string name="select_mirror">اختر مرآة</string>
|
<string name="select_mirror">اختر مرآة</string>
|
||||||
<string name="share">شارك</string>
|
<string name="share">شارك</string>
|
||||||
@ -159,12 +150,10 @@
|
|||||||
<string name="syncing_FORMAT">جاري مزامنة %s…</string>
|
<string name="syncing_FORMAT">جاري مزامنة %s…</string>
|
||||||
<string name="system">النظام</string>
|
<string name="system">النظام</string>
|
||||||
<string name="tap_to_install_DESC">اضغط للتثبيت.</string>
|
<string name="tap_to_install_DESC">اضغط للتثبيت.</string>
|
||||||
<string name="target">الهدف</string>
|
|
||||||
<string name="theme">السمة</string>
|
<string name="theme">السمة</string>
|
||||||
<string name="themes">السمات</string>
|
<string name="themes">السمات</string>
|
||||||
<string name="tracks_or_reports_your_activity">يتعقب أو يرفق نشاطك</string>
|
<string name="tracks_or_reports_your_activity">يتعقب أو يرفق نشاطك</string>
|
||||||
<string name="uninstall">إلغاء التثبيت</string>
|
<string name="uninstall">إلغاء التثبيت</string>
|
||||||
<string name="unverified">لم يُتحقق منه</string>
|
|
||||||
<string name="update">حدث</string>
|
<string name="update">حدث</string>
|
||||||
<string name="updates">التحديثات</string>
|
<string name="updates">التحديثات</string>
|
||||||
<string name="unknown">غير معروف</string>
|
<string name="unknown">غير معروف</string>
|
||||||
@ -183,10 +172,6 @@
|
|||||||
<string name="prefs_language_title">اللغة</string>
|
<string name="prefs_language_title">اللغة</string>
|
||||||
<string name="prefs_personalization">التفضيلات</string>
|
<string name="prefs_personalization">التفضيلات</string>
|
||||||
<string name="update_all">حدث الكل</string>
|
<string name="update_all">حدث الكل</string>
|
||||||
<string name="installed_applications">التطبيقات المثبَّتة</string>
|
|
||||||
<string name="sort_filter">افرز وصفِّ</string>
|
|
||||||
<string name="new_applications">التطبيقات الجديدة</string>
|
|
||||||
<string name="cleanup_description">الزمن المار قبل فحص وإزالة الملفات المنزَّلة</string>
|
|
||||||
<string name="cleanup_title">مدة تنظيف ملفات APK</string>
|
<string name="cleanup_title">مدة تنظيف ملفات APK</string>
|
||||||
<plurals name="days">
|
<plurals name="days">
|
||||||
<item quantity="zero">أقل من يوم</item>
|
<item quantity="zero">أقل من يوم</item>
|
||||||
@ -206,9 +191,6 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="only_on_wifi_with_charging">فقط على شبكة واي-فاي وعند الشحن</string>
|
<string name="only_on_wifi_with_charging">فقط على شبكة واي-فاي وعند الشحن</string>
|
||||||
<string name="io_error_DESC">تعذر أداء بعض الإجراءات.</string>
|
<string name="io_error_DESC">تعذر أداء بعض الإجراءات.</string>
|
||||||
<string name="no_internet">ليس لديك اتصال بالإنترنت</string>
|
|
||||||
<string name="allow_collapsing_toolbar">اسمح بتوسيع شريط التطبيقات العلوي</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">اسمح لشريط التطبيقات العلوي بالتوسع والطي</string>
|
|
||||||
<string name="material_you">لون النظام ( Material You )</string>
|
<string name="material_you">لون النظام ( Material You )</string>
|
||||||
<string name="material_you_desc">استخدم سمة ألوان النظام</string>
|
<string name="material_you_desc">استخدم سمة ألوان النظام</string>
|
||||||
<string name="favourites">المفضَّلات</string>
|
<string name="favourites">المفضَّلات</string>
|
||||||
@ -216,7 +198,6 @@
|
|||||||
<string name="force_clean_up">افرض التنظيف</string>
|
<string name="force_clean_up">افرض التنظيف</string>
|
||||||
<string name="force_clean_up_DESC">ينظِّف الملفَّات المتكرِّرة</string>
|
<string name="force_clean_up_DESC">ينظِّف الملفَّات المتكرِّرة</string>
|
||||||
<string name="enable_repo">مكِّن المستودع</string>
|
<string name="enable_repo">مكِّن المستودع</string>
|
||||||
<string name="restart_app">أعد تشغيل Droid-ify لرؤية التغييرات</string>
|
|
||||||
<string name="installing">يثبّت</string>
|
<string name="installing">يثبّت</string>
|
||||||
<string name="waiting_to_start_installation">في انتظار بدء التثبيت…</string>
|
<string name="waiting_to_start_installation">في انتظار بدء التثبيت…</string>
|
||||||
<string name="auto_update">حدِّث التطبيقات تلقائيًّا</string>
|
<string name="auto_update">حدِّث التطبيقات تلقائيًّا</string>
|
||||||
@ -230,7 +211,6 @@
|
|||||||
<string name="special_credits">شكر خاص</string>
|
<string name="special_credits">شكر خاص</string>
|
||||||
<string name="home_screen_swiping">ايماءات الشاشة الرئيسة</string>
|
<string name="home_screen_swiping">ايماءات الشاشة الرئيسة</string>
|
||||||
<string name="home_screen_swiping_DESC">اسمح للمستخدم بالتمرير بين الصفحات في الشاشة الرئيسة</string>
|
<string name="home_screen_swiping_DESC">اسمح للمستخدم بالتمرير بين الصفحات في الشاشة الرئيسة</string>
|
||||||
<string name="label_copy">انسخ</string>
|
|
||||||
<string name="proxy_port_error_not_int">يجب أن يكون منفذ الوكيل رقمًا صحيحًا</string>
|
<string name="proxy_port_error_not_int">يجب أن يكون منفذ الوكيل رقمًا صحيحًا</string>
|
||||||
<string name="repository_not_found">لم يُعثَر على المستودع</string>
|
<string name="repository_not_found">لم يُعثَر على المستودع</string>
|
||||||
<string name="import_settings_title">استيراد الإعدادات</string>
|
<string name="import_settings_title">استيراد الإعدادات</string>
|
||||||
@ -254,4 +234,14 @@
|
|||||||
<string name="ignore_signature">تجاهل التوقيع</string>
|
<string name="ignore_signature">تجاهل التوقيع</string>
|
||||||
<string name="insufficient_storage">مساحة غير كافية</string>
|
<string name="insufficient_storage">مساحة غير كافية</string>
|
||||||
<string name="insufficient_storage_DESC">لا توجد مساحة خالية كافية على الجهاز لتثبيت هذا التطبيق. حاول إفراغ بعض المساحة</string>
|
<string name="insufficient_storage_DESC">لا توجد مساحة خالية كافية على الجهاز لتثبيت هذا التطبيق. حاول إفراغ بعض المساحة</string>
|
||||||
</resources>
|
<string name="error_shizuku_not_granted">إذن Shizuku مفقود</string>
|
||||||
|
<string name="error_shizuku_not_granted_DESC">لم يتم منح إذن خدمة Shizuku. يُرجى التحقق من تطبيق Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">لا يبدو أن Shizuku مثبت</string>
|
||||||
|
<string name="open_shizuku">افتح Shizuku</string>
|
||||||
|
<string name="label_unknown_sdk">غير معروف (%d)</string>
|
||||||
|
<string name="error_shizuku_not_installed">Shizuku غير مثبت</string>
|
||||||
|
<string name="error_shizuku_not_running_DESC">خدمة Shizuku لا تعمل. يُرجى التحقق من تطبيق Shizuku</string>
|
||||||
|
<string name="label_open_video">فيديو</string>
|
||||||
|
<string name="error_shizuku_service_unavailable">Shizuku لا يعمل</string>
|
||||||
|
<string name="switch_to_default_installer">بدّل إلى الافتراضي</string>
|
||||||
|
</resources>
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
<string name="add_repository">Yeni qaynaq əlavə et</string>
|
<string name="add_repository">Yeni qaynaq əlavə et</string>
|
||||||
<string name="address">Ünvan</string>
|
<string name="address">Ünvan</string>
|
||||||
<string name="all_applications">Bütün applikasiyalar</string>
|
<string name="all_applications">Bütün applikasiyalar</string>
|
||||||
<string name="allow_collapsing_toolbar">Üst çubuğun genişlədilməsinə izn ver</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">Üst çubuğun genişləndirilməsinə və sıxılmasına izn ver</string>
|
|
||||||
<string name="already_exists">Zatən mövcuddur</string>
|
<string name="already_exists">Zatən mövcuddur</string>
|
||||||
<string name="always">Hər zaman</string>
|
<string name="always">Hər zaman</string>
|
||||||
<string name="anti_features">Anti-özəlliklər</string>
|
<string name="anti_features">Anti-özəlliklər</string>
|
||||||
@ -20,7 +18,6 @@
|
|||||||
<string name="changelog">Dəyişim günlüyü</string>
|
<string name="changelog">Dəyişim günlüyü</string>
|
||||||
<string name="changes">Dəyişikliklər</string>
|
<string name="changes">Dəyişikliklər</string>
|
||||||
<string name="cleanup_title">APK cleanup interval</string>
|
<string name="cleanup_title">APK cleanup interval</string>
|
||||||
<string name="cleanup_description">Period to check and remove downloaded files</string>
|
|
||||||
<string name="compiled_for_debugging">Xəta tapmaq üçün kompayl edildi</string>
|
<string name="compiled_for_debugging">Xəta tapmaq üçün kompayl edildi</string>
|
||||||
<string name="confirmation">Təsdiq</string>
|
<string name="confirmation">Təsdiq</string>
|
||||||
<string name="connecting">Bağlanılır…</string>
|
<string name="connecting">Bağlanılır…</string>
|
||||||
@ -78,8 +75,6 @@
|
|||||||
<string name="license_FORMAT">%s lisenziyası</string>
|
<string name="license_FORMAT">%s lisenziyası</string>
|
||||||
<string name="light">Açıq</string>
|
<string name="light">Açıq</string>
|
||||||
<string name="links">Linklər</string>
|
<string name="links">Linklər</string>
|
||||||
<string name="list_animation">Siyahı Animasiyaları</string>
|
|
||||||
<string name="list_animation_description">Siyahı canlandırmasını ana səhifədə göstər</string>
|
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="material_you_desc">Material you rəng temasını istifadə et</string>
|
<string name="material_you_desc">Material you rəng temasını istifadə et</string>
|
||||||
<string name="merging_FORMAT">%s birləşdirilir</string>
|
<string name="merging_FORMAT">%s birləşdirilir</string>
|
||||||
@ -92,7 +87,6 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="no_applications_available">İstifadə edilə bilən applikasiya yoxdur</string>
|
<string name="no_applications_available">İstifadə edilə bilən applikasiya yoxdur</string>
|
||||||
<string name="no_description_available_DESC">Açıqlama yoxdur</string>
|
<string name="no_description_available_DESC">Açıqlama yoxdur</string>
|
||||||
<string name="no_internet">İnternet bağlantınız yoxdur</string>
|
|
||||||
<string name="no_proxy">Proxy yoxdur</string>
|
<string name="no_proxy">Proxy yoxdur</string>
|
||||||
<string name="notify_about_updates">Applikasiyanın yeni versiyaları haqqında bilgiləndir</string>
|
<string name="notify_about_updates">Applikasiyanın yeni versiyaları haqqında bilgiləndir</string>
|
||||||
<string name="number_of_applications">Applikasiya sayı</string>
|
<string name="number_of_applications">Applikasiya sayı</string>
|
||||||
@ -144,16 +138,11 @@
|
|||||||
<string name="recently_updated">Bu yaxınlarda yeniləndi</string>
|
<string name="recently_updated">Bu yaxınlarda yeniləndi</string>
|
||||||
<string name="repositories">Anbarlar</string>
|
<string name="repositories">Anbarlar</string>
|
||||||
<string name="repository">Repozitoriya</string>
|
<string name="repository">Repozitoriya</string>
|
||||||
<string name="repository_not_used_DESC">Bu anbardan hələ istifadə olunmayıb. İçindəki proqramlara baxmaq üçün onu yandırın.</string>
|
|
||||||
<string name="repository_unsigned_DESC">İmzasız. Tətbiq siyahısını yoxlamaq mümkün olmadı. İmzasız depolardan proqramları endirərkən diqqətli olun.</string>
|
<string name="repository_unsigned_DESC">İmzasız. Tətbiq siyahısını yoxlamaq mümkün olmadı. İmzasız depolardan proqramları endirərkən diqqətli olun.</string>
|
||||||
<string name="repository_unreachable">Repozitoriya əlçatmazdır</string>
|
<string name="repository_unreachable">Repozitoriya əlçatmazdır</string>
|
||||||
<string name="requires_FORMAT">%s tələb edir</string>
|
<string name="requires_FORMAT">%s tələb edir</string>
|
||||||
<string name="restart_app">Dəyişiklikləri görmək üçün Droid-ify-ı yenidən başladın</string>
|
|
||||||
<string name="root_permission">Səssiz Quraşdırma</string>
|
|
||||||
<string name="root_permission_description">Səssiz quraşdırmalar üçün kök icazəsinə icazə verin</string>
|
|
||||||
<string name="save">Yadda saxla</string>
|
<string name="save">Yadda saxla</string>
|
||||||
<string name="saving_details">Detallar yadda saxlanılır…</string>
|
<string name="saving_details">Detallar yadda saxlanılır…</string>
|
||||||
<string name="screenshots">Ekran görüntüləri</string>
|
|
||||||
<string name="search">Axtar</string>
|
<string name="search">Axtar</string>
|
||||||
<string name="select_mirror">Güzgü seçin</string>
|
<string name="select_mirror">Güzgü seçin</string>
|
||||||
<string name="settings">Parametrlər</string>
|
<string name="settings">Parametrlər</string>
|
||||||
@ -173,17 +162,14 @@
|
|||||||
<string name="syncing">Sinxronizasiya</string>
|
<string name="syncing">Sinxronizasiya</string>
|
||||||
<string name="syncing_FORMAT">%s sinxronizasiya edilir…</string>
|
<string name="syncing_FORMAT">%s sinxronizasiya edilir…</string>
|
||||||
<string name="system">Sistem</string>
|
<string name="system">Sistem</string>
|
||||||
<string name="target">Hədəf</string>
|
|
||||||
<string name="theme">Mövzu</string>
|
<string name="theme">Mövzu</string>
|
||||||
<string name="themes">Mövzular</string>
|
<string name="themes">Mövzular</string>
|
||||||
<string name="tracks_or_reports_your_activity">Fəaliyyətinizi izləyir və ya hesabat verir</string>
|
<string name="tracks_or_reports_your_activity">Fəaliyyətinizi izləyir və ya hesabat verir</string>
|
||||||
<string name="unknown">Naməlum</string>
|
<string name="unknown">Naməlum</string>
|
||||||
<string name="unknown_error_DESC">Naməlum xəta.</string>
|
<string name="unknown_error_DESC">Naməlum xəta.</string>
|
||||||
<string name="unknown_FORMAT">Naməlum: %s</string>
|
<string name="unknown_FORMAT">Naməlum: %s</string>
|
||||||
<string name="unsigned">İmzasız</string>
|
|
||||||
<string name="unstable_updates">Qeyri-sabit yeniləmələr</string>
|
<string name="unstable_updates">Qeyri-sabit yeniləmələr</string>
|
||||||
<string name="unstable_updates_summary">Qeyri-sabit versiyaların quraşdırılmasını təklif edin</string>
|
<string name="unstable_updates_summary">Qeyri-sabit versiyaların quraşdırılmasını təklif edin</string>
|
||||||
<string name="unverified">Doğrulanmamış</string>
|
|
||||||
<string name="update">Yeniləyin</string>
|
<string name="update">Yeniləyin</string>
|
||||||
<string name="updates">Yeniləmələr</string>
|
<string name="updates">Yeniləmələr</string>
|
||||||
<string name="username">İstifadəçi adı</string>
|
<string name="username">İstifadəçi adı</string>
|
||||||
@ -197,16 +183,11 @@
|
|||||||
<string name="website">Veb sayt</string>
|
<string name="website">Veb sayt</string>
|
||||||
<string name="prefs_language_title">Dil</string>
|
<string name="prefs_language_title">Dil</string>
|
||||||
<string name="prefs_personalization">Fərdiləşdirmə</string>
|
<string name="prefs_personalization">Fərdiləşdirmə</string>
|
||||||
<string name="latest">Ən son</string>
|
|
||||||
<string name="explore">Araşdırın</string>
|
|
||||||
<string name="update_all">Hamısını yeniləyin</string>
|
<string name="update_all">Hamısını yeniləyin</string>
|
||||||
<string name="installed_applications">Quraşdırılmış proqramlar</string>
|
|
||||||
<string name="sort_filter">Çeşidləyin və Filtr edin</string>
|
|
||||||
<string name="new_applications">Yeni tətbiqlər</string>
|
|
||||||
<string name="show_less">Daha az göstər</string>
|
<string name="show_less">Daha az göstər</string>
|
||||||
<string name="sync_repositories_automatically">Repozitoriyaları avtomatik sinxronlaşdırın</string>
|
<string name="sync_repositories_automatically">Repozitoriyaları avtomatik sinxronlaşdırın</string>
|
||||||
<string name="uninstall">Silin</string>
|
<string name="uninstall">Silin</string>
|
||||||
<string name="upstream_source_code_is_not_free">Yuxarı mənbə kodu pulsuz deyil</string>
|
<string name="upstream_source_code_is_not_free">Yuxarı mənbə kodu pulsuz deyil</string>
|
||||||
<string name="validation_index_error_DESC">İndeksi doğrulamaq mümkün olmadı.</string>
|
<string name="validation_index_error_DESC">İndeksi doğrulamaq mümkün olmadı.</string>
|
||||||
<string name="tap_to_install_DESC">Quraşdırmaq üçün toxunun.</string>
|
<string name="tap_to_install_DESC">Quraşdırmaq üçün toxunun.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="action_failed">Не атрымалася выканаць дзеянне</string>
|
<string name="action_failed">Не атрымалася выканаць дзеянне</string>
|
||||||
<string name="allow_collapsing_toolbar">Дазволіць верхняй панэлі праграм пашырацца</string>
|
|
||||||
<string name="application_not_found">Не ўдалося знайсці гэтую праграму</string>
|
<string name="application_not_found">Не ўдалося знайсці гэтую праграму</string>
|
||||||
<string name="author_website">Сайт аўтара</string>
|
<string name="author_website">Сайт аўтара</string>
|
||||||
<string name="auto_update">Аўтаабнаўленне праграм</string>
|
<string name="auto_update">Аўтаабнаўленне праграм</string>
|
||||||
<string name="add_repository">Дадаць рэпазіторый</string>
|
<string name="add_repository">Дадаць рэпазіторый</string>
|
||||||
<string name="address">Адрас</string>
|
<string name="address">Адрас</string>
|
||||||
<string name="all_applications">Ўсе праграмы</string>
|
<string name="all_applications">Ўсе праграмы</string>
|
||||||
<string name="allow_collapsing_toolbar_DESC">Дазволіць верхнюю панэль праграмы пашыраць і згортваць</string>
|
|
||||||
<string name="already_exists">Ўжо існуе</string>
|
<string name="already_exists">Ўжо існуе</string>
|
||||||
<string name="always">Заўсёды</string>
|
<string name="always">Заўсёды</string>
|
||||||
<string name="amoled">Чорная</string>
|
<string name="amoled">Чорная</string>
|
||||||
@ -21,7 +19,6 @@
|
|||||||
<string name="cancel">Скасаваць</string>
|
<string name="cancel">Скасаваць</string>
|
||||||
<string name="all_applications_up_to_date">Усе вашыя праграмы абноўлены</string>
|
<string name="all_applications_up_to_date">Усе вашыя праграмы абноўлены</string>
|
||||||
<string name="delete">Выдаліць</string>
|
<string name="delete">Выдаліць</string>
|
||||||
<string name="cleanup_description">Перыяд для праверкі і выдалення спампаваных файлаў</string>
|
|
||||||
<string name="description">Апісанне</string>
|
<string name="description">Апісанне</string>
|
||||||
<string name="details">Дэталі</string>
|
<string name="details">Дэталі</string>
|
||||||
<string name="downloading_FORMAT">Ідзе загрузка %s…</string>
|
<string name="downloading_FORMAT">Ідзе загрузка %s…</string>
|
||||||
@ -80,7 +77,6 @@
|
|||||||
<string name="installing">Ўсталяванне</string>
|
<string name="installing">Ўсталяванне</string>
|
||||||
<string name="incompatible_platforms_DESC_FORMAT">Ваша платформа %1$s не падтрымліваецца. Падтрымліваюцца платформы: %2$s.</string>
|
<string name="incompatible_platforms_DESC_FORMAT">Ваша платформа %1$s не падтрымліваецца. Падтрымліваюцца платформы: %2$s.</string>
|
||||||
<string name="repository_unreachable">Рэпазіторый недаступны</string>
|
<string name="repository_unreachable">Рэпазіторый недаступны</string>
|
||||||
<string name="restart_app">Перазапусціце Droid-ify, каб убачыць змены</string>
|
|
||||||
<string name="incompatible_features_DESC">Адсутныя функцыі.</string>
|
<string name="incompatible_features_DESC">Адсутныя функцыі.</string>
|
||||||
<string name="no_applications_available">Няма даступных праграм</string>
|
<string name="no_applications_available">Няма даступных праграм</string>
|
||||||
<string name="password_missing">Пароль адсутнічае</string>
|
<string name="password_missing">Пароль адсутнічае</string>
|
||||||
@ -96,8 +92,6 @@
|
|||||||
<string name="other">Іншае</string>
|
<string name="other">Іншае</string>
|
||||||
<string name="link_copied_to_clipboard">Спасылка скапіявана</string>
|
<string name="link_copied_to_clipboard">Спасылка скапіявана</string>
|
||||||
<string name="processing_FORMAT">Апрацоўваецца %1$s…</string>
|
<string name="processing_FORMAT">Апрацоўваецца %1$s…</string>
|
||||||
<string name="label_copy">Капіяваць</string>
|
|
||||||
<string name="no_internet">У вас няма падключэння да інтэрнэту</string>
|
|
||||||
<string name="proxy_port_error_not_int">Порт проксі можа быць толькі цэлым лікам</string>
|
<string name="proxy_port_error_not_int">Порт проксі можа быць толькі цэлым лікам</string>
|
||||||
<string name="number_of_applications">Колькасць праграм</string>
|
<string name="number_of_applications">Колькасць праграм</string>
|
||||||
<string name="incompatible_with_FORMAT">Несумяшчальна з %s</string>
|
<string name="incompatible_with_FORMAT">Несумяшчальна з %s</string>
|
||||||
@ -158,19 +152,15 @@
|
|||||||
<string name="plus_more_FORMAT">+%d больш</string>
|
<string name="plus_more_FORMAT">+%d больш</string>
|
||||||
<string name="import_settings_title">Налады імпарту</string>
|
<string name="import_settings_title">Налады імпарту</string>
|
||||||
<string name="incompatible_api_DESC_FORMAT">Ваш %1$s (версія API %2$d) не падтрымліваецца. %3$s</string>
|
<string name="incompatible_api_DESC_FORMAT">Ваш %1$s (версія API %2$d) не падтрымліваецца. %3$s</string>
|
||||||
<string name="unsigned">Без подпісу</string>
|
|
||||||
<string name="contains_nsfw">Змяшчае NSFW кантэнт</string>
|
<string name="contains_nsfw">Змяшчае NSFW кантэнт</string>
|
||||||
<string name="select_mirror">Выберыце люстэрка</string>
|
<string name="select_mirror">Выберыце люстэрка</string>
|
||||||
<string name="list_animation_description">Паказаць анімацыю спісу на галоўнай старонцы</string>
|
|
||||||
<string name="syncing_FORMAT">Сінхранізацыя %s…</string>
|
<string name="syncing_FORMAT">Сінхранізацыя %s…</string>
|
||||||
<string name="import_export">Імпарт/Экспарт</string>
|
<string name="import_export">Імпарт/Экспарт</string>
|
||||||
<string name="tracks_or_reports_your_activity">Адсочвае або паведамляе аб вашай дзейнасці</string>
|
<string name="tracks_or_reports_your_activity">Адсочвае або паведамляе аб вашай дзейнасці</string>
|
||||||
<string name="website">Вэб-сайт</string>
|
<string name="website">Вэб-сайт</string>
|
||||||
<string name="merging_FORMAT">Аб\'яднанне %s</string>
|
<string name="merging_FORMAT">Аб\'яднанне %s</string>
|
||||||
<string name="waiting_to_start_download">Чаканне пачатку загрузкі…</string>
|
<string name="waiting_to_start_download">Чаканне пачатку загрузкі…</string>
|
||||||
<string name="explore">Агляд</string>
|
|
||||||
<string name="suggested">Рэкамендуецца</string>
|
<string name="suggested">Рэкамендуецца</string>
|
||||||
<string name="sort_filter">Сартаваць і фільтраваць</string>
|
|
||||||
<string name="open_DESC_FORMAT">Адкрыць %s?</string>
|
<string name="open_DESC_FORMAT">Адкрыць %s?</string>
|
||||||
<string name="validation_index_error_DESC">Не ўдалося праверыць індэкс.</string>
|
<string name="validation_index_error_DESC">Не ўдалося праверыць індэкс.</string>
|
||||||
<string name="shizuku_not_alive">Shizuku не працуе</string>
|
<string name="shizuku_not_alive">Shizuku не працуе</string>
|
||||||
@ -181,14 +171,12 @@
|
|||||||
<string name="theme">Тэма</string>
|
<string name="theme">Тэма</string>
|
||||||
<string name="socks_proxy">SOCKS проксі</string>
|
<string name="socks_proxy">SOCKS проксі</string>
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="target">Мэтавы</string>
|
|
||||||
<string name="waiting_to_start_installation">Чаканне пачатку ўстаноўкі…</string>
|
<string name="waiting_to_start_installation">Чаканне пачатку ўстаноўкі…</string>
|
||||||
<string name="signed_using_unsafe_algorithm">Падпісана з выкарыстаннем небяспечнага алгарытму</string>
|
<string name="signed_using_unsafe_algorithm">Падпісана з выкарыстаннем небяспечнага алгарытму</string>
|
||||||
<string name="source_code">Зыходны код</string>
|
<string name="source_code">Зыходны код</string>
|
||||||
<string name="username">Імя карыстальніка</string>
|
<string name="username">Імя карыстальніка</string>
|
||||||
<string name="version_FORMAT">Версія %s</string>
|
<string name="version_FORMAT">Версія %s</string>
|
||||||
<string name="light">Светлая</string>
|
<string name="light">Светлая</string>
|
||||||
<string name="installed_applications">Ўсталяваныя праграмы</string>
|
|
||||||
<string name="import_settings_DESC">Імпарт налад і абранага з файла</string>
|
<string name="import_settings_DESC">Імпарт налад і абранага з файла</string>
|
||||||
<string name="repository">Рэпазіторый</string>
|
<string name="repository">Рэпазіторый</string>
|
||||||
<string name="unstable_updates_summary">Прапанаваць усталёўваць нестабільныя версіі</string>
|
<string name="unstable_updates_summary">Прапанаваць усталёўваць нестабільныя версіі</string>
|
||||||
@ -196,17 +184,13 @@
|
|||||||
<string name="prefs_personalization">Персаналізацыя</string>
|
<string name="prefs_personalization">Персаналізацыя</string>
|
||||||
<string name="signature_FORMAT">Подпіс %s</string>
|
<string name="signature_FORMAT">Подпіс %s</string>
|
||||||
<string name="shizuku_installer">Shizuku устаноўшчык</string>
|
<string name="shizuku_installer">Shizuku устаноўшчык</string>
|
||||||
<string name="new_applications">Новыя праграмы</string>
|
|
||||||
<string name="uninstall">Выдаліць</string>
|
<string name="uninstall">Выдаліць</string>
|
||||||
<string name="skip">Прапусціць</string>
|
<string name="skip">Прапусціць</string>
|
||||||
<string name="export_settings_title">Налады экспарту</string>
|
<string name="export_settings_title">Налады экспарту</string>
|
||||||
<string name="export_repos_DESC">Экспарт усіх рэпазіторыяў з файла</string>
|
<string name="export_repos_DESC">Экспарт усіх рэпазіторыяў з файла</string>
|
||||||
<string name="import_repos_title">Імпарт рэпазіторыяў</string>
|
<string name="import_repos_title">Імпарт рэпазіторыяў</string>
|
||||||
<string name="screenshots">Скрыншоты</string>
|
|
||||||
<string name="recently_updated">Нядаўна абноўлены</string>
|
<string name="recently_updated">Нядаўна абноўлены</string>
|
||||||
<string name="sorting_order">Парадак сартавання</string>
|
<string name="sorting_order">Парадак сартавання</string>
|
||||||
<string name="unverified">Неправераныя</string>
|
|
||||||
<string name="root_permission">Ціхая ўстаноўка</string>
|
|
||||||
<string name="invalid_fingerprint_format">Няправільны фармат адбітка</string>
|
<string name="invalid_fingerprint_format">Няправільны фармат адбітка</string>
|
||||||
<string name="saving_details">Захаванне даных…</string>
|
<string name="saving_details">Захаванне даных…</string>
|
||||||
<string name="whats_new">Што новага</string>
|
<string name="whats_new">Што новага</string>
|
||||||
@ -218,14 +202,12 @@
|
|||||||
<string name="search">Пошук</string>
|
<string name="search">Пошук</string>
|
||||||
<string name="unknown_error_DESC">Невядомая памылка.</string>
|
<string name="unknown_error_DESC">Невядомая памылка.</string>
|
||||||
<string name="themes">Тэмы</string>
|
<string name="themes">Тэмы</string>
|
||||||
<string name="list_animation">Анімацыя спісаў</string>
|
|
||||||
<string name="home_screen_swiping_DESC">Дазволіць карыстальніку гартаць старонкі на галоўным экране</string>
|
<string name="home_screen_swiping_DESC">Дазволіць карыстальніку гартаць старонкі на галоўным экране</string>
|
||||||
<string name="export_repos_title">Экспарт рэпазіторыяў</string>
|
<string name="export_repos_title">Экспарт рэпазіторыяў</string>
|
||||||
<string name="show_less">Паказаць менш</string>
|
<string name="show_less">Паказаць менш</string>
|
||||||
<string name="settings">Налады</string>
|
<string name="settings">Налады</string>
|
||||||
<string name="upstream_source_code_is_not_free">Зыходны код не з\'яўляецца свабодным</string>
|
<string name="upstream_source_code_is_not_free">Зыходны код не з\'яўляецца свабодным</string>
|
||||||
<string name="versions">Версіі</string>
|
<string name="versions">Версіі</string>
|
||||||
<string name="repository_not_used_DESC">Гэты рэпазіторый яшчэ не выкарыстоўваўся. Вам трэба ўключыць яго для прагляду прымянення ў ім.</string>
|
|
||||||
<string name="import_repos_DESC">Імпарт усіх рэпазіторыяў з файла</string>
|
<string name="import_repos_DESC">Імпарт усіх рэпазіторыяў з файла</string>
|
||||||
<string name="system">Як у сістэме</string>
|
<string name="system">Як у сістэме</string>
|
||||||
<string name="special_credits">Асаблівыя падзякі</string>
|
<string name="special_credits">Асаблівыя падзякі</string>
|
||||||
@ -233,8 +215,6 @@
|
|||||||
<string name="show_older_versions">Паказаць старыя версіі</string>
|
<string name="show_older_versions">Паказаць старыя версіі</string>
|
||||||
<string name="shizuku_not_installed">Shizuku не ўстаноўлена</string>
|
<string name="shizuku_not_installed">Shizuku не ўстаноўлена</string>
|
||||||
<string name="unstable_updates">Нестабільнае абнаўленне</string>
|
<string name="unstable_updates">Нестабільнае абнаўленне</string>
|
||||||
<string name="latest">Апошнія</string>
|
|
||||||
<string name="root_permission_description">Падайце root-правы для ўключэння ціхай устаноўкі</string>
|
|
||||||
<string name="unknown_FORMAT">Невядома: %s</string>
|
<string name="unknown_FORMAT">Невядома: %s</string>
|
||||||
<string name="cannot_open_link">Немагчыма адкрыць спасылку</string>
|
<string name="cannot_open_link">Немагчыма адкрыць спасылку</string>
|
||||||
<string name="has_tethered_network">Прывязка да вызначанай сеткавай службы</string>
|
<string name="has_tethered_network">Прывязка да вызначанай сеткавай службы</string>
|
||||||
@ -246,4 +226,15 @@
|
|||||||
<string name="ignore_signature">Ігнараваць подпіс</string>
|
<string name="ignore_signature">Ігнараваць подпіс</string>
|
||||||
<string name="installation_failed_DESC">Не ўдалося ўсталяваць %s</string>
|
<string name="installation_failed_DESC">Не ўдалося ўсталяваць %s</string>
|
||||||
<string name="ignore_signature_summary">Ігнараванне праверкі подпісу пры ўстаноўцы apk, для карыстальнікаў LSPosed або прасунутых карыстальнікаў</string>
|
<string name="ignore_signature_summary">Ігнараванне праверкі подпісу пры ўстаноўцы apk, для карыстальнікаў LSPosed або прасунутых карыстальнікаў</string>
|
||||||
</resources>
|
<string name="error_shizuku_service_unavailable">Shizuku не працуе</string>
|
||||||
|
<string name="error_shizuku_not_running_DESC">Сэрвіс Shizuku не працуе. Калі ласка, праверце праграму Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_granted">Shizuku няма дазволу</string>
|
||||||
|
<string name="error_shizuku_not_granted_DESC">Не дадзены дазвол на сэрвіс Shizuku. Калі ласка, праверце праграму Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_installed">Shizuku не ўсталявана</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">Здаецца, Shizuku не ўсталявана</string>
|
||||||
|
<string name="insufficient_storage">Не хапае месца</string>
|
||||||
|
<string name="insufficient_storage_DESC">На вашай прыладзе не хапае памяці для ўсталявання гэтай праграмы. Паспрабуйце вызваліць крыху месца</string>
|
||||||
|
<string name="open_shizuku">Адкрыць Shizuku</string>
|
||||||
|
<string name="switch_to_default_installer">Пераключыцца на стандартны</string>
|
||||||
|
<string name="label_open_video">Відэа</string>
|
||||||
|
</resources>
|
||||||
|
@ -55,7 +55,6 @@
|
|||||||
<string name="license_FORMAT">%s лиценз</string>
|
<string name="license_FORMAT">%s лиценз</string>
|
||||||
<string name="light">Светла</string>
|
<string name="light">Светла</string>
|
||||||
<string name="links">Линкове</string>
|
<string name="links">Линкове</string>
|
||||||
<string name="list_animation_description">Анимирай списъка на главната страница</string>
|
|
||||||
<string name="merging_FORMAT">Сливане на %s</string>
|
<string name="merging_FORMAT">Сливане на %s</string>
|
||||||
<string name="name">Име</string>
|
<string name="name">Име</string>
|
||||||
<string name="network_error_DESC">Мрежова грешка</string>
|
<string name="network_error_DESC">Мрежова грешка</string>
|
||||||
@ -66,7 +65,7 @@
|
|||||||
<string name="notify_about_updates">Уведомления за актуализации</string>
|
<string name="notify_about_updates">Уведомления за актуализации</string>
|
||||||
<string name="number_of_applications">Брой приложения</string>
|
<string name="number_of_applications">Брой приложения</string>
|
||||||
<string name="ok">Окей</string>
|
<string name="ok">Окей</string>
|
||||||
<string name="only_on_wifi">Само на Wi-Fi</string>
|
<string name="only_on_wifi">Само при Wi-Fi</string>
|
||||||
<string name="open_DESC_FORMAT">Отвори %s\?</string>
|
<string name="open_DESC_FORMAT">Отвори %s\?</string>
|
||||||
<string name="other">Други</string>
|
<string name="other">Други</string>
|
||||||
<string name="parsing_index_error_DESC">Не може да се прочете индекс файла.</string>
|
<string name="parsing_index_error_DESC">Не може да се прочете индекс файла.</string>
|
||||||
@ -79,14 +78,10 @@
|
|||||||
<string name="recently_updated">Наскоро обновени</string>
|
<string name="recently_updated">Наскоро обновени</string>
|
||||||
<string name="repositories">Хранилища</string>
|
<string name="repositories">Хранилища</string>
|
||||||
<string name="repository">Хранилище</string>
|
<string name="repository">Хранилище</string>
|
||||||
<string name="repository_not_used_DESC">Това хранилище все още не е използвано.Включете го, за да видите приложенията в него.</string>
|
|
||||||
<string name="repository_unsigned_DESC">Неподписано. Не може да провери списъка с неподписаните приложения. Внимавайте с тегленето на приложения от неподписани хранилища.</string>
|
<string name="repository_unsigned_DESC">Неподписано. Не може да провери списъка с неподписаните приложения. Внимавайте с тегленето на приложения от неподписани хранилища.</string>
|
||||||
<string name="requires_FORMAT">Изисква %s</string>
|
<string name="requires_FORMAT">Изисква %s</string>
|
||||||
<string name="root_permission">Безшумна Инсталация</string>
|
|
||||||
<string name="root_permission_description">За безшумни инсталации дайте root разрешение</string>
|
|
||||||
<string name="save">Запази</string>
|
<string name="save">Запази</string>
|
||||||
<string name="saving_details">Запазване на подробности…</string>
|
<string name="saving_details">Запазване на подробности…</string>
|
||||||
<string name="screenshots">Екранни снимки</string>
|
|
||||||
<string name="select_mirror">Избери източник</string>
|
<string name="select_mirror">Избери източник</string>
|
||||||
<string name="share">Сподели</string>
|
<string name="share">Сподели</string>
|
||||||
<string name="show_more">Покажи повече</string>
|
<string name="show_more">Покажи повече</string>
|
||||||
@ -100,12 +95,10 @@
|
|||||||
<string name="suggested">Предложено</string>
|
<string name="suggested">Предложено</string>
|
||||||
<string name="sync_repositories_automatically">Автоматично синхронизиране на хранилищата</string>
|
<string name="sync_repositories_automatically">Автоматично синхронизиране на хранилищата</string>
|
||||||
<string name="syncing">Синхронизиране</string>
|
<string name="syncing">Синхронизиране</string>
|
||||||
<string name="target">Цел</string>
|
|
||||||
<string name="theme">Тема</string>
|
<string name="theme">Тема</string>
|
||||||
<string name="tracks_or_reports_your_activity">Проследява или отчита вашата дейност</string>
|
<string name="tracks_or_reports_your_activity">Проследява или отчита вашата дейност</string>
|
||||||
<string name="unknown">Неизвестно</string>
|
<string name="unknown">Неизвестно</string>
|
||||||
<string name="unknown_FORMAT">Неизвестно: %s</string>
|
<string name="unknown_FORMAT">Неизвестно: %s</string>
|
||||||
<string name="unverified">Непроверено</string>
|
|
||||||
<string name="update">Актуализация</string>
|
<string name="update">Актуализация</string>
|
||||||
<string name="updates">Актуализации</string>
|
<string name="updates">Актуализации</string>
|
||||||
<string name="username">Потребителско име</string>
|
<string name="username">Потребителско име</string>
|
||||||
@ -114,12 +107,7 @@
|
|||||||
<string name="waiting_to_start_download">В очакване да започне изтеглянето…</string>
|
<string name="waiting_to_start_download">В очакване да започне изтеглянето…</string>
|
||||||
<string name="whats_new">Какво е новото</string>
|
<string name="whats_new">Какво е новото</string>
|
||||||
<string name="show_less">Покажи по-малко</string>
|
<string name="show_less">Покажи по-малко</string>
|
||||||
<string name="latest">Последни</string>
|
|
||||||
<string name="explore">Разглеждане</string>
|
|
||||||
<string name="update_all">Инсталирай всички</string>
|
<string name="update_all">Инсталирай всички</string>
|
||||||
<string name="installed_applications">Инсталирани приложения</string>
|
|
||||||
<string name="sort_filter">Сортиране & Филтриране</string>
|
|
||||||
<string name="new_applications">Нови приложения</string>
|
|
||||||
<string name="anti_features">Антифункции</string>
|
<string name="anti_features">Антифункции</string>
|
||||||
<string name="author_website">Уебстраница на автора</string>
|
<string name="author_website">Уебстраница на автора</string>
|
||||||
<string name="cant_edit_sync_DESC">Не може да се редактират синхронизиращи се хранилища.</string>
|
<string name="cant_edit_sync_DESC">Не може да се редактират синхронизиращи се хранилища.</string>
|
||||||
@ -134,7 +122,6 @@
|
|||||||
<string name="incompatible_api_DESC_FORMAT">Вашата %1$s (АПИ версия %2$d) се поддържа. %3$s</string>
|
<string name="incompatible_api_DESC_FORMAT">Вашата %1$s (АПИ версия %2$d) се поддържа. %3$s</string>
|
||||||
<string name="incompatible_older_DESC">Тази версия е по-стара от инсталираната на вашето устройство. Деинсталирайте първо нея.</string>
|
<string name="incompatible_older_DESC">Тази версия е по-стара от инсталираната на вашето устройство. Деинсталирайте първо нея.</string>
|
||||||
<string name="invalid_username_format">Невалиден формат на потребителското име</string>
|
<string name="invalid_username_format">Невалиден формат на потребителското име</string>
|
||||||
<string name="list_animation">Анимации на списъците</string>
|
|
||||||
<string name="unstable_updates">Нестабилни актуализации</string>
|
<string name="unstable_updates">Нестабилни актуализации</string>
|
||||||
<string name="incompatible_signature_DESC">Тази версия е подписана със сертификат, различен от този, инсталиран на вашето устройство. Деинсталирайте първо нея.</string>
|
<string name="incompatible_signature_DESC">Тази версия е подписана със сертификат, различен от този, инсталиран на вашето устройство. Деинсталирайте първо нея.</string>
|
||||||
<string name="incompatible_versions_summary">Показване на версии, несъвместими с устройството</string>
|
<string name="incompatible_versions_summary">Показване на версии, несъвместими с устройството</string>
|
||||||
@ -170,7 +157,6 @@
|
|||||||
<string name="tap_to_install_DESC">Докосни за инсталиране.</string>
|
<string name="tap_to_install_DESC">Докосни за инсталиране.</string>
|
||||||
<string name="unknown_error_DESC">Неизвестна грешка.</string>
|
<string name="unknown_error_DESC">Неизвестна грешка.</string>
|
||||||
<string name="unstable_updates_summary">Предложи инсталирането на нестабилни версии</string>
|
<string name="unstable_updates_summary">Предложи инсталирането на нестабилни версии</string>
|
||||||
<string name="unsigned">Неподписано</string>
|
|
||||||
<string name="upstream_source_code_is_not_free">Актуалният програмен код вече не е със свободен лиценз</string>
|
<string name="upstream_source_code_is_not_free">Актуалният програмен код вече не е със свободен лиценз</string>
|
||||||
<string name="username_missing">Потребителско име липсва</string>
|
<string name="username_missing">Потребителско име липсва</string>
|
||||||
<string name="validation_index_error_DESC">Не може да валидира индексът.</string>
|
<string name="validation_index_error_DESC">Не може да валидира индексът.</string>
|
||||||
@ -188,24 +174,19 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="only_on_wifi_with_charging">Само при Wi-Fi и зареждане</string>
|
<string name="only_on_wifi_with_charging">Само при Wi-Fi и зареждане</string>
|
||||||
<string name="cleanup_title">Интервал за почистване на APK</string>
|
<string name="cleanup_title">Интервал за почистване на APK</string>
|
||||||
<string name="cleanup_description">Период за проверка и премахване на изтеглените файлове</string>
|
|
||||||
<plurals name="hours">
|
<plurals name="hours">
|
||||||
<item quantity="one">Час</item>
|
<item quantity="one">Час</item>
|
||||||
<item quantity="other">Часа</item>
|
<item quantity="other">Часа</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="no_internet">Нямате интернет връзка</string>
|
|
||||||
<string name="allow_collapsing_toolbar">Разрешете горната лента на приложението да се разшири</string>
|
|
||||||
<string name="io_error_DESC">Невъзможност за извършване на определени действия.</string>
|
<string name="io_error_DESC">Невъзможност за извършване на определени действия.</string>
|
||||||
<string name="allow_collapsing_toolbar_DESC">Разрешете горната лента на приложението да се разширява и свива</string>
|
|
||||||
<string name="material_you_desc">Използвайте material you цветова тема</string>
|
<string name="material_you_desc">Използвайте material you цветова тема</string>
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="auto_update">Автоматично актуализиране на приложения</string>
|
<string name="auto_update">Автоматично актуализиране на приложения</string>
|
||||||
<string name="installing">Инсталиране</string>
|
<string name="installing">Инсталиране</string>
|
||||||
<string name="auto_update_apps">Опитайте се да инсталирате актуализации автоматично</string>
|
<string name="auto_update_apps">Опитайте се да инсталирате актуализации автоматично</string>
|
||||||
<string name="restart_app">Рестартирайте Droid-ify, за да видите промените</string>
|
|
||||||
<string name="waiting_to_start_installation">Изчакване за стартиране на инсталацията…</string>
|
<string name="waiting_to_start_installation">Изчакване за стартиране на инсталацията…</string>
|
||||||
<string name="favourites">Любими</string>
|
<string name="favourites">Любими</string>
|
||||||
<string name="enable_repo">Активирайте хранилището</string>
|
<string name="enable_repo">Активирай хранилището</string>
|
||||||
<string name="force_clean_up">Принудително почистване</string>
|
<string name="force_clean_up">Принудително почистване</string>
|
||||||
<string name="force_clean_up_DESC">Почиства излишните файлове</string>
|
<string name="force_clean_up_DESC">Почиства излишните файлове</string>
|
||||||
<string name="repository_unreachable">Хранилището е недостъпно</string>
|
<string name="repository_unreachable">Хранилището е недостъпно</string>
|
||||||
@ -215,7 +196,6 @@
|
|||||||
<string name="home_screen_swiping">Плъзгане на началния екран</string>
|
<string name="home_screen_swiping">Плъзгане на началния екран</string>
|
||||||
<string name="contains_nsfw">Съдържа неподходящо за работа съдържание</string>
|
<string name="contains_nsfw">Съдържа неподходящо за работа съдържание</string>
|
||||||
<string name="shizuku_not_alive">Shizuku не работи</string>
|
<string name="shizuku_not_alive">Shizuku не работи</string>
|
||||||
<string name="label_copy">Копирай</string>
|
|
||||||
<string name="proxy_port_error_not_int">Прокси портът може да бъде само цяло число</string>
|
<string name="proxy_port_error_not_int">Прокси портът може да бъде само цяло число</string>
|
||||||
<string name="home_screen_swiping_DESC">Позволете на потребителя да плъзга между страниците в началния екран</string>
|
<string name="home_screen_swiping_DESC">Позволете на потребителя да плъзга между страниците в началния екран</string>
|
||||||
<string name="repository_not_found">Следното хранилище не бе намерено</string>
|
<string name="repository_not_found">Следното хранилище не бе намерено</string>
|
||||||
@ -225,12 +205,12 @@
|
|||||||
<string name="import_settings_title">Внеси Настройки</string>
|
<string name="import_settings_title">Внеси Настройки</string>
|
||||||
<string name="import_settings_DESC">Внасяне на настройки и любими от файл</string>
|
<string name="import_settings_DESC">Внасяне на настройки и любими от файл</string>
|
||||||
<string name="export_settings_title">Изнеси Настройки</string>
|
<string name="export_settings_title">Изнеси Настройки</string>
|
||||||
<string name="export_repos_DESC">Изнеси всички хранилища във файл</string>
|
<string name="export_repos_DESC">Изнасяне на всички хранилища във файл</string>
|
||||||
<string name="import_repos_title">Внеси хранилища</string>
|
<string name="import_repos_title">Внеси хранилища</string>
|
||||||
<string name="export_settings_DESC">Изнасяне на настройки и любими във файл</string>
|
<string name="export_settings_DESC">Изнасяне на настройки и любими във файл</string>
|
||||||
<string name="export_repos_title">Изнеси хранилища</string>
|
<string name="export_repos_title">Изнеси хранилища</string>
|
||||||
<string name="cannot_open_link">Линкът не може да се отвори</string>
|
<string name="cannot_open_link">Линкът не може да се отвори</string>
|
||||||
<string name="import_repos_DESC">Внеси всички хранилища от файл</string>
|
<string name="import_repos_DESC">Внасяне на всички хранилища от файл</string>
|
||||||
<string name="has_tethered_network">Обвързан с определена мрежова услуга</string>
|
<string name="has_tethered_network">Обвързан с определена мрежова услуга</string>
|
||||||
<string name="require_background_access">Изискване на фонов достъп</string>
|
<string name="require_background_access">Изискване на фонов достъп</string>
|
||||||
<string name="require_background_access_DESC">Необходим е фонов достъп, за да стартирате правилно фоновото синхронизиране</string>
|
<string name="require_background_access_DESC">Необходим е фонов достъп, за да стартирате правилно фоновото синхронизиране</string>
|
||||||
@ -242,4 +222,14 @@
|
|||||||
<string name="ignore_signature_summary">*Внимание* Игнорирайте проверката на подписа при инсталиране на APK за LSPosed потребители или напреднали потребители</string>
|
<string name="ignore_signature_summary">*Внимание* Игнорирайте проверката на подписа при инсталиране на APK за LSPosed потребители или напреднали потребители</string>
|
||||||
<string name="insufficient_storage">Недостатъчно място</string>
|
<string name="insufficient_storage">Недостатъчно място</string>
|
||||||
<string name="insufficient_storage_DESC">Няма достатъчно свободно място на устройството за инсталиране на това приложение. Опитайте да освободите малко място</string>
|
<string name="insufficient_storage_DESC">Няма достатъчно свободно място на устройството за инсталиране на това приложение. Опитайте да освободите малко място</string>
|
||||||
</resources>
|
<string name="error_shizuku_not_installed">Shizuku Не е инсталиран</string>
|
||||||
|
<string name="label_open_video">Видео</string>
|
||||||
|
<string name="switch_to_default_installer">Превключване към подразбиране</string>
|
||||||
|
<string name="open_shizuku">Отворете Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_running_DESC">Услугата Shizuku не работи. Моля, проверете в приложението Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_granted">Липсва разрешение за Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_granted_DESC">Разрешението за услуга Shizuku не е дадено. Моля, проверете в приложението Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">Shizuku изглежда не е инсталиран</string>
|
||||||
|
<string name="error_shizuku_service_unavailable">Shizuku Не работи</string>
|
||||||
|
<string name="label_unknown_sdk">Неизвестен (%d)</string>
|
||||||
|
</resources>
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
<string name="already_exists">আগে থেকেই আছে</string>
|
<string name="already_exists">আগে থেকেই আছে</string>
|
||||||
<string name="always">সর্বদা</string>
|
<string name="always">সর্বদা</string>
|
||||||
<string name="amoled">অন্ধকার</string>
|
<string name="amoled">অন্ধকার</string>
|
||||||
<string name="allow_collapsing_toolbar">অ্যাপের টপ বার সম্প্রসারিত হতে দাও</string>
|
|
||||||
<string name="could_not_validate_FORMAT">%s সত্যায়িত করা সম্ভব হয়নি</string>
|
<string name="could_not_validate_FORMAT">%s সত্যায়িত করা সম্ভব হয়নি</string>
|
||||||
<string name="donate">অনুদান</string>
|
<string name="donate">অনুদান</string>
|
||||||
<string name="description">বর্ণনা</string>
|
<string name="description">বর্ণনা</string>
|
||||||
@ -30,7 +29,6 @@
|
|||||||
<item quantity="other">ঘণ্টা</item>
|
<item quantity="other">ঘণ্টা</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="incompatible_api_max_DESC_FORMAT">সর্বোচ্চ এপিআই সংস্করণ %d।</string>
|
<string name="incompatible_api_max_DESC_FORMAT">সর্বোচ্চ এপিআই সংস্করণ %d।</string>
|
||||||
<string name="allow_collapsing_toolbar_DESC">অ্যাপের টপ বার সম্প্রসারিত ও সংকুচিত হতে দাও</string>
|
|
||||||
<string name="anti_features">অপবৈশিষ্ট্য</string>
|
<string name="anti_features">অপবৈশিষ্ট্য</string>
|
||||||
<string name="has_advertising">বিজ্ঞাপন আছে</string>
|
<string name="has_advertising">বিজ্ঞাপন আছে</string>
|
||||||
<string name="http_proxy">HTTP প্রক্সি</string>
|
<string name="http_proxy">HTTP প্রক্সি</string>
|
||||||
@ -60,7 +58,6 @@
|
|||||||
<string name="delete_repository_DESC">রিপোজিটরি ডিলিট করতে চান\?</string>
|
<string name="delete_repository_DESC">রিপোজিটরি ডিলিট করতে চান\?</string>
|
||||||
<string name="edit_repository">রিপোজিটরি সম্পাদনা করুন</string>
|
<string name="edit_repository">রিপোজিটরি সম্পাদনা করুন</string>
|
||||||
<string name="ignore_this_update">এই সংস্করণটি অগ্রাহ্য করো</string>
|
<string name="ignore_this_update">এই সংস্করণটি অগ্রাহ্য করো</string>
|
||||||
<string name="cleanup_description">ডাউনলোড করা নথিগুলো পরীক্ষা এবং অপসারণের সময়কাল</string>
|
|
||||||
<string name="compiled_for_debugging">ডিবাগিংয়ের জন্য কম্পাইল করা হয়েছে</string>
|
<string name="compiled_for_debugging">ডিবাগিংয়ের জন্য কম্পাইল করা হয়েছে</string>
|
||||||
<string name="bug_tracker">বাগ ট্র্যাকার</string>
|
<string name="bug_tracker">বাগ ট্র্যাকার</string>
|
||||||
<string name="incompatible_signature_DESC">এই সংস্করণটি আপনার ডিভাইসে ইনস্টল করা একটি থেকে একটি ভিন্ন শংসাপত্রের সাথে স্বাক্ষরিত৷ প্রথমে এটি আনইনস্টল করুন।</string>
|
<string name="incompatible_signature_DESC">এই সংস্করণটি আপনার ডিভাইসে ইনস্টল করা একটি থেকে একটি ভিন্ন শংসাপত্রের সাথে স্বাক্ষরিত৷ প্রথমে এটি আনইনস্টল করুন।</string>
|
||||||
@ -91,8 +88,6 @@
|
|||||||
<string name="license">লাইসেন্স</string>
|
<string name="license">লাইসেন্স</string>
|
||||||
<string name="license_FORMAT">%s লাইসেন্স</string>
|
<string name="license_FORMAT">%s লাইসেন্স</string>
|
||||||
<string name="light">আলো</string>
|
<string name="light">আলো</string>
|
||||||
<string name="list_animation">তালিকা অ্যানিমেশন</string>
|
|
||||||
<string name="list_animation_description">প্রধান পৃষ্ঠায় তালিকা অ্যানিমেশন দেখান</string>
|
|
||||||
<string name="merging_FORMAT">%s মার্জ করা হচ্ছে</string>
|
<string name="merging_FORMAT">%s মার্জ করা হচ্ছে</string>
|
||||||
<string name="material_you">উপাদান আপনি</string>
|
<string name="material_you">উপাদান আপনি</string>
|
||||||
<string name="session_installer">সেশন ইনস্টলার</string>
|
<string name="session_installer">সেশন ইনস্টলার</string>
|
||||||
@ -108,7 +103,6 @@
|
|||||||
<item quantity="other">নতুন সংস্করণ সহ %dটি অ্যাপ্লিকেশন।</item>
|
<item quantity="other">নতুন সংস্করণ সহ %dটি অ্যাপ্লিকেশন।</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="no_applications_installed">কোনো ইনস্টল করা অ্যাপ্লিকেশন নেই</string>
|
<string name="no_applications_installed">কোনো ইনস্টল করা অ্যাপ্লিকেশন নেই</string>
|
||||||
<string name="no_internet">আপনার কোন ইন্টারনেট সংযোগ নেই</string>
|
|
||||||
<string name="no_matching_applications_found">এই ধরনের কোনো অ্যাপ্লিকেশন খুঁজে পাওয়া যায়নি</string>
|
<string name="no_matching_applications_found">এই ধরনের কোনো অ্যাপ্লিকেশন খুঁজে পাওয়া যায়নি</string>
|
||||||
<string name="number_of_applications">আবেদনের সংখ্যা</string>
|
<string name="number_of_applications">আবেদনের সংখ্যা</string>
|
||||||
<string name="auto_update">স্বয়ংক্রিয়ভাবে অ্যাপ্লিকেশন হালনাগাদ</string>
|
<string name="auto_update">স্বয়ংক্রিয়ভাবে অ্যাপ্লিকেশন হালনাগাদ</string>
|
||||||
@ -129,8 +123,6 @@
|
|||||||
<string name="proxy_port">প্রক্সি পর্ট</string>
|
<string name="proxy_port">প্রক্সি পর্ট</string>
|
||||||
<string name="recently_updated">সম্প্রতি আপডেট করা হয়েছে</string>
|
<string name="recently_updated">সম্প্রতি আপডেট করা হয়েছে</string>
|
||||||
<string name="repository">ভান্ডার</string>
|
<string name="repository">ভান্ডার</string>
|
||||||
<string name="repository_not_used_DESC">এই সংগ্রহস্থল এখনও ব্যবহার করা হয় নি. এটিতে থাকা অ্যাপ্লিকেশনগুলি দেখতে এটি চালু করুন।</string>
|
|
||||||
<string name="restart_app">পরিবর্তনগুলি দেখতে Droid-ify পুনরায় চালু করুন</string>
|
|
||||||
<string name="show_older_versions">পুরানো সংস্করণ দেখান</string>
|
<string name="show_older_versions">পুরানো সংস্করণ দেখান</string>
|
||||||
<string name="plus_more_FORMAT">+%d আরো</string>
|
<string name="plus_more_FORMAT">+%d আরো</string>
|
||||||
<string name="favourites">প্রিয়</string>
|
<string name="favourites">প্রিয়</string>
|
||||||
@ -149,10 +141,7 @@
|
|||||||
<string name="project_website">প্রকল্প ওয়েবসাইট</string>
|
<string name="project_website">প্রকল্প ওয়েবসাইট</string>
|
||||||
<string name="repository_unreachable">রিপোজিটরি পৌঁছানো যায় না</string>
|
<string name="repository_unreachable">রিপোজিটরি পৌঁছানো যায় না</string>
|
||||||
<string name="requires_FORMAT">%s প্রয়োজন</string>
|
<string name="requires_FORMAT">%s প্রয়োজন</string>
|
||||||
<string name="root_permission">নীরব ইনস্টল</string>
|
|
||||||
<string name="saving_details">বিবরণ সংরক্ষণ করা হচ্ছে…</string>
|
<string name="saving_details">বিবরণ সংরক্ষণ করা হচ্ছে…</string>
|
||||||
<string name="screenshots">স্ক্রিনশট</string>
|
|
||||||
<string name="root_permission_description">নীরব ইনস্টলেশনের জন্য রুট অনুমতির অনুমতি দিন</string>
|
|
||||||
<string name="save">সংরক্ষণ</string>
|
<string name="save">সংরক্ষণ</string>
|
||||||
<string name="search">অনুসন্ধান করুন</string>
|
<string name="search">অনুসন্ধান করুন</string>
|
||||||
<string name="select_mirror">একটি আয়না নির্বাচন করুন</string>
|
<string name="select_mirror">একটি আয়না নির্বাচন করুন</string>
|
||||||
@ -172,24 +161,18 @@
|
|||||||
<string name="syncing">সিঙ্ক হচ্ছে</string>
|
<string name="syncing">সিঙ্ক হচ্ছে</string>
|
||||||
<string name="system">পদ্ধতি</string>
|
<string name="system">পদ্ধতি</string>
|
||||||
<string name="tap_to_install_DESC">ইনস্টল করতে আলতো চাপুন।</string>
|
<string name="tap_to_install_DESC">ইনস্টল করতে আলতো চাপুন।</string>
|
||||||
<string name="target">টার্গেট</string>
|
|
||||||
<string name="uninstall">আনইনস্টল করুন</string>
|
<string name="uninstall">আনইনস্টল করুন</string>
|
||||||
<string name="unknown">অজানা</string>
|
<string name="unknown">অজানা</string>
|
||||||
<string name="unknown_error_DESC">অজানা ত্রুটি.</string>
|
<string name="unknown_error_DESC">অজানা ত্রুটি.</string>
|
||||||
<string name="unknown_FORMAT">অজানা: %s</string>
|
<string name="unknown_FORMAT">অজানা: %s</string>
|
||||||
<string name="unsigned">স্বাক্ষরবিহীন</string>
|
|
||||||
<string name="unverified">যাচাই করা হয়নি</string>
|
|
||||||
<string name="username">ব্যবহারকারীর নাম</string>
|
<string name="username">ব্যবহারকারীর নাম</string>
|
||||||
<string name="version_FORMAT">সংস্করণ %s</string>
|
<string name="version_FORMAT">সংস্করণ %s</string>
|
||||||
<string name="website">ওয়েবসাইট</string>
|
<string name="website">ওয়েবসাইট</string>
|
||||||
<string name="prefs_personalization">ব্যক্তিগতকরণ</string>
|
<string name="prefs_personalization">ব্যক্তিগতকরণ</string>
|
||||||
<string name="show_less">প্রদর্শন কম</string>
|
<string name="show_less">প্রদর্শন কম</string>
|
||||||
<string name="latest">সর্বশেষ</string>
|
|
||||||
<string name="sort_filter">বাছাই এবং ফিল্টার</string>
|
|
||||||
<string name="sync_repositories">সিঙ্ক রিপোজিটরি</string>
|
<string name="sync_repositories">সিঙ্ক রিপোজিটরি</string>
|
||||||
<string name="tracks_or_reports_your_activity">আপনার কার্যকলাপ ট্র্যাক বা রিপোর্ট</string>
|
<string name="tracks_or_reports_your_activity">আপনার কার্যকলাপ ট্র্যাক বা রিপোর্ট</string>
|
||||||
<string name="versions">সংস্করণ</string>
|
<string name="versions">সংস্করণ</string>
|
||||||
<string name="explore">অন্বেষণ</string>
|
|
||||||
<string name="syncing_FORMAT">%s সিঙ্ক হচ্ছে…</string>
|
<string name="syncing_FORMAT">%s সিঙ্ক হচ্ছে…</string>
|
||||||
<string name="whats_new">নতুন কি</string>
|
<string name="whats_new">নতুন কি</string>
|
||||||
<string name="themes">রঙ</string>
|
<string name="themes">রঙ</string>
|
||||||
@ -204,12 +187,49 @@
|
|||||||
<string name="waiting_to_start_installation">ইনস্টলেশন শুরু করার জন্য অপেক্ষা করা হচ্ছে…</string>
|
<string name="waiting_to_start_installation">ইনস্টলেশন শুরু করার জন্য অপেক্ষা করা হচ্ছে…</string>
|
||||||
<string name="upstream_source_code_is_not_free">আপস্ট্রিম সোর্স কোড বিনামূল্যে নয়</string>
|
<string name="upstream_source_code_is_not_free">আপস্ট্রিম সোর্স কোড বিনামূল্যে নয়</string>
|
||||||
<string name="validation_index_error_DESC">সূচক যাচাই করা যায়নি.</string>
|
<string name="validation_index_error_DESC">সূচক যাচাই করা যায়নি.</string>
|
||||||
<string name="installed_applications">ইনস্টল করা অ্যাপ্লিকেশন</string>
|
|
||||||
<string name="update">হালনাগাদ</string>
|
<string name="update">হালনাগাদ</string>
|
||||||
<string name="waiting_to_start_download">ডাউনলোড শুরু করার জন্য অপেক্ষা করা হচ্ছে…</string>
|
<string name="waiting_to_start_download">ডাউনলোড শুরু করার জন্য অপেক্ষা করা হচ্ছে…</string>
|
||||||
<string name="prefs_language_title">ভাষা</string>
|
<string name="prefs_language_title">ভাষা</string>
|
||||||
<string name="new_applications">নতুন অ্যাপ্লিকেশন</string>
|
|
||||||
<string name="cannot_open_link">লিংকটি ওপেন করা সম্ভব হয়নি</string>
|
<string name="cannot_open_link">লিংকটি ওপেন করা সম্ভব হয়নি</string>
|
||||||
<string name="import_export">ইম্পোর্ট/এক্সপোর্ট</string>
|
<string name="import_export">ইম্পোর্ট/এক্সপোর্ট</string>
|
||||||
<string name="import_settings_title">সেটিংস ইম্পোর্ট করুন</string>
|
<string name="import_settings_title">সেটিংস ইম্পোর্ট করুন</string>
|
||||||
</resources>
|
<string name="uninstalled_application">অপসারিত</string>
|
||||||
|
<string name="special_credits">বিশেষ কৃতজ্ঞতাস্বীকার</string>
|
||||||
|
<string name="error_shizuku_not_granted_DESC">শিজুকু সেবার অনুমতি দেওয়া হয়নি। শিজুকু অ্যাপটি দেখো</string>
|
||||||
|
<string name="ignore_signature_summary">*সতর্কতা* এপিকে ইন্সটলে সময় স্বাক্ষর যাচাইকরণ এড়াও, এলএসপোজড ব্যবহারকারী বা অগ্রগামী ব্যবহারকারীর জন্য</string>
|
||||||
|
<string name="contains_nsfw">নিষিদ্ধ বিষয়বস্ত বিদ্যমান</string>
|
||||||
|
<string name="label_open_video">ভিডিও</string>
|
||||||
|
<string name="export_settings_title">পছন্দসমূহ রপ্তানি করো</string>
|
||||||
|
<string name="insufficient_storage">অপর্যাপ্ত জায়গা</string>
|
||||||
|
<string name="shizuku_not_alive">শিজুকু চলছে না</string>
|
||||||
|
<string name="error_shizuku_not_running_DESC">শিজুকু চলছে না। অনুগ্রহ করে শিজুকু অ্যাপ দেখো</string>
|
||||||
|
<string name="export_repos_DESC">সব ভাণ্ডার ফাইলে রপ্তানি</string>
|
||||||
|
<string name="home_screen_swiping_DESC">ব্যবহারকারীকে মূলপাতাসমূহের মধ্যে টান দেওয়া অনুমোদন করো</string>
|
||||||
|
<string name="connection_error_DESC">সার্ভারে যুক্ত হতে ব্যর্থ</string>
|
||||||
|
<string name="shizuku_not_installed">শিজুকু ইন্সটল করা নেই</string>
|
||||||
|
<string name="installation_failed">ইন্সটল ব্যর্থ</string>
|
||||||
|
<string name="installation_failed_DESC">%s ইন্সটল করতে ব্যর্থ</string>
|
||||||
|
<string name="ignore_signature">স্বাক্ষর উপেক্ষা করো</string>
|
||||||
|
<string name="error_shizuku_service_unavailable">শিজুকু চলছে না</string>
|
||||||
|
<string name="error_shizuku_not_granted">শিজুকু অনুমতি নেই</string>
|
||||||
|
<string name="error_shizuku_not_installed">শিজুকু ইন্সটল করা হয়নি</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">শিজুকু মনে হচ্ছে না ইন্সটল করা</string>
|
||||||
|
<string name="import_settings_DESC">পছন্দসমূহ ফাইল থেকে আমদানি করো</string>
|
||||||
|
<string name="export_settings_DESC">পছন্দসমূহ ফাইলে রপ্তানি করো</string>
|
||||||
|
<string name="import_repos_title">ভাণ্ডার আমদানি করো</string>
|
||||||
|
<string name="import_repos_DESC">ফাইল থেকে সব ভাণ্ডার আমদানি করো</string>
|
||||||
|
<string name="export_repos_title">ভাণ্ডার রপ্তানি</string>
|
||||||
|
<string name="has_non_free_components">অমুক্ত অংশ আছে</string>
|
||||||
|
<string name="has_tethered_network">একটি নির্দিষ্ট নেটওয়ার্ক সেবার সাথে আবদ্ধ</string>
|
||||||
|
<string name="home_screen_swiping">মূলপাতা টান দেওয়া(সোয়াইপিং)</string>
|
||||||
|
<string name="socket_error_DESC">সার্ভার নতুন প্যাকেট সরবরাহে ব্যর্থ।</string>
|
||||||
|
<string name="uninstalled_application_DESC">%s অপসারিত হয়েছে</string>
|
||||||
|
<string name="insufficient_storage_DESC">এই অ্যাপটি ইন্সটল করার জন্য পর্যাপ্ত জায়গা নেই। কিছু জায়গা পরিষ্কারের চেষ্টা করো</string>
|
||||||
|
<string name="open_shizuku">শিজুকু খুলো</string>
|
||||||
|
<string name="proxy_port_error_not_int">প্রক্সি পোর্ট শুধু পূর্ণ ধনাত্মক সংখ্যা হতে পারে</string>
|
||||||
|
<string name="require_background_access">পটভূমিতে চলার অনুমতি প্রয়োজন</string>
|
||||||
|
<string name="require_background_access_DESC">পটভূমি অনুমোদন প্রয়োজন পটভূমি সিঙ্কের জন্য</string>
|
||||||
|
<string name="repository_not_found">এই ভাণ্ডারগুলো পাওয়া যায়নি</string>
|
||||||
|
<string name="switch_to_default_installer">সহজাতে পরিবর্তন করো</string>
|
||||||
|
<string name="label_unknown_sdk">অজানা (%d)</string>
|
||||||
|
</resources>
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
<string name="changes">Canvis</string>
|
<string name="changes">Canvis</string>
|
||||||
<string name="checking_repository">Comprovant repositori…</string>
|
<string name="checking_repository">Comprovant repositori…</string>
|
||||||
<string name="cleanup_title">Interval de neteja de l\'APK</string>
|
<string name="cleanup_title">Interval de neteja de l\'APK</string>
|
||||||
<string name="cleanup_description">Període per comprovar i eliminar els fitxers descarregats</string>
|
|
||||||
<string name="compiled_for_debugging">Compilat per a depuració</string>
|
<string name="compiled_for_debugging">Compilat per a depuració</string>
|
||||||
<string name="confirmation">Confirmació</string>
|
<string name="confirmation">Confirmació</string>
|
||||||
<string name="connecting">Connectant…</string>
|
<string name="connecting">Connectant…</string>
|
||||||
@ -87,11 +86,8 @@
|
|||||||
<string name="recently_updated">Recentment actualitzat</string>
|
<string name="recently_updated">Recentment actualitzat</string>
|
||||||
<string name="repositories">Repositoris</string>
|
<string name="repositories">Repositoris</string>
|
||||||
<string name="repository">Repositori</string>
|
<string name="repository">Repositori</string>
|
||||||
<string name="repository_not_used_DESC">Aquest repositori no ha estat utilitzat tot i així. Gira\'l damunt per veure les aplicacions en ell.</string>
|
|
||||||
<string name="repository_unsigned_DESC">Sense signar. No podria verificar la llista d\'aplicació. Ser prudent descarregar aplicacions des de repositoris sense signar.</string>
|
<string name="repository_unsigned_DESC">Sense signar. No podria verificar la llista d\'aplicació. Ser prudent descarregar aplicacions des de repositoris sense signar.</string>
|
||||||
<string name="requires_FORMAT">Requereix %s</string>
|
<string name="requires_FORMAT">Requereix %s</string>
|
||||||
<string name="root_permission">Silenciós Instal·lar</string>
|
|
||||||
<string name="root_permission_description">Permet permís d\'arrel per silenciós instal·la</string>
|
|
||||||
<string name="save">Salva</string>
|
<string name="save">Salva</string>
|
||||||
<string name="search">Recerca</string>
|
<string name="search">Recerca</string>
|
||||||
<string name="select_mirror">Selecciona un mirall</string>
|
<string name="select_mirror">Selecciona un mirall</string>
|
||||||
@ -112,10 +108,8 @@
|
|||||||
<string name="unknown">Desconegut</string>
|
<string name="unknown">Desconegut</string>
|
||||||
<string name="unknown_error_DESC">Error desconegut.</string>
|
<string name="unknown_error_DESC">Error desconegut.</string>
|
||||||
<string name="unknown_FORMAT">Desconegut: %s</string>
|
<string name="unknown_FORMAT">Desconegut: %s</string>
|
||||||
<string name="unsigned">Sense signar</string>
|
|
||||||
<string name="unstable_updates">Actualitzacions inestables</string>
|
<string name="unstable_updates">Actualitzacions inestables</string>
|
||||||
<string name="unstable_updates_summary">Suggereix instal·lant versions inestables</string>
|
<string name="unstable_updates_summary">Suggereix instal·lant versions inestables</string>
|
||||||
<string name="unverified">Sense verificar</string>
|
|
||||||
<string name="update">Actualització</string>
|
<string name="update">Actualització</string>
|
||||||
<string name="updates">Actualitzacions</string>
|
<string name="updates">Actualitzacions</string>
|
||||||
<string name="upstream_source_code_is_not_free">El codi font no és lliure</string>
|
<string name="upstream_source_code_is_not_free">El codi font no és lliure</string>
|
||||||
@ -129,12 +123,7 @@
|
|||||||
<string name="prefs_language_title">Llengua</string>
|
<string name="prefs_language_title">Llengua</string>
|
||||||
<string name="prefs_personalization">Personalització</string>
|
<string name="prefs_personalization">Personalització</string>
|
||||||
<string name="show_less">Mostrar menys</string>
|
<string name="show_less">Mostrar menys</string>
|
||||||
<string name="latest">Més recent</string>
|
|
||||||
<string name="explore">Explora</string>
|
|
||||||
<string name="update_all">Actualitzar tot</string>
|
<string name="update_all">Actualitzar tot</string>
|
||||||
<string name="installed_applications">Aplicacions instal·lades</string>
|
|
||||||
<string name="sort_filter">Ordenar i filtrar</string>
|
|
||||||
<string name="new_applications">Aplicacions noves</string>
|
|
||||||
<string name="fingerprint">Empremta digital</string>
|
<string name="fingerprint">Empremta digital</string>
|
||||||
<string name="incompatible_platforms_DESC_FORMAT">El vostre %1$s el programa no és recolzat. Programes recolzats: %2$s.</string>
|
<string name="incompatible_platforms_DESC_FORMAT">El vostre %1$s el programa no és recolzat. Programes recolzats: %2$s.</string>
|
||||||
<string name="all_applications">Totes les aplicacions</string>
|
<string name="all_applications">Totes les aplicacions</string>
|
||||||
@ -165,17 +154,14 @@
|
|||||||
<string name="license_FORMAT">%s llicència</string>
|
<string name="license_FORMAT">%s llicència</string>
|
||||||
<string name="no_proxy">Cap proxy</string>
|
<string name="no_proxy">Cap proxy</string>
|
||||||
<string name="link_copied_to_clipboard">El nexe va copiar a portapapers</string>
|
<string name="link_copied_to_clipboard">El nexe va copiar a portapapers</string>
|
||||||
<string name="target">Objectiu</string>
|
|
||||||
<string name="license">Llicència</string>
|
<string name="license">Llicència</string>
|
||||||
<string name="theme">Tema</string>
|
<string name="theme">Tema</string>
|
||||||
<string name="invalid_username_format">Nul username format</string>
|
<string name="invalid_username_format">Nul username format</string>
|
||||||
<string name="launch">Executa</string>
|
<string name="launch">Executa</string>
|
||||||
<string name="light">Llum</string>
|
<string name="light">Llum</string>
|
||||||
<string name="links">Nexes</string>
|
<string name="links">Nexes</string>
|
||||||
<string name="list_animation">Animacions de llista</string>
|
|
||||||
<string name="size">Mida</string>
|
<string name="size">Mida</string>
|
||||||
<string name="no_applications_installed">Aplicacions instal·lades no</string>
|
<string name="no_applications_installed">Aplicacions instal·lades no</string>
|
||||||
<string name="list_animation_description">L\'espectacle llista animació en la pàgina major</string>
|
|
||||||
<string name="merging_FORMAT">Fusionant %s</string>
|
<string name="merging_FORMAT">Fusionant %s</string>
|
||||||
<string name="network_error_DESC">Error de xarxa</string>
|
<string name="network_error_DESC">Error de xarxa</string>
|
||||||
<string name="new_updates_available">Versions noves de les aplicacions disponibles</string>
|
<string name="new_updates_available">Versions noves de les aplicacions disponibles</string>
|
||||||
@ -188,15 +174,11 @@
|
|||||||
<string name="no_description_available_DESC">Cap descripció disponible</string>
|
<string name="no_description_available_DESC">Cap descripció disponible</string>
|
||||||
<string name="notify_about_updates_summary">Mostra una notificació quan les versions noves són disponibles</string>
|
<string name="notify_about_updates_summary">Mostra una notificació quan les versions noves són disponibles</string>
|
||||||
<string name="saving_details">Salvant detalls…</string>
|
<string name="saving_details">Salvant detalls…</string>
|
||||||
<string name="screenshots">Captures de pantalla</string>
|
|
||||||
<string name="no_matching_applications_found">No podria trobar qualsevol tals aplicacions</string>
|
<string name="no_matching_applications_found">No podria trobar qualsevol tals aplicacions</string>
|
||||||
<string name="notify_about_updates">Notifica sobre versions noves d\'aplicacions</string>
|
<string name="notify_about_updates">Notifica sobre versions noves d\'aplicacions</string>
|
||||||
<string name="show_older_versions">Mostrar versions més velles</string>
|
<string name="show_older_versions">Mostrar versions més velles</string>
|
||||||
<string name="suggested">Suggerit</string>
|
<string name="suggested">Suggerit</string>
|
||||||
<string name="syncing">Sincronitzant</string>
|
<string name="syncing">Sincronitzant</string>
|
||||||
<string name="no_internet">No teniu cap connexió a Internet</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">Permet que la barra d\'aplicacions superior s\'expandeixi i es col·lapsi</string>
|
|
||||||
<string name="allow_collapsing_toolbar">Permet que la barra d\'aplicacions superior s\'expandeixi</string>
|
|
||||||
<string name="io_error_DESC">No es pot realitzar determinades accions.</string>
|
<string name="io_error_DESC">No es pot realitzar determinades accions.</string>
|
||||||
<string name="auto_update">Actualització automàtica d\'aplicacions</string>
|
<string name="auto_update">Actualització automàtica d\'aplicacions</string>
|
||||||
<string name="auto_update_apps">Intenta instal·lar les actualitzacions automàticament</string>
|
<string name="auto_update_apps">Intenta instal·lar les actualitzacions automàticament</string>
|
||||||
@ -208,7 +190,6 @@
|
|||||||
<string name="force_clean_up_DESC">Neteja els fitxers redundants</string>
|
<string name="force_clean_up_DESC">Neteja els fitxers redundants</string>
|
||||||
<string name="enable_repo">Habiliteu el repositori</string>
|
<string name="enable_repo">Habiliteu el repositori</string>
|
||||||
<string name="waiting_to_start_installation">S\'està esperant per iniciar la instal·lació…</string>
|
<string name="waiting_to_start_installation">S\'està esperant per iniciar la instal·lació…</string>
|
||||||
<string name="restart_app">Reinicieu Droid-ify per veure els canvis</string>
|
|
||||||
<string name="installing">Instal·lació</string>
|
<string name="installing">Instal·lació</string>
|
||||||
<string name="import_settings_DESC">Importa configuració i preferits des de fitxer</string>
|
<string name="import_settings_DESC">Importa configuració i preferits des de fitxer</string>
|
||||||
<string name="has_tethered_network">Enllaçat a un determinat servei de xarxa</string>
|
<string name="has_tethered_network">Enllaçat a un determinat servei de xarxa</string>
|
||||||
@ -222,4 +203,4 @@
|
|||||||
<string name="export_repos_title">Exporta els repositoris</string>
|
<string name="export_repos_title">Exporta els repositoris</string>
|
||||||
<string name="export_repos_DESC">Exporta tots els repositoris a un fitxer</string>
|
<string name="export_repos_DESC">Exporta tots els repositoris a un fitxer</string>
|
||||||
<string name="home_screen_swiping">Lliscar la pantalla d\'inici</string>
|
<string name="home_screen_swiping">Lliscar la pantalla d\'inici</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
8
app/src/main/res/values-ckb/strings.xml
Normal file
8
app/src/main/res/values-ckb/strings.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="action_failed">کردارەکە شکستیهێنا</string>
|
||||||
|
<string name="amoled">ڕەش</string>
|
||||||
|
<string name="dark">تاریک</string>
|
||||||
|
<string name="address">ناونیشان</string>
|
||||||
|
<string name="always">هەمووکات</string>
|
||||||
|
</resources>
|
@ -78,8 +78,6 @@
|
|||||||
<string name="license">Licence</string>
|
<string name="license">Licence</string>
|
||||||
<string name="license_FORMAT">%s licence</string>
|
<string name="license_FORMAT">%s licence</string>
|
||||||
<string name="links">Odkazy</string>
|
<string name="links">Odkazy</string>
|
||||||
<string name="list_animation">List Animací</string>
|
|
||||||
<string name="list_animation_description">Zobrazit animaci listu na hlavní stránce</string>
|
|
||||||
<string name="merging_FORMAT">Slučování %s</string>
|
<string name="merging_FORMAT">Slučování %s</string>
|
||||||
<string name="name">Název</string>
|
<string name="name">Název</string>
|
||||||
<string name="network_error_DESC">Chyba sítě</string>
|
<string name="network_error_DESC">Chyba sítě</string>
|
||||||
@ -110,14 +108,10 @@
|
|||||||
<string name="promotes_non_free_software">Propaguje ne-svobodný software</string>
|
<string name="promotes_non_free_software">Propaguje ne-svobodný software</string>
|
||||||
<string name="provided_by_FORMAT">Poskytuje %s</string>
|
<string name="provided_by_FORMAT">Poskytuje %s</string>
|
||||||
<string name="proxy">Proxy</string>
|
<string name="proxy">Proxy</string>
|
||||||
<string name="repository_not_used_DESC">Tento zdroj zatím použit. Zapněte jej pro zobrazení aplikací na něm.</string>
|
|
||||||
<string name="repository_unsigned_DESC">Nepodepsáno. Nezdařilo se ověřit seznam aplikací. Buďte opatrní při stahování aplikací z nepodepsaných zdrojů.</string>
|
<string name="repository_unsigned_DESC">Nepodepsáno. Nezdařilo se ověřit seznam aplikací. Buďte opatrní při stahování aplikací z nepodepsaných zdrojů.</string>
|
||||||
<string name="requires_FORMAT">Vyžaduje %s</string>
|
<string name="requires_FORMAT">Vyžaduje %s</string>
|
||||||
<string name="root_permission">Tichá instalace</string>
|
|
||||||
<string name="root_permission_description">Povolit root oprávnění pro tiché instalace</string>
|
|
||||||
<string name="save">Uložit</string>
|
<string name="save">Uložit</string>
|
||||||
<string name="saving_details">Ukládám detaily…</string>
|
<string name="saving_details">Ukládám detaily…</string>
|
||||||
<string name="screenshots">Snímky obrazovky</string>
|
|
||||||
<string name="search">Hledat</string>
|
<string name="search">Hledat</string>
|
||||||
<string name="share">Sdílet</string>
|
<string name="share">Sdílet</string>
|
||||||
<string name="show_more">Zobrazit více</string>
|
<string name="show_more">Zobrazit více</string>
|
||||||
@ -137,7 +131,6 @@
|
|||||||
<string name="syncing_FORMAT">Synchronizuji %s…</string>
|
<string name="syncing_FORMAT">Synchronizuji %s…</string>
|
||||||
<string name="system">Systém</string>
|
<string name="system">Systém</string>
|
||||||
<string name="tap_to_install_DESC">Klikněte pro instalaci.</string>
|
<string name="tap_to_install_DESC">Klikněte pro instalaci.</string>
|
||||||
<string name="target">Cíl</string>
|
|
||||||
<string name="theme">Téma</string>
|
<string name="theme">Téma</string>
|
||||||
<string name="themes">Témata</string>
|
<string name="themes">Témata</string>
|
||||||
<string name="tracks_or_reports_your_activity">Sleduje nebo hlásí vaší aktivitu</string>
|
<string name="tracks_or_reports_your_activity">Sleduje nebo hlásí vaší aktivitu</string>
|
||||||
@ -145,9 +138,7 @@
|
|||||||
<string name="unknown">Neznámé</string>
|
<string name="unknown">Neznámé</string>
|
||||||
<string name="unknown_error_DESC">Neznámá chyba.</string>
|
<string name="unknown_error_DESC">Neznámá chyba.</string>
|
||||||
<string name="unknown_FORMAT">Neznámé: %s</string>
|
<string name="unknown_FORMAT">Neznámé: %s</string>
|
||||||
<string name="unsigned">Nepodepsáno</string>
|
|
||||||
<string name="unstable_updates">Nestabilní aktualizace</string>
|
<string name="unstable_updates">Nestabilní aktualizace</string>
|
||||||
<string name="unverified">Neověřeno</string>
|
|
||||||
<string name="update">Aktualizovat</string>
|
<string name="update">Aktualizovat</string>
|
||||||
<string name="updates">Aktualizace</string>
|
<string name="updates">Aktualizace</string>
|
||||||
<string name="upstream_source_code_is_not_free">Originální zdrojový kód není svobodný</string>
|
<string name="upstream_source_code_is_not_free">Originální zdrojový kód není svobodný</string>
|
||||||
@ -163,12 +154,7 @@
|
|||||||
<string name="prefs_language_title">Jazyk</string>
|
<string name="prefs_language_title">Jazyk</string>
|
||||||
<string name="prefs_personalization">Personalizace</string>
|
<string name="prefs_personalization">Personalizace</string>
|
||||||
<string name="show_less">Zobrazit méně</string>
|
<string name="show_less">Zobrazit méně</string>
|
||||||
<string name="latest">Nejnovější</string>
|
|
||||||
<string name="explore">Prozkoumat</string>
|
|
||||||
<string name="update_all">Aktualizovat vše</string>
|
<string name="update_all">Aktualizovat vše</string>
|
||||||
<string name="installed_applications">Instalované aplikace</string>
|
|
||||||
<string name="sort_filter">Třídit & Filtrovat</string>
|
|
||||||
<string name="new_applications">Nové aplikace</string>
|
|
||||||
<string name="action_failed">Akce se nezdařila</string>
|
<string name="action_failed">Akce se nezdařila</string>
|
||||||
<string name="all_applications">Všechny aplikace</string>
|
<string name="all_applications">Všechny aplikace</string>
|
||||||
<string name="amoled">Černá</string>
|
<string name="amoled">Černá</string>
|
||||||
@ -194,12 +180,8 @@
|
|||||||
<item quantity="other">hodin</item>
|
<item quantity="other">hodin</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="cleanup_title">Interval čištění APK</string>
|
<string name="cleanup_title">Interval čištění APK</string>
|
||||||
<string name="cleanup_description">Období pro kontrolu a odstranění stažených souborů</string>
|
|
||||||
<string name="only_on_wifi_with_charging">Pouze na Wi-Fi a při nabíjení</string>
|
<string name="only_on_wifi_with_charging">Pouze na Wi-Fi a při nabíjení</string>
|
||||||
<string name="io_error_DESC">Nepodařilo se vykonat některé akce.</string>
|
<string name="io_error_DESC">Nepodařilo se vykonat některé akce.</string>
|
||||||
<string name="no_internet">Nejste připojeni k internetu</string>
|
|
||||||
<string name="allow_collapsing_toolbar">Povolení rozšíření horního panelu aplikací</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">Povolení rozbalování a sbalování horního panelu aplikace</string>
|
|
||||||
<string name="material_you_desc">Použít barevný motiv Material You</string>
|
<string name="material_you_desc">Použít barevný motiv Material You</string>
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="favourites">Oblíbené</string>
|
<string name="favourites">Oblíbené</string>
|
||||||
@ -207,7 +189,6 @@
|
|||||||
<string name="force_clean_up">Vynutit vyčištění</string>
|
<string name="force_clean_up">Vynutit vyčištění</string>
|
||||||
<string name="repository_unreachable">Repozitář nedostupný</string>
|
<string name="repository_unreachable">Repozitář nedostupný</string>
|
||||||
<string name="enable_repo">Povolit repozitář</string>
|
<string name="enable_repo">Povolit repozitář</string>
|
||||||
<string name="restart_app">Pro zobrazení změn restartujte Droid-ify</string>
|
|
||||||
<string name="waiting_to_start_installation">Čekání na spuštění instalace…</string>
|
<string name="waiting_to_start_installation">Čekání na spuštění instalace…</string>
|
||||||
<string name="installing">Instalace</string>
|
<string name="installing">Instalace</string>
|
||||||
<string name="auto_update">Automatická aktualizace aplikací</string>
|
<string name="auto_update">Automatická aktualizace aplikací</string>
|
||||||
@ -221,7 +202,6 @@
|
|||||||
<string name="special_credits">Speciální poděkování</string>
|
<string name="special_credits">Speciální poděkování</string>
|
||||||
<string name="home_screen_swiping">Posouvání na domovské stránce</string>
|
<string name="home_screen_swiping">Posouvání na domovské stránce</string>
|
||||||
<string name="home_screen_swiping_DESC">Umožnit uživateli posouvat mezi stránkami na domovské stránce</string>
|
<string name="home_screen_swiping_DESC">Umožnit uživateli posouvat mezi stránkami na domovské stránce</string>
|
||||||
<string name="label_copy">Kopírovat</string>
|
|
||||||
<string name="repository_not_found">Následující repozitář nebyl nalezen</string>
|
<string name="repository_not_found">Následující repozitář nebyl nalezen</string>
|
||||||
<string name="proxy_port_error_not_int">Port proxy smí být pouze celé číslo</string>
|
<string name="proxy_port_error_not_int">Port proxy smí být pouze celé číslo</string>
|
||||||
<string name="import_settings_title">Importovat nastavení</string>
|
<string name="import_settings_title">Importovat nastavení</string>
|
||||||
@ -245,4 +225,14 @@
|
|||||||
<string name="uninstalled_application">Odinstalováno</string>
|
<string name="uninstalled_application">Odinstalováno</string>
|
||||||
<string name="insufficient_storage">Nedostatek místa</string>
|
<string name="insufficient_storage">Nedostatek místa</string>
|
||||||
<string name="insufficient_storage_DESC">Na zařízení není dostatek místa k instalaci této aplikace. Zkuste uvolnit trochu místa</string>
|
<string name="insufficient_storage_DESC">Na zařízení není dostatek místa k instalaci této aplikace. Zkuste uvolnit trochu místa</string>
|
||||||
</resources>
|
<string name="error_shizuku_service_unavailable">Shizuku není spuštěno</string>
|
||||||
|
<string name="error_shizuku_not_granted">Chybějící oprávnění Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_granted_DESC">Nebylo uděleno oprávnění ke službě Shizuku. Zkontrolujte prosím aplikaci Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">Aplikace Shizuku nejspíše není nainstalována</string>
|
||||||
|
<string name="switch_to_default_installer">Přepnout na výchozí</string>
|
||||||
|
<string name="label_unknown_sdk">Neznámé (%d)</string>
|
||||||
|
<string name="error_shizuku_not_running_DESC">Služba Shizuku není spuštěna. Zkontrolujte prosím aplikaci Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_installed">Shizuku není nainstalováno</string>
|
||||||
|
<string name="label_open_video">Video</string>
|
||||||
|
<string name="open_shizuku">Otevřít Shizuku</string>
|
||||||
|
</resources>
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
<string name="cancel">Annuller</string>
|
<string name="cancel">Annuller</string>
|
||||||
<string name="add_repository">Tilføj repository</string>
|
<string name="add_repository">Tilføj repository</string>
|
||||||
<string name="address">Adresse</string>
|
<string name="address">Adresse</string>
|
||||||
<string name="allow_collapsing_toolbar">Lad øverste app-linje udvide sig</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">Lad øverste app-linje udvide og skjule sig</string>
|
|
||||||
<string name="anti_features">Anti-funktioner</string>
|
<string name="anti_features">Anti-funktioner</string>
|
||||||
<string name="author_email">Udviklerens e-mail</string>
|
<string name="author_email">Udviklerens e-mail</string>
|
||||||
<string name="author_website">Udviklerens hjemmeside</string>
|
<string name="author_website">Udviklerens hjemmeside</string>
|
||||||
@ -24,7 +22,6 @@
|
|||||||
<string name="changelog">Ændringslog</string>
|
<string name="changelog">Ændringslog</string>
|
||||||
<string name="changes">Ændringer</string>
|
<string name="changes">Ændringer</string>
|
||||||
<string name="cleanup_title">APK-oprydningsinterval</string>
|
<string name="cleanup_title">APK-oprydningsinterval</string>
|
||||||
<string name="cleanup_description">Periodisk kontrol og fjernelse af hentede filer</string>
|
|
||||||
<string name="confirmation">Bekræftelse</string>
|
<string name="confirmation">Bekræftelse</string>
|
||||||
<string name="connecting">Forbinder…</string>
|
<string name="connecting">Forbinder…</string>
|
||||||
<string name="contains_non_free_media">Indeholder ikke-frie medier</string>
|
<string name="contains_non_free_media">Indeholder ikke-frie medier</string>
|
||||||
@ -42,10 +39,10 @@
|
|||||||
<string name="downloaded_FORMAT">Hentet %s</string>
|
<string name="downloaded_FORMAT">Hentet %s</string>
|
||||||
<string name="downloading">Henter</string>
|
<string name="downloading">Henter</string>
|
||||||
<string name="downloading_FORMAT">Henter %s…</string>
|
<string name="downloading_FORMAT">Henter %s…</string>
|
||||||
<string name="import_export">Import/Eksport</string>
|
<string name="import_export">Import/eksport</string>
|
||||||
<string name="import_settings_title">Importér Indstillinger</string>
|
<string name="import_settings_title">Importér indstillinger</string>
|
||||||
<string name="import_settings_DESC">Importér indstillinger og favoritter fra fil</string>
|
<string name="import_settings_DESC">Importér indstillinger og favoritter fra fil</string>
|
||||||
<string name="export_settings_title">Eksportér Indstillinger</string>
|
<string name="export_settings_title">Eksportér indstillinger</string>
|
||||||
<string name="favourites">Favoritter</string>
|
<string name="favourites">Favoritter</string>
|
||||||
<string name="file_format_error_DESC">Ugyldigt filformat.</string>
|
<string name="file_format_error_DESC">Ugyldigt filformat.</string>
|
||||||
<string name="fingerprint">Fingeraftryk</string>
|
<string name="fingerprint">Fingeraftryk</string>
|
||||||
@ -63,8 +60,8 @@
|
|||||||
<string name="connection_error_DESC">Kunne ikke forbinde til server</string>
|
<string name="connection_error_DESC">Kunne ikke forbinde til server</string>
|
||||||
<string name="ignore_all_updates">Ignorer alle nye versioner</string>
|
<string name="ignore_all_updates">Ignorer alle nye versioner</string>
|
||||||
<string name="incompatible_api_DESC_FORMAT">Din %1$s (API-version %2$d) understøttes ikke. %3$s</string>
|
<string name="incompatible_api_DESC_FORMAT">Din %1$s (API-version %2$d) understøttes ikke. %3$s</string>
|
||||||
<string name="incompatible_api_max_DESC_FORMAT">Maksimal API-version er %d.</string>
|
<string name="incompatible_api_max_DESC_FORMAT">Maks. API-version er %d.</string>
|
||||||
<string name="incompatible_api_min_DESC_FORMAT">Minimum API-version er %d.</string>
|
<string name="incompatible_api_min_DESC_FORMAT">Min. API-version er %d.</string>
|
||||||
<string name="incompatible_features_DESC">Manglende funktioner.</string>
|
<string name="incompatible_features_DESC">Manglende funktioner.</string>
|
||||||
<string name="incompatible_older_DESC">Denne version er ældre end den, der er installeret på din enhed. Afinstaller den først.</string>
|
<string name="incompatible_older_DESC">Denne version er ældre end den, der er installeret på din enhed. Afinstaller den først.</string>
|
||||||
<string name="incompatible_version">Inkompatibel version</string>
|
<string name="incompatible_version">Inkompatibel version</string>
|
||||||
@ -74,7 +71,7 @@
|
|||||||
<string name="install">Installer</string>
|
<string name="install">Installer</string>
|
||||||
<string name="install_types">Installationstyper</string>
|
<string name="install_types">Installationstyper</string>
|
||||||
<string name="installer">Installatør</string>
|
<string name="installer">Installatør</string>
|
||||||
<string name="shizuku_installer">Shizuku Installatør</string>
|
<string name="shizuku_installer">Shizuku-installatør</string>
|
||||||
<string name="shizuku_not_alive">Shizuku kører ikke</string>
|
<string name="shizuku_not_alive">Shizuku kører ikke</string>
|
||||||
<string name="shizuku_not_installed">Shizuku er ikke installeret</string>
|
<string name="shizuku_not_installed">Shizuku er ikke installeret</string>
|
||||||
<string name="installing">Installerer</string>
|
<string name="installing">Installerer</string>
|
||||||
@ -83,19 +80,17 @@
|
|||||||
<string name="invalid_fingerprint_format">Ugyldigt fingeraftryksformat</string>
|
<string name="invalid_fingerprint_format">Ugyldigt fingeraftryksformat</string>
|
||||||
<string name="invalid_username_format">Ugyldigt brugernavnsformat</string>
|
<string name="invalid_username_format">Ugyldigt brugernavnsformat</string>
|
||||||
<string name="io_error_DESC">Kan ikke udføre visse handlinger.</string>
|
<string name="io_error_DESC">Kan ikke udføre visse handlinger.</string>
|
||||||
<string name="label_copy">Kopiér</string>
|
|
||||||
<string name="launch">Start</string>
|
<string name="launch">Start</string>
|
||||||
<string name="license">Licens</string>
|
<string name="license">Licens</string>
|
||||||
<string name="license_FORMAT">%s licens</string>
|
<string name="license_FORMAT">%s licens</string>
|
||||||
<string name="light">Lys</string>
|
<string name="light">Lys</string>
|
||||||
<string name="link_copied_to_clipboard">Link kopieret</string>
|
<string name="link_copied_to_clipboard">Link kopieret</string>
|
||||||
<string name="links">Links</string>
|
<string name="links">Links</string>
|
||||||
<string name="list_animation">Listeanimationer</string>
|
<string name="home_screen_swiping">Strygning på startside</string>
|
||||||
<string name="home_screen_swiping">Strygning på Startskærm</string>
|
|
||||||
<string name="socket_error_DESC">Server kunne ikke levere ny pakke.</string>
|
<string name="socket_error_DESC">Server kunne ikke levere ny pakke.</string>
|
||||||
<string name="http_proxy">HTTP-proxy</string>
|
<string name="http_proxy">HTTP-proxy</string>
|
||||||
<string name="incompatible_platforms_DESC_FORMAT">Din %1$s platform understøttes ikke. Understøttede platforme: %2$s.</string>
|
<string name="incompatible_platforms_DESC_FORMAT">Din %1$s platform understøttes ikke. Understøttede platforme: %2$s.</string>
|
||||||
<string name="root_installer">Root Installatør</string>
|
<string name="root_installer">Root-installatør</string>
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="material_you_desc">Brug Material You-farvetema</string>
|
<string name="material_you_desc">Brug Material You-farvetema</string>
|
||||||
<string name="merging_FORMAT">Fletter %s</string>
|
<string name="merging_FORMAT">Fletter %s</string>
|
||||||
@ -110,7 +105,6 @@
|
|||||||
<string name="no_applications_available">Ingen tilgængelige applikationer</string>
|
<string name="no_applications_available">Ingen tilgængelige applikationer</string>
|
||||||
<string name="no_applications_installed">Ingen installerede applikationer</string>
|
<string name="no_applications_installed">Ingen installerede applikationer</string>
|
||||||
<string name="no_description_available_DESC">Ingen beskrivelse tilgængelig</string>
|
<string name="no_description_available_DESC">Ingen beskrivelse tilgængelig</string>
|
||||||
<string name="no_internet">Du har ingen internetforbindelse</string>
|
|
||||||
<string name="no_matching_applications_found">Kunne ikke finde sådanne applikationer</string>
|
<string name="no_matching_applications_found">Kunne ikke finde sådanne applikationer</string>
|
||||||
<string name="no_proxy">Ingen proxy</string>
|
<string name="no_proxy">Ingen proxy</string>
|
||||||
<string name="notify_about_updates">Underret om opdateringer</string>
|
<string name="notify_about_updates">Underret om opdateringer</string>
|
||||||
@ -119,10 +113,10 @@
|
|||||||
<string name="ok">OK</string>
|
<string name="ok">OK</string>
|
||||||
<string name="only_compatible_with_FORMAT">Kun kompatibel med %s</string>
|
<string name="only_compatible_with_FORMAT">Kun kompatibel med %s</string>
|
||||||
<string name="only_on_wifi">Kun på Wi-Fi</string>
|
<string name="only_on_wifi">Kun på Wi-Fi</string>
|
||||||
<string name="only_on_wifi_with_charging">Kun på Wi-Fi & Opladning</string>
|
<string name="only_on_wifi_with_charging">Kun på Wi-Fi og opladning</string>
|
||||||
<string name="open_DESC_FORMAT">Åbn %s?</string>
|
<string name="open_DESC_FORMAT">Åbn %s?</string>
|
||||||
<string name="other">Andet</string>
|
<string name="other">Andet</string>
|
||||||
<string name="parsing_index_error_DESC">Kunne ikke analysere indeksfilen.</string>
|
<string name="parsing_index_error_DESC">Kunne ikke fortolke indeksfilen.</string>
|
||||||
<string name="password">Adgangskode</string>
|
<string name="password">Adgangskode</string>
|
||||||
<string name="password_missing">Manglende adgangskode</string>
|
<string name="password_missing">Manglende adgangskode</string>
|
||||||
<string name="plus_more_FORMAT">+%d mere</string>
|
<string name="plus_more_FORMAT">+%d mere</string>
|
||||||
@ -136,10 +130,8 @@
|
|||||||
<string name="proxy_port_error_not_int">Proxyport kan kun være et heltal</string>
|
<string name="proxy_port_error_not_int">Proxyport kan kun være et heltal</string>
|
||||||
<string name="proxy_type">Proxytype</string>
|
<string name="proxy_type">Proxytype</string>
|
||||||
<string name="requires_FORMAT">Kræver %s</string>
|
<string name="requires_FORMAT">Kræver %s</string>
|
||||||
<string name="restart_app">Genstart Droid-ify for at se ændringer</string>
|
|
||||||
<string name="save">Gem</string>
|
<string name="save">Gem</string>
|
||||||
<string name="saving_details">Gemmer detaljer…</string>
|
<string name="saving_details">Gemmer detaljer…</string>
|
||||||
<string name="screenshots">Skærmbilleder</string>
|
|
||||||
<string name="settings">Indstillinger</string>
|
<string name="settings">Indstillinger</string>
|
||||||
<string name="share">Del</string>
|
<string name="share">Del</string>
|
||||||
<string name="signed_using_unsafe_algorithm">Signeret med en usikker algoritme</string>
|
<string name="signed_using_unsafe_algorithm">Signeret med en usikker algoritme</string>
|
||||||
@ -153,26 +145,20 @@
|
|||||||
<string name="themes">Temaer</string>
|
<string name="themes">Temaer</string>
|
||||||
<string name="tracks_or_reports_your_activity">Sporer eller rapporterer din aktivitet</string>
|
<string name="tracks_or_reports_your_activity">Sporer eller rapporterer din aktivitet</string>
|
||||||
<string name="repositories">Repositories</string>
|
<string name="repositories">Repositories</string>
|
||||||
<string name="repository_not_used_DESC">Dette repository er ikke blevet brugt endnu. Slå det til for at se applikationer i den.</string>
|
|
||||||
<string name="repository_not_found">Følgende repository blev ikke fundet</string>
|
<string name="repository_not_found">Følgende repository blev ikke fundet</string>
|
||||||
<string name="repository_unsigned_DESC">Usigneret. Kunne ikke verificere applikationslisten. Vær forsigtig med at hente applikationer fra usignerede repositories.</string>
|
<string name="repository_unsigned_DESC">Usigneret. Kunne ikke verificere applikationslisten. Vær forsigtig med at hente applikationer fra usignerede repositories.</string>
|
||||||
<string name="repository_unreachable">Repository utilgængeligt</string>
|
<string name="repository_unreachable">Repository utilgængeligt</string>
|
||||||
<string name="root_permission">Stille Installation</string>
|
|
||||||
<string name="root_permission_description">Tillad root for stille installationer</string>
|
|
||||||
<string name="select_mirror">Vælg et mirror</string>
|
<string name="select_mirror">Vælg et mirror</string>
|
||||||
<string name="socks_proxy">SOCKS-proxy</string>
|
<string name="socks_proxy">SOCKS-proxy</string>
|
||||||
<string name="sync_repositories">Synkroniser repositories</string>
|
<string name="sync_repositories">Synkroniser repositories</string>
|
||||||
<string name="sync_repositories_automatically">Synkroniser repositories automatisk</string>
|
<string name="sync_repositories_automatically">Synkroniser repositories automatisk</string>
|
||||||
<string name="target">Mål</string>
|
|
||||||
<string name="repository">Repository</string>
|
<string name="repository">Repository</string>
|
||||||
<string name="uninstall">Afinstaller</string>
|
<string name="uninstall">Afinstaller</string>
|
||||||
<string name="unknown">Ukendt</string>
|
<string name="unknown">Ukendt</string>
|
||||||
<string name="unknown_error_DESC">Ukendt fejl.</string>
|
<string name="unknown_error_DESC">Ukendt fejl.</string>
|
||||||
<string name="unknown_FORMAT">Ukendt: %s</string>
|
<string name="unknown_FORMAT">Ukendt: %s</string>
|
||||||
<string name="unsigned">Usigneret</string>
|
|
||||||
<string name="unstable_updates">Ustabile opdateringer</string>
|
<string name="unstable_updates">Ustabile opdateringer</string>
|
||||||
<string name="unstable_updates_summary">Foreslå at installere ustabile versioner</string>
|
<string name="unstable_updates_summary">Foreslå at installere ustabile versioner</string>
|
||||||
<string name="unverified">Ikke verificeret</string>
|
|
||||||
<string name="upstream_source_code_is_not_free">Den oprindelige kildekode er ikke gratis</string>
|
<string name="upstream_source_code_is_not_free">Den oprindelige kildekode er ikke gratis</string>
|
||||||
<string name="username">Brugernavn</string>
|
<string name="username">Brugernavn</string>
|
||||||
<string name="username_missing">Manglende brugernavn</string>
|
<string name="username_missing">Manglende brugernavn</string>
|
||||||
@ -187,18 +173,13 @@
|
|||||||
<string name="prefs_language_title">Sprog</string>
|
<string name="prefs_language_title">Sprog</string>
|
||||||
<string name="prefs_personalization">Personalisering</string>
|
<string name="prefs_personalization">Personalisering</string>
|
||||||
<string name="show_less">Vis mindre</string>
|
<string name="show_less">Vis mindre</string>
|
||||||
<string name="latest">Seneste</string>
|
|
||||||
<string name="explore">Udforsk</string>
|
|
||||||
<string name="update_all">Opdater alle</string>
|
<string name="update_all">Opdater alle</string>
|
||||||
<string name="installed_applications">Installerede applikationer</string>
|
|
||||||
<string name="sort_filter">Sortér & Filtrér</string>
|
|
||||||
<string name="new_applications">Nye applikationer</string>
|
|
||||||
<string name="updates">Opdateringer</string>
|
<string name="updates">Opdateringer</string>
|
||||||
<string name="donate">Donér</string>
|
<string name="donate">Donér</string>
|
||||||
<string name="export_settings_DESC">Eksportér indstillinger og favoritter til fil</string>
|
<string name="export_settings_DESC">Eksportér indstillinger og favoritter til fil</string>
|
||||||
<string name="has_non_free_components">Har ikke-frie komponenter</string>
|
<string name="has_non_free_components">Har ikke-frie komponenter</string>
|
||||||
<string name="has_tethered_network">Bundet til en bestemt netværkstjeneste</string>
|
<string name="has_tethered_network">Bundet til en bestemt netværkstjeneste</string>
|
||||||
<string name="home_screen_swiping_DESC">Tillad at stryge mellem sider på startskærm</string>
|
<string name="home_screen_swiping_DESC">Tillad at stryge mellem sider på startside</string>
|
||||||
<string name="ignore_this_update">Ignorer denne version</string>
|
<string name="ignore_this_update">Ignorer denne version</string>
|
||||||
<string name="incompatible_signature_DESC">Denne version er signeret med et andet certifikat end den, der er installeret på din enhed. Afinstaller den først.</string>
|
<string name="incompatible_signature_DESC">Denne version er signeret med et andet certifikat end den, der er installeret på din enhed. Afinstaller den først.</string>
|
||||||
<string name="installed">Installeret</string>
|
<string name="installed">Installeret</string>
|
||||||
@ -220,26 +201,35 @@
|
|||||||
<string name="compiled_for_debugging">Kompileret til fejlfinding</string>
|
<string name="compiled_for_debugging">Kompileret til fejlfinding</string>
|
||||||
<string name="delete_repository_DESC">Slet repositoriet?</string>
|
<string name="delete_repository_DESC">Slet repositoriet?</string>
|
||||||
<string name="edit_repository">Rediger repository</string>
|
<string name="edit_repository">Rediger repository</string>
|
||||||
<string name="import_repos_title">Importér Repositories</string>
|
<string name="import_repos_title">Importér repositories</string>
|
||||||
<string name="import_repos_DESC">Importér alle repositories fra fil</string>
|
<string name="import_repos_DESC">Importér alle repositories fra fil</string>
|
||||||
<string name="export_repos_title">Eksportér Repositories</string>
|
<string name="export_repos_title">Eksportér repositories</string>
|
||||||
<string name="export_repos_DESC">Eksportér alle repositories til fil</string>
|
<string name="export_repos_DESC">Eksportér alle repositories til fil</string>
|
||||||
<string name="enable_repo">Aktivér repositoriet</string>
|
<string name="enable_repo">Aktivér repositoriet</string>
|
||||||
<string name="credits">Krediteringer</string>
|
<string name="credits">Krediteringer</string>
|
||||||
<string name="update">Opdatering</string>
|
<string name="update">Opdatering</string>
|
||||||
<string name="list_animation_description">Vis listeanimation på hovedsiden</string>
|
|
||||||
<string name="require_background_access_DESC">Baggrundsadgang er nødvendig for at køre baggrundssynkronisering korrekt</string>
|
<string name="require_background_access_DESC">Baggrundsadgang er nødvendig for at køre baggrundssynkronisering korrekt</string>
|
||||||
<string name="require_background_access">Kræver Baggrundsadgang</string>
|
<string name="require_background_access">Kræver baggrundsadgang</string>
|
||||||
<string name="legacy_installer">Ældre Installatør</string>
|
<string name="legacy_installer">Ældre installatør</string>
|
||||||
<string name="session_installer">Session Installatør</string>
|
<string name="session_installer">Sessionsinstallatør</string>
|
||||||
<string name="special_credits">Særlige Krediteringer</string>
|
<string name="special_credits">Særlige Krediteringer</string>
|
||||||
<string name="contains_nsfw">Indeholder potentielt stødende indhold</string>
|
<string name="contains_nsfw">Indeholder potentielt stødende indhold</string>
|
||||||
<string name="ignore_signature_summary">*Advarsel* Ignorer signaturverifikation ved APK-installation; for LSPosed- eller avancerede brugere</string>
|
<string name="ignore_signature_summary">*Advarsel* Ignorer signaturverifikation ved APK-installation. For LSPosed- eller avancerede brugere</string>
|
||||||
<string name="installation_failed">Installation Mislykkedes</string>
|
<string name="installation_failed">Installation mislykkedes</string>
|
||||||
<string name="installation_failed_DESC">Kunne ikke installere %s</string>
|
<string name="installation_failed_DESC">Kunne ikke installere %s</string>
|
||||||
<string name="uninstalled_application">Afinstalleret</string>
|
<string name="uninstalled_application">Afinstalleret</string>
|
||||||
<string name="uninstalled_application_DESC">%s blev afinstalleret</string>
|
<string name="uninstalled_application_DESC">%s blev afinstalleret</string>
|
||||||
<string name="ignore_signature">Ignorer Signatur</string>
|
<string name="ignore_signature">Ignorer signatur</string>
|
||||||
<string name="insufficient_storage">Utilstrækkelig plads</string>
|
<string name="insufficient_storage">Utilstrækkelig plads</string>
|
||||||
<string name="insufficient_storage_DESC">Enheden har ikke nok ledig plads til at installere denne applikation. Prøv at frigøre noget plads</string>
|
<string name="insufficient_storage_DESC">Enheden har ikke nok ledig plads til at installere denne applikation. Prøv at frigøre noget plads</string>
|
||||||
</resources>
|
<string name="error_shizuku_not_running_DESC">Shizuku-tjenesten kører ikke. Tjek venligst i Shizuku-appen</string>
|
||||||
|
<string name="error_shizuku_not_granted">Shizuku-tilladelse mangler</string>
|
||||||
|
<string name="error_shizuku_not_granted_DESC">Shizuku-tilladelse er ikke givet. Tjek venligst i Shizuku-appen</string>
|
||||||
|
<string name="error_shizuku_not_installed">Shizuku ikke installeret</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">Shizuku ser ikke ud til at være installeret</string>
|
||||||
|
<string name="open_shizuku">Åbn Shizuku</string>
|
||||||
|
<string name="label_unknown_sdk">Ukendt (%d)</string>
|
||||||
|
<string name="switch_to_default_installer">Skift til standard</string>
|
||||||
|
<string name="label_open_video">Video</string>
|
||||||
|
<string name="error_shizuku_service_unavailable">Shizuku kører ikke</string>
|
||||||
|
</resources>
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="add_repository">Repository hinzufügen</string>
|
<string name="add_repository">Paketquelle hinzufügen</string>
|
||||||
<string name="all_applications">Alle Anwendungen</string>
|
<string name="all_applications">Alle Apps</string>
|
||||||
<string name="all_applications_up_to_date">All deine Anwendungen sind aktuell</string>
|
<string name="all_applications_up_to_date">Alle Apps sind aktuell</string>
|
||||||
<string name="already_exists">Bereits vorhanden</string>
|
<string name="already_exists">Bereits vorhanden</string>
|
||||||
<string name="always">Immer</string>
|
<string name="always">Immer</string>
|
||||||
<string name="address">Adresse</string>
|
<string name="address">Adresse</string>
|
||||||
<string name="action_failed">Vorgang fehlgeschlagen</string>
|
<string name="action_failed">Vorgang fehlgeschlagen</string>
|
||||||
<string name="amoled">Schwarz</string>
|
<string name="amoled">Schwarz</string>
|
||||||
<string name="application">Anwendung</string>
|
<string name="application">App</string>
|
||||||
<string name="anti_features">Unerwünschte Merkmale</string>
|
<string name="anti_features">Unerwünschte Merkmale</string>
|
||||||
<string name="available">Entdecken</string>
|
<string name="available">Entdecken</string>
|
||||||
<string name="cancel">Abbrechen</string>
|
<string name="cancel">Abbrechen</string>
|
||||||
<string name="application_not_found">Diese Anwendung konnte nicht gefunden werden</string>
|
<string name="application_not_found">App konnte nicht gefunden werden</string>
|
||||||
<string name="bug_tracker">Fehlerverwaltung</string>
|
<string name="bug_tracker">Fehlerverwaltung</string>
|
||||||
<string name="changelog">Änderungsprotokoll</string>
|
<string name="changelog">Änderungsprotokoll</string>
|
||||||
<string name="cant_edit_sync_DESC">Die Paketquelle kann nicht bearbeitet werden, da sie gerade synchronisiert wird.</string>
|
<string name="cant_edit_sync_DESC">Die Paketquelle kann nicht bearbeitet werden, da sie gerade synchronisiert wird.</string>
|
||||||
<string name="checking_repository">Paketquelle wird abgefragt …</string>
|
<string name="checking_repository">Paketquelle wird abgefragt …</string>
|
||||||
<string name="compiled_for_debugging">Kompiliert für die Fehlersuche</string>
|
<string name="compiled_for_debugging">Kompiliert für die Fehlersuche</string>
|
||||||
<string name="connecting">Verbinde …</string>
|
<string name="connecting">Wird verbunden …</string>
|
||||||
<string name="confirmation">Bestätigung</string>
|
<string name="confirmation">Bestätigung</string>
|
||||||
<string name="could_not_validate_FORMAT">Konnte %s nicht validieren</string>
|
<string name="could_not_validate_FORMAT">%s konnte nicht überprüft werden</string>
|
||||||
<string name="dark">Dunkel</string>
|
<string name="dark">Dunkel</string>
|
||||||
<string name="contains_non_free_media">Enthält nicht-freie Medien</string>
|
<string name="contains_non_free_media">Enthält nicht-freie Medien</string>
|
||||||
<string name="credits">Mitwirkende</string>
|
<string name="credits">Mitwirkende</string>
|
||||||
@ -37,146 +37,132 @@
|
|||||||
<string name="incompatible_features_DESC">Fehlende Funktionen.</string>
|
<string name="incompatible_features_DESC">Fehlende Funktionen.</string>
|
||||||
<string name="incompatible_platforms_DESC_FORMAT">Deine %1$s-Plattform wird nicht unterstützt. Unterstützte Plattformen: %2$s.</string>
|
<string name="incompatible_platforms_DESC_FORMAT">Deine %1$s-Plattform wird nicht unterstützt. Unterstützte Plattformen: %2$s.</string>
|
||||||
<string name="installed">Installiert</string>
|
<string name="installed">Installiert</string>
|
||||||
<string name="incompatible_versions_summary">Mit dem Gerät inkompatible Anwendungsversionen anzeigen</string>
|
<string name="incompatible_versions_summary">Mit diesem Gerät inkompatible App-Versionen anzeigen</string>
|
||||||
<string name="install_types">Installationstypen</string>
|
<string name="install_types">Installationsarten</string>
|
||||||
<string name="install">Installieren</string>
|
<string name="install">Installieren</string>
|
||||||
<string name="integrity_check_error_DESC">Integrität konnte nicht überprüft werden.</string>
|
<string name="integrity_check_error_DESC">Integrität konnte nicht überprüft werden.</string>
|
||||||
<string name="invalid_metadata_error_DESC">Ungültige Metadaten.</string>
|
<string name="invalid_metadata_error_DESC">Ungültige Metadaten.</string>
|
||||||
<string name="invalid_signature_error_DESC">Ungültige Signatur.</string>
|
<string name="invalid_signature_error_DESC">Ungültige Signatur.</string>
|
||||||
<string name="launch">Öffnen</string>
|
<string name="launch">Öffnen</string>
|
||||||
<string name="light">Hell</string>
|
<string name="light">Hell</string>
|
||||||
<string name="list_animation_description">Listenanimation auf der Hauptseite anzeigen</string>
|
<string name="new_updates_available">Neue Versionen von Apps verfügbar</string>
|
||||||
<string name="new_updates_available">Neue Anwendungsversionen verfügbar</string>
|
|
||||||
<string name="never">Nie</string>
|
<string name="never">Nie</string>
|
||||||
<string name="network_error_DESC">Netzwerkfehler</string>
|
<string name="network_error_DESC">Netzwerkfehler</string>
|
||||||
<string name="notify_about_updates">Über neue Versionen benachrichtigen</string>
|
<string name="notify_about_updates">Update-Benachrichtigungen</string>
|
||||||
<string name="no_description_available_DESC">Keine Beschreibung vorhanden</string>
|
<string name="no_description_available_DESC">Keine Beschreibung vorhanden</string>
|
||||||
<string name="no_matching_applications_found">Keine derartigen Anwendungen konnten gefunden werden</string>
|
<string name="no_matching_applications_found">Keine derartigen Apps auffindbar</string>
|
||||||
<string name="no_applications_installed">Keine installierten Anwendungen</string>
|
<string name="no_applications_installed">Keine installierten Apps</string>
|
||||||
<string name="only_on_wifi">Nur bei Wi-Fi</string>
|
<string name="only_on_wifi">Nur mit WLAN</string>
|
||||||
<string name="open_DESC_FORMAT">Öffne %s\?</string>
|
<string name="open_DESC_FORMAT">%s öffnen?</string>
|
||||||
<string name="other">Andere</string>
|
<string name="other">Andere</string>
|
||||||
<string name="number_of_applications">Anzahl der Anwendungen</string>
|
<string name="number_of_applications">Anzahl der Apps</string>
|
||||||
<string name="ok">OK</string>
|
<string name="ok">OK</string>
|
||||||
<string name="permissions">Berechtigungen</string>
|
<string name="permissions">Berechtigungen</string>
|
||||||
<string name="plus_more_FORMAT">+%d mehr</string>
|
<string name="plus_more_FORMAT">+%d mehr</string>
|
||||||
<string name="settings">Einstellungen</string>
|
<string name="settings">Einstellungen</string>
|
||||||
<string name="processing_FORMAT">Verarbeitung %1$s …</string>
|
<string name="processing_FORMAT">%1$s wird verarbeitet …</string>
|
||||||
<string name="promotes_non_free_software">Bewirbt unfreie Software</string>
|
<string name="promotes_non_free_software">Bewirbt nicht-freie Software</string>
|
||||||
<string name="proxy">Proxy</string>
|
<string name="proxy">Proxy</string>
|
||||||
<string name="repositories">Paketquellen</string>
|
<string name="repositories">Paketquellen</string>
|
||||||
<string name="requires_FORMAT">Benötigt %s</string>
|
<string name="requires_FORMAT">Benötigt %s</string>
|
||||||
<string name="root_permission">Stumme Installation</string>
|
|
||||||
<string name="save">Speichern</string>
|
<string name="save">Speichern</string>
|
||||||
<string name="saving_details">Details werden gespeichert …</string>
|
<string name="saving_details">Details werden gespeichert …</string>
|
||||||
<string name="screenshots">Bildschirmfotos</string>
|
|
||||||
<string name="skip">Überspringen</string>
|
<string name="skip">Überspringen</string>
|
||||||
<string name="suggested">Empfohlen</string>
|
<string name="suggested">Empfohlen</string>
|
||||||
<string name="syncing">Synchronisierung</string>
|
<string name="syncing">Synchronisierung</string>
|
||||||
<string name="themes">Themen</string>
|
<string name="themes">Designs</string>
|
||||||
<string name="target">Ziel</string>
|
|
||||||
<string name="unknown">Unbekannt</string>
|
<string name="unknown">Unbekannt</string>
|
||||||
<string name="uninstall">Deinstallation</string>
|
<string name="uninstall">Deinstallieren</string>
|
||||||
<string name="unsigned">Unsigniert</string>
|
|
||||||
<string name="update">Aktualisierung</string>
|
<string name="update">Aktualisierung</string>
|
||||||
<string name="version">Version</string>
|
<string name="version">Version</string>
|
||||||
<string name="versions">Versionen</string>
|
<string name="versions">Versionen</string>
|
||||||
<string name="whats_new">Was gibt es Neues</string>
|
<string name="whats_new">Neu hinzugefügt</string>
|
||||||
<string name="waiting_to_start_download">Warten auf den Downloadbeginn …</string>
|
<string name="waiting_to_start_download">Warten auf den Start des Downloads …</string>
|
||||||
<string name="validation_index_error_DESC">Der Index konnte nicht validiert werden.</string>
|
<string name="validation_index_error_DESC">Der Index konnte nicht überprüft werden.</string>
|
||||||
<string name="website">Webseite</string>
|
<string name="website">Website</string>
|
||||||
<string name="changes">Änderungen</string>
|
<string name="changes">Änderungen</string>
|
||||||
<string name="author_email">Autor-E-Mail-Adresse</string>
|
<string name="author_email">E-Mail-Adresse</string>
|
||||||
<string name="could_not_download_FORMAT">Konnte %s nicht herunterladen</string>
|
<string name="could_not_download_FORMAT">%s konnte nicht heruntergeladen werden</string>
|
||||||
<string name="author_website">Autor-Webseite</string>
|
<string name="author_website">Website</string>
|
||||||
<string name="delete">Löschen</string>
|
<string name="delete">Löschen</string>
|
||||||
<string name="recently_updated">Zuletzt aktualisiert</string>
|
<string name="recently_updated">Kürzlich aktualisiert</string>
|
||||||
<string name="license">Lizenz</string>
|
<string name="license">Lizenz</string>
|
||||||
<string name="could_not_sync_FORMAT">Konnte %s nicht synchronisieren</string>
|
<string name="could_not_sync_FORMAT">%s konnte nicht synchronisiert werden</string>
|
||||||
<string name="only_compatible_with_FORMAT">Nur kompatibel mit %s</string>
|
<string name="only_compatible_with_FORMAT">Nur kompatibel mit %s</string>
|
||||||
<string name="license_FORMAT">%s-Lizenz</string>
|
<string name="license_FORMAT">%s-Lizenz</string>
|
||||||
<string name="link_copied_to_clipboard">Link kopiert</string>
|
<string name="link_copied_to_clipboard">Link kopiert</string>
|
||||||
<string name="project_website">Projekt-Website</string>
|
<string name="project_website">Website des Projekts</string>
|
||||||
<string name="proxy_type">Proxy Typ</string>
|
<string name="proxy_type">Proxy-Art</string>
|
||||||
<string name="repository">Paketquelle</string>
|
<string name="repository">Paketquelle</string>
|
||||||
<string name="parsing_index_error_DESC">Die Indexdatei konnte nicht geparst werden.</string>
|
<string name="parsing_index_error_DESC">Die Indexdatei konnte nicht geparst werden.</string>
|
||||||
<string name="password">Passwort</string>
|
<string name="password">Passwort</string>
|
||||||
<string name="notify_about_updates_summary">Eine Benachrichtigung anzeigen, wenn neue Versionen verfügbar sind</string>
|
<string name="notify_about_updates_summary">Benachrichtigung anzeigen, wenn neue Versionen verfügbar sind</string>
|
||||||
<string name="provided_by_FORMAT">Bereitgestellt von %s</string>
|
<string name="provided_by_FORMAT">Bereitgestellt von %s</string>
|
||||||
<string name="source_code_no_longer_available">Quellcode nicht mehr verfügbar</string>
|
<string name="source_code_no_longer_available">Quellcode nicht mehr verfügbar</string>
|
||||||
<string name="invalid_username_format">Ungültiges Benutzernamen-Format</string>
|
<string name="invalid_username_format">Ungültiges Format des Benutzernamens</string>
|
||||||
<string name="no_proxy">Kein Proxy</string>
|
<string name="no_proxy">Kein Proxy</string>
|
||||||
<string name="password_missing">Passwort fehlt</string>
|
<string name="password_missing">Passwort fehlt</string>
|
||||||
<string name="source_code">Quellcode</string>
|
<string name="source_code">Quellcode</string>
|
||||||
<string name="sync_repositories">Paketquellen synchronisieren</string>
|
<string name="sync_repositories">Paketquellen synchronisieren</string>
|
||||||
<string name="sync_repositories_automatically">Paketquellen automatisch synchronisieren</string>
|
<string name="sync_repositories_automatically">Paketquellen automatisch synchronisieren</string>
|
||||||
<string name="repository_not_used_DESC">Diese Paketquelle wurde noch nicht verwendet. Aktivieren Sie es, um die darin enthaltenen Anwendungen anzuzeigen.</string>
|
|
||||||
<string name="signature_FORMAT">Signatur %s</string>
|
<string name="signature_FORMAT">Signatur %s</string>
|
||||||
<string name="has_non_free_dependencies">Enthält nicht-freie Abhängigkeiten</string>
|
<string name="has_non_free_dependencies">Enthält nicht-freie Abhängigkeiten</string>
|
||||||
<string name="incompatible_version">Inkompatible Version</string>
|
<string name="incompatible_version">Inkompatible Version</string>
|
||||||
<string name="system">System</string>
|
<string name="system">System</string>
|
||||||
<string name="theme">Thema</string>
|
<string name="theme">Design</string>
|
||||||
<string name="ignore_all_updates">Alle neuen Versionen ignorieren</string>
|
<string name="ignore_all_updates">Alle neuen Versionen ignorieren</string>
|
||||||
<string name="ignore_this_update">Diese Version ignorieren</string>
|
<string name="ignore_this_update">Diese Version ignorieren</string>
|
||||||
<string name="size">Größe</string>
|
<string name="size">Größe</string>
|
||||||
<string name="updates">Aktualisierungen</string>
|
<string name="updates">Updates</string>
|
||||||
<string name="username">Benutzername</string>
|
<string name="username">Benutzername</string>
|
||||||
<string name="version_FORMAT">Version %s</string>
|
<string name="version_FORMAT">Version %s</string>
|
||||||
<string name="downloading">Herunterladen</string>
|
<string name="downloading">Wird heruntergeladen …</string>
|
||||||
<string name="share">Teilen</string>
|
<string name="share">Teilen</string>
|
||||||
<string name="show_more">Zeige mehr</string>
|
<string name="show_more">Mehr anzeigen</string>
|
||||||
<string name="show_older_versions">Ältere Versionen zeigen</string>
|
<string name="show_older_versions">Ältere Versionen anzeigen</string>
|
||||||
<string name="unverified">Ungeprüft</string>
|
|
||||||
<string name="username_missing">Benutzername fehlt</string>
|
<string name="username_missing">Benutzername fehlt</string>
|
||||||
<string name="edit_repository">Paketquelle bearbeiten</string>
|
<string name="edit_repository">Paketquelle bearbeiten</string>
|
||||||
<string name="file_format_error_DESC">Ungültiges Dateiformat.</string>
|
<string name="file_format_error_DESC">Ungültiges Dateiformat.</string>
|
||||||
<string name="downloading_FORMAT">%s wird heruntergeladen …</string>
|
<string name="downloading_FORMAT">%s wird heruntergeladen …</string>
|
||||||
<string name="incompatible_with_FORMAT">Inkompatibel mit %s</string>
|
<string name="incompatible_with_FORMAT">Inkompatibel mit %s</string>
|
||||||
<string name="incompatible_versions">Inkompatible Versionen</string>
|
<string name="incompatible_versions">Inkompatible Versionen</string>
|
||||||
<string name="invalid_address">Ungültige Adresse</string>
|
<string name="invalid_address">Ungültige Adresse</string>
|
||||||
<string name="invalid_fingerprint_format">Ungültiges Fingerabdruckformat</string>
|
<string name="invalid_fingerprint_format">Ungültiges Fingerabdruckformat</string>
|
||||||
<string name="invalid_permissions_error_DESC">Ungültige Berechtigungen.</string>
|
<string name="invalid_permissions_error_DESC">Ungültige Berechtigungen.</string>
|
||||||
<string name="promotes_non_free_network_services">Bewirbt unfreie Netzwerkdienste</string>
|
<string name="promotes_non_free_network_services">Bewirbt nicht-freie Netzwerkdienste</string>
|
||||||
<string name="unknown_FORMAT">Unbekannt: %s</string>
|
<string name="unknown_FORMAT">Unbekannt: %s</string>
|
||||||
<string name="unknown_error_DESC">Unbekannter Fehler.</string>
|
<string name="unknown_error_DESC">Unbekannter Fehler.</string>
|
||||||
<string name="syncing_FORMAT">Synchronisierung %s …</string>
|
<string name="syncing_FORMAT">%s wird synchronisiert …</string>
|
||||||
<string name="incompatible_signature_DESC">Diese Version ist mit einem anderen Zertifikat signiert, als die auf Deinem Gerät installierte. Deinstalliere diese zuerst.</string>
|
<string name="incompatible_signature_DESC">Diese Version ist mit einem anderen Zertifikat signiert als die auf deinem Gerät installierte Version. Deinstalliere diese zuerst.</string>
|
||||||
<string name="delete_repository_DESC">Die Paketquelle löschen\?</string>
|
<string name="delete_repository_DESC">Paketquelle löschen?</string>
|
||||||
<string name="incompatible_older_DESC">Diese Version ist älter als die auf deinem Gerät installierte. Deinstalliere diese zuerst.</string>
|
<string name="incompatible_older_DESC">Diese Version ist älter als diejenige, die auf deinem Gerät installiert ist. Deinstalliere diese zuerst.</string>
|
||||||
<string name="incompatible_api_DESC_FORMAT">Deine %1$s (API-Version %2$d) wird nicht unterstützt. %3$s</string>
|
<string name="incompatible_api_DESC_FORMAT">Deine %1$s (API-Version %2$d) wird nicht unterstützt. %3$s</string>
|
||||||
<string name="incompatible_api_min_DESC_FORMAT">Die minimale API-Version ist %d.</string>
|
<string name="incompatible_api_min_DESC_FORMAT">Die minimale API-Version ist %d.</string>
|
||||||
<string name="repository_unsigned_DESC">Nicht signiert. Die Anwendungsliste konnte nicht verifiziert werden. Sei vorsichtig beim Herunterladen von Anwendungen aus nicht signierten Paketquellen.</string>
|
<string name="repository_unsigned_DESC">Nicht signiert. Die App-Liste konnte nicht verifiziert werden. Sei beim Herunterladen von Apps aus nicht signierten Paketquellen vorsichtig.</string>
|
||||||
<string name="unstable_updates_summary">Installation von instabilen Versionen vorschlagen</string>
|
<string name="unstable_updates_summary">Installation von instabilen Versionen vorschlagen</string>
|
||||||
<string name="unstable_updates">Instabile Aktualisierungen</string>
|
<string name="unstable_updates">Instabile Updates</string>
|
||||||
<string name="root_permission_description">Root-Rechte für stille Installationen zulassen</string>
|
<string name="proxy_host">Proxy-Host</string>
|
||||||
<string name="proxy_host">Proxy Host</string>
|
<string name="tap_to_install_DESC">Zum Installieren tippen.</string>
|
||||||
<string name="tap_to_install_DESC">Tippe um zu installieren.</string>
|
<string name="tracks_or_reports_your_activity">Verfolgt oder versendet deine Aktivitäten</string>
|
||||||
<string name="tracks_or_reports_your_activity">Verfolgt oder erfasst deine Aktivitäten</string>
|
<string name="proxy_port">Proxy-Port</string>
|
||||||
<string name="proxy_port">Proxy Port</string>
|
<string name="search">Suchen</string>
|
||||||
<string name="search">Suche</string>
|
|
||||||
<string name="sorting_order">Sortierreihenfolge</string>
|
<string name="sorting_order">Sortierreihenfolge</string>
|
||||||
<string name="socks_proxy">SOCKS Proxy</string>
|
<string name="socks_proxy">SOCKS-Proxy</string>
|
||||||
<string name="no_applications_available">Keine Anwendungen verfügbar</string>
|
<string name="no_applications_available">Keine Apps verfügbar</string>
|
||||||
<plurals name="new_updates_DESC_FORMAT">
|
<plurals name="new_updates_DESC_FORMAT">
|
||||||
<item quantity="one">%d Anwendung hat eine neue Version.</item>
|
<item quantity="one">%d App hat eine neue Version.</item>
|
||||||
<item quantity="other">%d Anwendungen haben eine neue Version.</item>
|
<item quantity="other">%d Apps haben eine neue Version.</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="signed_using_unsafe_algorithm">Mit einem unsicheren Algorithmus signiert</string>
|
<string name="signed_using_unsafe_algorithm">Mit einem unsicheren Algorithmus signiert</string>
|
||||||
<string name="select_mirror">Wähle einen Spiegel</string>
|
<string name="select_mirror">Wähle einen Spiegel</string>
|
||||||
<string name="list_animation">Animationen anzeigen</string>
|
|
||||||
<string name="links">Links</string>
|
<string name="links">Links</string>
|
||||||
<string name="merging_FORMAT">Führe %s zusammen</string>
|
<string name="merging_FORMAT">%s wird zusammengeführt …</string>
|
||||||
<string name="name">Name</string>
|
<string name="name">Name</string>
|
||||||
<string name="upstream_source_code_is_not_free">Der Upstream-Quellcode ist nicht frei</string>
|
<string name="upstream_source_code_is_not_free">Der Upstream-Quellcode ist nicht frei</string>
|
||||||
<string name="prefs_language_title">Sprache</string>
|
<string name="prefs_language_title">Sprache</string>
|
||||||
<string name="prefs_personalization">Personalisierung</string>
|
<string name="prefs_personalization">Personalisieren</string>
|
||||||
<string name="show_less">Weniger anzeigen</string>
|
<string name="show_less">Weniger anzeigen</string>
|
||||||
<string name="latest">Neueste</string>
|
|
||||||
<string name="explore">Entdecken</string>
|
|
||||||
<string name="update_all">Alle aktualisieren</string>
|
<string name="update_all">Alle aktualisieren</string>
|
||||||
<string name="installed_applications">Installierte Anwendungen</string>
|
|
||||||
<string name="sort_filter">Sortieren und filtern</string>
|
|
||||||
<string name="new_applications">Neue Anwendungen</string>
|
|
||||||
<plurals name="days">
|
<plurals name="days">
|
||||||
<item quantity="one">Tag</item>
|
<item quantity="one">Tag</item>
|
||||||
<item quantity="other">Tage</item>
|
<item quantity="other">Tage</item>
|
||||||
@ -185,61 +171,65 @@
|
|||||||
<item quantity="one">Stunde</item>
|
<item quantity="one">Stunde</item>
|
||||||
<item quantity="other">Stunden</item>
|
<item quantity="other">Stunden</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="only_on_wifi_with_charging">Nur während des Ladevorgangs und aktiviertem WLAN</string>
|
<string name="only_on_wifi_with_charging">Nur mit WLAN während des Aufladens</string>
|
||||||
<string name="installer">Installationsmethode</string>
|
<string name="installer">Installationsmethode</string>
|
||||||
<string name="cleanup_description">Zeitraum zum Prüfen und Entfernen heruntergeladener Dateien</string>
|
|
||||||
<string name="cleanup_title">APK-Bereinigungsintervall</string>
|
<string name="cleanup_title">APK-Bereinigungsintervall</string>
|
||||||
<string name="root_installer">Root-Installation</string>
|
<string name="root_installer">Root-Installation</string>
|
||||||
<string name="legacy_installer">Alte Installationsmethode</string>
|
<string name="legacy_installer">Alte Installationsmethode</string>
|
||||||
<string name="session_installer">Sitzungs-Installation</string>
|
<string name="session_installer">Sitzungsinstallation</string>
|
||||||
<string name="shizuku_installer">Shizuku-Installation</string>
|
<string name="shizuku_installer">Shizuku-Installation</string>
|
||||||
<string name="io_error_DESC">Bestimmte Aktionen können nicht durchgeführt werden.</string>
|
<string name="io_error_DESC">Bestimmte Aktionen können nicht durchgeführt werden.</string>
|
||||||
<string name="no_internet">Sie haben keine Internetverbindung</string>
|
|
||||||
<string name="allow_collapsing_toolbar">Erweiterung der oberen Anwendungsleiste zulassen</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">Das Erweitern und Reduzieren der oberen Anwendungsleiste erlauben</string>
|
|
||||||
<string name="favourites">Favoriten</string>
|
<string name="favourites">Favoriten</string>
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="material_you_desc">Material You-Farbschema verwenden</string>
|
<string name="material_you_desc">Material You-Farbschema verwenden</string>
|
||||||
<string name="repository_unreachable">Repository unerreichbar</string>
|
<string name="repository_unreachable">Paketquelle unerreichbar</string>
|
||||||
<string name="force_clean_up">Aufräumen erzwingen</string>
|
<string name="force_clean_up">Bereinigung erzwingen</string>
|
||||||
<string name="enable_repo">Repository aktivieren</string>
|
<string name="enable_repo">Paketquelle aktivieren</string>
|
||||||
<string name="force_clean_up_DESC">Entfernt doppelte Dateien</string>
|
<string name="force_clean_up_DESC">Entfernt doppelte Dateien</string>
|
||||||
<string name="installing">Installation</string>
|
<string name="installing">Wird installiert …</string>
|
||||||
<string name="restart_app">Starten Sie Droid-ify neu, um die Änderungen zu sehen</string>
|
<string name="waiting_to_start_installation">Warten auf den Start der Installation …</string>
|
||||||
<string name="waiting_to_start_installation">Warten auf den Beginn der Installation …</string>
|
|
||||||
<string name="auto_update">Apps automatisch aktualisieren</string>
|
<string name="auto_update">Apps automatisch aktualisieren</string>
|
||||||
<string name="auto_update_apps">Versuche, Updates automatisch zu installieren</string>
|
<string name="auto_update_apps">Updates möglichst automatisch installieren</string>
|
||||||
<string name="has_non_free_components">Hat nicht-freie Komponenten</string>
|
<string name="has_non_free_components">Enthält nicht-freie Komponenten</string>
|
||||||
<string name="socket_error_DESC">Server konnte kein neues Datenpaket liefern.</string>
|
<string name="socket_error_DESC">Server konnte kein neues Datenpaket liefern.</string>
|
||||||
<string name="shizuku_not_alive">Shizuku läuft nicht</string>
|
<string name="shizuku_not_alive">Shizuku läuft nicht</string>
|
||||||
<string name="contains_nsfw">Enthält für den Arbeitsplatz unangemessene Inhalte</string>
|
<string name="contains_nsfw">Enthält für den Arbeitsplatz unangemessene Inhalte</string>
|
||||||
<string name="connection_error_DESC">Verbindung zum Server nicht möglich</string>
|
<string name="connection_error_DESC">Verbindung zum Server nicht möglich</string>
|
||||||
<string name="shizuku_not_installed">Shizuku ist nicht installiert</string>
|
<string name="shizuku_not_installed">Shizuku ist nicht installiert</string>
|
||||||
<string name="home_screen_swiping">Wischgesten</string>
|
<string name="home_screen_swiping">Wischgesten</string>
|
||||||
<string name="home_screen_swiping_DESC">Dem Benutzer erlauben, auf dem Startbildschirm zwischen den Seiten zu wischen</string>
|
<string name="home_screen_swiping_DESC">Durch Wischen nach links/rechts zwischen Seiten navigieren</string>
|
||||||
<string name="special_credits">Besonderer Dank</string>
|
<string name="special_credits">Besonderer Dank</string>
|
||||||
<string name="label_copy">Kopieren</string>
|
|
||||||
<string name="proxy_port_error_not_int">Proxy-Port muss eine natürliche Zahl sein</string>
|
<string name="proxy_port_error_not_int">Proxy-Port muss eine natürliche Zahl sein</string>
|
||||||
<string name="repository_not_found">Folgende Repos konnten nicht gefunden werden</string>
|
<string name="repository_not_found">Folgende Paketquelle konnten nicht gefunden werden</string>
|
||||||
<string name="import_settings_title">Einstellungen importieren</string>
|
<string name="import_settings_title">Einstellungen importieren</string>
|
||||||
<string name="import_export">Importieren/Exportieren</string>
|
<string name="import_export">Importieren/Exportieren</string>
|
||||||
<string name="import_settings_DESC">Importiere Einstellung und Favoriten von Datei</string>
|
<string name="import_settings_DESC">Einstellungen und Favoriten aus Datei importieren</string>
|
||||||
<string name="export_settings_title">Einstellungen exportieren</string>
|
<string name="export_settings_title">Einstellungen exportieren</string>
|
||||||
<string name="export_repos_DESC">Alle Repositories in eine Datei exportieren</string>
|
<string name="export_repos_DESC">Paketquellen in eine Datei exportieren</string>
|
||||||
<string name="import_repos_title">Importiere eine Sammlung</string>
|
<string name="import_repos_title">Paketquellen importieren</string>
|
||||||
<string name="export_settings_DESC">Einstellungen und Favoriten in eine Datei exportieren</string>
|
<string name="export_settings_DESC">Einstellungen und Favoriten in eine Datei exportieren</string>
|
||||||
<string name="export_repos_title">Repositories exportieren</string>
|
<string name="export_repos_title">Paketquellen exportieren</string>
|
||||||
<string name="import_repos_DESC">Alle Repositories aus einer Datei importieren</string>
|
<string name="import_repos_DESC">Paketquellen aus einer Datei importieren</string>
|
||||||
<string name="cannot_open_link">Link kann nicht geöffnet werden</string>
|
<string name="cannot_open_link">Link kann nicht geöffnet werden</string>
|
||||||
<string name="has_tethered_network">An einen bestimmten Netzwerkdienst gebunden</string>
|
<string name="has_tethered_network">An einen bestimmten Netzwerkdienst gebunden</string>
|
||||||
<string name="ignore_signature">Signatur ignorieren</string>
|
<string name="ignore_signature">Signatur ignorieren</string>
|
||||||
<string name="ignore_signature_summary">*Achtung* Signaturüberprüfung bei der Installation der APK ignorieren. Für LSPosed-Benutzer oder Experten.</string>
|
<string name="ignore_signature_summary">*Achtung* Signaturüberprüfung bei der Installation der APK ignorieren. Für LSPosed-Benutzer oder Experten</string>
|
||||||
<string name="installation_failed">Installation fehlgeschlagen</string>
|
<string name="installation_failed">Installation fehlgeschlagen</string>
|
||||||
<string name="uninstalled_application_DESC">%s wurde deinstalliert</string>
|
<string name="uninstalled_application_DESC">%s wurde deinstalliert</string>
|
||||||
<string name="installation_failed_DESC">%s konnte nicht installiert werden</string>
|
<string name="installation_failed_DESC">%s konnte nicht installiert werden</string>
|
||||||
<string name="uninstalled_application">Deinstalliert</string>
|
<string name="uninstalled_application">Deinstalliert</string>
|
||||||
<string name="require_background_access">Hintergrundzugriff anfordern</string>
|
<string name="require_background_access">Hintergrundzugriff anfordern</string>
|
||||||
<string name="require_background_access_DESC">Hintergrundzugriff ist erforderlich, um die Hintergrundsynchronisation ordnungsgemäß durchzuführen</string>
|
<string name="require_background_access_DESC">Hintergrundzugriff ist erforderlich, um die Hintergrundsynchronisation ordnungsgemäß durchzuführen</string>
|
||||||
<string name="insufficient_storage">Nicht genug Speicherplatz</string>
|
<string name="insufficient_storage">Nicht genügend Speicherplatz</string>
|
||||||
<string name="insufficient_storage_DESC">Es gibt nicht genug Speicherplatz, um diese Anwendung zu installieren. Versuche etwas Platz zu schafffen.</string>
|
<string name="insufficient_storage_DESC">Nicht genügend Speicherplatz, um diese App zu installieren. Versuche, etwas Platz zu schaffen</string>
|
||||||
</resources>
|
<string name="error_shizuku_not_granted">Shizuku-Erlaubnis fehlt</string>
|
||||||
|
<string name="error_shizuku_not_granted_DESC">Erlaubnis für den Shizuku-Dienst ist nicht gewährt. Bitte in der Shizuku-App prüfen</string>
|
||||||
|
<string name="error_shizuku_not_installed">Shizuku nicht installiert</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">Shizuku scheint nicht installiert zu sein</string>
|
||||||
|
<string name="switch_to_default_installer">Auf Standard wechseln</string>
|
||||||
|
<string name="open_shizuku">Shizuku öffnen</string>
|
||||||
|
<string name="error_shizuku_service_unavailable">Shizuku läuft nicht</string>
|
||||||
|
<string name="error_shizuku_not_running_DESC">Der Shizuku-Dienst läuft nicht. Bitte in der Shizuku-App prüfen</string>
|
||||||
|
<string name="label_open_video">Video</string>
|
||||||
|
<string name="label_unknown_sdk">Unbekannt (%d)</string>
|
||||||
|
</resources>
|
||||||
|
@ -64,8 +64,6 @@
|
|||||||
<string name="light">Φωτεινό</string>
|
<string name="light">Φωτεινό</string>
|
||||||
<string name="link_copied_to_clipboard">Ο σύνδεσμος αντιγράφηκε</string>
|
<string name="link_copied_to_clipboard">Ο σύνδεσμος αντιγράφηκε</string>
|
||||||
<string name="links">Σύνδεσμοι</string>
|
<string name="links">Σύνδεσμοι</string>
|
||||||
<string name="list_animation">Κινήσεις Λίστας</string>
|
|
||||||
<string name="list_animation_description">Εμφάνιση κινήσεων λίστας στην αρχική σελίδα</string>
|
|
||||||
<string name="merging_FORMAT">Συγχώνευση %s</string>
|
<string name="merging_FORMAT">Συγχώνευση %s</string>
|
||||||
<string name="name">Όνομα</string>
|
<string name="name">Όνομα</string>
|
||||||
<string name="network_error_DESC">Σφάλμα δικτύου</string>
|
<string name="network_error_DESC">Σφάλμα δικτύου</string>
|
||||||
@ -107,10 +105,8 @@
|
|||||||
<string name="repository">Αποθετήριο</string>
|
<string name="repository">Αποθετήριο</string>
|
||||||
<string name="repository_unsigned_DESC">Μη υπογεγραμμένο. Αδυναμία επαλήθευσης της λίστας εφαρμογών. Προσέχετε όταν κατεβάζετε εφαρμογές από μη υπογεγραμμένα αποθετήρια.</string>
|
<string name="repository_unsigned_DESC">Μη υπογεγραμμένο. Αδυναμία επαλήθευσης της λίστας εφαρμογών. Προσέχετε όταν κατεβάζετε εφαρμογές από μη υπογεγραμμένα αποθετήρια.</string>
|
||||||
<string name="requires_FORMAT">Απαιτεί %s</string>
|
<string name="requires_FORMAT">Απαιτεί %s</string>
|
||||||
<string name="root_permission">Σιωπηλή Εγκατάσταση</string>
|
|
||||||
<string name="save">Αποθήκευση</string>
|
<string name="save">Αποθήκευση</string>
|
||||||
<string name="saving_details">Αποθήκευση λεπτομερειών…</string>
|
<string name="saving_details">Αποθήκευση λεπτομερειών…</string>
|
||||||
<string name="screenshots">Στιγμιότυπα οθόνης</string>
|
|
||||||
<string name="search">Αναζήτηση</string>
|
<string name="search">Αναζήτηση</string>
|
||||||
<string name="select_mirror">Επιλέξτε ένα mirror</string>
|
<string name="select_mirror">Επιλέξτε ένα mirror</string>
|
||||||
<string name="share">Κοινοποίηση</string>
|
<string name="share">Κοινοποίηση</string>
|
||||||
@ -139,11 +135,8 @@
|
|||||||
<string name="unstable_updates_summary">Πρόταση για εγκατάσταση ασταθών εκδόσεων</string>
|
<string name="unstable_updates_summary">Πρόταση για εγκατάσταση ασταθών εκδόσεων</string>
|
||||||
<string name="update">Ενημέρωση</string>
|
<string name="update">Ενημέρωση</string>
|
||||||
<string name="updates">Ενημερώσεις</string>
|
<string name="updates">Ενημερώσεις</string>
|
||||||
<string name="unsigned">Μη υπογεγραμμένο</string>
|
|
||||||
<string name="unverified">Μη επιβεβαιωμένο</string>
|
|
||||||
<string name="delete">Διαγραφή</string>
|
<string name="delete">Διαγραφή</string>
|
||||||
<string name="recently_updated">Πρόσφατα ενημερωμένα</string>
|
<string name="recently_updated">Πρόσφατα ενημερωμένα</string>
|
||||||
<string name="target">Στόχος</string>
|
|
||||||
<string name="whats_new">Τι νέο υπάρχει</string>
|
<string name="whats_new">Τι νέο υπάρχει</string>
|
||||||
<string name="upstream_source_code_is_not_free">Upstream source code is not free</string>
|
<string name="upstream_source_code_is_not_free">Upstream source code is not free</string>
|
||||||
<string name="username">Όνομα χρήστη</string>
|
<string name="username">Όνομα χρήστη</string>
|
||||||
@ -161,28 +154,20 @@
|
|||||||
<string name="incompatible_signature_DESC">Αυτή η έκδοση είναι υπογεγραμμένη με ένα διαφορετικό πιστοποιητικό από αυτή που είναι εγκατεστημένη στη συσκευή σας. Απεγκαταστήστε εκείνη πρώτα.</string>
|
<string name="incompatible_signature_DESC">Αυτή η έκδοση είναι υπογεγραμμένη με ένα διαφορετικό πιστοποιητικό από αυτή που είναι εγκατεστημένη στη συσκευή σας. Απεγκαταστήστε εκείνη πρώτα.</string>
|
||||||
<string name="integrity_check_error_DESC">Αδυναμία ελέγχου ακεραιότητας.</string>
|
<string name="integrity_check_error_DESC">Αδυναμία ελέγχου ακεραιότητας.</string>
|
||||||
<string name="invalid_signature_error_DESC">Μη έγκυρη υπογραφή.</string>
|
<string name="invalid_signature_error_DESC">Μη έγκυρη υπογραφή.</string>
|
||||||
<string name="repository_not_used_DESC">Αυτό το αποθετήριο δεν έχει χρησιμοποιηθεί ακόμα. Χρειάζεται να το ενεργοποιήσετε για να δείτε τις εφαρμογές που παρέχει.</string>
|
|
||||||
<string name="signed_using_unsafe_algorithm">Έχει υπογραφεί χρησιμοποιώντας έναν μη ασφαλή αλγόριθμο</string>
|
<string name="signed_using_unsafe_algorithm">Έχει υπογραφεί χρησιμοποιώντας έναν μη ασφαλή αλγόριθμο</string>
|
||||||
<string name="socks_proxy">SOCKS διακομιστής μεσολάβησης</string>
|
<string name="socks_proxy">SOCKS διακομιστής μεσολάβησης</string>
|
||||||
<string name="tracks_or_reports_your_activity">Καταγράφει ή αναφέρει τη δραστηριότητά σας</string>
|
<string name="tracks_or_reports_your_activity">Καταγράφει ή αναφέρει τη δραστηριότητά σας</string>
|
||||||
<string name="validation_index_error_DESC">Αδυναμία επαλήθευσης δείκτη.</string>
|
<string name="validation_index_error_DESC">Αδυναμία επαλήθευσης δείκτη.</string>
|
||||||
<string name="root_permission_description">Επιτρέψτε την άδεια root για σιωπηλή εγκατάσταση</string>
|
|
||||||
<string name="amoled">Amoled</string>
|
<string name="amoled">Amoled</string>
|
||||||
<string name="prefs_personalization">Εξατομίκευση</string>
|
<string name="prefs_personalization">Εξατομίκευση</string>
|
||||||
<string name="prefs_language_title">Γλώσσα</string>
|
<string name="prefs_language_title">Γλώσσα</string>
|
||||||
<string name="latest">Πρόσφατα</string>
|
|
||||||
<string name="sort_filter">Ταξινόμηση & Φιλτράρισμα</string>
|
|
||||||
<string name="installed_applications">Εγκατεστημένες εφαρμογές</string>
|
|
||||||
<string name="installer">Πρόγραμμα Εγκατάστασης</string>
|
<string name="installer">Πρόγραμμα Εγκατάστασης</string>
|
||||||
<string name="legacy_installer">Παλιό πρόγραμμα Εγκατάστασης</string>
|
<string name="legacy_installer">Παλιό πρόγραμμα Εγκατάστασης</string>
|
||||||
<string name="session_installer">Πρόγραμμα Εκατάστασης Συνεδρίας</string>
|
<string name="session_installer">Πρόγραμμα Εκατάστασης Συνεδρίας</string>
|
||||||
<string name="root_installer">Πρόγραμμα Εγκατάστασης Root</string>
|
<string name="root_installer">Πρόγραμμα Εγκατάστασης Root</string>
|
||||||
<string name="shizuku_installer">Πρόγραμμα Εγκατάστασης Shizuku</string>
|
<string name="shizuku_installer">Πρόγραμμα Εγκατάστασης Shizuku</string>
|
||||||
<string name="show_less">Εμφάνιση Λιγότερων</string>
|
<string name="show_less">Εμφάνιση Λιγότερων</string>
|
||||||
<string name="explore">Εξερεύνηση</string>
|
|
||||||
<string name="update_all">Ενημέρωση όλων</string>
|
<string name="update_all">Ενημέρωση όλων</string>
|
||||||
<string name="new_applications">Νέες εφαρμογές</string>
|
|
||||||
<string name="cleanup_description">Period to check and remove downloaded files</string>
|
|
||||||
<string name="cleanup_title">APK cleanup interval</string>
|
<string name="cleanup_title">APK cleanup interval</string>
|
||||||
<plurals name="days">
|
<plurals name="days">
|
||||||
<item quantity="one">Ημέρα</item>
|
<item quantity="one">Ημέρα</item>
|
||||||
@ -194,9 +179,6 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="only_on_wifi_with_charging">Μόνο σε Wi-Fi και Φόρτιση</string>
|
<string name="only_on_wifi_with_charging">Μόνο σε Wi-Fi και Φόρτιση</string>
|
||||||
<string name="io_error_DESC">Δεν είναι δυνατή η εκτέλεση ορισμένων ενεργειών.</string>
|
<string name="io_error_DESC">Δεν είναι δυνατή η εκτέλεση ορισμένων ενεργειών.</string>
|
||||||
<string name="no_internet">Δεν έχετε σύνδεση στο διαδίκτυο</string>
|
|
||||||
<string name="allow_collapsing_toolbar">Να επιτρέπεται η Επέκταση της Γραμμής Κορυφαίων Εφαρμογών</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">Να επιτρέπεται η επέκταση και σύμπτυξη της επάνω γραμμής εφαρμογών</string>
|
|
||||||
<string name="material_you_desc">Χρησιμοποιήστε material you με θέμα το χρώμα σας</string>
|
<string name="material_you_desc">Χρησιμοποιήστε material you με θέμα το χρώμα σας</string>
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="favourites">Αγαπημένα</string>
|
<string name="favourites">Αγαπημένα</string>
|
||||||
@ -204,7 +186,6 @@
|
|||||||
<string name="force_clean_up">Αναγκαστική εκκαθάριση</string>
|
<string name="force_clean_up">Αναγκαστική εκκαθάριση</string>
|
||||||
<string name="force_clean_up_DESC">Καθαρίζει τα περιττά αρχεία</string>
|
<string name="force_clean_up_DESC">Καθαρίζει τα περιττά αρχεία</string>
|
||||||
<string name="enable_repo">Ενεργοποιήστε το αποθετήριο</string>
|
<string name="enable_repo">Ενεργοποιήστε το αποθετήριο</string>
|
||||||
<string name="restart_app">Επανεκκινήστε το Droid-ify για να δείτε αλλαγές</string>
|
|
||||||
<string name="installing">Εγκατάσταση</string>
|
<string name="installing">Εγκατάσταση</string>
|
||||||
<string name="waiting_to_start_installation">Αναμονή για έναρξη εγκατάστασης…</string>
|
<string name="waiting_to_start_installation">Αναμονή για έναρξη εγκατάστασης…</string>
|
||||||
<string name="auto_update">Αυτόματη ενημέρωση εφαρμογών</string>
|
<string name="auto_update">Αυτόματη ενημέρωση εφαρμογών</string>
|
||||||
@ -218,7 +199,6 @@
|
|||||||
<string name="shizuku_not_installed">Το Shizuku δεν είναι εγκατεστημένο</string>
|
<string name="shizuku_not_installed">Το Shizuku δεν είναι εγκατεστημένο</string>
|
||||||
<string name="home_screen_swiping">Σύρσιμο Αρχικής Οθόνης</string>
|
<string name="home_screen_swiping">Σύρσιμο Αρχικής Οθόνης</string>
|
||||||
<string name="home_screen_swiping_DESC">Επιτρέψτε στον χρήστη να συρθεί μεταξύ σελίδων στην αρχική οθόνη</string>
|
<string name="home_screen_swiping_DESC">Επιτρέψτε στον χρήστη να συρθεί μεταξύ σελίδων στην αρχική οθόνη</string>
|
||||||
<string name="label_copy">Αντιγραφή</string>
|
|
||||||
<string name="repository_not_found">Το παρακάτω αποθετήριο δεν βρέθηκε</string>
|
<string name="repository_not_found">Το παρακάτω αποθετήριο δεν βρέθηκε</string>
|
||||||
<string name="proxy_port_error_not_int">Η θύρα Proxy μπορεί να είναι μόνο Ακέραιος</string>
|
<string name="proxy_port_error_not_int">Η θύρα Proxy μπορεί να είναι μόνο Ακέραιος</string>
|
||||||
<string name="import_settings_title">Εισαγωγή Ρυθμίσεων</string>
|
<string name="import_settings_title">Εισαγωγή Ρυθμίσεων</string>
|
||||||
@ -240,4 +220,16 @@
|
|||||||
<string name="uninstalled_application_DESC">Το %s απεγκαταστάθηκε</string>
|
<string name="uninstalled_application_DESC">Το %s απεγκαταστάθηκε</string>
|
||||||
<string name="ignore_signature">Αγνόησή Υπογραφής</string>
|
<string name="ignore_signature">Αγνόησή Υπογραφής</string>
|
||||||
<string name="ignore_signature_summary">Αγνοήστε την επαλήθευση υπογραφής κατά την εγκατάσταση apk, για χρήστες με LSP ή προχωρημένους χρήστες</string>
|
<string name="ignore_signature_summary">Αγνοήστε την επαλήθευση υπογραφής κατά την εγκατάσταση apk, για χρήστες με LSP ή προχωρημένους χρήστες</string>
|
||||||
</resources>
|
<string name="error_shizuku_not_granted_DESC">Η άδεια λειτουργίας της υπηρεσίας Shizuku δεν έχει παραχωρηθεί. Ελέγξτε την εφαρμογή Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_installed">Το Shizuku δεν έχει εγκατασταθεί</string>
|
||||||
|
<string name="open_shizuku">Άνοιγμα Shizuku</string>
|
||||||
|
<string name="label_unknown_sdk">Άγνωστο (%d)</string>
|
||||||
|
<string name="label_open_video">Βίντεο</string>
|
||||||
|
<string name="switch_to_default_installer">Μετάβαση στην Προεπιλογή</string>
|
||||||
|
<string name="insufficient_storage">Ανεπαρκής Χώρος</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">Το Shizuku δεν φαίνεται να είναι εγκατεστημένο</string>
|
||||||
|
<string name="error_shizuku_service_unavailable">Δεν είναι σε λειτουργία το Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_running_DESC">Η υπηρεσία Shizuku δεν λειτουργεί. Ελέγξτε την εφαρμογή Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_granted">Λείπει η άδεια Shizuku</string>
|
||||||
|
<string name="insufficient_storage_DESC">Δεν υπάρχει αρκετός ελεύθερος χώρος στη συσκευή για την εγκατάσταση αυτής της εφαρμογής. Προσπαθήστε να ελευθερώσετε και να καθαρίσετε λίγο χώρο</string>
|
||||||
|
</resources>
|
||||||
|
@ -29,14 +29,12 @@
|
|||||||
<string name="incompatible_api_DESC_FORMAT">Via %1$s (API-versio %2$d) ne estas subtenata. %3$s</string>
|
<string name="incompatible_api_DESC_FORMAT">Via %1$s (API-versio %2$d) ne estas subtenata. %3$s</string>
|
||||||
<string name="only_on_wifi">Nur sur Wi-Fi</string>
|
<string name="only_on_wifi">Nur sur Wi-Fi</string>
|
||||||
<string name="password">Pasvorto</string>
|
<string name="password">Pasvorto</string>
|
||||||
<string name="unsigned">Nesubskribita</string>
|
|
||||||
<string name="cleanup_title">Intervalo de purigado de APK</string>
|
<string name="cleanup_title">Intervalo de purigado de APK</string>
|
||||||
<string name="repository_unsigned_DESC">Nesubskribita. Ne eblis kontroli la aplikliston. Atentu elŝutante aplikaĵojn el nesubskribitaj deponejoj.</string>
|
<string name="repository_unsigned_DESC">Nesubskribita. Ne eblis kontroli la aplikliston. Atentu elŝutante aplikaĵojn el nesubskribitaj deponejoj.</string>
|
||||||
<string name="contains_nsfw">Enhavas enhavon ne taŭgan por laboro</string>
|
<string name="contains_nsfw">Enhavas enhavon ne taŭgan por laboro</string>
|
||||||
<string name="select_mirror">Elekti spegulon</string>
|
<string name="select_mirror">Elekti spegulon</string>
|
||||||
<string name="has_non_free_components">Havas neliberajn komponantojn</string>
|
<string name="has_non_free_components">Havas neliberajn komponantojn</string>
|
||||||
<string name="promotes_non_free_network_services">Promocias ne-liberajn retservojn</string>
|
<string name="promotes_non_free_network_services">Promocias ne-liberajn retservojn</string>
|
||||||
<string name="list_animation_description">Montri listanimacion sur la ĉefpaĝo</string>
|
|
||||||
<string name="syncing_FORMAT">Sinkroniganta %s…</string>
|
<string name="syncing_FORMAT">Sinkroniganta %s…</string>
|
||||||
<string name="favourites">Favoratoj</string>
|
<string name="favourites">Favoratoj</string>
|
||||||
<string name="tracks_or_reports_your_activity">Spuras aŭ raportas vian agadon</string>
|
<string name="tracks_or_reports_your_activity">Spuras aŭ raportas vian agadon</string>
|
||||||
@ -49,11 +47,9 @@
|
|||||||
<string name="waiting_to_start_download">Atendante komenci elŝuton…</string>
|
<string name="waiting_to_start_download">Atendante komenci elŝuton…</string>
|
||||||
<string name="auto_update_apps">Provi instali ĝisdatigojn aŭtomate</string>
|
<string name="auto_update_apps">Provi instali ĝisdatigojn aŭtomate</string>
|
||||||
<string name="downloading">Elŝutanta</string>
|
<string name="downloading">Elŝutanta</string>
|
||||||
<string name="explore">Esplori</string>
|
|
||||||
<string name="notify_about_updates_summary">Montri sciigon kiam novaj versioj estas disponebla</string>
|
<string name="notify_about_updates_summary">Montri sciigon kiam novaj versioj estas disponebla</string>
|
||||||
<string name="suggested">Sugestita</string>
|
<string name="suggested">Sugestita</string>
|
||||||
<string name="permissions">Permesoj</string>
|
<string name="permissions">Permesoj</string>
|
||||||
<string name="sort_filter">Ordigi ⳤ Filtri</string>
|
|
||||||
<string name="open_DESC_FORMAT">Ĉu malfermi %s\?</string>
|
<string name="open_DESC_FORMAT">Ĉu malfermi %s\?</string>
|
||||||
<string name="validation_index_error_DESC">Indekso ne povis esti validigita.</string>
|
<string name="validation_index_error_DESC">Indekso ne povis esti validigita.</string>
|
||||||
<string name="new_updates_available">Novaj versioj de aplikaĵoj disponeblaj</string>
|
<string name="new_updates_available">Novaj versioj de aplikaĵoj disponeblaj</string>
|
||||||
@ -70,7 +66,6 @@
|
|||||||
<string name="installing">Instalante</string>
|
<string name="installing">Instalante</string>
|
||||||
<string name="incompatible_platforms_DESC_FORMAT">Via %1$s platformo ne estas subtenata. Subtenataj platformoj: %2$s.</string>
|
<string name="incompatible_platforms_DESC_FORMAT">Via %1$s platformo ne estas subtenata. Subtenataj platformoj: %2$s.</string>
|
||||||
<string name="repository_unreachable">Deponejo neatingebla</string>
|
<string name="repository_unreachable">Deponejo neatingebla</string>
|
||||||
<string name="restart_app">Rekomenci Droid-ify por vidi ŝanĝojn</string>
|
|
||||||
<string name="username_missing">Uzantnomo mankas</string>
|
<string name="username_missing">Uzantnomo mankas</string>
|
||||||
<string name="connecting">Konektanta…</string>
|
<string name="connecting">Konektanta…</string>
|
||||||
<string name="update">Ĝisdatigi</string>
|
<string name="update">Ĝisdatigi</string>
|
||||||
@ -83,7 +78,6 @@
|
|||||||
<string name="password_missing">Pasvorto mankas</string>
|
<string name="password_missing">Pasvorto mankas</string>
|
||||||
<string name="description">Priskribo</string>
|
<string name="description">Priskribo</string>
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="target">Celo</string>
|
|
||||||
<string name="waiting_to_start_installation">Atendante komenci instaladon…</string>
|
<string name="waiting_to_start_installation">Atendante komenci instaladon…</string>
|
||||||
<string name="installed">Instalita</string>
|
<string name="installed">Instalita</string>
|
||||||
<string name="name">Nomo</string>
|
<string name="name">Nomo</string>
|
||||||
@ -94,7 +88,6 @@
|
|||||||
<string name="version_FORMAT">Versio %s</string>
|
<string name="version_FORMAT">Versio %s</string>
|
||||||
<string name="light">Hela</string>
|
<string name="light">Hela</string>
|
||||||
<string name="all_applications">Ĉiuj aplikaĵoj</string>
|
<string name="all_applications">Ĉiuj aplikaĵoj</string>
|
||||||
<string name="installed_applications">Instalitaj aplikaĵoj</string>
|
|
||||||
<string name="proxy_port">Prokura haveno</string>
|
<string name="proxy_port">Prokura haveno</string>
|
||||||
<string name="requires_FORMAT">Postulas %s</string>
|
<string name="requires_FORMAT">Postulas %s</string>
|
||||||
<string name="delete">Forigi</string>
|
<string name="delete">Forigi</string>
|
||||||
@ -112,10 +105,7 @@
|
|||||||
<string name="link_copied_to_clipboard">Ligilo kopiita</string>
|
<string name="link_copied_to_clipboard">Ligilo kopiita</string>
|
||||||
<string name="processing_FORMAT">Prilaboranta %1$s…</string>
|
<string name="processing_FORMAT">Prilaboranta %1$s…</string>
|
||||||
<string name="shizuku_installer">Shizuku Instalilo</string>
|
<string name="shizuku_installer">Shizuku Instalilo</string>
|
||||||
<string name="new_applications">Novaj aplikaĵoj</string>
|
|
||||||
<string name="label_copy">Kopii</string>
|
|
||||||
<string name="uninstall">Malinstali</string>
|
<string name="uninstall">Malinstali</string>
|
||||||
<string name="no_internet">Vi ne havas interretan konekton</string>
|
|
||||||
<string name="skip">Preterpasi</string>
|
<string name="skip">Preterpasi</string>
|
||||||
<string name="downloaded_FORMAT">Elŝutis %s</string>
|
<string name="downloaded_FORMAT">Elŝutis %s</string>
|
||||||
<string name="cant_edit_sync_DESC">Ne povas redakti deponejon ĉar ĝi nun sinkronigas.</string>
|
<string name="cant_edit_sync_DESC">Ne povas redakti deponejon ĉar ĝi nun sinkronigas.</string>
|
||||||
@ -125,7 +115,6 @@
|
|||||||
<string name="network_error_DESC">Reteraro</string>
|
<string name="network_error_DESC">Reteraro</string>
|
||||||
<string name="license">Licenco</string>
|
<string name="license">Licenco</string>
|
||||||
<string name="auto_update">Aŭtomate ĝisdatigi aplikaĵoj</string>
|
<string name="auto_update">Aŭtomate ĝisdatigi aplikaĵoj</string>
|
||||||
<string name="screenshots">Ekrankopioj</string>
|
|
||||||
<string name="recently_updated">Lastatempe ĝisdatigita</string>
|
<string name="recently_updated">Lastatempe ĝisdatigita</string>
|
||||||
<string name="already_exists">Jam ekzistas</string>
|
<string name="already_exists">Jam ekzistas</string>
|
||||||
<string name="author_website">Aŭtora retejo</string>
|
<string name="author_website">Aŭtora retejo</string>
|
||||||
@ -133,12 +122,10 @@
|
|||||||
<string name="edit_repository">Redakti deponejon</string>
|
<string name="edit_repository">Redakti deponejon</string>
|
||||||
<string name="sorting_order">Ordo de ordigo</string>
|
<string name="sorting_order">Ordo de ordigo</string>
|
||||||
<string name="ignore_this_update">Ignori ĉi tiun version</string>
|
<string name="ignore_this_update">Ignori ĉi tiun version</string>
|
||||||
<string name="unverified">Nekontrolita</string>
|
|
||||||
<string name="http_proxy">HTTP prokurilo</string>
|
<string name="http_proxy">HTTP prokurilo</string>
|
||||||
<string name="application">Aplikaĵo</string>
|
<string name="application">Aplikaĵo</string>
|
||||||
<string name="always">Ĉiam</string>
|
<string name="always">Ĉiam</string>
|
||||||
<string name="address">Adreso</string>
|
<string name="address">Adreso</string>
|
||||||
<string name="root_permission">Silenta Instalo</string>
|
|
||||||
<string name="no_description_available_DESC">Neniu priskribo disponebla</string>
|
<string name="no_description_available_DESC">Neniu priskribo disponebla</string>
|
||||||
<string name="invalid_fingerprint_format">Nevalida fingrospura formato</string>
|
<string name="invalid_fingerprint_format">Nevalida fingrospura formato</string>
|
||||||
<string name="saving_details">Konservanta detalojn…</string>
|
<string name="saving_details">Konservanta detalojn…</string>
|
||||||
@ -163,7 +150,6 @@
|
|||||||
<string name="search">Serĉi</string>
|
<string name="search">Serĉi</string>
|
||||||
<string name="unknown_error_DESC">Nekonata eraro.</string>
|
<string name="unknown_error_DESC">Nekonata eraro.</string>
|
||||||
<string name="themes">Haŭtoj</string>
|
<string name="themes">Haŭtoj</string>
|
||||||
<string name="list_animation">Enlistigi Animacioj</string>
|
|
||||||
<string name="file_format_error_DESC">Nevalida dosierformato.</string>
|
<string name="file_format_error_DESC">Nevalida dosierformato.</string>
|
||||||
<plurals name="new_updates_DESC_FORMAT">
|
<plurals name="new_updates_DESC_FORMAT">
|
||||||
<item quantity="one">%d aplikaĵo havas novan version.</item>
|
<item quantity="one">%d aplikaĵo havas novan version.</item>
|
||||||
@ -176,15 +162,12 @@
|
|||||||
<string name="project_website">Projekto retejo</string>
|
<string name="project_website">Projekto retejo</string>
|
||||||
<string name="donate">Donaci</string>
|
<string name="donate">Donaci</string>
|
||||||
<string name="add_repository">Aldoni deponejo</string>
|
<string name="add_repository">Aldoni deponejo</string>
|
||||||
<string name="allow_collapsing_toolbar">Permesi al Supra Aplika Breto Etendi</string>
|
|
||||||
<string name="could_not_validate_FORMAT">Ne eblis validigi %s</string>
|
<string name="could_not_validate_FORMAT">Ne eblis validigi %s</string>
|
||||||
<string name="available">Esplori</string>
|
<string name="available">Esplori</string>
|
||||||
<string name="show_less">Montri Malpli</string>
|
<string name="show_less">Montri Malpli</string>
|
||||||
<string name="never">Neniam</string>
|
<string name="never">Neniam</string>
|
||||||
<string name="no_matching_applications_found">Ne povis trovi tiajn aplikaĵojn</string>
|
<string name="no_matching_applications_found">Ne povis trovi tiajn aplikaĵojn</string>
|
||||||
<string name="incompatible_api_min_DESC_FORMAT">La minimuma API-versio estas %d.</string>
|
<string name="incompatible_api_min_DESC_FORMAT">La minimuma API-versio estas %d.</string>
|
||||||
<string name="allow_collapsing_toolbar_DESC">Permesi al supra aplika breto etendi kaj maletendi</string>
|
|
||||||
<string name="cleanup_description">Periodo por kontroli kaj forigi elŝutitajn dosierojn</string>
|
|
||||||
<string name="settings">Agordoj</string>
|
<string name="settings">Agordoj</string>
|
||||||
<string name="invalid_address">Nevalida adreso</string>
|
<string name="invalid_address">Nevalida adreso</string>
|
||||||
<string name="upstream_source_code_is_not_free">La kontraŭflua fontkodo ne estas libera</string>
|
<string name="upstream_source_code_is_not_free">La kontraŭflua fontkodo ne estas libera</string>
|
||||||
@ -193,7 +176,6 @@
|
|||||||
<string name="checking_repository">Kontrolanta deponejon…</string>
|
<string name="checking_repository">Kontrolanta deponejon…</string>
|
||||||
<string name="versions">Versioj</string>
|
<string name="versions">Versioj</string>
|
||||||
<string name="incompatible_api_max_DESC_FORMAT">La maksimuma API-versio estas %d.</string>
|
<string name="incompatible_api_max_DESC_FORMAT">La maksimuma API-versio estas %d.</string>
|
||||||
<string name="repository_not_used_DESC">Ĉi tiu deponejo ankoraŭ ne estis uzata. Ŝaltu ĝin por vidi la aplikaĵojn en ĝi.</string>
|
|
||||||
<string name="parsing_index_error_DESC">Ne eblis analizi la indeksan dosieron.</string>
|
<string name="parsing_index_error_DESC">Ne eblis analizi la indeksan dosieron.</string>
|
||||||
<string name="install">Instali</string>
|
<string name="install">Instali</string>
|
||||||
<string name="system">Sistemo</string>
|
<string name="system">Sistemo</string>
|
||||||
@ -215,10 +197,8 @@
|
|||||||
<string name="integrity_check_error_DESC">Ne eblis kontroli integrecon.</string>
|
<string name="integrity_check_error_DESC">Ne eblis kontroli integrecon.</string>
|
||||||
<string name="application_not_found">Ne eblis trovi tiun aplikaĵon</string>
|
<string name="application_not_found">Ne eblis trovi tiun aplikaĵon</string>
|
||||||
<string name="proxy">Prokurilo</string>
|
<string name="proxy">Prokurilo</string>
|
||||||
<string name="latest">Plej lasta</string>
|
|
||||||
<string name="credits">Kreditoj</string>
|
<string name="credits">Kreditoj</string>
|
||||||
<string name="repositories">Deponejoj</string>
|
<string name="repositories">Deponejoj</string>
|
||||||
<string name="root_permission_description">Permesi radikan permeson por silenta instalo</string>
|
|
||||||
<string name="compiled_for_debugging">Kompilita por sencimigado</string>
|
<string name="compiled_for_debugging">Kompilita por sencimigado</string>
|
||||||
<string name="unknown_FORMAT">Nekonata: %s</string>
|
<string name="unknown_FORMAT">Nekonata: %s</string>
|
||||||
<string name="import_settings_title">Importi Agordojn</string>
|
<string name="import_settings_title">Importi Agordojn</string>
|
||||||
@ -240,4 +220,4 @@
|
|||||||
<string name="has_tethered_network">Ligita al certa retservo</string>
|
<string name="has_tethered_network">Ligita al certa retservo</string>
|
||||||
<string name="require_background_access">Postuli fonan aliron</string>
|
<string name="require_background_access">Postuli fonan aliron</string>
|
||||||
<string name="require_background_access_DESC">Fona aliro estas bezonata por ĝuste fari fonan sinkronigon</string>
|
<string name="require_background_access_DESC">Fona aliro estas bezonata por ĝuste fari fonan sinkronigon</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -74,8 +74,6 @@
|
|||||||
<string name="light">Claro</string>
|
<string name="light">Claro</string>
|
||||||
<string name="link_copied_to_clipboard">Enlace copiado</string>
|
<string name="link_copied_to_clipboard">Enlace copiado</string>
|
||||||
<string name="links">Enlaces</string>
|
<string name="links">Enlaces</string>
|
||||||
<string name="list_animation">Animaciones de la lista</string>
|
|
||||||
<string name="list_animation_description">Mostrar la animación de la lista en la página principal</string>
|
|
||||||
<string name="merging_FORMAT">Uniendo %s</string>
|
<string name="merging_FORMAT">Uniendo %s</string>
|
||||||
<string name="name">Nombre</string>
|
<string name="name">Nombre</string>
|
||||||
<string name="network_error_DESC">Error de red</string>
|
<string name="network_error_DESC">Error de red</string>
|
||||||
@ -112,14 +110,10 @@
|
|||||||
<string name="recently_updated">Actualizado recientemente</string>
|
<string name="recently_updated">Actualizado recientemente</string>
|
||||||
<string name="repositories">Repositorios</string>
|
<string name="repositories">Repositorios</string>
|
||||||
<string name="repository">Repositorio</string>
|
<string name="repository">Repositorio</string>
|
||||||
<string name="repository_not_used_DESC">Este repositorio no se ha utilizado todavía. Actívalo para ver las aplicaciones que contiene.</string>
|
|
||||||
<string name="repository_unsigned_DESC">Sin firmar. No se ha podido verificar la lista de aplicaciones. Ten cuidado al descargar aplicaciones de repositorios no firmados.</string>
|
<string name="repository_unsigned_DESC">Sin firmar. No se ha podido verificar la lista de aplicaciones. Ten cuidado al descargar aplicaciones de repositorios no firmados.</string>
|
||||||
<string name="requires_FORMAT">Requiere %s</string>
|
<string name="requires_FORMAT">Requiere %s</string>
|
||||||
<string name="root_permission">Instalación silenciosa</string>
|
|
||||||
<string name="root_permission_description">Conceder permiso root para las instalaciones silenciosas</string>
|
|
||||||
<string name="save">Guardar</string>
|
<string name="save">Guardar</string>
|
||||||
<string name="saving_details">Guardando detalles…</string>
|
<string name="saving_details">Guardando detalles…</string>
|
||||||
<string name="screenshots">Capturas de pantalla</string>
|
|
||||||
<string name="search">Buscar</string>
|
<string name="search">Buscar</string>
|
||||||
<string name="select_mirror">Selecciona un espejo</string>
|
<string name="select_mirror">Selecciona un espejo</string>
|
||||||
<string name="share">Compartir</string>
|
<string name="share">Compartir</string>
|
||||||
@ -140,7 +134,6 @@
|
|||||||
<string name="syncing_FORMAT">Sincronizando %s…</string>
|
<string name="syncing_FORMAT">Sincronizando %s…</string>
|
||||||
<string name="system">Sistema</string>
|
<string name="system">Sistema</string>
|
||||||
<string name="tap_to_install_DESC">Pulse para instalar.</string>
|
<string name="tap_to_install_DESC">Pulse para instalar.</string>
|
||||||
<string name="target">Objetivo</string>
|
|
||||||
<string name="theme">Tema</string>
|
<string name="theme">Tema</string>
|
||||||
<string name="themes">Temas</string>
|
<string name="themes">Temas</string>
|
||||||
<string name="tracks_or_reports_your_activity">Rastrea o informa de tu actividad</string>
|
<string name="tracks_or_reports_your_activity">Rastrea o informa de tu actividad</string>
|
||||||
@ -148,10 +141,8 @@
|
|||||||
<string name="unknown">Desconocido</string>
|
<string name="unknown">Desconocido</string>
|
||||||
<string name="unknown_error_DESC">Error desconocido.</string>
|
<string name="unknown_error_DESC">Error desconocido.</string>
|
||||||
<string name="unknown_FORMAT">Desconocido: %s</string>
|
<string name="unknown_FORMAT">Desconocido: %s</string>
|
||||||
<string name="unsigned">No firmado</string>
|
|
||||||
<string name="unstable_updates">Actualizaciones inestables</string>
|
<string name="unstable_updates">Actualizaciones inestables</string>
|
||||||
<string name="unstable_updates_summary">Sugerir la instalación de versiones inestables</string>
|
<string name="unstable_updates_summary">Sugerir la instalación de versiones inestables</string>
|
||||||
<string name="unverified">No verificado</string>
|
|
||||||
<string name="update">Actualizar</string>
|
<string name="update">Actualizar</string>
|
||||||
<string name="updates">Actualizaciones</string>
|
<string name="updates">Actualizaciones</string>
|
||||||
<string name="upstream_source_code_is_not_free">El código fuente no es libre</string>
|
<string name="upstream_source_code_is_not_free">El código fuente no es libre</string>
|
||||||
@ -172,19 +163,13 @@
|
|||||||
<string name="prefs_language_title">Idioma</string>
|
<string name="prefs_language_title">Idioma</string>
|
||||||
<string name="prefs_personalization">Personalización</string>
|
<string name="prefs_personalization">Personalización</string>
|
||||||
<string name="show_less">Mostrar menos</string>
|
<string name="show_less">Mostrar menos</string>
|
||||||
<string name="latest">Lo más reciente</string>
|
|
||||||
<string name="explore">Explorar</string>
|
|
||||||
<string name="installed_applications">Aplicaciones instaladas</string>
|
|
||||||
<string name="sort_filter">Ordenar y filtrar</string>
|
|
||||||
<string name="update_all">Actualizar todo</string>
|
<string name="update_all">Actualizar todo</string>
|
||||||
<string name="new_applications">Nuevas aplicaciones</string>
|
|
||||||
<string name="root_installer">Instalador root</string>
|
<string name="root_installer">Instalador root</string>
|
||||||
<string name="installer">Instalador</string>
|
<string name="installer">Instalador</string>
|
||||||
<string name="session_installer">Instalador de sesión</string>
|
<string name="session_installer">Instalador de sesión</string>
|
||||||
<string name="legacy_installer">Instalador heredado</string>
|
<string name="legacy_installer">Instalador heredado</string>
|
||||||
<string name="shizuku_installer">Instalador de Shizuku</string>
|
<string name="shizuku_installer">Instalador de Shizuku</string>
|
||||||
<string name="cleanup_title">Intervalo de limpieza de APKs</string>
|
<string name="cleanup_title">Intervalo de limpieza de APKs</string>
|
||||||
<string name="cleanup_description">Periodo para comprobar y eliminar los archivos descargados</string>
|
|
||||||
<plurals name="days">
|
<plurals name="days">
|
||||||
<item quantity="one">Día</item>
|
<item quantity="one">Día</item>
|
||||||
<item quantity="many">Días</item>
|
<item quantity="many">Días</item>
|
||||||
@ -197,9 +182,6 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="only_on_wifi_with_charging">Solo en Wi-Fi y cargando</string>
|
<string name="only_on_wifi_with_charging">Solo en Wi-Fi y cargando</string>
|
||||||
<string name="io_error_DESC">No se pueden realizar ciertas acciones.</string>
|
<string name="io_error_DESC">No se pueden realizar ciertas acciones.</string>
|
||||||
<string name="no_internet">No hay conexión a internet</string>
|
|
||||||
<string name="allow_collapsing_toolbar">Permitir que la barra superior de la aplicación se expanda</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">Permitir que la barra superior de la aplicación se expanda y se contraiga</string>
|
|
||||||
<string name="material_you_desc">Utiliza el tema de color Material You</string>
|
<string name="material_you_desc">Utiliza el tema de color Material You</string>
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="favourites">Favoritas</string>
|
<string name="favourites">Favoritas</string>
|
||||||
@ -208,7 +190,6 @@
|
|||||||
<string name="force_clean_up_DESC">Limpiar archivos redundantes</string>
|
<string name="force_clean_up_DESC">Limpiar archivos redundantes</string>
|
||||||
<string name="enable_repo">Habilitar el repositorio</string>
|
<string name="enable_repo">Habilitar el repositorio</string>
|
||||||
<string name="installing">Instalando</string>
|
<string name="installing">Instalando</string>
|
||||||
<string name="restart_app">Reinicia Droid-ify para ver los cambios</string>
|
|
||||||
<string name="waiting_to_start_installation">Esperando para iniciar la instalación…</string>
|
<string name="waiting_to_start_installation">Esperando para iniciar la instalación…</string>
|
||||||
<string name="auto_update">Actualizar automáticamente las aplicaciones</string>
|
<string name="auto_update">Actualizar automáticamente las aplicaciones</string>
|
||||||
<string name="auto_update_apps">Intentar instalar actualizaciones automáticamente</string>
|
<string name="auto_update_apps">Intentar instalar actualizaciones automáticamente</string>
|
||||||
@ -221,7 +202,6 @@
|
|||||||
<string name="special_credits">Gracias a</string>
|
<string name="special_credits">Gracias a</string>
|
||||||
<string name="home_screen_swiping">Deslizamiento por la pantalla de inicio</string>
|
<string name="home_screen_swiping">Deslizamiento por la pantalla de inicio</string>
|
||||||
<string name="home_screen_swiping_DESC">Permitir al usuario pasar de una página a otra en la pantalla de inicio</string>
|
<string name="home_screen_swiping_DESC">Permitir al usuario pasar de una página a otra en la pantalla de inicio</string>
|
||||||
<string name="label_copy">Copiar</string>
|
|
||||||
<string name="repository_not_found">No pudimos encontrar el siguiente repositorio</string>
|
<string name="repository_not_found">No pudimos encontrar el siguiente repositorio</string>
|
||||||
<string name="proxy_port_error_not_int">El puerto del proxy sólo puede ser un número entero</string>
|
<string name="proxy_port_error_not_int">El puerto del proxy sólo puede ser un número entero</string>
|
||||||
<string name="import_settings_title">Importar configuración</string>
|
<string name="import_settings_title">Importar configuración</string>
|
||||||
@ -245,4 +225,14 @@
|
|||||||
<string name="uninstalled_application">Desinstalada</string>
|
<string name="uninstalled_application">Desinstalada</string>
|
||||||
<string name="insufficient_storage">Espacio insuficiente</string>
|
<string name="insufficient_storage">Espacio insuficiente</string>
|
||||||
<string name="insufficient_storage_DESC">No hay suficiente espacio libre en el dispositivo para instalar esta aplicación. Intente liberar algo de espacio</string>
|
<string name="insufficient_storage_DESC">No hay suficiente espacio libre en el dispositivo para instalar esta aplicación. Intente liberar algo de espacio</string>
|
||||||
</resources>
|
<string name="error_shizuku_not_granted_DESC">No se permitió el permiso del servicio de Shizuku. Por favor revisa la app de Shizuku</string>
|
||||||
|
<string name="error_shizuku_service_unavailable">Shizuku no está ejecutando</string>
|
||||||
|
<string name="error_shizuku_not_running_DESC">El servicio de Shizuku no está corriendo. Por favor revisa la app de Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_granted">Falta permiso de Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_installed">Shizuku no está instalado</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">Al parecer Shizuku no está instalado</string>
|
||||||
|
<string name="open_shizuku">Abrir Shizuku</string>
|
||||||
|
<string name="switch_to_default_installer">Cambiar a Predeterminado</string>
|
||||||
|
<string name="label_open_video">Video</string>
|
||||||
|
<string name="label_unknown_sdk">Desconocido (%d)</string>
|
||||||
|
</resources>
|
||||||
|
235
app/src/main/res/values-et/strings.xml
Normal file
235
app/src/main/res/values-et/strings.xml
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="cannot_open_link">Linki ei saa avada</string>
|
||||||
|
<string name="auto_update_apps">Ürita värskendusi automaatselt paigaldada</string>
|
||||||
|
<string name="add_repository">Lisa hoidla</string>
|
||||||
|
<string name="address">Aadress</string>
|
||||||
|
<string name="all_applications">Kõik rakendused</string>
|
||||||
|
<string name="already_exists">Juba olemas</string>
|
||||||
|
<string name="always">Alati</string>
|
||||||
|
<string name="amoled">Must</string>
|
||||||
|
<string name="anti_features">Anti-omadused</string>
|
||||||
|
<string name="application">Rakendus</string>
|
||||||
|
<string name="author_email">Autori e-post</string>
|
||||||
|
<string name="author_website">Autori veebileht</string>
|
||||||
|
<string name="auto_update">Uuenda rakendusi automaatselt</string>
|
||||||
|
<string name="available">Avasta</string>
|
||||||
|
<string name="bug_tracker">Veajälgija</string>
|
||||||
|
<string name="cancel">Tühista</string>
|
||||||
|
<string name="cant_edit_sync_DESC">Hoidlat ei saa redigeerida, kuna seda sünkroonitakse praegu.</string>
|
||||||
|
<string name="changelog">Muudatuste logi</string>
|
||||||
|
<string name="changes">Muudatused</string>
|
||||||
|
<string name="checking_repository">Hoidla kontrollimine…</string>
|
||||||
|
<string name="cleanup_title">APK puhastamise intervall</string>
|
||||||
|
<string name="confirmation">Kinnitus</string>
|
||||||
|
<string name="contains_non_free_media">Sisaldab mittevaba meediat</string>
|
||||||
|
<string name="could_not_download_FORMAT">%s allalaadimine nurjus</string>
|
||||||
|
<string name="could_not_sync_FORMAT">%s sünkroonimine nurjus</string>
|
||||||
|
<string name="credits">Tänud</string>
|
||||||
|
<string name="dark">Tume</string>
|
||||||
|
<string name="delete">Kustuta</string>
|
||||||
|
<string name="description">Kirjeldus</string>
|
||||||
|
<string name="details">Üksikasjad</string>
|
||||||
|
<string name="donate">Anneta</string>
|
||||||
|
<string name="downloading">Allalaadimine</string>
|
||||||
|
<string name="downloaded_FORMAT">%s laeti alla</string>
|
||||||
|
<string name="edit_repository">Redigeeri hoidlat</string>
|
||||||
|
<string name="error_shizuku_service_unavailable">Shizuku ei tööta</string>
|
||||||
|
<string name="error_shizuku_not_running_DESC">Shizuku teenus ei tööta. Palun kontrolli Shizuku rakendust</string>
|
||||||
|
<string name="error_shizuku_not_granted">Shizuku luba puudub</string>
|
||||||
|
<string name="error_shizuku_not_installed">Shizuku pole paigaldatud</string>
|
||||||
|
<string name="import_export">Impordi/ekspordi</string>
|
||||||
|
<string name="import_settings_title">Impordi seaded</string>
|
||||||
|
<string name="import_settings_DESC">Impordi seaded ja lemmikud failist</string>
|
||||||
|
<string name="export_settings_title">Ekspordi seaded</string>
|
||||||
|
<string name="import_repos_DESC">Impordi kõik hoidlad failist</string>
|
||||||
|
<string name="export_repos_title">Ekspordi hoidlad</string>
|
||||||
|
<string name="export_repos_DESC">Ekspordi kõik hoidlad faili</string>
|
||||||
|
<string name="enable_repo">Luba hoidla</string>
|
||||||
|
<string name="favourites">Lemmikud</string>
|
||||||
|
<string name="fingerprint">Sõrmejälg</string>
|
||||||
|
<string name="force_clean_up">Sundpuhastus</string>
|
||||||
|
<string name="force_clean_up_DESC">Puhastab üleliigsed failid</string>
|
||||||
|
<string name="has_advertising">Sisaldab reklaami</string>
|
||||||
|
<string name="has_non_free_dependencies">Omab mittevabu sõltuvusi</string>
|
||||||
|
<string name="has_non_free_components">Omab mittevabu komponente</string>
|
||||||
|
<string name="has_security_vulnerabilities">Omab turvaauke</string>
|
||||||
|
<string name="has_tethered_network">Seotud teatud võrguteenusega</string>
|
||||||
|
<string name="home_screen_swiping">Avakuval nipsamine</string>
|
||||||
|
<string name="home_screen_swiping_DESC">Luba kasutajal avakuval nipsates lehti vahetada</string>
|
||||||
|
<plurals name="hours">
|
||||||
|
<item quantity="one">tund</item>
|
||||||
|
<item quantity="other">tundi</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="connection_error_DESC">Serveriga ei õnnestunud ühendust luua</string>
|
||||||
|
<string name="http_proxy">HTTP puhverserver</string>
|
||||||
|
<string name="incompatible_api_max_DESC_FORMAT">Suurim API versioon on %d.</string>
|
||||||
|
<string name="incompatible_features_DESC">Puuduvad funktsioonid.</string>
|
||||||
|
<string name="incompatible_older_DESC">See versioon on vanem kui seadmesse paigaldatud versioon. Esmalt eemalda see.</string>
|
||||||
|
<string name="incompatible_version">Ühildumatu versioon</string>
|
||||||
|
<string name="action_failed">Toiming nurjus</string>
|
||||||
|
<string name="all_applications_up_to_date">Kõik rakendused on ajakohased</string>
|
||||||
|
<plurals name="days">
|
||||||
|
<item quantity="one">päev</item>
|
||||||
|
<item quantity="other">päeva</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="application_not_found">Seda rakendust ei leitud</string>
|
||||||
|
<string name="error_shizuku_not_granted_DESC">Shizuku teenusele pole luba antud. Palun kontrolli Shizuku rakendust</string>
|
||||||
|
<string name="compiled_for_debugging">Kompileeritud silumiseks</string>
|
||||||
|
<string name="could_not_validate_FORMAT">%s valideerimine nurjus</string>
|
||||||
|
<string name="connecting">Ühendamine…</string>
|
||||||
|
<string name="socket_error_DESC">Serveril ei õnnestunud uut paketti pakkuda.</string>
|
||||||
|
<string name="incompatible_versions">Ühildumatud versioonid</string>
|
||||||
|
<string name="delete_repository_DESC">Kas kustutada hoidla?</string>
|
||||||
|
<string name="import_repos_title">Impordi hoidlad</string>
|
||||||
|
<string name="downloading_FORMAT">%s allalaadimine…</string>
|
||||||
|
<string name="incompatible_api_DESC_FORMAT">Sinu %1$s (API versioon %2$d) ei ole toetatud. %3$s</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">Paistab, et Shizuku pole paigaldatud</string>
|
||||||
|
<string name="export_settings_DESC">Ekspordi seaded ja lemmikud faili</string>
|
||||||
|
<string name="file_format_error_DESC">Kehtetu failivorming.</string>
|
||||||
|
<string name="incompatible_api_min_DESC_FORMAT">Väikseim API versioon on %d.</string>
|
||||||
|
<string name="incompatible_platforms_DESC_FORMAT">Sinu %1$s platvormi ei toetata. Toetatud platvormid: %2$s.</string>
|
||||||
|
<string name="ignore_all_updates">Eira kõiki uusi versioone</string>
|
||||||
|
<string name="ignore_this_update">Eira seda versiooni</string>
|
||||||
|
<string name="http_error_DESC">Vigane serveri vastus.</string>
|
||||||
|
<string name="incompatible_signature_DESC">See versioon on allkirjastatud erineva sertifikaadiga kui seadmesse paigaldatu. Esmalt eemalda see.</string>
|
||||||
|
<string name="uninstalled_application">Eemaldatud</string>
|
||||||
|
<string name="integrity_check_error_DESC">Terviklikkust ei saanud kontrollida.</string>
|
||||||
|
<string name="invalid_address">Vigane aadress</string>
|
||||||
|
<string name="invalid_metadata_error_DESC">Vigased metaandmed.</string>
|
||||||
|
<string name="invalid_permissions_error_DESC">Vigased load.</string>
|
||||||
|
<string name="invalid_signature_error_DESC">Vigane allkiri.</string>
|
||||||
|
<string name="io_error_DESC">Teatud toiminguid ei saa teha.</string>
|
||||||
|
<string name="launch">Käivita</string>
|
||||||
|
<string name="license">Litsents</string>
|
||||||
|
<string name="license_FORMAT">%s litsents</string>
|
||||||
|
<string name="light">Hele</string>
|
||||||
|
<string name="material_you_desc">Kasuta Material You värviskeemi</string>
|
||||||
|
<string name="merging_FORMAT">Ühendatakse %s</string>
|
||||||
|
<string name="name">Nimi</string>
|
||||||
|
<string name="new_updates_available">Saadaval on rakenduste uued versioonid</string>
|
||||||
|
<plurals name="new_updates_DESC_FORMAT">
|
||||||
|
<item quantity="one">%d uuendus saadaval.</item>
|
||||||
|
<item quantity="other">%d uuendust saadaval.</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="no_applications_available">Saadaolevaid rakendusi pole</string>
|
||||||
|
<string name="no_proxy">Puhverserverita</string>
|
||||||
|
<string name="notify_about_updates">Teavita uuendustest</string>
|
||||||
|
<string name="notify_about_updates_summary">Kuva märguanne, kui uued versioonid on saadaval</string>
|
||||||
|
<string name="number_of_applications">Rakenduste arv</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="only_compatible_with_FORMAT">Ühildub ainult %s</string>
|
||||||
|
<string name="only_on_wifi">Ainult WiFi võrgus</string>
|
||||||
|
<string name="open_DESC_FORMAT">Kas avada %s?</string>
|
||||||
|
<string name="other">Muud</string>
|
||||||
|
<string name="password">Parool</string>
|
||||||
|
<string name="permissions">Load</string>
|
||||||
|
<string name="project_website">Projekti veebileht</string>
|
||||||
|
<string name="promotes_non_free_network_services">Reklaamib mittevabu võrguteenuseid</string>
|
||||||
|
<string name="provided_by_FORMAT">Pakub %s</string>
|
||||||
|
<string name="proxy_host">Puhverserveri masin</string>
|
||||||
|
<string name="proxy_type">Puhverserveri tüüp</string>
|
||||||
|
<string name="repository">Hoidla</string>
|
||||||
|
<string name="repository_not_found">Järgnevat hoidlat ei leitud</string>
|
||||||
|
<string name="repository_unreachable">Hoidla on kättesaamatu</string>
|
||||||
|
<string name="requires_FORMAT">Nõuab %s</string>
|
||||||
|
<string name="require_background_access">Küsi taustal töötamise luba</string>
|
||||||
|
<string name="require_background_access_DESC">Taustal sünkroonimise õnnestumiseks tuleb lubada taustal töötamine</string>
|
||||||
|
<string name="save">Salvesta</string>
|
||||||
|
<string name="saving_details">Üksikasjade salvestamine…</string>
|
||||||
|
<string name="settings">Seaded</string>
|
||||||
|
<string name="share">Jaga</string>
|
||||||
|
<string name="show_more">Näita rohkem</string>
|
||||||
|
<string name="signature_FORMAT">Allkiri %s</string>
|
||||||
|
<string name="signed_using_unsafe_algorithm">Allkirjastatud kasutades ebaturvalist algoritmi</string>
|
||||||
|
<string name="skip">Jäta vahele</string>
|
||||||
|
<string name="special_credits">Eriline tänu</string>
|
||||||
|
<string name="suggested">Soovitatud</string>
|
||||||
|
<string name="sync_repositories">Sünkrooni hoidlad</string>
|
||||||
|
<string name="syncing_FORMAT">%s sünkroonimine…</string>
|
||||||
|
<string name="system">Süsteem</string>
|
||||||
|
<string name="tap_to_install_DESC">Puuduta paigaldamiseks.</string>
|
||||||
|
<string name="tracks_or_reports_your_activity">Jälgib või teatab sinu tegevusest</string>
|
||||||
|
<string name="ignore_signature">Eira allkirja</string>
|
||||||
|
<string name="no_applications_installed">Paigaldatud rakendusi pole</string>
|
||||||
|
<string name="network_error_DESC">Võrgu viga</string>
|
||||||
|
<string name="links">Lingid</string>
|
||||||
|
<string name="never">Mitte kunagi</string>
|
||||||
|
<string name="installation_failed_DESC">%s paigaldamine nurjus</string>
|
||||||
|
<string name="uninstalled_application_DESC">%s eemaldati</string>
|
||||||
|
<string name="invalid_fingerprint_format">Vigane sõrmejäljevorming</string>
|
||||||
|
<string name="invalid_username_format">Vigane kasutajanime vorming</string>
|
||||||
|
<string name="link_copied_to_clipboard">Link kopeeriti</string>
|
||||||
|
<string name="material_you">Material You</string>
|
||||||
|
<string name="open_shizuku">Ava Shizuku</string>
|
||||||
|
<string name="no_matching_applications_found">Selliseid rakendusi ei leitud</string>
|
||||||
|
<string name="recently_updated">Hiljuti värskendatud</string>
|
||||||
|
<string name="no_description_available_DESC">Kirjeldus puudub</string>
|
||||||
|
<string name="only_on_wifi_with_charging">Ainult WiFi võrgus laadimise ajal</string>
|
||||||
|
<string name="plus_more_FORMAT">+%d veel</string>
|
||||||
|
<string name="promotes_non_free_software">Reklaamib mittevaba tarkvara</string>
|
||||||
|
<string name="proxy_port_error_not_int">Puhverserveri port saab olla ainult täisarv</string>
|
||||||
|
<string name="show_older_versions">Kuva vanemad versioonid</string>
|
||||||
|
<string name="themes">Teemad</string>
|
||||||
|
<string name="parsing_index_error_DESC">Indeksfaili ei saanud sõeluda.</string>
|
||||||
|
<string name="proxy_port">Puhverserveri port</string>
|
||||||
|
<string name="repositories">Hoidlad</string>
|
||||||
|
<string name="password_missing">Parool puudub</string>
|
||||||
|
<string name="proxy">Puhverserver</string>
|
||||||
|
<string name="sorting_order">Sorteerimisjärjekord</string>
|
||||||
|
<string name="repository_unsigned_DESC">Allkirjata. Rakenduste loendit ei saanud kinnitada. Ole ettevaatlik rakenduste allalaadimisel allkirjastamata hoidlatest.</string>
|
||||||
|
<string name="size">Suurus</string>
|
||||||
|
<string name="source_code_no_longer_available">Lähtekood pole enam saadaval</string>
|
||||||
|
<string name="switch_to_default_installer">Lülitu vaikeseadele</string>
|
||||||
|
<string name="syncing">Sünkroonimine</string>
|
||||||
|
<string name="uninstall">Eemalda</string>
|
||||||
|
<string name="unknown_error_DESC">Tundmatu viga.</string>
|
||||||
|
<string name="unstable_updates_summary">Paku ebastabiilsete versioonide paigaldamist</string>
|
||||||
|
<string name="unknown">Tundmatu</string>
|
||||||
|
<string name="unknown_FORMAT">Tundmatu: %s</string>
|
||||||
|
<string name="unstable_updates">Ebastabiilsed uuendused</string>
|
||||||
|
<string name="processing_FORMAT">%1$s töötlemine…</string>
|
||||||
|
<string name="search">Otsi</string>
|
||||||
|
<string name="select_mirror">Vali peegel</string>
|
||||||
|
<string name="socks_proxy">SOCKS puhverserver</string>
|
||||||
|
<string name="source_code">Lähtekood</string>
|
||||||
|
<string name="sync_repositories_automatically">Sünkrooni hoidlad automaatselt</string>
|
||||||
|
<string name="theme">Teema</string>
|
||||||
|
<string name="incompatible_versions_summary">Kuva seadmega mitteühilduvaid rakenduste versioone</string>
|
||||||
|
<string name="incompatible_with_FORMAT">Ei ühildu rakendusega %s</string>
|
||||||
|
<string name="install">Paigalda</string>
|
||||||
|
<string name="install_types">Paigalduse tüübid</string>
|
||||||
|
<string name="installer">Paigaldaja</string>
|
||||||
|
<string name="insufficient_storage">Ruumi napib</string>
|
||||||
|
<string name="legacy_installer">Vana paigaldaja</string>
|
||||||
|
<string name="session_installer">Seansi paigaldaja</string>
|
||||||
|
<string name="shizuku_installer">Shizuku paigaldaja</string>
|
||||||
|
<string name="root_installer">Root-paigaldaja</string>
|
||||||
|
<string name="shizuku_not_alive">Shizuku ei tööta</string>
|
||||||
|
<string name="shizuku_not_installed">Shizuku pole paigaldatud</string>
|
||||||
|
<string name="installed">Paigaldatud</string>
|
||||||
|
<string name="installing">Paigaldamine</string>
|
||||||
|
<string name="installation_failed">Paigaldamine nurjus</string>
|
||||||
|
<string name="ignore_signature_summary">*Hoiatus* LSPosed-kasutajate või edasijõudnud kasutajate puhul eira APK paigaldamisel allkirja kontrollimist</string>
|
||||||
|
<string name="update">Uuendus</string>
|
||||||
|
<string name="upstream_source_code_is_not_free">Algne lähtekood ei ole vaba</string>
|
||||||
|
<string name="username">Kasutajanimi</string>
|
||||||
|
<string name="username_missing">Kasutajanimi puudub</string>
|
||||||
|
<string name="validation_index_error_DESC">Indeksit ei saadud kinnitada.</string>
|
||||||
|
<string name="version">Versioon</string>
|
||||||
|
<string name="version_FORMAT">Versioon %s</string>
|
||||||
|
<string name="versions">Versioonid</string>
|
||||||
|
<string name="waiting_to_start_installation">Paigaldamise alustamise ootel…</string>
|
||||||
|
<string name="whats_new">Mis on uut</string>
|
||||||
|
<string name="website">Veebileht</string>
|
||||||
|
<string name="update_all">Uuenda kõik</string>
|
||||||
|
<string name="label_open_video">Video</string>
|
||||||
|
<string name="label_unknown_sdk">Tundmatu (%d)</string>
|
||||||
|
<string name="show_less">Näita vähem</string>
|
||||||
|
<string name="prefs_personalization">Kohandamine</string>
|
||||||
|
<string name="contains_nsfw">Sisaldab NSFW sisu</string>
|
||||||
|
<string name="insufficient_storage_DESC">Seadmes pole selle rakenduse paigaldamiseks piisavalt vaba ruumi. Proovi ruumi vabastada</string>
|
||||||
|
<string name="waiting_to_start_download">Allalaadimise alustamise ootel…</string>
|
||||||
|
<string name="prefs_language_title">Keel</string>
|
||||||
|
<string name="updates">Uuendused</string>
|
||||||
|
</resources>
|
@ -50,7 +50,6 @@
|
|||||||
<string name="invalid_metadata_error_DESC">فراداده نادرست.</string>
|
<string name="invalid_metadata_error_DESC">فراداده نادرست.</string>
|
||||||
<string name="invalid_permissions_error_DESC">دسترسیهای نادرست.</string>
|
<string name="invalid_permissions_error_DESC">دسترسیهای نادرست.</string>
|
||||||
<string name="links">پیوندها</string>
|
<string name="links">پیوندها</string>
|
||||||
<string name="list_animation_description">نمایش لیست انیمیشن در صفحهاصلی</string>
|
|
||||||
<string name="merging_FORMAT">ادغام %s</string>
|
<string name="merging_FORMAT">ادغام %s</string>
|
||||||
<string name="name">نام</string>
|
<string name="name">نام</string>
|
||||||
<string name="network_error_DESC">خطای شبکه</string>
|
<string name="network_error_DESC">خطای شبکه</string>
|
||||||
@ -63,19 +62,16 @@
|
|||||||
<string name="other">دیگر</string>
|
<string name="other">دیگر</string>
|
||||||
<string name="parsing_index_error_DESC">فایل ایندکس قابل تحلیل نیست.</string>
|
<string name="parsing_index_error_DESC">فایل ایندکس قابل تحلیل نیست.</string>
|
||||||
<string name="open_DESC_FORMAT">باز کردن %s ؟</string>
|
<string name="open_DESC_FORMAT">باز کردن %s ؟</string>
|
||||||
<string name="repository_not_used_DESC">این مخزن هنوز استفاده نشده. فعالش کنید تا کارههای داخلش را ببینید.</string>
|
|
||||||
<string name="unknown">ناشناس</string>
|
<string name="unknown">ناشناس</string>
|
||||||
<string name="uninstall">پاک کردن</string>
|
<string name="uninstall">پاک کردن</string>
|
||||||
<string name="waiting_to_start_download">منتظر شروع بارگیری…</string>
|
<string name="waiting_to_start_download">منتظر شروع بارگیری…</string>
|
||||||
<string name="versions">نسخهها</string>
|
<string name="versions">نسخهها</string>
|
||||||
<string name="cleanup_title">وقفه پاکسازی APK</string>
|
<string name="cleanup_title">وقفه پاکسازی APK</string>
|
||||||
<string name="cleanup_description">دوره بررسی و پاک سازی داده های دریافت شده</string>
|
|
||||||
<string name="has_security_vulnerabilities">دارای حفرههای امنیتی</string>
|
<string name="has_security_vulnerabilities">دارای حفرههای امنیتی</string>
|
||||||
<string name="http_error_DESC">پاسخ نادرست از مرکز.</string>
|
<string name="http_error_DESC">پاسخ نادرست از مرکز.</string>
|
||||||
<string name="incompatible_versions">نسخههای ناسازگار</string>
|
<string name="incompatible_versions">نسخههای ناسازگار</string>
|
||||||
<string name="incompatible_with_FORMAT">ناسازگاری با %s</string>
|
<string name="incompatible_with_FORMAT">ناسازگاری با %s</string>
|
||||||
<string name="invalid_signature_error_DESC">امضای نادرست.</string>
|
<string name="invalid_signature_error_DESC">امضای نادرست.</string>
|
||||||
<string name="list_animation">لیست انیمیشنها</string>
|
|
||||||
<string name="no_applications_available">هیچ کارهای فراهم نیست</string>
|
<string name="no_applications_available">هیچ کارهای فراهم نیست</string>
|
||||||
<string name="no_applications_installed">هیچ کارهای نصب نیست</string>
|
<string name="no_applications_installed">هیچ کارهای نصب نیست</string>
|
||||||
<string name="number_of_applications">تعداد کارهها</string>
|
<string name="number_of_applications">تعداد کارهها</string>
|
||||||
@ -85,7 +81,6 @@
|
|||||||
<string name="plus_more_FORMAT">%d+ بیشتر</string>
|
<string name="plus_more_FORMAT">%d+ بیشتر</string>
|
||||||
<string name="settings">تنظیمات</string>
|
<string name="settings">تنظیمات</string>
|
||||||
<string name="processing_FORMAT">درحالپردازش %1$s …</string>
|
<string name="processing_FORMAT">درحالپردازش %1$s …</string>
|
||||||
<string name="root_permission_description">اجازه دسترسی روت برای نصب بدونپرسش</string>
|
|
||||||
<string name="signature_FORMAT">امضاء %s</string>
|
<string name="signature_FORMAT">امضاء %s</string>
|
||||||
<string name="signed_using_unsafe_algorithm">با الگوریتم ناامن امضاء شده</string>
|
<string name="signed_using_unsafe_algorithm">با الگوریتم ناامن امضاء شده</string>
|
||||||
<string name="size">حجم</string>
|
<string name="size">حجم</string>
|
||||||
@ -103,10 +98,7 @@
|
|||||||
<string name="prefs_language_title">زبان</string>
|
<string name="prefs_language_title">زبان</string>
|
||||||
<string name="prefs_personalization">شخصیسازی</string>
|
<string name="prefs_personalization">شخصیسازی</string>
|
||||||
<string name="show_less">نمایش کمتر</string>
|
<string name="show_less">نمایش کمتر</string>
|
||||||
<string name="latest">آخرین</string>
|
|
||||||
<string name="explore">اکتشاف</string>
|
|
||||||
<string name="update_all">بهروزرسانی همه</string>
|
<string name="update_all">بهروزرسانی همه</string>
|
||||||
<string name="sort_filter">ترتیب و فیلتر</string>
|
|
||||||
<string name="root_installer">نصاب روت</string>
|
<string name="root_installer">نصاب روت</string>
|
||||||
<string name="installer">نصاب</string>
|
<string name="installer">نصاب</string>
|
||||||
<string name="legacy_installer">نصاب قدیمی</string>
|
<string name="legacy_installer">نصاب قدیمی</string>
|
||||||
@ -126,8 +118,6 @@
|
|||||||
<string name="repositories">مخازن</string>
|
<string name="repositories">مخازن</string>
|
||||||
<string name="repository">مخزن</string>
|
<string name="repository">مخزن</string>
|
||||||
<string name="requires_FORMAT">نیازمند %s</string>
|
<string name="requires_FORMAT">نیازمند %s</string>
|
||||||
<string name="root_permission">نصب بدونپرسش</string>
|
|
||||||
<string name="screenshots">اسکرینشاتها</string>
|
|
||||||
<string name="search">جستجو</string>
|
<string name="search">جستجو</string>
|
||||||
<string name="select_mirror">از کجا دریافت کنم</string>
|
<string name="select_mirror">از کجا دریافت کنم</string>
|
||||||
<string name="share">همرسانی</string>
|
<string name="share">همرسانی</string>
|
||||||
@ -135,15 +125,12 @@
|
|||||||
<string name="saving_details">درحالذخیره جزییات…</string>
|
<string name="saving_details">درحالذخیره جزییات…</string>
|
||||||
<string name="show_more">نمایش بیشتر</string>
|
<string name="show_more">نمایش بیشتر</string>
|
||||||
<string name="show_older_versions">نمایش نسخههای قدیمی</string>
|
<string name="show_older_versions">نمایش نسخههای قدیمی</string>
|
||||||
<string name="target">هدف</string>
|
|
||||||
<string name="theme">پوسته</string>
|
<string name="theme">پوسته</string>
|
||||||
<string name="themes">پوستهها</string>
|
<string name="themes">پوستهها</string>
|
||||||
<string name="tracks_or_reports_your_activity">رهگیری یا گزارش فعالیت شما</string>
|
<string name="tracks_or_reports_your_activity">رهگیری یا گزارش فعالیت شما</string>
|
||||||
<string name="unknown_error_DESC">خطای ناشناخته.</string>
|
<string name="unknown_error_DESC">خطای ناشناخته.</string>
|
||||||
<string name="unknown_FORMAT">ناشناخته: %s</string>
|
<string name="unknown_FORMAT">ناشناخته: %s</string>
|
||||||
<string name="unsigned">امضاءنشده</string>
|
|
||||||
<string name="unstable_updates">بهروزرسانی های ناپایدار</string>
|
<string name="unstable_updates">بهروزرسانی های ناپایدار</string>
|
||||||
<string name="unverified">تایید نشده</string>
|
|
||||||
<string name="username">نامکاربری</string>
|
<string name="username">نامکاربری</string>
|
||||||
<string name="validation_index_error_DESC">ایندکس قابل تایید شدن نیست.</string>
|
<string name="validation_index_error_DESC">ایندکس قابل تایید شدن نیست.</string>
|
||||||
<string name="whats_new">چه خبر</string>
|
<string name="whats_new">چه خبر</string>
|
||||||
@ -188,20 +175,14 @@
|
|||||||
<string name="unstable_updates_summary">پیشنهاد نصب نسخههای آزمایشی</string>
|
<string name="unstable_updates_summary">پیشنهاد نصب نسخههای آزمایشی</string>
|
||||||
<string name="source_code_no_longer_available">کد منبع دیگر موجود نیست</string>
|
<string name="source_code_no_longer_available">کد منبع دیگر موجود نیست</string>
|
||||||
<string name="syncing_FORMAT">در حال بهروزرسانی %s …</string>
|
<string name="syncing_FORMAT">در حال بهروزرسانی %s …</string>
|
||||||
<string name="installed_applications">کارههای نصب شده</string>
|
|
||||||
<string name="updates">بهروزرسانی ها</string>
|
<string name="updates">بهروزرسانی ها</string>
|
||||||
<string name="new_applications">کارههای جدید</string>
|
|
||||||
<string name="version">نسخه</string>
|
<string name="version">نسخه</string>
|
||||||
<string name="version_FORMAT">نسخه %s</string>
|
<string name="version_FORMAT">نسخه %s</string>
|
||||||
<string name="no_internet">شما هیچ اتصال اینترنتی ندارید</string>
|
|
||||||
<string name="io_error_DESC">قادر به انجام برخی اقدامات خاص نیست.</string>
|
<string name="io_error_DESC">قادر به انجام برخی اقدامات خاص نیست.</string>
|
||||||
<string name="allow_collapsing_toolbar">به نوار بالای کاره اجازه دهید تا گسترش یابد</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">به نوار بالای کاره اجازه دهید تا گسترده و فشرده شود</string>
|
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="material_you_desc">از پوسته رنگی material you استفاده کنید</string>
|
<string name="material_you_desc">از پوسته رنگی material you استفاده کنید</string>
|
||||||
<string name="enable_repo">مخزن را فعال کنید</string>
|
<string name="enable_repo">مخزن را فعال کنید</string>
|
||||||
<string name="force_clean_up">پاکسازی اجباری</string>
|
<string name="force_clean_up">پاکسازی اجباری</string>
|
||||||
<string name="restart_app">برای مشاهده تغییرات، Droid-ify را مجددا راه اندازی کنید</string>
|
|
||||||
<string name="favourites">موارد دلخواه</string>
|
<string name="favourites">موارد دلخواه</string>
|
||||||
<string name="repository_unreachable">مخزن قابل دسترسی نیست</string>
|
<string name="repository_unreachable">مخزن قابل دسترسی نیست</string>
|
||||||
<string name="auto_update">بهروز رسانی خودکار کارهها</string>
|
<string name="auto_update">بهروز رسانی خودکار کارهها</string>
|
||||||
@ -230,7 +211,6 @@
|
|||||||
<string name="socket_error_DESC">سرور در فراهم کردن بسته اطلاعات جدید ناموفق بود</string>
|
<string name="socket_error_DESC">سرور در فراهم کردن بسته اطلاعات جدید ناموفق بود</string>
|
||||||
<string name="connection_error_DESC">اتصال به سرور ناموفق بود</string>
|
<string name="connection_error_DESC">اتصال به سرور ناموفق بود</string>
|
||||||
<string name="home_screen_swiping">حرکات صفحه اصلی</string>
|
<string name="home_screen_swiping">حرکات صفحه اصلی</string>
|
||||||
<string name="label_copy">کپی</string>
|
|
||||||
<string name="special_credits">تشکر ویژه</string>
|
<string name="special_credits">تشکر ویژه</string>
|
||||||
<string name="require_background_access">نیازمند دسترسی پسزمینه</string>
|
<string name="require_background_access">نیازمند دسترسی پسزمینه</string>
|
||||||
<string name="require_background_access_DESC">برای همگامسازی در پسزمینه، دسترسی پسزمینه لازم است</string>
|
<string name="require_background_access_DESC">برای همگامسازی در پسزمینه، دسترسی پسزمینه لازم است</string>
|
||||||
@ -241,4 +221,16 @@
|
|||||||
<string name="ignore_signature_summary">هنگام نصب APK ، برای کاربران Lsposed یا کاربران پیشرفته ، تأیید امضا نادیده گرفته شود</string>
|
<string name="ignore_signature_summary">هنگام نصب APK ، برای کاربران Lsposed یا کاربران پیشرفته ، تأیید امضا نادیده گرفته شود</string>
|
||||||
<string name="installation_failed_DESC">نصب %s ناموفق بود</string>
|
<string name="installation_failed_DESC">نصب %s ناموفق بود</string>
|
||||||
<string name="insufficient_storage_DESC">فضای کافی برای نصب این برنامه روی دستگاه وجود ندارد. سعی کنید مقداری فضا خالی کنید.</string>
|
<string name="insufficient_storage_DESC">فضای کافی برای نصب این برنامه روی دستگاه وجود ندارد. سعی کنید مقداری فضا خالی کنید.</string>
|
||||||
</resources>
|
<string name="label_targets_sdk">هدف: اندروید %s</string>
|
||||||
|
<string name="error_shizuku_not_granted">دسترسی شیزوکو داده نشده</string>
|
||||||
|
<string name="error_shizuku_not_running_DESC">خدمت شیزوکو اجرا نمیشود. لطفا برنامه شیزوکو را بررسی کنید</string>
|
||||||
|
<string name="error_shizuku_service_unavailable">شیزوکو اجرا نمیشود</string>
|
||||||
|
<string name="error_shizuku_not_granted_DESC">مجوز خدمت شیزوکو داده نشده. لطفا برنامه شیزوکو را بررسی کنید</string>
|
||||||
|
<string name="error_shizuku_not_installed">شیزوکو نصب نشده</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">به نظر میرسد شیزوکو نصب نشده</string>
|
||||||
|
<string name="insufficient_storage">فضای ناکافی</string>
|
||||||
|
<string name="open_shizuku">بازکردن شیزوکو</string>
|
||||||
|
<string name="switch_to_default_installer">جابهجایی به عادی</string>
|
||||||
|
<string name="label_open_video">ویدیو</string>
|
||||||
|
<string name="label_unknown_sdk">ناشناخته (%d)</string>
|
||||||
|
</resources>
|
||||||
|
@ -72,8 +72,6 @@
|
|||||||
<string name="light">Vaalea</string>
|
<string name="light">Vaalea</string>
|
||||||
<string name="link_copied_to_clipboard">Linkki kopioitu</string>
|
<string name="link_copied_to_clipboard">Linkki kopioitu</string>
|
||||||
<string name="links">Linkit</string>
|
<string name="links">Linkit</string>
|
||||||
<string name="list_animation">Luettelon animaatiot</string>
|
|
||||||
<string name="list_animation_description">Näytä luettelon animaatio pääsivulla</string>
|
|
||||||
<string name="merging_FORMAT">Yhdistetään %s</string>
|
<string name="merging_FORMAT">Yhdistetään %s</string>
|
||||||
<string name="name">Nimi</string>
|
<string name="name">Nimi</string>
|
||||||
<string name="network_error_DESC">Verkkovirhe</string>
|
<string name="network_error_DESC">Verkkovirhe</string>
|
||||||
@ -95,11 +93,8 @@
|
|||||||
<string name="repositories">Ohjelmavarastot</string>
|
<string name="repositories">Ohjelmavarastot</string>
|
||||||
<string name="repository">Ohjelmavarasto</string>
|
<string name="repository">Ohjelmavarasto</string>
|
||||||
<string name="requires_FORMAT">Vaatii %s</string>
|
<string name="requires_FORMAT">Vaatii %s</string>
|
||||||
<string name="root_permission">Hiljainen asennus</string>
|
|
||||||
<string name="root_permission_description">Salli pääkäyttäjän oikeudet hiljaisiin asennuksiin</string>
|
|
||||||
<string name="save">Tallenna</string>
|
<string name="save">Tallenna</string>
|
||||||
<string name="saving_details">Tallennetaan tietoja…</string>
|
<string name="saving_details">Tallennetaan tietoja…</string>
|
||||||
<string name="screenshots">Kuvakaappaukset</string>
|
|
||||||
<string name="only_on_wifi">Vain Wi-Fi verkossa</string>
|
<string name="only_on_wifi">Vain Wi-Fi verkossa</string>
|
||||||
<string name="open_DESC_FORMAT">Avaa %s\?</string>
|
<string name="open_DESC_FORMAT">Avaa %s\?</string>
|
||||||
<string name="other">Muut</string>
|
<string name="other">Muut</string>
|
||||||
@ -127,9 +122,7 @@
|
|||||||
<string name="unknown">Tuntematon</string>
|
<string name="unknown">Tuntematon</string>
|
||||||
<string name="unknown_error_DESC">Tuntematon virhe.</string>
|
<string name="unknown_error_DESC">Tuntematon virhe.</string>
|
||||||
<string name="unknown_FORMAT">Tuntematon: %s</string>
|
<string name="unknown_FORMAT">Tuntematon: %s</string>
|
||||||
<string name="unsigned">Allekirjoittamaton</string>
|
|
||||||
<string name="unstable_updates">Epävakaat päivitykset</string>
|
<string name="unstable_updates">Epävakaat päivitykset</string>
|
||||||
<string name="unverified">Vahvistamaton</string>
|
|
||||||
<string name="upstream_source_code_is_not_free">Alkuperäinen lähdekoodi ei ole vapaa</string>
|
<string name="upstream_source_code_is_not_free">Alkuperäinen lähdekoodi ei ole vapaa</string>
|
||||||
<string name="website">Verkkosivusto</string>
|
<string name="website">Verkkosivusto</string>
|
||||||
<string name="whats_new">Mitä uutta</string>
|
<string name="whats_new">Mitä uutta</string>
|
||||||
@ -151,13 +144,11 @@
|
|||||||
<string name="syncing_FORMAT">Synkronoidaan %s…</string>
|
<string name="syncing_FORMAT">Synkronoidaan %s…</string>
|
||||||
<string name="themes">Teemat</string>
|
<string name="themes">Teemat</string>
|
||||||
<string name="theme">Teema</string>
|
<string name="theme">Teema</string>
|
||||||
<string name="target">Kohde</string>
|
|
||||||
<string name="tap_to_install_DESC">Napauta asentaaksesi.</string>
|
<string name="tap_to_install_DESC">Napauta asentaaksesi.</string>
|
||||||
<string name="system">Järjestelmä</string>
|
<string name="system">Järjestelmä</string>
|
||||||
<string name="update">Päivitys</string>
|
<string name="update">Päivitys</string>
|
||||||
<string name="updates">Päivitykset</string>
|
<string name="updates">Päivitykset</string>
|
||||||
<string name="promotes_non_free_software">Edistää ei-vapaita ohjelmia</string>
|
<string name="promotes_non_free_software">Edistää ei-vapaita ohjelmia</string>
|
||||||
<string name="repository_not_used_DESC">Tätä ohjelmavarastoa ei ole vielä käytetty. Ota se käyttöön nähdäksesi siinä olevat sovellukset.</string>
|
|
||||||
<string name="proxy">Välityspalvelin</string>
|
<string name="proxy">Välityspalvelin</string>
|
||||||
<string name="repository_unsigned_DESC">Allekirjoittamaton. Sovellusluetteloa ei voitu tarkistaa. Ole varovainen ladatessasi sovelluksia allekirjoittamattomista arkistoista.</string>
|
<string name="repository_unsigned_DESC">Allekirjoittamaton. Sovellusluetteloa ei voitu tarkistaa. Ole varovainen ladatessasi sovelluksia allekirjoittamattomista arkistoista.</string>
|
||||||
<string name="version_FORMAT">Versio %s</string>
|
<string name="version_FORMAT">Versio %s</string>
|
||||||
@ -171,19 +162,13 @@
|
|||||||
<string name="prefs_personalization">Mukauttaminen</string>
|
<string name="prefs_personalization">Mukauttaminen</string>
|
||||||
<string name="prefs_language_title">Kieli</string>
|
<string name="prefs_language_title">Kieli</string>
|
||||||
<string name="show_less">Näytä vähemmän</string>
|
<string name="show_less">Näytä vähemmän</string>
|
||||||
<string name="latest">Uusimmat</string>
|
|
||||||
<string name="explore">Tutustu</string>
|
|
||||||
<string name="update_all">Päivitä kaikki</string>
|
<string name="update_all">Päivitä kaikki</string>
|
||||||
<string name="installed_applications">Asennetut sovellukset</string>
|
|
||||||
<string name="new_applications">Uudet sovellukset</string>
|
|
||||||
<string name="sort_filter">Lajittele ja suodata</string>
|
|
||||||
<string name="installer">Asentaja</string>
|
<string name="installer">Asentaja</string>
|
||||||
<string name="legacy_installer">Vanha asentaja</string>
|
<string name="legacy_installer">Vanha asentaja</string>
|
||||||
<string name="session_installer">Sessioasentaja</string>
|
<string name="session_installer">Sessioasentaja</string>
|
||||||
<string name="root_installer">Root-asentaja</string>
|
<string name="root_installer">Root-asentaja</string>
|
||||||
<string name="shizuku_installer">Shizuku-asentaja</string>
|
<string name="shizuku_installer">Shizuku-asentaja</string>
|
||||||
<string name="cleanup_title">APK:n puhdistusväli</string>
|
<string name="cleanup_title">APK:n puhdistusväli</string>
|
||||||
<string name="cleanup_description">Aika ladattujen tiedostojen tarkistamiseen ja poistamiseen</string>
|
|
||||||
<plurals name="days">
|
<plurals name="days">
|
||||||
<item quantity="one">Päivä</item>
|
<item quantity="one">Päivä</item>
|
||||||
<item quantity="other">Päivää</item>
|
<item quantity="other">Päivää</item>
|
||||||
@ -194,9 +179,6 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="only_on_wifi_with_charging">Vain Wi-Fi verkossa latauksessa ollessa</string>
|
<string name="only_on_wifi_with_charging">Vain Wi-Fi verkossa latauksessa ollessa</string>
|
||||||
<string name="io_error_DESC">Tiettyjä toimia ei voida suorittaa.</string>
|
<string name="io_error_DESC">Tiettyjä toimia ei voida suorittaa.</string>
|
||||||
<string name="allow_collapsing_toolbar">Salli yläosan sovelluspalkin laajeneminen</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">Salli yläosan sovelluspalkin laajentua ja tiivistyä</string>
|
|
||||||
<string name="no_internet">Ei internet yhteyttä</string>
|
|
||||||
<string name="favourites">Suosikit</string>
|
<string name="favourites">Suosikit</string>
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="material_you_desc">Käytä Material You -väriteemaa</string>
|
<string name="material_you_desc">Käytä Material You -väriteemaa</string>
|
||||||
@ -205,7 +187,6 @@
|
|||||||
<string name="force_clean_up_DESC">Puhdistaa tarpeettomat tiedostot</string>
|
<string name="force_clean_up_DESC">Puhdistaa tarpeettomat tiedostot</string>
|
||||||
<string name="repository_unreachable">Ohjelmavarasto ei ole tavoitettavissa</string>
|
<string name="repository_unreachable">Ohjelmavarasto ei ole tavoitettavissa</string>
|
||||||
<string name="installing">Asentaa</string>
|
<string name="installing">Asentaa</string>
|
||||||
<string name="restart_app">Käynnistä Droid-ify uudelleen nähdäksesi muutokset</string>
|
|
||||||
<string name="waiting_to_start_installation">Odotetaan asennuksen aloittamista…</string>
|
<string name="waiting_to_start_installation">Odotetaan asennuksen aloittamista…</string>
|
||||||
<string name="auto_update">Päivitä sovelluksia automaattisesti</string>
|
<string name="auto_update">Päivitä sovelluksia automaattisesti</string>
|
||||||
<string name="auto_update_apps">Yritä asentaa päivitykset automaattisesti</string>
|
<string name="auto_update_apps">Yritä asentaa päivitykset automaattisesti</string>
|
||||||
@ -215,7 +196,6 @@
|
|||||||
<string name="shizuku_not_alive">Shizuku ei ole käynnissä</string>
|
<string name="shizuku_not_alive">Shizuku ei ole käynnissä</string>
|
||||||
<string name="connection_error_DESC">Palvelimeen ei saatu yhteyttä</string>
|
<string name="connection_error_DESC">Palvelimeen ei saatu yhteyttä</string>
|
||||||
<string name="socket_error_DESC">Palvelin ei pystynyt toimittamaan uutta pakettia.</string>
|
<string name="socket_error_DESC">Palvelin ei pystynyt toimittamaan uutta pakettia.</string>
|
||||||
<string name="label_copy">Kopioi</string>
|
|
||||||
<string name="proxy_port_error_not_int">Välityspalvelimen portti voi olla vain kokonaisluku</string>
|
<string name="proxy_port_error_not_int">Välityspalvelimen portti voi olla vain kokonaisluku</string>
|
||||||
<string name="home_screen_swiping_DESC">Salli käyttäjän pyyhkäistä sivujen välillä aloitusnäytössä</string>
|
<string name="home_screen_swiping_DESC">Salli käyttäjän pyyhkäistä sivujen välillä aloitusnäytössä</string>
|
||||||
<string name="repository_not_found">Seuraavaa ohjelmavarastoa ei löytynyt</string>
|
<string name="repository_not_found">Seuraavaa ohjelmavarastoa ei löytynyt</string>
|
||||||
|
@ -61,7 +61,6 @@
|
|||||||
<string name="source_code">Code source</string>
|
<string name="source_code">Code source</string>
|
||||||
<string name="size">Taille</string>
|
<string name="size">Taille</string>
|
||||||
<string name="skip">Ignorer</string>
|
<string name="skip">Ignorer</string>
|
||||||
<string name="screenshots">Captures d’écran</string>
|
|
||||||
<string name="search">Chercher</string>
|
<string name="search">Chercher</string>
|
||||||
<string name="select_mirror">Sélectionnez un miroir</string>
|
<string name="select_mirror">Sélectionnez un miroir</string>
|
||||||
<string name="share">Partager</string>
|
<string name="share">Partager</string>
|
||||||
@ -81,7 +80,6 @@
|
|||||||
<string name="website">Site internet</string>
|
<string name="website">Site internet</string>
|
||||||
<string name="update">Mettre à jour</string>
|
<string name="update">Mettre à jour</string>
|
||||||
<string name="updates">Mises à jour</string>
|
<string name="updates">Mises à jour</string>
|
||||||
<string name="unverified">Non vérifié</string>
|
|
||||||
<string name="unknown_FORMAT">Inconnu : %s</string>
|
<string name="unknown_FORMAT">Inconnu : %s</string>
|
||||||
<string name="unknown_error_DESC">Erreur inconnue.</string>
|
<string name="unknown_error_DESC">Erreur inconnue.</string>
|
||||||
<string name="add_repository">Ajouter un dépôt</string>
|
<string name="add_repository">Ajouter un dépôt</string>
|
||||||
@ -98,7 +96,6 @@
|
|||||||
<string name="uninstall">Désinstaller</string>
|
<string name="uninstall">Désinstaller</string>
|
||||||
<string name="could_not_validate_FORMAT">Impossible de valider %s</string>
|
<string name="could_not_validate_FORMAT">Impossible de valider %s</string>
|
||||||
<string name="system">Système</string>
|
<string name="system">Système</string>
|
||||||
<string name="target">Cible</string>
|
|
||||||
<string name="password_missing">Mot de passe manquant</string>
|
<string name="password_missing">Mot de passe manquant</string>
|
||||||
<string name="credits">Crédits</string>
|
<string name="credits">Crédits</string>
|
||||||
<string name="themes">Thèmes</string>
|
<string name="themes">Thèmes</string>
|
||||||
@ -116,7 +113,6 @@
|
|||||||
<string name="incompatible_features_DESC">Fonctionnalités manquantes.</string>
|
<string name="incompatible_features_DESC">Fonctionnalités manquantes.</string>
|
||||||
<string name="incompatible_older_DESC">Cette version est plus ancienne que celle qui est installée sur votre appareil. Désinstallez-la d’abord.</string>
|
<string name="incompatible_older_DESC">Cette version est plus ancienne que celle qui est installée sur votre appareil. Désinstallez-la d’abord.</string>
|
||||||
<string name="notify_about_updates_summary">Afficher une notification quand de nouvelles versions sont disponibles</string>
|
<string name="notify_about_updates_summary">Afficher une notification quand de nouvelles versions sont disponibles</string>
|
||||||
<string name="repository_not_used_DESC">Ce dépôt n’a pas encore été utilisé. Activez-le pour voir les applications qu’il contient.</string>
|
|
||||||
<string name="no_applications_installed">Aucune application installée</string>
|
<string name="no_applications_installed">Aucune application installée</string>
|
||||||
<string name="repository_unsigned_DESC">Non signé. Impossible de vérifier la liste d’applis. Soyez prudents lorsque vous téléchargez des applis de dépôts non signés.</string>
|
<string name="repository_unsigned_DESC">Non signé. Impossible de vérifier la liste d’applis. Soyez prudents lorsque vous téléchargez des applis de dépôts non signés.</string>
|
||||||
<string name="has_non_free_dependencies">Dépend d’applications qui ne sont pas libres</string>
|
<string name="has_non_free_dependencies">Dépend d’applications qui ne sont pas libres</string>
|
||||||
@ -143,8 +139,6 @@
|
|||||||
<string name="proxy_host">Adresse du proxy</string>
|
<string name="proxy_host">Adresse du proxy</string>
|
||||||
<string name="proxy_port">Port du proxy</string>
|
<string name="proxy_port">Port du proxy</string>
|
||||||
<string name="proxy_type">Type de proxy</string>
|
<string name="proxy_type">Type de proxy</string>
|
||||||
<string name="root_permission">Installation silencieuse</string>
|
|
||||||
<string name="root_permission_description">Autoriser la permission de l’utilisateur root pour les installations silencieuses</string>
|
|
||||||
<string name="show_older_versions">Afficher les versions plus anciennes</string>
|
<string name="show_older_versions">Afficher les versions plus anciennes</string>
|
||||||
<string name="signature_FORMAT">Signature %s</string>
|
<string name="signature_FORMAT">Signature %s</string>
|
||||||
<string name="signed_using_unsafe_algorithm">Signé avec un algorithme qui n’est pas sécurisé</string>
|
<string name="signed_using_unsafe_algorithm">Signé avec un algorithme qui n’est pas sécurisé</string>
|
||||||
@ -152,7 +146,6 @@
|
|||||||
<string name="sync_repositories_automatically">Synchroniser les dépôts automatiquement</string>
|
<string name="sync_repositories_automatically">Synchroniser les dépôts automatiquement</string>
|
||||||
<string name="syncing">Synchronisation en cours</string>
|
<string name="syncing">Synchronisation en cours</string>
|
||||||
<string name="syncing_FORMAT">Synchronisation de %s en cours…</string>
|
<string name="syncing_FORMAT">Synchronisation de %s en cours…</string>
|
||||||
<string name="unsigned">Non-signé</string>
|
|
||||||
<string name="unstable_updates">Mises à jour instables</string>
|
<string name="unstable_updates">Mises à jour instables</string>
|
||||||
<string name="upstream_source_code_is_not_free">Le code source n’est pas entièrement libre</string>
|
<string name="upstream_source_code_is_not_free">Le code source n’est pas entièrement libre</string>
|
||||||
<string name="username">Nom d’utilisateur</string>
|
<string name="username">Nom d’utilisateur</string>
|
||||||
@ -161,30 +154,22 @@
|
|||||||
<string name="incompatible_api_DESC_FORMAT">Votre %1$s (API version %2$d) n’est pas pris en charge. %3$s</string>
|
<string name="incompatible_api_DESC_FORMAT">Votre %1$s (API version %2$d) n’est pas pris en charge. %3$s</string>
|
||||||
<string name="integrity_check_error_DESC">Impossible de vérifier l’intégrité.</string>
|
<string name="integrity_check_error_DESC">Impossible de vérifier l’intégrité.</string>
|
||||||
<string name="invalid_fingerprint_format">Format d’empreinte digitale non valide</string>
|
<string name="invalid_fingerprint_format">Format d’empreinte digitale non valide</string>
|
||||||
<string name="list_animation">Animations de listes</string>
|
|
||||||
<string name="processing_FORMAT">Traitement de %1$s…</string>
|
<string name="processing_FORMAT">Traitement de %1$s…</string>
|
||||||
<string name="parsing_index_error_DESC">Impossible d’analyser le fichier d’index.</string>
|
<string name="parsing_index_error_DESC">Impossible d’analyser le fichier d’index.</string>
|
||||||
<string name="merging_FORMAT">Fusionner %s</string>
|
<string name="merging_FORMAT">Fusionner %s</string>
|
||||||
<string name="list_animation_description">Afficher l’animation de la liste sur la page principale</string>
|
|
||||||
<string name="sorting_order">Ordre de tri</string>
|
<string name="sorting_order">Ordre de tri</string>
|
||||||
<string name="requires_FORMAT">Requiert %s</string>
|
<string name="requires_FORMAT">Requiert %s</string>
|
||||||
<string name="unstable_updates_summary">Suggérer l’installation de versions instables</string>
|
<string name="unstable_updates_summary">Suggérer l’installation de versions instables</string>
|
||||||
<string name="prefs_language_title">Langue</string>
|
<string name="prefs_language_title">Langue</string>
|
||||||
<string name="prefs_personalization">Personnalisation</string>
|
<string name="prefs_personalization">Personnalisation</string>
|
||||||
<string name="show_less">Afficher moins</string>
|
<string name="show_less">Afficher moins</string>
|
||||||
<string name="latest">Le plus récent</string>
|
|
||||||
<string name="sort_filter">Trier et filtrer</string>
|
|
||||||
<string name="new_applications">Nouvelles applications</string>
|
|
||||||
<string name="explore">Explorer</string>
|
|
||||||
<string name="update_all">Tout mettre à jour</string>
|
<string name="update_all">Tout mettre à jour</string>
|
||||||
<string name="installed_applications">Applications installées</string>
|
|
||||||
<string name="session_installer">Installateur de session</string>
|
<string name="session_installer">Installateur de session</string>
|
||||||
<string name="legacy_installer">Installateur hérité</string>
|
<string name="legacy_installer">Installateur hérité</string>
|
||||||
<string name="installer">Installateur</string>
|
<string name="installer">Installateur</string>
|
||||||
<string name="root_installer">Installateur racine</string>
|
<string name="root_installer">Installateur racine</string>
|
||||||
<string name="shizuku_installer">Installateur Shizuku</string>
|
<string name="shizuku_installer">Installateur Shizuku</string>
|
||||||
<string name="cleanup_title">Intervalle de nettoyage des APK</string>
|
<string name="cleanup_title">Intervalle de nettoyage des APK</string>
|
||||||
<string name="cleanup_description">Période de vérification et de suppression des fichiers téléchargés</string>
|
|
||||||
<plurals name="days">
|
<plurals name="days">
|
||||||
<item quantity="one">Jour</item>
|
<item quantity="one">Jour</item>
|
||||||
<item quantity="many">Jours</item>
|
<item quantity="many">Jours</item>
|
||||||
@ -197,9 +182,6 @@
|
|||||||
</plurals>
|
</plurals>
|
||||||
<string name="only_on_wifi_with_charging">Uniquement sur Wi-Fi et charge</string>
|
<string name="only_on_wifi_with_charging">Uniquement sur Wi-Fi et charge</string>
|
||||||
<string name="io_error_DESC">Impossible d’effectuer certaines actions.</string>
|
<string name="io_error_DESC">Impossible d’effectuer certaines actions.</string>
|
||||||
<string name="no_internet">Vous n’avez pas de connexion internet</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">Autoriser l\'expansion et la réduction de la barre supérieure de l\'appli</string>
|
|
||||||
<string name="allow_collapsing_toolbar">Autoriser l\'expansion de la barre supérieure de l\'appli</string>
|
|
||||||
<string name="material_you_desc">Utiliser le thème couleur Material You</string>
|
<string name="material_you_desc">Utiliser le thème couleur Material You</string>
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="favourites">Favoris</string>
|
<string name="favourites">Favoris</string>
|
||||||
@ -208,7 +190,6 @@
|
|||||||
<string name="force_clean_up_DESC">Nettoyer les fichiers redondants</string>
|
<string name="force_clean_up_DESC">Nettoyer les fichiers redondants</string>
|
||||||
<string name="enable_repo">Activer le dépôt</string>
|
<string name="enable_repo">Activer le dépôt</string>
|
||||||
<string name="installing">Installation</string>
|
<string name="installing">Installation</string>
|
||||||
<string name="restart_app">Redémarrez Droid-ify pour voir les changements</string>
|
|
||||||
<string name="waiting_to_start_installation">En attente du démarrage de l\'installation…</string>
|
<string name="waiting_to_start_installation">En attente du démarrage de l\'installation…</string>
|
||||||
<string name="auto_update">Mise à jour automatique des applis</string>
|
<string name="auto_update">Mise à jour automatique des applis</string>
|
||||||
<string name="auto_update_apps">Essayez d\'installer les mises à jour automatiquement</string>
|
<string name="auto_update_apps">Essayez d\'installer les mises à jour automatiquement</string>
|
||||||
@ -221,7 +202,6 @@
|
|||||||
<string name="special_credits">Crédits spéciaux</string>
|
<string name="special_credits">Crédits spéciaux</string>
|
||||||
<string name="home_screen_swiping">Balayage de l\'écran d\'accueil</string>
|
<string name="home_screen_swiping">Balayage de l\'écran d\'accueil</string>
|
||||||
<string name="home_screen_swiping_DESC">Permettre à l\'utilisateur de passer d\'une page à l\'autre dans l\'écran d\'accueil</string>
|
<string name="home_screen_swiping_DESC">Permettre à l\'utilisateur de passer d\'une page à l\'autre dans l\'écran d\'accueil</string>
|
||||||
<string name="label_copy">Copier</string>
|
|
||||||
<string name="repository_not_found">Le dépôt suivant n\'a pas été trouvé</string>
|
<string name="repository_not_found">Le dépôt suivant n\'a pas été trouvé</string>
|
||||||
<string name="proxy_port_error_not_int">Le port proxy ne peut être qu\'un entier</string>
|
<string name="proxy_port_error_not_int">Le port proxy ne peut être qu\'un entier</string>
|
||||||
<string name="import_settings_title">Importer les paramètres</string>
|
<string name="import_settings_title">Importer les paramètres</string>
|
||||||
@ -245,4 +225,14 @@
|
|||||||
<string name="ignore_signature_summary">*Attention* Ignorer la vérification de la signature lors de l\'installation de l\'APK, pour les utilisateurs de LSPosed ou les utilisateurs avancés</string>
|
<string name="ignore_signature_summary">*Attention* Ignorer la vérification de la signature lors de l\'installation de l\'APK, pour les utilisateurs de LSPosed ou les utilisateurs avancés</string>
|
||||||
<string name="insufficient_storage">Espace insuffisant</string>
|
<string name="insufficient_storage">Espace insuffisant</string>
|
||||||
<string name="insufficient_storage_DESC">Il n\'y a pas assez d\'espace libre sur l\'appareil pour installer cette application. Essayez de libérer de l\'espace</string>
|
<string name="insufficient_storage_DESC">Il n\'y a pas assez d\'espace libre sur l\'appareil pour installer cette application. Essayez de libérer de l\'espace</string>
|
||||||
</resources>
|
<string name="error_shizuku_not_running_DESC">Le service Shizuku n\'est pas démarré. Merci de le vérifier dans l\'appli Shizuku</string>
|
||||||
|
<string name="error_shizuku_service_unavailable">Shizuku Non Démarré</string>
|
||||||
|
<string name="error_shizuku_not_granted">Permission Shizuku Manquante</string>
|
||||||
|
<string name="error_shizuku_not_granted_DESC">La permission du service Shizuku n\'est pas accordée. Merci de la vérifier via l\'appli Shizuku</string>
|
||||||
|
<string name="error_shizuku_not_installed">Shizuku Non Installé</string>
|
||||||
|
<string name="error_shizuku_not_installed_DESC">Shizuku ne semble pas être installé</string>
|
||||||
|
<string name="open_shizuku">Ouvrir Shizuku</string>
|
||||||
|
<string name="label_open_video">Vidéo</string>
|
||||||
|
<string name="label_unknown_sdk">Inconnu (%d)</string>
|
||||||
|
<string name="switch_to_default_installer">Rétablir par défaut</string>
|
||||||
|
</resources>
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
<string name="changes">Cambios</string>
|
<string name="changes">Cambios</string>
|
||||||
<string name="checking_repository">Comprobando o repositorio…</string>
|
<string name="checking_repository">Comprobando o repositorio…</string>
|
||||||
<string name="cleanup_title">APK cleanup interval</string>
|
<string name="cleanup_title">APK cleanup interval</string>
|
||||||
<string name="cleanup_description">Period to check and remove downloaded files</string>
|
|
||||||
<string name="compiled_for_debugging">Compilado para a depuración</string>
|
<string name="compiled_for_debugging">Compilado para a depuración</string>
|
||||||
<string name="confirmation">Confirmación</string>
|
<string name="confirmation">Confirmación</string>
|
||||||
<string name="connecting">Conectando…</string>
|
<string name="connecting">Conectando…</string>
|
||||||
@ -38,8 +37,6 @@
|
|||||||
<string name="light">Claro</string>
|
<string name="light">Claro</string>
|
||||||
<string name="link_copied_to_clipboard">A ligazón copiouse no portapapeis</string>
|
<string name="link_copied_to_clipboard">A ligazón copiouse no portapapeis</string>
|
||||||
<string name="links">Ligazóns</string>
|
<string name="links">Ligazóns</string>
|
||||||
<string name="list_animation">Lista de animacións</string>
|
|
||||||
<string name="list_animation_description">Mostra a animación da lista na páxina principal</string>
|
|
||||||
<string name="merging_FORMAT">Fusionando %s</string>
|
<string name="merging_FORMAT">Fusionando %s</string>
|
||||||
<string name="name">Nome</string>
|
<string name="name">Nome</string>
|
||||||
<string name="network_error_DESC">Erro na rede</string>
|
<string name="network_error_DESC">Erro na rede</string>
|
||||||
@ -74,9 +71,7 @@
|
|||||||
<string name="recently_updated">Actualizado recentemente</string>
|
<string name="recently_updated">Actualizado recentemente</string>
|
||||||
<string name="repositories">Repositorios</string>
|
<string name="repositories">Repositorios</string>
|
||||||
<string name="repository">Repositorio</string>
|
<string name="repository">Repositorio</string>
|
||||||
<string name="repository_not_used_DESC">Este repositorio aínda non se utilizou. Accéndeo para ver as aplicacións nel.</string>
|
|
||||||
<string name="requires_FORMAT">Require %s</string>
|
<string name="requires_FORMAT">Require %s</string>
|
||||||
<string name="screenshots">Capturas de pantalla</string>
|
|
||||||
<string name="search">Procurar</string>
|
<string name="search">Procurar</string>
|
||||||
<string name="select_mirror">Seleccione un espello</string>
|
<string name="select_mirror">Seleccione un espello</string>
|
||||||
<string name="share">Compartir</string>
|
<string name="share">Compartir</string>
|
||||||
@ -91,7 +86,6 @@
|
|||||||
<string name="sync_repositories_automatically">Sincronizar repositorios automaticamente</string>
|
<string name="sync_repositories_automatically">Sincronizar repositorios automaticamente</string>
|
||||||
<string name="syncing">Sincronización</string>
|
<string name="syncing">Sincronización</string>
|
||||||
<string name="system">Sistema</string>
|
<string name="system">Sistema</string>
|
||||||
<string name="target">Obxectivo</string>
|
|
||||||
<string name="theme">Tema</string>
|
<string name="theme">Tema</string>
|
||||||
<string name="themes">Temas</string>
|
<string name="themes">Temas</string>
|
||||||
<string name="tracks_or_reports_your_activity">Rastrexa ou informa da túa actividade</string>
|
<string name="tracks_or_reports_your_activity">Rastrexa ou informa da túa actividade</string>
|
||||||
@ -100,7 +94,6 @@
|
|||||||
<string name="unknown_error_DESC">Erro descoñecido.</string>
|
<string name="unknown_error_DESC">Erro descoñecido.</string>
|
||||||
<string name="unknown_FORMAT">Descoñecido: %s</string>
|
<string name="unknown_FORMAT">Descoñecido: %s</string>
|
||||||
<string name="unstable_updates">Actualizacións inestables</string>
|
<string name="unstable_updates">Actualizacións inestables</string>
|
||||||
<string name="unverified">Sen verificar</string>
|
|
||||||
<string name="update">Actualizar</string>
|
<string name="update">Actualizar</string>
|
||||||
<string name="updates">Actualizacións</string>
|
<string name="updates">Actualizacións</string>
|
||||||
<string name="upstream_source_code_is_not_free">O código fonte non é ceibe</string>
|
<string name="upstream_source_code_is_not_free">O código fonte non é ceibe</string>
|
||||||
@ -114,12 +107,7 @@
|
|||||||
<string name="prefs_language_title">Lingua</string>
|
<string name="prefs_language_title">Lingua</string>
|
||||||
<string name="prefs_personalization">Personalización</string>
|
<string name="prefs_personalization">Personalización</string>
|
||||||
<string name="show_less">Mostrar menos</string>
|
<string name="show_less">Mostrar menos</string>
|
||||||
<string name="latest">Derradeiro</string>
|
|
||||||
<string name="explore">Explora</string>
|
|
||||||
<string name="update_all">Actualiza todo</string>
|
<string name="update_all">Actualiza todo</string>
|
||||||
<string name="installed_applications">Aplicacións instaladas</string>
|
|
||||||
<string name="sort_filter">Ordear e filtrar</string>
|
|
||||||
<string name="new_applications">Novas aplicacións</string>
|
|
||||||
<string name="all_applications">Todas as aplicacións</string>
|
<string name="all_applications">Todas as aplicacións</string>
|
||||||
<string name="amoled">Negro</string>
|
<string name="amoled">Negro</string>
|
||||||
<string name="already_exists">Xa existe</string>
|
<string name="already_exists">Xa existe</string>
|
||||||
@ -178,8 +166,6 @@
|
|||||||
<string name="only_on_wifi">Só con wifi</string>
|
<string name="only_on_wifi">Só con wifi</string>
|
||||||
<string name="only_on_wifi_with_charging">Só con wifi e carga</string>
|
<string name="only_on_wifi_with_charging">Só con wifi e carga</string>
|
||||||
<string name="proxy">Proxy</string>
|
<string name="proxy">Proxy</string>
|
||||||
<string name="root_permission">Instalación silenciosa</string>
|
|
||||||
<string name="root_permission_description">Permitir permiso de root para instalacións silenciosas</string>
|
|
||||||
<string name="repository_unsigned_DESC">Sen asinar. Non se puido verificar a lista de solicitudes. Teña coidado ao descargar aplicacións desde repositorios sen asinar.</string>
|
<string name="repository_unsigned_DESC">Sen asinar. Non se puido verificar a lista de solicitudes. Teña coidado ao descargar aplicacións desde repositorios sen asinar.</string>
|
||||||
<string name="save">Gardar</string>
|
<string name="save">Gardar</string>
|
||||||
<string name="sorting_order">Orde de clasificación</string>
|
<string name="sorting_order">Orde de clasificación</string>
|
||||||
@ -189,14 +175,10 @@
|
|||||||
<string name="show_older_versions">Mostrar versións antigas</string>
|
<string name="show_older_versions">Mostrar versións antigas</string>
|
||||||
<string name="source_code">Código fonte</string>
|
<string name="source_code">Código fonte</string>
|
||||||
<string name="tap_to_install_DESC">Preme para instalar.</string>
|
<string name="tap_to_install_DESC">Preme para instalar.</string>
|
||||||
<string name="unsigned">Sen asinar</string>
|
|
||||||
<string name="unstable_updates_summary">Suxire instalar versións inestables</string>
|
<string name="unstable_updates_summary">Suxire instalar versións inestables</string>
|
||||||
<string name="validation_index_error_DESC">Non se puido validar o índice.</string>
|
<string name="validation_index_error_DESC">Non se puido validar o índice.</string>
|
||||||
<string name="version">Versión</string>
|
<string name="version">Versión</string>
|
||||||
<string name="io_error_DESC">Non se poden realizar determinadas accións.</string>
|
<string name="io_error_DESC">Non se poden realizar determinadas accións.</string>
|
||||||
<string name="no_internet">Non tes conexión a internet</string>
|
|
||||||
<string name="allow_collapsing_toolbar">Permitir ca barra das aplicacións superior se amplíe</string>
|
|
||||||
<string name="allow_collapsing_toolbar_DESC">Permitir cas barras das aplicacións superior se amplíe e contraiga</string>
|
|
||||||
<string name="material_you">Material You</string>
|
<string name="material_you">Material You</string>
|
||||||
<string name="material_you_desc">Usalo material que coloree o tema</string>
|
<string name="material_you_desc">Usalo material que coloree o tema</string>
|
||||||
<string name="favourites">Favoritas</string>
|
<string name="favourites">Favoritas</string>
|
||||||
@ -205,7 +187,6 @@
|
|||||||
<string name="force_clean_up">Forzala limpeza</string>
|
<string name="force_clean_up">Forzala limpeza</string>
|
||||||
<string name="enable_repo">Activalo repositorio</string>
|
<string name="enable_repo">Activalo repositorio</string>
|
||||||
<string name="installing">Instalando</string>
|
<string name="installing">Instalando</string>
|
||||||
<string name="restart_app">Reinicia Droid-ify para velos cambios</string>
|
|
||||||
<string name="waiting_to_start_installation">Agardando para iniciala instalación…</string>
|
<string name="waiting_to_start_installation">Agardando para iniciala instalación…</string>
|
||||||
<string name="auto_update">Actualizacións automática das aplicacións</string>
|
<string name="auto_update">Actualizacións automática das aplicacións</string>
|
||||||
<string name="auto_update_apps">Tenta instalar actualizacións automaticamente</string>
|
<string name="auto_update_apps">Tenta instalar actualizacións automaticamente</string>
|
||||||
@ -213,4 +194,4 @@
|
|||||||
<string name="import_export">Importación/exportación</string>
|
<string name="import_export">Importación/exportación</string>
|
||||||
<string name="import_settings_DESC">Importalos axustes e favoritos dende un fixeiro</string>
|
<string name="import_settings_DESC">Importalos axustes e favoritos dende un fixeiro</string>
|
||||||
<string name="cannot_open_link">Non se pode abrir a ligazón</string>
|
<string name="cannot_open_link">Non se pode abrir a ligazón</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user