mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-15 06:52:49 +01:00
chore: merge upstream changes.
Signed-off-by: KaiserBh <kaiserbh@proton.me>
This commit is contained in:
commit
4b9ccb9b75
2
.github/workflows/build_pull_request.yml
vendored
2
.github/workflows/build_pull_request.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
||||
uses: actions/dependency-review-action@v3
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
2
.github/workflows/build_push.yml
vendored
2
.github/workflows/build_push.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
||||
uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: adopt
|
||||
|
@ -22,7 +22,7 @@ android {
|
||||
defaultConfig {
|
||||
applicationId = "eu.kanade.tachiyomi"
|
||||
|
||||
versionCode = 110
|
||||
versionCode = 111
|
||||
versionName = "0.14.7"
|
||||
|
||||
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
||||
@ -196,7 +196,6 @@ dependencies {
|
||||
|
||||
// RxJava
|
||||
implementation(libs.rxjava)
|
||||
implementation(libs.flowreactivenetwork)
|
||||
|
||||
// Networking
|
||||
implementation(libs.bundles.okhttp)
|
||||
|
@ -7,6 +7,9 @@
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
|
||||
<!-- Storage -->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<!-- For background jobs -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
@ -21,6 +24,8 @@
|
||||
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.READ_APP_SPECIFIC_LOCALES" />
|
||||
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
|
||||
<!-- Remove permission from Firebase dependency -->
|
||||
<uses-permission android:name="com.google.android.gms.permission.AD_ID"
|
||||
@ -36,6 +41,8 @@
|
||||
android:largeHeap="true"
|
||||
android:localeConfig="@xml/locales_config"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:preserveLegacyExternalStorage="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Tachiyomi">
|
||||
@ -151,10 +158,6 @@
|
||||
android:name=".data.notification.NotificationReceiver"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name=".data.download.DownloadService"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name=".extension.util.ExtensionInstallService"
|
||||
android:exported="false" />
|
||||
@ -168,6 +171,11 @@
|
||||
android:value="true" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="androidx.work.impl.foreground.SystemForegroundService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
tools:node="merge" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
|
@ -190,6 +190,7 @@ private fun ExtensionDetails(
|
||||
key = { it.source.id },
|
||||
) { source ->
|
||||
SourceSwitchPreference(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
source = source,
|
||||
onClickSourcePreferences = onClickSourcePreferences,
|
||||
onClickSource = onClickSource,
|
||||
|
@ -58,6 +58,7 @@ private fun ExtensionFilterContent(
|
||||
) {
|
||||
items(state.languages) { language ->
|
||||
SwitchPreferenceWidget(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
title = LocaleHelper.getSourceDisplayName(language, context),
|
||||
checked = language in state.enabledLanguages,
|
||||
onCheckedChanged = { onClickLang(language) },
|
||||
|
@ -148,12 +148,14 @@ private fun ExtensionContent(
|
||||
}
|
||||
ExtensionHeader(
|
||||
textRes = header.textRes,
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
action = action,
|
||||
)
|
||||
}
|
||||
is ExtensionUiModel.Header.Text -> {
|
||||
ExtensionHeader(
|
||||
text = header.text,
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -165,6 +167,7 @@ private fun ExtensionContent(
|
||||
key = { "extension-${it.hashCode()}" },
|
||||
) { item ->
|
||||
ExtensionItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
item = item,
|
||||
onClickItem = {
|
||||
when (it) {
|
||||
|
@ -132,6 +132,7 @@ private fun MigrateSourceList(
|
||||
key = { (source, _) -> "migrate-${source.id}" },
|
||||
) { (source, count) ->
|
||||
MigrateSourceItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
source = source,
|
||||
count = count,
|
||||
onClickItem = { onClickItem(source) },
|
||||
|
@ -68,6 +68,7 @@ private fun SourcesFilterContent(
|
||||
contentType = "source-filter-header",
|
||||
) {
|
||||
SourcesFilterHeader(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
language = language,
|
||||
enabled = enabled,
|
||||
onClickItem = onClickLanguage,
|
||||
@ -80,6 +81,7 @@ private fun SourcesFilterContent(
|
||||
contentType = { "source-filter-item" },
|
||||
) { source ->
|
||||
SourcesFilterItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
source = source,
|
||||
enabled = "${source.id}" !in state.disabledSources,
|
||||
onClickItem = onClickSource,
|
||||
|
@ -74,10 +74,12 @@ fun SourcesScreen(
|
||||
when (model) {
|
||||
is SourceUiModel.Header -> {
|
||||
SourceHeader(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
language = model.language,
|
||||
)
|
||||
}
|
||||
is SourceUiModel.Item -> SourceItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
source = model.source,
|
||||
onClickItem = onClickItem,
|
||||
onLongClickItem = onLongClickItem,
|
||||
|
@ -107,6 +107,7 @@ private fun CategoryContent(
|
||||
key = { _, category -> "category-${category.id}" },
|
||||
) { index, category ->
|
||||
CategoryListItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
category = category,
|
||||
canMoveUp = index != 0,
|
||||
canMoveDown = index != categories.lastIndex,
|
||||
|
@ -123,6 +123,7 @@ private fun HistoryScreenContent(
|
||||
when (item) {
|
||||
is HistoryUiModel.Header -> {
|
||||
RelativeDateHeader(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
date = item.date,
|
||||
relativeTime = relativeTime,
|
||||
dateFormat = dateFormat,
|
||||
@ -131,6 +132,7 @@ private fun HistoryScreenContent(
|
||||
is HistoryUiModel.Item -> {
|
||||
val value = item.item
|
||||
HistoryItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
history = value,
|
||||
onClickCover = { onClickCover(value) },
|
||||
onClickResume = { onClickResume(value) },
|
||||
|
@ -114,7 +114,8 @@ object SettingsDataScreen : SearchableSettings {
|
||||
return Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(MR.strings.pref_storage_location),
|
||||
subtitle = remember(storageDir) {
|
||||
(UniFile.fromUri(context, storageDir.toUri())?.filePath)
|
||||
val file = UniFile.fromUri(context, storageDir.toUri())
|
||||
file?.filePath ?: file?.uri?.toString()
|
||||
} ?: stringResource(MR.strings.invalid_location, storageDir),
|
||||
onClick = {
|
||||
try {
|
||||
|
@ -13,7 +13,6 @@ import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.more.settings.PreferenceScaffold
|
||||
import eu.kanade.presentation.more.settings.screen.about.AboutScreen
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.WebViewUtil
|
||||
import kotlinx.coroutines.guava.await
|
||||
|
@ -18,17 +18,18 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import androidx.lifecycle.asFlow
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkQuery
|
||||
import cafe.adriel.voyager.core.model.ScreenModel
|
||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.presentation.util.ioCoroutineScope
|
||||
import eu.kanade.tachiyomi.util.lang.toDateTimestampString
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
@ -39,6 +40,9 @@ import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
import tachiyomi.presentation.core.util.plus
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.Date
|
||||
|
||||
class WorkerInfoScreen : Screen() {
|
||||
|
||||
@ -116,22 +120,19 @@ class WorkerInfoScreen : Screen() {
|
||||
private val workManager = context.workManager
|
||||
|
||||
val finished = workManager
|
||||
.getWorkInfosLiveData(
|
||||
.getWorkInfosFlow(
|
||||
WorkQuery.fromStates(WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, WorkInfo.State.CANCELLED),
|
||||
)
|
||||
.asFlow()
|
||||
.map(::constructString)
|
||||
.stateIn(ioCoroutineScope, SharingStarted.WhileSubscribed(), "")
|
||||
|
||||
val running = workManager
|
||||
.getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.RUNNING))
|
||||
.asFlow()
|
||||
.getWorkInfosFlow(WorkQuery.fromStates(WorkInfo.State.RUNNING))
|
||||
.map(::constructString)
|
||||
.stateIn(ioCoroutineScope, SharingStarted.WhileSubscribed(), "")
|
||||
|
||||
val enqueued = workManager
|
||||
.getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.ENQUEUED))
|
||||
.asFlow()
|
||||
.getWorkInfosFlow(WorkQuery.fromStates(WorkInfo.State.ENQUEUED))
|
||||
.map(::constructString)
|
||||
.stateIn(ioCoroutineScope, SharingStarted.WhileSubscribed(), "")
|
||||
|
||||
@ -146,6 +147,16 @@ class WorkerInfoScreen : Screen() {
|
||||
appendLine(" - $it")
|
||||
}
|
||||
appendLine("State: ${workInfo.state}")
|
||||
if (workInfo.state == WorkInfo.State.ENQUEUED) {
|
||||
appendLine(
|
||||
"Next scheduled run: ${Date(workInfo.nextScheduleTimeMillis).toDateTimestampString(
|
||||
UiPreferences.dateFormat(
|
||||
Injekt.get<UiPreferences>().dateFormat().get(),
|
||||
),
|
||||
)}",
|
||||
)
|
||||
appendLine("Attempt #${workInfo.runAttemptCount + 1}")
|
||||
}
|
||||
appendLine()
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
package eu.kanade.presentation.reader
|
||||
|
||||
import androidx.annotation.IntRange
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import kotlin.math.abs
|
||||
|
||||
@Composable
|
||||
fun BrightnessOverlay(
|
||||
@IntRange(from = -100, to = 100) value: Int,
|
||||
) {
|
||||
if (value >= 0) return
|
||||
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.graphicsLayer {
|
||||
alpha = abs(value) / 100f
|
||||
},
|
||||
) {
|
||||
drawRect(Color.Black)
|
||||
}
|
||||
}
|
@ -11,8 +11,6 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.domain.manga.model.readerOrientation
|
||||
@ -72,7 +70,7 @@ private fun DialogContent(
|
||||
selected = mode
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
imageVector = ImageVector.vectorResource(mode.iconRes),
|
||||
imageVector = mode.icon,
|
||||
title = stringResource(mode.stringRes),
|
||||
)
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
package eu.kanade.presentation.reader
|
||||
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.IntRange
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.BlendMode
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import kotlin.math.abs
|
||||
|
||||
@Composable
|
||||
fun ReaderContentOverlay(
|
||||
@IntRange(from = -100, to = 100) brightness: Int,
|
||||
@ColorInt color: Int?,
|
||||
colorBlendMode: BlendMode?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (brightness < 0) {
|
||||
val brightnessAlpha = remember(brightness) {
|
||||
abs(brightness) / 100f
|
||||
}
|
||||
|
||||
Canvas(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.graphicsLayer {
|
||||
alpha = brightnessAlpha
|
||||
},
|
||||
) {
|
||||
drawRect(Color.Black)
|
||||
}
|
||||
}
|
||||
|
||||
if (color != null) {
|
||||
Canvas(
|
||||
modifier = modifier
|
||||
.fillMaxSize(),
|
||||
) {
|
||||
drawRect(
|
||||
color = Color(color),
|
||||
blendMode = colorBlendMode ?: BlendMode.SrcOver,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -49,7 +49,7 @@ fun BottomReaderBar(
|
||||
|
||||
IconButton(onClick = onClickOrientation) {
|
||||
Icon(
|
||||
painter = painterResource(orientation.iconRes),
|
||||
imageVector = orientation.icon,
|
||||
contentDescription = stringResource(MR.strings.rotation_type),
|
||||
)
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package eu.kanade.presentation.reader.settings
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.Text
|
||||
@ -10,6 +9,7 @@ import androidx.core.graphics.alpha
|
||||
import androidx.core.graphics.blue
|
||||
import androidx.core.graphics.green
|
||||
import androidx.core.graphics.red
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences.Companion.ColorFilterMode
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
||||
import tachiyomi.core.preference.getAndSet
|
||||
import tachiyomi.i18n.MR
|
||||
@ -21,25 +21,6 @@ import tachiyomi.presentation.core.util.collectAsState
|
||||
|
||||
@Composable
|
||||
internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) {
|
||||
val colorFilterModes = buildList {
|
||||
addAll(
|
||||
listOf(
|
||||
MR.strings.label_default,
|
||||
MR.strings.filter_mode_multiply,
|
||||
MR.strings.filter_mode_screen,
|
||||
),
|
||||
)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
addAll(
|
||||
listOf(
|
||||
MR.strings.filter_mode_overlay,
|
||||
MR.strings.filter_mode_lighten,
|
||||
MR.strings.filter_mode_darken,
|
||||
),
|
||||
)
|
||||
}
|
||||
}.map { stringResource(it) }
|
||||
|
||||
val customBrightness by screenModel.preferences.customBrightness().collectAsState()
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_custom_brightness),
|
||||
@ -118,11 +99,11 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
|
||||
val colorFilterMode by screenModel.preferences.colorFilterMode().collectAsState()
|
||||
SettingsChipRow(MR.strings.pref_color_filter_mode) {
|
||||
colorFilterModes.mapIndexed { index, it ->
|
||||
ColorFilterMode.mapIndexed { index, it ->
|
||||
FilterChip(
|
||||
selected = colorFilterMode == index,
|
||||
onClick = { screenModel.preferences.colorFilterMode().set(index) },
|
||||
label = { Text(it) },
|
||||
label = { Text(stringResource(it.first)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -193,6 +193,7 @@ fun TrackerSearch(
|
||||
type = it.publishing_type.toLowerCase(Locale.current).capitalize(Locale.current),
|
||||
startDate = it.start_date,
|
||||
status = it.publishing_status.toLowerCase(Locale.current).capitalize(Locale.current),
|
||||
score = it.score,
|
||||
description = it.summary.trim(),
|
||||
selected = it == selected,
|
||||
onClick = { onSelectedChange(it) },
|
||||
@ -218,6 +219,7 @@ private fun SearchResultItem(
|
||||
type: String,
|
||||
startDate: String,
|
||||
status: String,
|
||||
score: Float,
|
||||
description: String,
|
||||
selected: Boolean,
|
||||
onClick: () -> Unit,
|
||||
@ -279,6 +281,12 @@ private fun SearchResultItem(
|
||||
text = status,
|
||||
)
|
||||
}
|
||||
if (score != -1f) {
|
||||
SearchResultItemDetails(
|
||||
title = stringResource(MR.strings.score),
|
||||
text = score.toString(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (description.isNotBlank()) {
|
||||
|
@ -53,6 +53,7 @@ internal fun LazyListScope.updatesLastUpdatedItem(
|
||||
item(key = "updates-lastUpdated") {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.animateItemPlacement()
|
||||
.padding(horizontal = MaterialTheme.padding.medium, vertical = MaterialTheme.padding.small),
|
||||
) {
|
||||
Text(
|
||||
@ -89,12 +90,14 @@ internal fun LazyListScope.updatesUiItems(
|
||||
when (item) {
|
||||
is UpdatesUiModel.Header -> {
|
||||
ListGroupHeader(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
text = item.date,
|
||||
)
|
||||
}
|
||||
is UpdatesUiModel.Item -> {
|
||||
val updatesItem = item.item
|
||||
UpdatesUiItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
update = updatesItem.update,
|
||||
selected = updatesItem.selected,
|
||||
readProgress = updatesItem.update.lastPageRead
|
||||
|
@ -416,6 +416,11 @@ object Migrations {
|
||||
newKey = { Preference.appStateKey(it) },
|
||||
)
|
||||
}
|
||||
if (oldVersion < 111) {
|
||||
File(context.cacheDir, "dl_index_cache")
|
||||
.takeIf { it.exists() }
|
||||
?.delete()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.system.cancelNotification
|
||||
import eu.kanade.tachiyomi.util.system.isRunning
|
||||
import eu.kanade.tachiyomi.util.system.setForegroundSafely
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.system.logcat
|
||||
@ -39,19 +40,14 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete
|
||||
|
||||
if (isAutoBackup && BackupRestoreJob.isRunning(context)) return Result.retry()
|
||||
|
||||
val backupPreferences = Injekt.get<BackupPreferences>()
|
||||
|
||||
val uri = inputData.getString(LOCATION_URI_KEY)?.toUri()
|
||||
?: getAutomaticBackupLocation()
|
||||
?: return Result.failure()
|
||||
|
||||
val flags = inputData.getInt(BACKUP_FLAGS_KEY, BackupCreateFlags.AutomaticDefaults)
|
||||
setForegroundSafely()
|
||||
|
||||
try {
|
||||
setForeground(getForegroundInfo())
|
||||
} catch (e: IllegalStateException) {
|
||||
logcat(LogPriority.ERROR, e) { "Not allowed to run on foreground service" }
|
||||
}
|
||||
val flags = inputData.getInt(BACKUP_FLAGS_KEY, BackupCreateFlags.AutomaticDefaults)
|
||||
val backupPreferences = Injekt.get<BackupPreferences>()
|
||||
|
||||
return try {
|
||||
val location = BackupCreator(context).createBackup(uri, flags, isAutoBackup)
|
||||
|
@ -1,6 +1,5 @@
|
||||
package eu.kanade.tachiyomi.data.backup
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.hippo.unifile.UniFile
|
||||
@ -31,7 +30,6 @@ import eu.kanade.tachiyomi.data.backup.models.backupTrackMapper
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.source.preferenceKey
|
||||
import eu.kanade.tachiyomi.source.sourcePreferences
|
||||
import eu.kanade.tachiyomi.util.system.hasPermission
|
||||
import kotlinx.serialization.protobuf.ProtoBuf
|
||||
import logcat.LogPriority
|
||||
import okio.buffer
|
||||
@ -73,10 +71,6 @@ class BackupCreator(
|
||||
* @param isAutoBackup backup called from scheduled backup job
|
||||
*/
|
||||
suspend fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean): String {
|
||||
if (!context.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
throw IllegalStateException(context.stringResource(MR.strings.missing_storage_permission))
|
||||
}
|
||||
|
||||
val databaseManga = getFavorites.await()
|
||||
val backup = Backup(
|
||||
backupMangas(databaseManga, flags),
|
||||
|
@ -79,11 +79,7 @@ class BackupNotifier(private val context: Context) {
|
||||
addAction(
|
||||
R.drawable.ic_share_24dp,
|
||||
context.stringResource(MR.strings.action_share),
|
||||
NotificationReceiver.shareBackupPendingBroadcast(
|
||||
context,
|
||||
unifile.uri,
|
||||
Notifications.ID_BACKUP_COMPLETE,
|
||||
),
|
||||
NotificationReceiver.shareBackupPendingBroadcast(context, unifile.uri),
|
||||
)
|
||||
|
||||
show(Notifications.ID_BACKUP_COMPLETE)
|
||||
|
@ -12,6 +12,7 @@ import androidx.work.workDataOf
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.system.cancelNotification
|
||||
import eu.kanade.tachiyomi.util.system.isRunning
|
||||
import eu.kanade.tachiyomi.util.system.setForegroundSafely
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import logcat.LogPriority
|
||||
@ -29,11 +30,7 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
|
||||
?: return Result.failure()
|
||||
val sync = inputData.getBoolean(SYNC_KEY, false)
|
||||
|
||||
try {
|
||||
setForeground(getForegroundInfo())
|
||||
} catch (e: IllegalStateException) {
|
||||
logcat(LogPriority.ERROR, e) { "Not allowed to run on foreground service" }
|
||||
}
|
||||
setForegroundSafely()
|
||||
|
||||
return try {
|
||||
val restorer = BackupRestorer(context, notifier)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.data.coil
|
||||
|
||||
import androidx.core.net.toUri
|
||||
import coil.ImageLoader
|
||||
import coil.decode.DataSource
|
||||
import coil.decode.ImageSource
|
||||
@ -10,6 +11,7 @@ import coil.fetch.SourceResult
|
||||
import coil.network.HttpException
|
||||
import coil.request.Options
|
||||
import coil.request.Parameters
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher.Companion.USE_CUSTOM_COVER
|
||||
import eu.kanade.tachiyomi.network.await
|
||||
@ -24,6 +26,7 @@ import okio.Path.Companion.toOkioPath
|
||||
import okio.Source
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import okio.source
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.MangaCover
|
||||
@ -69,8 +72,9 @@ class MangaCoverFetcher(
|
||||
// diskCacheKey is thumbnail_url
|
||||
if (url == null) error("No cover specified")
|
||||
return when (getResourceType(url)) {
|
||||
Type.URL -> httpLoader()
|
||||
Type.File -> fileLoader(File(url.substringAfter("file://")))
|
||||
Type.URI -> fileUriLoader(url)
|
||||
Type.URL -> httpLoader()
|
||||
null -> error("Invalid image")
|
||||
}
|
||||
}
|
||||
@ -83,6 +87,18 @@ class MangaCoverFetcher(
|
||||
)
|
||||
}
|
||||
|
||||
private fun fileUriLoader(uri: String): FetchResult {
|
||||
val source = UniFile.fromUri(options.context, uri.toUri())!!
|
||||
.openInputStream()
|
||||
.source()
|
||||
.buffer()
|
||||
return SourceResult(
|
||||
source = ImageSource(source = source, context = options.context),
|
||||
mimeType = "image/*",
|
||||
dataSource = DataSource.DISK,
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun httpLoader(): FetchResult {
|
||||
// Only cache separately if it's a library item
|
||||
val libraryCoverCacheFile = if (isLibraryManga) {
|
||||
@ -256,12 +272,15 @@ class MangaCoverFetcher(
|
||||
cover.isNullOrEmpty() -> null
|
||||
cover.startsWith("http", true) || cover.startsWith("Custom-", true) -> Type.URL
|
||||
cover.startsWith("/") || cover.startsWith("file://") -> Type.File
|
||||
cover.startsWith("content") -> Type.URI
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private enum class Type {
|
||||
File, URL
|
||||
File,
|
||||
URI,
|
||||
URL,
|
||||
}
|
||||
|
||||
class MangaFactory(
|
||||
|
@ -94,7 +94,7 @@ class DownloadCache(
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||
|
||||
private val diskCacheFile: File
|
||||
get() = File(context.cacheDir, "dl_index_cache")
|
||||
get() = File(context.cacheDir, "dl_index_cache_v2")
|
||||
|
||||
private val rootDownloadsDirLock = Mutex()
|
||||
private var rootDownloadsDir = RootDirectory(provider.downloadsDir)
|
||||
|
@ -0,0 +1,117 @@
|
||||
package eu.kanade.tachiyomi.data.download
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.os.Build
|
||||
import androidx.lifecycle.asFlow
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.ForegroundInfo
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.system.isConnectedToWifi
|
||||
import eu.kanade.tachiyomi.util.system.isOnline
|
||||
import eu.kanade.tachiyomi.util.system.notificationBuilder
|
||||
import eu.kanade.tachiyomi.util.system.setForegroundSafely
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import tachiyomi.domain.download.service.DownloadPreferences
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
/**
|
||||
* This worker is used to manage the downloader. The system can decide to stop the worker, in
|
||||
* which case the downloader is also stopped. It's also stopped while there's no network available.
|
||||
*/
|
||||
class DownloadJob(context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) {
|
||||
|
||||
private val downloadManager: DownloadManager = Injekt.get()
|
||||
private val downloadPreferences: DownloadPreferences = Injekt.get()
|
||||
|
||||
override suspend fun getForegroundInfo(): ForegroundInfo {
|
||||
val notification = applicationContext.notificationBuilder(Notifications.CHANNEL_DOWNLOADER_PROGRESS) {
|
||||
setContentTitle(applicationContext.getString(R.string.download_notifier_downloader_title))
|
||||
setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
}.build()
|
||||
return ForegroundInfo(
|
||||
Notifications.ID_DOWNLOAD_CHAPTER_PROGRESS,
|
||||
notification,
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||
} else {
|
||||
0
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
var active = checkConnectivity() && downloadManager.downloaderStart()
|
||||
|
||||
if (!active) {
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
setForegroundSafely()
|
||||
|
||||
// Keep the worker running when needed
|
||||
while (active) {
|
||||
delay(100)
|
||||
active = !isStopped && downloadManager.isRunning && checkConnectivity()
|
||||
}
|
||||
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private fun checkConnectivity(): Boolean {
|
||||
return with(applicationContext) {
|
||||
if (isOnline()) {
|
||||
val noWifi = downloadPreferences.downloadOnlyOverWifi().get() && !isConnectedToWifi()
|
||||
if (noWifi) {
|
||||
downloadManager.downloaderStop(
|
||||
applicationContext.getString(R.string.download_notifier_text_only_wifi),
|
||||
)
|
||||
}
|
||||
!noWifi
|
||||
} else {
|
||||
downloadManager.downloaderStop(applicationContext.getString(R.string.download_notifier_no_network))
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "Downloader"
|
||||
|
||||
fun start(context: Context) {
|
||||
val request = OneTimeWorkRequestBuilder<DownloadJob>()
|
||||
.addTag(TAG)
|
||||
.build()
|
||||
WorkManager.getInstance(context)
|
||||
.enqueueUniqueWork(TAG, ExistingWorkPolicy.REPLACE, request)
|
||||
}
|
||||
|
||||
fun stop(context: Context) {
|
||||
WorkManager.getInstance(context)
|
||||
.cancelUniqueWork(TAG)
|
||||
}
|
||||
|
||||
fun isRunning(context: Context): Boolean {
|
||||
return WorkManager.getInstance(context)
|
||||
.getWorkInfosForUniqueWork(TAG)
|
||||
.get()
|
||||
.let { list -> list.count { it.state == WorkInfo.State.RUNNING } == 1 }
|
||||
}
|
||||
|
||||
fun isRunningFlow(context: Context): Flow<Boolean> {
|
||||
return WorkManager.getInstance(context)
|
||||
.getWorkInfosForUniqueWorkLiveData(TAG)
|
||||
.asFlow()
|
||||
.map { list -> list.count { it.state == WorkInfo.State.RUNNING } == 1 }
|
||||
}
|
||||
}
|
||||
}
|
@ -46,6 +46,9 @@ class DownloadManager(
|
||||
*/
|
||||
private val downloader = Downloader(context, provider, cache)
|
||||
|
||||
val isRunning: Boolean
|
||||
get() = downloader.isRunning
|
||||
|
||||
/**
|
||||
* Queue to delay the deletion of a list of chapters until triggered.
|
||||
*/
|
||||
@ -59,13 +62,19 @@ class DownloadManager(
|
||||
fun downloaderStop(reason: String? = null) = downloader.stop(reason)
|
||||
|
||||
val isDownloaderRunning
|
||||
get() = DownloadService.isRunning
|
||||
get() = DownloadJob.isRunningFlow(context)
|
||||
|
||||
/**
|
||||
* Tells the downloader to begin downloads.
|
||||
*/
|
||||
fun startDownloads() {
|
||||
DownloadService.start(context)
|
||||
if (downloader.isRunning) return
|
||||
|
||||
if (DownloadJob.isRunning(context)) {
|
||||
downloader.start()
|
||||
} else {
|
||||
DownloadJob.start(context)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,22 +103,16 @@ class DownloadManager(
|
||||
return queueState.value.find { it.chapter.id == chapterId }
|
||||
}
|
||||
|
||||
fun startDownloadNow(chapterId: Long?) {
|
||||
if (chapterId == null) return
|
||||
val download = getQueuedDownloadOrNull(chapterId)
|
||||
fun startDownloadNow(chapterId: Long) {
|
||||
val existingDownload = getQueuedDownloadOrNull(chapterId)
|
||||
// If not in queue try to start a new download
|
||||
val toAdd = download ?: runBlocking { Download.fromChapterId(chapterId) } ?: return
|
||||
val queue = queueState.value.toMutableList()
|
||||
download?.let { queue.remove(it) }
|
||||
queue.add(0, toAdd)
|
||||
reorderQueue(queue)
|
||||
if (!downloader.isRunning) {
|
||||
if (DownloadService.isRunning(context)) {
|
||||
downloader.start()
|
||||
} else {
|
||||
DownloadService.start(context)
|
||||
}
|
||||
val toAdd = existingDownload ?: runBlocking { Download.fromChapterId(chapterId) } ?: return
|
||||
queueState.value.toMutableList().apply {
|
||||
existingDownload?.let { remove(it) }
|
||||
add(0, toAdd)
|
||||
reorderQueue(this)
|
||||
}
|
||||
startDownloads()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,7 +146,7 @@ class DownloadManager(
|
||||
addAll(0, downloads)
|
||||
reorderQueue(this)
|
||||
}
|
||||
if (!DownloadService.isRunning(context)) DownloadService.start(context)
|
||||
if (!DownloadJob.isRunning(context)) startDownloads()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,151 +0,0 @@
|
||||
package eu.kanade.tachiyomi.data.download
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import android.os.PowerManager
|
||||
import androidx.core.content.ContextCompat
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.system.acquireWakeLock
|
||||
import eu.kanade.tachiyomi.util.system.isConnectedToWifi
|
||||
import eu.kanade.tachiyomi.util.system.isOnline
|
||||
import eu.kanade.tachiyomi.util.system.isServiceRunning
|
||||
import eu.kanade.tachiyomi.util.system.notificationBuilder
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import logcat.LogPriority
|
||||
import ru.beryukhov.reactivenetwork.ReactiveNetwork
|
||||
import tachiyomi.core.i18n.stringResource
|
||||
import tachiyomi.core.util.lang.withUIContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.download.service.DownloadPreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
/**
|
||||
* This service is used to manage the downloader. The system can decide to stop the service, in
|
||||
* which case the downloader is also stopped. It's also stopped while there's no network available.
|
||||
* While the downloader is running, a wake lock will be held.
|
||||
*/
|
||||
class DownloadService : Service() {
|
||||
|
||||
companion object {
|
||||
|
||||
private val _isRunning = MutableStateFlow(false)
|
||||
val isRunning = _isRunning.asStateFlow()
|
||||
|
||||
/**
|
||||
* Starts this service.
|
||||
*
|
||||
* @param context the application context.
|
||||
*/
|
||||
fun start(context: Context) {
|
||||
val intent = Intent(context, DownloadService::class.java)
|
||||
ContextCompat.startForegroundService(context, intent)
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this service.
|
||||
*
|
||||
* @param context the application context.
|
||||
*/
|
||||
fun stop(context: Context) {
|
||||
context.stopService(Intent(context, DownloadService::class.java))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status of the service.
|
||||
*
|
||||
* @param context the application context.
|
||||
* @return true if the service is running, false otherwise.
|
||||
*/
|
||||
fun isRunning(context: Context): Boolean {
|
||||
return context.isServiceRunning(DownloadService::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
private val downloadManager: DownloadManager by injectLazy()
|
||||
private val downloadPreferences: DownloadPreferences by injectLazy()
|
||||
|
||||
/**
|
||||
* Wake lock to prevent the device to enter sleep mode.
|
||||
*/
|
||||
private lateinit var wakeLock: PowerManager.WakeLock
|
||||
|
||||
private lateinit var scope: CoroutineScope
|
||||
|
||||
override fun onCreate() {
|
||||
scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
||||
startForeground(Notifications.ID_DOWNLOAD_CHAPTER_PROGRESS, getPlaceholderNotification())
|
||||
wakeLock = acquireWakeLock(javaClass.name)
|
||||
_isRunning.value = true
|
||||
listenNetworkChanges()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
scope.cancel()
|
||||
_isRunning.value = false
|
||||
downloadManager.downloaderStop()
|
||||
if (wakeLock.isHeld) {
|
||||
wakeLock.release()
|
||||
}
|
||||
}
|
||||
|
||||
// Not used
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
// Not used
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return null
|
||||
}
|
||||
|
||||
private fun downloaderStop(string: StringResource) {
|
||||
downloadManager.downloaderStop(stringResource(string))
|
||||
}
|
||||
|
||||
private fun listenNetworkChanges() {
|
||||
ReactiveNetwork()
|
||||
.observeNetworkConnectivity(applicationContext)
|
||||
.onEach {
|
||||
withUIContext {
|
||||
if (isOnline()) {
|
||||
if (downloadPreferences.downloadOnlyOverWifi().get() && !isConnectedToWifi()) {
|
||||
downloaderStop(MR.strings.download_notifier_text_only_wifi)
|
||||
} else {
|
||||
val started = downloadManager.downloaderStart()
|
||||
if (!started) stopSelf()
|
||||
}
|
||||
} else {
|
||||
downloaderStop(MR.strings.download_notifier_no_network)
|
||||
}
|
||||
}
|
||||
}
|
||||
.catch { error ->
|
||||
withUIContext {
|
||||
logcat(LogPriority.ERROR, error)
|
||||
toast(MR.strings.download_queue_error)
|
||||
stopSelf()
|
||||
}
|
||||
}
|
||||
.launchIn(scope)
|
||||
}
|
||||
|
||||
private fun getPlaceholderNotification(): Notification {
|
||||
return notificationBuilder(Notifications.CHANNEL_DOWNLOADER_PROGRESS) {
|
||||
setContentTitle(stringResource(MR.strings.download_notifier_downloader_title))
|
||||
}.build()
|
||||
}
|
||||
}
|
@ -161,10 +161,7 @@ class Downloader(
|
||||
|
||||
isPaused = false
|
||||
|
||||
// Prevent recursion when DownloadService.onDestroy() calls downloader.stop()
|
||||
if (DownloadService.isRunning.value) {
|
||||
DownloadService.stop(context)
|
||||
}
|
||||
DownloadJob.stop(context)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -310,7 +307,7 @@ class Downloader(
|
||||
)
|
||||
}
|
||||
}
|
||||
DownloadService.start(context)
|
||||
DownloadJob.start(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package eu.kanade.tachiyomi.data.library
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.os.Build
|
||||
import androidx.work.BackoffPolicy
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.CoroutineWorker
|
||||
@ -28,6 +30,7 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
|
||||
import eu.kanade.tachiyomi.util.system.isConnectedToWifi
|
||||
import eu.kanade.tachiyomi.util.system.isRunning
|
||||
import eu.kanade.tachiyomi.util.system.setForegroundSafely
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.async
|
||||
@ -106,11 +109,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
setForeground(getForegroundInfo())
|
||||
} catch (e: IllegalStateException) {
|
||||
logcat(LogPriority.ERROR, e) { "Not allowed to set foreground job" }
|
||||
}
|
||||
setForegroundSafely()
|
||||
|
||||
libraryPreferences.lastUpdatedTimestamp().set(Date().time)
|
||||
|
||||
@ -140,6 +139,11 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
return ForegroundInfo(
|
||||
Notifications.ID_LIBRARY_PROGRESS,
|
||||
notifier.progressNotificationBuilder.build(),
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||
} else {
|
||||
0
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package eu.kanade.tachiyomi.data.library
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.os.Build
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.ForegroundInfo
|
||||
@ -16,6 +18,7 @@ import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.source.UnmeteredSource
|
||||
import eu.kanade.tachiyomi.util.prepUpdateCover
|
||||
import eu.kanade.tachiyomi.util.system.isRunning
|
||||
import eu.kanade.tachiyomi.util.system.setForegroundSafely
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.async
|
||||
@ -51,11 +54,7 @@ class MetadataUpdateJob(private val context: Context, workerParams: WorkerParame
|
||||
private var mangaToUpdate: List<LibraryManga> = mutableListOf()
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
try {
|
||||
setForeground(getForegroundInfo())
|
||||
} catch (e: IllegalStateException) {
|
||||
logcat(LogPriority.ERROR, e) { "Not allowed to set foreground job" }
|
||||
}
|
||||
setForegroundSafely()
|
||||
|
||||
addMangaToQueue()
|
||||
|
||||
@ -82,6 +81,11 @@ class MetadataUpdateJob(private val context: Context, workerParams: WorkerParame
|
||||
return ForegroundInfo(
|
||||
Notifications.ID_LIBRARY_PROGRESS,
|
||||
notifier.progressNotificationBuilder.build(),
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||
} else {
|
||||
0
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.core.net.toUri
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
@ -15,7 +16,6 @@ import eu.kanade.tachiyomi.data.updater.AppUpdateDownloadJob
|
||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||
import eu.kanade.tachiyomi.util.system.cancelNotification
|
||||
import eu.kanade.tachiyomi.util.system.getParcelableExtraCompat
|
||||
import eu.kanade.tachiyomi.util.system.notificationManager
|
||||
@ -36,7 +36,6 @@ import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
|
||||
|
||||
/**
|
||||
@ -65,15 +64,13 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
ACTION_SHARE_IMAGE ->
|
||||
shareImage(
|
||||
context,
|
||||
intent.getStringExtra(EXTRA_FILE_LOCATION)!!,
|
||||
intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1),
|
||||
intent.getStringExtra(EXTRA_URI)!!.toUri(),
|
||||
)
|
||||
// Delete image from path and dismiss notification
|
||||
ACTION_DELETE_IMAGE ->
|
||||
deleteImage(
|
||||
context,
|
||||
intent.getStringExtra(EXTRA_FILE_LOCATION)!!,
|
||||
intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1),
|
||||
intent.getStringExtra(EXTRA_URI)!!.toUri(),
|
||||
)
|
||||
// Share backup file
|
||||
ACTION_SHARE_BACKUP ->
|
||||
@ -81,7 +78,6 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
context,
|
||||
intent.getParcelableExtraCompat(EXTRA_URI)!!,
|
||||
"application/x-protobuf+gzip",
|
||||
intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1),
|
||||
)
|
||||
ACTION_CANCEL_RESTORE -> cancelRestore(context)
|
||||
|
||||
@ -140,12 +136,10 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
* Called to start share intent to share image
|
||||
*
|
||||
* @param context context of application
|
||||
* @param path path of file
|
||||
* @param notificationId id of notification
|
||||
* @param uri path of file
|
||||
*/
|
||||
private fun shareImage(context: Context, path: String, notificationId: Int) {
|
||||
dismissNotification(context, notificationId)
|
||||
context.startActivity(File(path).getUriCompat(context).toShareIntent(context))
|
||||
private fun shareImage(context: Context, uri: Uri) {
|
||||
context.startActivity(uri.toShareIntent(context))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,10 +147,8 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
*
|
||||
* @param context context of application
|
||||
* @param path path of file
|
||||
* @param notificationId id of notification
|
||||
*/
|
||||
private fun shareFile(context: Context, uri: Uri, fileMimeType: String, notificationId: Int) {
|
||||
dismissNotification(context, notificationId)
|
||||
private fun shareFile(context: Context, uri: Uri, fileMimeType: String) {
|
||||
context.startActivity(uri.toShareIntent(context, fileMimeType))
|
||||
}
|
||||
|
||||
@ -183,17 +175,11 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
/**
|
||||
* Called to delete image
|
||||
*
|
||||
* @param path path of file
|
||||
* @param notificationId id of notification
|
||||
* @param uri path of file
|
||||
*/
|
||||
private fun deleteImage(context: Context, path: String, notificationId: Int) {
|
||||
dismissNotification(context, notificationId)
|
||||
|
||||
// Delete file
|
||||
val file = File(path)
|
||||
file.delete()
|
||||
|
||||
DiskUtil.scanMedia(context, file.toUri())
|
||||
private fun deleteImage(context: Context, uri: Uri) {
|
||||
UniFile.fromUri(context, uri)?.delete()
|
||||
DiskUtil.scanMedia(context, uri)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -423,18 +409,17 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [PendingIntent] that starts a service which cancels the notification and starts a share activity
|
||||
* Returns [PendingIntent] that starts a share activity
|
||||
*
|
||||
* @param context context of application
|
||||
* @param path location path of file
|
||||
* @param uri location path of file
|
||||
* @param notificationId id of notification
|
||||
* @return [PendingIntent]
|
||||
*/
|
||||
internal fun shareImagePendingBroadcast(context: Context, path: String, notificationId: Int): PendingIntent {
|
||||
internal fun shareImagePendingBroadcast(context: Context, uri: Uri): PendingIntent {
|
||||
val intent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_SHARE_IMAGE
|
||||
putExtra(EXTRA_FILE_LOCATION, path)
|
||||
putExtra(EXTRA_NOTIFICATION_ID, notificationId)
|
||||
putExtra(EXTRA_URI, uri.toString())
|
||||
}
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
@ -448,15 +433,13 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
* Returns [PendingIntent] that starts a service which removes an image from disk
|
||||
*
|
||||
* @param context context of application
|
||||
* @param path location path of file
|
||||
* @param notificationId id of notification
|
||||
* @param uri location path of file
|
||||
* @return [PendingIntent]
|
||||
*/
|
||||
internal fun deleteImagePendingBroadcast(context: Context, path: String, notificationId: Int): PendingIntent {
|
||||
internal fun deleteImagePendingBroadcast(context: Context, uri: Uri): PendingIntent {
|
||||
val intent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_DELETE_IMAGE
|
||||
putExtra(EXTRA_FILE_LOCATION, path)
|
||||
putExtra(EXTRA_NOTIFICATION_ID, notificationId)
|
||||
putExtra(EXTRA_URI, uri.toString())
|
||||
}
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
@ -639,14 +622,12 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
*
|
||||
* @param context context of application
|
||||
* @param uri uri of backup file
|
||||
* @param notificationId id of notification
|
||||
* @return [PendingIntent]
|
||||
*/
|
||||
internal fun shareBackupPendingBroadcast(context: Context, uri: Uri, notificationId: Int): PendingIntent {
|
||||
internal fun shareBackupPendingBroadcast(context: Context, uri: Uri): PendingIntent {
|
||||
val intent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_SHARE_BACKUP
|
||||
putExtra(EXTRA_URI, uri)
|
||||
putExtra(EXTRA_NOTIFICATION_ID, notificationId)
|
||||
}
|
||||
return PendingIntent.getBroadcast(
|
||||
context,
|
||||
|
@ -153,6 +153,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||
|month
|
||||
|day
|
||||
|}
|
||||
|averageScore
|
||||
|}
|
||||
|}
|
||||
|}
|
||||
@ -309,6 +310,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
|
||||
struct["status"]!!.jsonPrimitive.contentOrNull ?: "",
|
||||
parseDate(struct, "startDate"),
|
||||
struct["chapters"]!!.jsonPrimitive.intOrNull ?: 0,
|
||||
struct["averageScore"]?.jsonPrimitive?.intOrNull ?: -1,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ data class ALManga(
|
||||
val publishing_status: String,
|
||||
val start_date_fuzzy: Long,
|
||||
val total_chapters: Int,
|
||||
val average_score: Int,
|
||||
) {
|
||||
|
||||
fun toTrack() = TrackSearch.create(TrackerManager.ANILIST).apply {
|
||||
@ -27,6 +28,7 @@ data class ALManga(
|
||||
total_chapters = this@ALManga.total_chapters
|
||||
cover_url = image_url_lge
|
||||
summary = description?.htmlDecode() ?: ""
|
||||
score = average_score.toFloat()
|
||||
tracking_url = AnilistApi.mangaUrl(media_id)
|
||||
publishing_status = this@ALManga.publishing_status
|
||||
publishing_type = format
|
||||
|
@ -11,6 +11,7 @@ import eu.kanade.tachiyomi.network.parseAs
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.contentOrNull
|
||||
import kotlinx.serialization.json.floatOrNull
|
||||
import kotlinx.serialization.json.int
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
@ -108,11 +109,13 @@ class BangumiApi(
|
||||
} else {
|
||||
0
|
||||
}
|
||||
val rating = obj["rating"]?.jsonObject?.get("score")?.jsonPrimitive?.floatOrNull ?: -1f
|
||||
return TrackSearch.create(trackId).apply {
|
||||
media_id = obj["id"]!!.jsonPrimitive.long
|
||||
title = obj["name_cn"]!!.jsonPrimitive.content
|
||||
cover_url = coverUrl
|
||||
summary = obj["name"]!!.jsonPrimitive.content
|
||||
score = rating
|
||||
tracking_url = obj["url"]!!.jsonPrimitive.content
|
||||
total_chapters = totalChapters
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ class KitsuApi(private val client: OkHttpClient, interceptor: KitsuInterceptor)
|
||||
private const val algoliaAppId = "AWQO5J657S"
|
||||
private const val algoliaFilter =
|
||||
"&facetFilters=%5B%22kind%3Amanga%22%5D&attributesToRetrieve=" +
|
||||
"%5B%22synopsis%22%2C%22canonicalTitle%22%2C%22chapterCount%22%2C%22" +
|
||||
"%5B%22synopsis%22%2C%22averageRating%22%2C%22canonicalTitle%22%2C%22chapterCount%22%2C%22" +
|
||||
"posterImage%22%2C%22startDate%22%2C%22subtype%22%2C%22endDate%22%2C%20%22id%22%5D"
|
||||
|
||||
fun mangaUrl(remoteId: Long): String {
|
||||
|
@ -28,6 +28,7 @@ class KitsuSearchManga(obj: JsonObject) {
|
||||
null
|
||||
}
|
||||
private val synopsis = obj["synopsis"]?.jsonPrimitive?.contentOrNull
|
||||
private val rating = obj["averageRating"]?.jsonPrimitive?.contentOrNull?.toFloatOrNull()
|
||||
private var startDate = obj["startDate"]?.jsonPrimitive?.contentOrNull?.let {
|
||||
val outputDf = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
||||
outputDf.format(Date(it.toLong() * 1000))
|
||||
@ -42,6 +43,7 @@ class KitsuSearchManga(obj: JsonObject) {
|
||||
cover_url = original ?: ""
|
||||
summary = synopsis ?: ""
|
||||
tracking_url = KitsuApi.mangaUrl(media_id)
|
||||
score = rating ?: -1f
|
||||
publishing_status = if (endDate == null) {
|
||||
"Publishing"
|
||||
} else {
|
||||
|
@ -20,7 +20,7 @@ class TrackSearch : Track {
|
||||
|
||||
override var total_chapters: Int = 0
|
||||
|
||||
override var score: Float = 0f
|
||||
override var score: Float = -1f
|
||||
|
||||
override var status: Int = 0
|
||||
|
||||
|
@ -16,6 +16,7 @@ import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.boolean
|
||||
import kotlinx.serialization.json.contentOrNull
|
||||
import kotlinx.serialization.json.float
|
||||
import kotlinx.serialization.json.floatOrNull
|
||||
import kotlinx.serialization.json.int
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
@ -103,7 +104,7 @@ class MyAnimeListApi(
|
||||
.appendPath(id.toString())
|
||||
.appendQueryParameter(
|
||||
"fields",
|
||||
"id,title,synopsis,num_chapters,main_picture,status,media_type,start_date",
|
||||
"id,title,synopsis,num_chapters,mean,main_picture,status,media_type,start_date",
|
||||
)
|
||||
.build()
|
||||
with(json) {
|
||||
@ -117,6 +118,7 @@ class MyAnimeListApi(
|
||||
title = obj["title"]!!.jsonPrimitive.content
|
||||
summary = obj["synopsis"]?.jsonPrimitive?.content ?: ""
|
||||
total_chapters = obj["num_chapters"]!!.jsonPrimitive.int
|
||||
score = obj["mean"]?.jsonPrimitive?.floatOrNull ?: -1f
|
||||
cover_url =
|
||||
obj["main_picture"]?.jsonObject?.get("large")?.jsonPrimitive?.content
|
||||
?: ""
|
||||
|
@ -107,6 +107,7 @@ class ShikimoriApi(
|
||||
total_chapters = obj["chapters"]!!.jsonPrimitive.int
|
||||
cover_url = baseUrl + obj["image"]!!.jsonObject["preview"]!!.jsonPrimitive.content
|
||||
summary = ""
|
||||
score = obj["score"]!!.jsonPrimitive.float
|
||||
tracking_url = baseUrl + obj["url"]!!.jsonPrimitive.content
|
||||
publishing_status = obj["status"]!!.jsonPrimitive.content
|
||||
publishing_type = obj["kind"]!!.jsonPrimitive.content
|
||||
|
@ -17,13 +17,12 @@ import eu.kanade.tachiyomi.network.await
|
||||
import eu.kanade.tachiyomi.network.newCachelessCallWithProgress
|
||||
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||
import eu.kanade.tachiyomi.util.storage.saveTo
|
||||
import eu.kanade.tachiyomi.util.system.setForegroundSafely
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import logcat.LogPriority
|
||||
import okhttp3.internal.http2.ErrorCode
|
||||
import okhttp3.internal.http2.StreamResetException
|
||||
import tachiyomi.core.i18n.stringResource
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
@ -43,11 +42,7 @@ class AppUpdateDownloadJob(private val context: Context, workerParams: WorkerPar
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
try {
|
||||
setForeground(getForegroundInfo())
|
||||
} catch (e: IllegalStateException) {
|
||||
logcat(LogPriority.ERROR, e) { "Not allowed to run on foreground service" }
|
||||
}
|
||||
setForegroundSafely()
|
||||
|
||||
withIOContext {
|
||||
downloadApk(title, url)
|
||||
|
@ -10,7 +10,6 @@ import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
||||
import eu.kanade.tachiyomi.ui.security.UnlockActivity
|
||||
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil
|
||||
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.isAuthenticationSupported
|
||||
import eu.kanade.tachiyomi.util.system.overridePendingTransitionCompat
|
||||
import eu.kanade.tachiyomi.util.view.setSecureScreen
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
@ -107,7 +106,7 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
|
||||
if (activity.isAuthenticationSupported()) {
|
||||
if (!SecureActivityDelegate.requireUnlock) return
|
||||
activity.startActivity(Intent(activity, UnlockActivity::class.java))
|
||||
activity.overridePendingTransitionCompat(0, 0)
|
||||
activity.overridePendingTransition(0, 0)
|
||||
} else {
|
||||
securityPreferences.useAuthenticator().set(false)
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
data class MigrationFlag(
|
||||
|
@ -11,12 +11,14 @@ import eu.kanade.tachiyomi.source.model.Page
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@ -137,8 +139,8 @@ class DownloadQueueScreenModel(
|
||||
adapter = null
|
||||
}
|
||||
|
||||
val isDownloaderRunning
|
||||
get() = downloadManager.isDownloaderRunning
|
||||
val isDownloaderRunning = downloadManager.isDownloaderRunning
|
||||
.stateIn(screenModelScope, SharingStarted.WhileSubscribed(5000), false)
|
||||
|
||||
fun getDownloadStatusFlow() = downloadManager.statusFlow()
|
||||
fun getDownloadProgressFlow() = downloadManager.progressFlow()
|
||||
|
@ -34,17 +34,16 @@ import androidx.core.transition.doOnEnd
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
import com.google.android.material.elevation.SurfaceColors
|
||||
import com.google.android.material.transition.platform.MaterialContainerTransform
|
||||
import dev.chrisbanes.insetter.applyInsetter
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.presentation.reader.BrightnessOverlay
|
||||
import eu.kanade.presentation.reader.DisplayRefreshHost
|
||||
import eu.kanade.presentation.reader.OrientationSelectDialog
|
||||
import eu.kanade.presentation.reader.PageIndicatorText
|
||||
import eu.kanade.presentation.reader.ReaderContentOverlay
|
||||
import eu.kanade.presentation.reader.ReaderPageActionsDialog
|
||||
import eu.kanade.presentation.reader.ReadingModeSelectDialog
|
||||
import eu.kanade.presentation.reader.appbars.ReaderAppBars
|
||||
@ -70,7 +69,6 @@ import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressIndicator
|
||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||
import eu.kanade.tachiyomi.util.system.hasDisplayCutout
|
||||
import eu.kanade.tachiyomi.util.system.isNightMode
|
||||
import eu.kanade.tachiyomi.util.system.overridePendingTransitionCompat
|
||||
import eu.kanade.tachiyomi.util.system.toShareIntent
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.view.setComposeContent
|
||||
@ -90,7 +88,6 @@ import tachiyomi.core.util.lang.launchIO
|
||||
import tachiyomi.core.util.lang.launchNonCancellable
|
||||
import tachiyomi.core.util.lang.withUIContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@ -139,7 +136,7 @@ class ReaderActivity : BaseActivity() {
|
||||
*/
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
registerSecureActivity(this)
|
||||
overridePendingTransitionCompat(R.anim.shared_axis_x_push_enter, R.anim.shared_axis_x_push_exit)
|
||||
overridePendingTransition(R.anim.shared_axis_x_push_enter, R.anim.shared_axis_x_push_exit)
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@ -185,7 +182,7 @@ class ReaderActivity : BaseActivity() {
|
||||
.map { it.manga }
|
||||
.distinctUntilChanged()
|
||||
.filterNotNull()
|
||||
.onEach(::setManga)
|
||||
.onEach { updateViewer() }
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
viewModel.state
|
||||
@ -270,7 +267,7 @@ class ReaderActivity : BaseActivity() {
|
||||
override fun finish() {
|
||||
viewModel.onActivityFinish()
|
||||
super.finish()
|
||||
overridePendingTransitionCompat(R.anim.shared_axis_x_pop_enter, R.anim.shared_axis_x_pop_exit)
|
||||
overridePendingTransition(R.anim.shared_axis_x_pop_enter, R.anim.shared_axis_x_pop_exit)
|
||||
}
|
||||
|
||||
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
@ -332,11 +329,24 @@ class ReaderActivity : BaseActivity() {
|
||||
val isFullscreen by readerPreferences.fullscreen().collectAsState()
|
||||
val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState()
|
||||
|
||||
val colorOverlayEnabled by readerPreferences.colorFilter().collectAsState()
|
||||
val colorOverlay by readerPreferences.colorFilterValue().collectAsState()
|
||||
val colorOverlayMode by readerPreferences.colorFilterMode().collectAsState()
|
||||
val colorOverlayBlendMode = remember(colorOverlayMode) {
|
||||
ReaderPreferences.ColorFilterMode.getOrNull(colorOverlayMode)?.second
|
||||
}
|
||||
|
||||
val cropBorderPaged by readerPreferences.cropBorders().collectAsState()
|
||||
val cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState()
|
||||
val isPagerType = ReadingMode.isPagerType(viewModel.getMangaReadingMode())
|
||||
val cropEnabled = if (isPagerType) cropBorderPaged else cropBorderWebtoon
|
||||
|
||||
ReaderContentOverlay(
|
||||
brightness = state.brightnessOverlayValue,
|
||||
color = colorOverlay.takeIf { colorOverlayEnabled },
|
||||
colorBlendMode = colorOverlayBlendMode,
|
||||
)
|
||||
|
||||
ReaderAppBars(
|
||||
visible = state.menuVisible,
|
||||
fullscreen = isFullscreen,
|
||||
@ -379,10 +389,6 @@ class ReaderActivity : BaseActivity() {
|
||||
onClickSettings = viewModel::openSettingsDialog,
|
||||
)
|
||||
|
||||
BrightnessOverlay(
|
||||
value = state.brightnessOverlayValue,
|
||||
)
|
||||
|
||||
if (flashOnPageChange) {
|
||||
DisplayRefreshHost(
|
||||
hostState = displayRefreshHost,
|
||||
@ -479,10 +485,9 @@ class ReaderActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the presenter when a manga is ready. Used to instantiate the appropriate viewer
|
||||
* and the toolbar title.
|
||||
* Called from the presenter when a manga is ready. Used to instantiate the appropriate viewer.
|
||||
*/
|
||||
private fun setManga(manga: Manga) {
|
||||
private fun updateViewer() {
|
||||
val prevViewer = viewModel.state.value.viewer
|
||||
val newViewer = ReadingMode.toViewer(viewModel.getMangaReadingMode(), this)
|
||||
|
||||
@ -806,14 +811,6 @@ class ReaderActivity : BaseActivity() {
|
||||
.onEach(::setCustomBrightness)
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
readerPreferences.colorFilter().changes()
|
||||
.onEach(::setColorFilter)
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
readerPreferences.colorFilterMode().changes()
|
||||
.onEach { setColorFilter(readerPreferences.colorFilter().get()) }
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
merge(readerPreferences.grayscale().changes(), readerPreferences.invertedColors().changes())
|
||||
.onEach { setLayerPaint(readerPreferences.grayscale().get(), readerPreferences.invertedColors().get()) }
|
||||
.launchIn(lifecycleScope)
|
||||
@ -885,20 +882,6 @@ class ReaderActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color filter overlay according to [enabled].
|
||||
*/
|
||||
private fun setColorFilter(enabled: Boolean) {
|
||||
if (enabled) {
|
||||
readerPreferences.colorFilterValue().changes()
|
||||
.sample(100)
|
||||
.onEach(::setColorFilterValue)
|
||||
.launchIn(lifecycleScope)
|
||||
} else {
|
||||
binding.colorOverlay.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the brightness of the screen. Range is [-75, 100].
|
||||
* From -75 to -1 a semi-transparent black view is overlaid with the minimum brightness.
|
||||
@ -920,15 +903,6 @@ class ReaderActivity : BaseActivity() {
|
||||
|
||||
viewModel.setBrightnessOverlayValue(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color filter [value].
|
||||
*/
|
||||
private fun setColorFilterValue(value: Int) {
|
||||
binding.colorOverlay.isVisible = true
|
||||
binding.colorOverlay.setFilterColor(value, readerPreferences.colorFilterMode().get())
|
||||
}
|
||||
|
||||
private fun setLayerPaint(grayscale: Boolean, invertedColors: Boolean) {
|
||||
val paint = if (grayscale || invertedColors) getCombinedPaint(grayscale, invertedColors) else null
|
||||
binding.viewerContainer.setLayerType(LAYER_TYPE_HARDWARE, paint)
|
||||
|
@ -1,36 +0,0 @@
|
||||
package eu.kanade.tachiyomi.ui.reader
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.graphics.PorterDuff
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.core.graphics.toXfermode
|
||||
|
||||
class ReaderColorFilterView(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
) : View(context, attrs) {
|
||||
|
||||
private val colorFilterPaint: Paint = Paint()
|
||||
|
||||
fun setFilterColor(color: Int, filterMode: Int) {
|
||||
colorFilterPaint.color = color
|
||||
colorFilterPaint.xfermode = when (filterMode) {
|
||||
1 -> PorterDuff.Mode.MULTIPLY
|
||||
2 -> PorterDuff.Mode.SCREEN
|
||||
3 -> PorterDuff.Mode.OVERLAY
|
||||
4 -> PorterDuff.Mode.LIGHTEN
|
||||
5 -> PorterDuff.Mode.DARKEN
|
||||
else -> PorterDuff.Mode.SRC_OVER
|
||||
}.toXfermode()
|
||||
|
||||
invalidate()
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
super.onDraw(canvas)
|
||||
canvas.drawPaint(colorFilterPaint)
|
||||
}
|
||||
}
|
@ -81,13 +81,13 @@ class SaveImageNotifier(private val context: Context) {
|
||||
addAction(
|
||||
R.drawable.ic_share_24dp,
|
||||
context.stringResource(MR.strings.action_share),
|
||||
NotificationReceiver.shareImagePendingBroadcast(context, uri.path!!, notificationId),
|
||||
NotificationReceiver.shareImagePendingBroadcast(context, uri),
|
||||
)
|
||||
// Delete action
|
||||
addAction(
|
||||
R.drawable.ic_delete_24dp,
|
||||
context.stringResource(MR.strings.action_delete),
|
||||
NotificationReceiver.deleteImagePendingBroadcast(context, uri.path!!, notificationId),
|
||||
NotificationReceiver.deleteImagePendingBroadcast(context, uri),
|
||||
)
|
||||
|
||||
updateNotification()
|
||||
|
@ -1,57 +1,62 @@
|
||||
package eu.kanade.tachiyomi.ui.reader.setting
|
||||
|
||||
import android.content.pm.ActivityInfo
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ScreenLockLandscape
|
||||
import androidx.compose.material.icons.filled.ScreenLockPortrait
|
||||
import androidx.compose.material.icons.filled.ScreenRotation
|
||||
import androidx.compose.material.icons.filled.StayCurrentLandscape
|
||||
import androidx.compose.material.icons.filled.StayCurrentPortrait
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
|
||||
enum class ReaderOrientation(
|
||||
val flag: Int,
|
||||
val stringRes: StringResource,
|
||||
@DrawableRes val iconRes: Int,
|
||||
val icon: ImageVector,
|
||||
val flagValue: Int,
|
||||
) {
|
||||
DEFAULT(
|
||||
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED,
|
||||
MR.strings.label_default,
|
||||
R.drawable.ic_screen_rotation_24dp,
|
||||
Icons.Default.ScreenRotation,
|
||||
0x00000000,
|
||||
),
|
||||
FREE(
|
||||
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED,
|
||||
MR.strings.rotation_free,
|
||||
R.drawable.ic_screen_rotation_24dp,
|
||||
Icons.Default.ScreenRotation,
|
||||
0x00000008,
|
||||
),
|
||||
PORTRAIT(
|
||||
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT,
|
||||
MR.strings.rotation_portrait,
|
||||
R.drawable.ic_stay_current_portrait_24dp,
|
||||
Icons.Default.StayCurrentPortrait,
|
||||
0x00000010,
|
||||
),
|
||||
LANDSCAPE(
|
||||
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE,
|
||||
MR.strings.rotation_landscape,
|
||||
R.drawable.ic_stay_current_landscape_24dp,
|
||||
Icons.Default.StayCurrentLandscape,
|
||||
0x00000018,
|
||||
),
|
||||
LOCKED_PORTRAIT(
|
||||
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT,
|
||||
MR.strings.rotation_force_portrait,
|
||||
R.drawable.ic_screen_lock_portrait_24dp,
|
||||
Icons.Default.ScreenLockPortrait,
|
||||
0x00000020,
|
||||
),
|
||||
LOCKED_LANDSCAPE(
|
||||
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,
|
||||
MR.strings.rotation_force_landscape,
|
||||
R.drawable.ic_screen_lock_landscape_24dp,
|
||||
Icons.Default.ScreenLockLandscape,
|
||||
0x00000028,
|
||||
),
|
||||
REVERSE_PORTRAIT(
|
||||
ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT,
|
||||
MR.strings.rotation_reverse_portrait,
|
||||
R.drawable.ic_stay_current_portrait_24dp,
|
||||
Icons.Default.StayCurrentPortrait,
|
||||
0x00000030,
|
||||
),
|
||||
;
|
||||
|
@ -1,5 +1,7 @@
|
||||
package eu.kanade.tachiyomi.ui.reader.setting
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.ui.graphics.BlendMode
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.core.preference.getEnum
|
||||
@ -178,5 +180,24 @@ class ReaderPreferences(
|
||||
MR.strings.zoom_start_right,
|
||||
MR.strings.zoom_start_center,
|
||||
)
|
||||
|
||||
val ColorFilterMode = buildList {
|
||||
addAll(
|
||||
listOf(
|
||||
MR.strings.label_default to BlendMode.SrcOver,
|
||||
MR.strings.filter_mode_multiply to BlendMode.Modulate,
|
||||
MR.strings.filter_mode_screen to BlendMode.Screen,
|
||||
),
|
||||
)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
addAll(
|
||||
listOf(
|
||||
MR.strings.filter_mode_overlay to BlendMode.Overlay,
|
||||
MR.strings.filter_mode_lighten to BlendMode.Lighten,
|
||||
MR.strings.filter_mode_darken to BlendMode.Darken,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
||||
import eu.kanade.tachiyomi.util.system.WebViewUtil
|
||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||
import eu.kanade.tachiyomi.util.system.overridePendingTransitionCompat
|
||||
import eu.kanade.tachiyomi.util.system.toShareIntent
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.view.setComposeContent
|
||||
@ -36,7 +35,7 @@ class WebViewActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
overridePendingTransitionCompat(R.anim.shared_axis_x_push_enter, R.anim.shared_axis_x_push_exit)
|
||||
overridePendingTransition(R.anim.shared_axis_x_push_enter, R.anim.shared_axis_x_push_exit)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (!WebViewUtil.supportsWebView(this)) {
|
||||
@ -78,7 +77,7 @@ class WebViewActivity : BaseActivity() {
|
||||
|
||||
override fun finish() {
|
||||
super.finish()
|
||||
overridePendingTransitionCompat(R.anim.shared_axis_x_pop_enter, R.anim.shared_axis_x_pop_exit)
|
||||
overridePendingTransition(R.anim.shared_axis_x_pop_enter, R.anim.shared_axis_x_pop_exit)
|
||||
}
|
||||
|
||||
private fun shareWebpage(url: String) {
|
||||
|
@ -1,14 +0,0 @@
|
||||
package eu.kanade.tachiyomi.util.system
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import androidx.annotation.AnimRes
|
||||
|
||||
fun Activity.overridePendingTransitionCompat(@AnimRes enterAnim: Int, @AnimRes exitAnim: Int) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
overrideActivityTransition(Activity.OVERRIDE_TRANSITION_OPEN, enterAnim, exitAnim)
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
overridePendingTransition(enterAnim, exitAnim)
|
||||
}
|
||||
}
|
@ -1,18 +1,15 @@
|
||||
package eu.kanade.tachiyomi.util.system
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import androidx.core.content.PermissionChecker
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.net.toUri
|
||||
import com.hippo.unifile.UniFile
|
||||
@ -55,39 +52,9 @@ fun Context.copyToClipboard(label: String, content: String) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the give permission is granted.
|
||||
*
|
||||
* @param permission the permission to check.
|
||||
* @return true if it has permissions.
|
||||
*/
|
||||
fun Context.hasPermission(
|
||||
permission: String,
|
||||
) = PermissionChecker.checkSelfPermission(this, permission) == PermissionChecker.PERMISSION_GRANTED
|
||||
|
||||
val Context.powerManager: PowerManager
|
||||
get() = getSystemService()!!
|
||||
|
||||
/**
|
||||
* Convenience method to acquire a partial wake lock.
|
||||
*/
|
||||
fun Context.acquireWakeLock(tag: String): PowerManager.WakeLock {
|
||||
val wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "$tag:WakeLock")
|
||||
wakeLock.acquire()
|
||||
return wakeLock
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given service class is running.
|
||||
*/
|
||||
fun Context.isServiceRunning(serviceClass: Class<*>): Boolean {
|
||||
val className = serviceClass.name
|
||||
val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||
@Suppress("DEPRECATION")
|
||||
return manager.getRunningServices(Integer.MAX_VALUE)
|
||||
.any { className == it.service.className }
|
||||
}
|
||||
|
||||
fun Context.openInBrowser(url: String, forceDefaultBrowser: Boolean = false) {
|
||||
this.openInBrowser(url.toUri(), forceDefaultBrowser)
|
||||
}
|
||||
@ -200,11 +167,3 @@ fun Context.isInstalledFromFDroid(): Boolean {
|
||||
// F-Droid builds typically disable the updater
|
||||
(!BuildConfig.INCLUDE_UPDATER && !isDevFlavor)
|
||||
}
|
||||
|
||||
fun Context.getApplicationIcon(pkgName: String): Drawable? {
|
||||
return try {
|
||||
packageManager.getApplicationIcon(pkgName)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,12 @@
|
||||
package eu.kanade.tachiyomi.util.system
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import kotlinx.coroutines.delay
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.system.logcat
|
||||
|
||||
val Context.workManager: WorkManager
|
||||
get() = WorkManager.getInstance(this)
|
||||
@ -11,3 +15,21 @@ fun WorkManager.isRunning(tag: String): Boolean {
|
||||
val list = this.getWorkInfosByTag(tag).get()
|
||||
return list.any { it.state == WorkInfo.State.RUNNING }
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes this worker run in the context of a foreground service.
|
||||
*
|
||||
* Note that this function is a no-op if the process is subject to foreground
|
||||
* service restrictions.
|
||||
*
|
||||
* Moving to foreground service context requires the worker to run a bit longer,
|
||||
* allowing Service.startForeground() to be called and avoiding system crash.
|
||||
*/
|
||||
suspend fun CoroutineWorker.setForegroundSafely() {
|
||||
try {
|
||||
setForeground(getForegroundInfo())
|
||||
delay(500)
|
||||
} catch (e: IllegalStateException) {
|
||||
logcat(LogPriority.ERROR, e) { "Not allowed to set foreground job" }
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- 34% of 12% = ~4% -->
|
||||
<item android:alpha="0.34" android:color="?attr/colorControlHighlight" />
|
||||
</selector>
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="?attr/colorPrimary" android:state_enabled="true"/>
|
||||
<item android:alpha="@dimen/material_emphasis_disabled" android:color="?attr/colorOnSurface"/>
|
||||
</selector>
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:alpha="0.24" android:color="?attr/colorPrimary" android:state_enabled="true"/>
|
||||
<item android:alpha="@dimen/material_emphasis_disabled" android:color="?attr/colorOnSurface"/>
|
||||
</selector>
|
@ -1,7 +0,0 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<size
|
||||
android:width="24dp"
|
||||
android:height="24dp" />
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
@ -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="#000"
|
||||
android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10s10,-4.5 10,-10S17.5,2 12,2zM17,18H7v-2h10V18zM10.3,14L7,10.7l1.4,-1.4l1.9,1.9l5.3,-5.3L17,7.3L10.3,14z" />
|
||||
</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="#000"
|
||||
android:pathData="M21,5L3,5c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2L23,7c0,-1.1 -0.9,-2 -2,-2zM19,17L5,17L5,7h14v10zM10,16h4c0.55,0 1,-0.45 1,-1v-3c0,-0.55 -0.45,-1 -1,-1v-1c0,-1.11 -0.9,-2 -2,-2 -1.11,0 -2,0.9 -2,2v1c-0.55,0 -1,0.45 -1,1v3c0,0.55 0.45,1 1,1zM10.8,10c0,-0.66 0.54,-1.2 1.2,-1.2 0.66,0 1.2,0.54 1.2,1.2v1h-2.4v-1z" />
|
||||
</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="#000"
|
||||
android:pathData="M10,16h4c0.55,0 1,-0.45 1,-1v-3c0,-0.55 -0.45,-1 -1,-1v-1c0,-1.11 -0.9,-2 -2,-2 -1.11,0 -2,0.9 -2,2v1c-0.55,0 -1,0.45 -1,1v3c0,0.55 0.45,1 1,1zM10.8,10c0,-0.66 0.54,-1.2 1.2,-1.2 0.66,0 1.2,0.54 1.2,1.2v1h-2.4v-1zM17,1L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2L19,3c0,-1.1 -0.9,-2 -2,-2zM17,19L7,19L7,5h10v14z" />
|
||||
</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="#000"
|
||||
android:pathData="M16.48,2.52c3.27,1.55 5.61,4.72 5.97,8.48h1.5C23.44,4.84 18.29,0 12,0l-0.66,0.03 3.81,3.81 1.33,-1.32zM10.23,1.75c-0.59,-0.59 -1.54,-0.59 -2.12,0L1.75,8.11c-0.59,0.59 -0.59,1.54 0,2.12l12.02,12.02c0.59,0.59 1.54,0.59 2.12,0l6.36,-6.36c0.59,-0.59 0.59,-1.54 0,-2.12L10.23,1.75zM14.83,21.19L2.81,9.17l6.36,-6.36 12.02,12.02 -6.36,6.36zM7.52,21.48C4.25,19.94 1.91,16.76 1.55,13L0.05,13C0.56,19.16 5.71,24 12,24l0.66,-0.03 -3.81,-3.81 -1.33,1.32z" />
|
||||
</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="#000"
|
||||
android:pathData="M1.01,7L1,17c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2V7c0,-1.1 -0.9,-2 -2,-2H3c-1.1,0 -1.99,0.9 -1.99,2zM19,7v10H5V7h14z" />
|
||||
</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="#000"
|
||||
android:pathData="M17,1.01L7,1c-1.1,0 -1.99,0.9 -1.99,2v18c0,1.1 0.89,2 1.99,2h10c1.1,0 2,-0.9 2,-2V3c0,-1.1 -0.9,-1.99 -2,-1.99zM17,19H7V5h10v14z" />
|
||||
</vector>
|
@ -1,7 +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="#FFF" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11,19.93c-3.95,-0.49 -7,-3.85 -7,-7.93 0,-0.62 0.08,-1.21 0.21,-1.79L9,15v1c0,1.1 0.9,2 2,2v1.93zM17.9,17.39c-0.26,-0.81 -1,-1.39 -1.9,-1.39h-1v-3c0,-0.55 -0.45,-1 -1,-1L8,12v-2h2c0.55,0 1,-0.45 1,-1L11,7h2c1.1,0 2,-0.9 2,-2v-0.41c2.93,1.19 5,4.06 5,7.41 0,2.08 -0.8,3.97 -2.1,5.39z"/>
|
||||
</vector>
|
@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@android:color/transparent"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item
|
||||
android:gravity="bottom">
|
||||
<shape>
|
||||
<size android:height="1dp" />
|
||||
<solid android:color="?attr/colorSurfaceVariant" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
@ -21,12 +21,6 @@
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<eu.kanade.tachiyomi.ui.reader.ReaderColorFilterView
|
||||
android:id="@+id/color_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone" />
|
||||
|
||||
<eu.kanade.tachiyomi.ui.reader.ReaderNavigationOverlayView
|
||||
android:id="@+id/navigation_overlay"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -1,3 +0,0 @@
|
||||
<resources>
|
||||
<dimen name="screen_edge_margin">24dp</dimen>
|
||||
</resources>
|
@ -1,6 +1,4 @@
|
||||
<resources>
|
||||
<dimen name="screen_edge_margin">16dp</dimen>
|
||||
|
||||
<dimen name="appwidget_background_radius">16dp</dimen>
|
||||
<dimen name="appwidget_inner_radius">12dp</dimen>
|
||||
</resources>
|
||||
|
@ -1,5 +1,5 @@
|
||||
[versions]
|
||||
agp_version = "8.1.4"
|
||||
agp_version = "8.2.0"
|
||||
lifecycle_version = "2.6.2"
|
||||
paging_version = "3.2.1"
|
||||
|
||||
@ -20,14 +20,14 @@ lifecycle-common = { module = "androidx.lifecycle:lifecycle-common", version.ref
|
||||
lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "lifecycle_version" }
|
||||
lifecycle-runtimektx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle_version" }
|
||||
|
||||
workmanager = "androidx.work:work-runtime-ktx:2.8.1"
|
||||
workmanager = "androidx.work:work-runtime:2.9.0"
|
||||
|
||||
paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "paging_version" }
|
||||
paging-compose = { module = "androidx.paging:paging-compose", version.ref = "paging_version" }
|
||||
|
||||
benchmark-macro = "androidx.benchmark:benchmark-macro-junit4:1.2.1"
|
||||
test-ext = "androidx.test.ext:junit-ktx:1.2.0-alpha01"
|
||||
test-espresso-core = "androidx.test.espresso:espresso-core:3.6.0-alpha01"
|
||||
benchmark-macro = "androidx.benchmark:benchmark-macro-junit4:1.2.2"
|
||||
test-ext = "androidx.test.ext:junit-ktx:1.2.0-alpha02"
|
||||
test-espresso-core = "androidx.test.espresso:espresso-core:3.6.0-alpha02"
|
||||
test-uiautomator = "androidx.test.uiautomator:uiautomator:2.3.0-alpha05"
|
||||
|
||||
[bundles]
|
||||
|
@ -1,6 +1,6 @@
|
||||
[versions]
|
||||
compiler = "1.5.4"
|
||||
compose-bom = "2023.12.00-alpha02"
|
||||
compiler = "1.5.5"
|
||||
compose-bom = "2023.12.00-alpha03"
|
||||
accompanist = "0.33.2-alpha"
|
||||
|
||||
[libraries]
|
||||
|
@ -15,7 +15,6 @@ android-shortcut-gradle = "com.github.zellius:android-shortcut-gradle-plugin:0.1
|
||||
google-services-gradle = "com.google.gms:google-services:4.4.0"
|
||||
|
||||
rxjava = "io.reactivex:rxjava:1.3.8"
|
||||
flowreactivenetwork = "ru.beryukhov:flowreactivenetwork:1.0.4"
|
||||
|
||||
okhttp-core = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp_version" }
|
||||
okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp_version" }
|
||||
@ -27,7 +26,7 @@ conscrypt-android = "org.conscrypt:conscrypt-android:2.5.2"
|
||||
|
||||
quickjs-android = "app.cash.quickjs:quickjs-android:0.9.2"
|
||||
|
||||
jsoup = "org.jsoup:jsoup:1.16.2"
|
||||
jsoup = "org.jsoup:jsoup:1.17.1"
|
||||
|
||||
disklrucache = "com.jakewharton:disklrucache:2.0.2"
|
||||
unifile = "com.github.tachiyomiorg:unifile:7c257e1c64"
|
||||
@ -94,11 +93,10 @@ voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.
|
||||
voyager-tab-navigator = { module = "cafe.adriel.voyager:voyager-tab-navigator", version.ref = "voyager" }
|
||||
voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" }
|
||||
|
||||
ktlint = "org.jlleitschuh.gradle:ktlint-gradle:11.6.1"
|
||||
ktlint = "org.jlleitschuh.gradle:ktlint-gradle:12.0.2"
|
||||
google-api-services-drive = "com.google.apis:google-api-services-drive:v3-rev197-1.25.0"
|
||||
google-api-client-oauth = "com.google.oauth-client:google-oauth-client:1.34.1"
|
||||
|
||||
|
||||
[bundles]
|
||||
okhttp = ["okhttp-core", "okhttp-logging", "okhttp-brotli", "okhttp-dnsoverhttps"]
|
||||
js-engine = ["quickjs-android"]
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
@ -158,12 +158,10 @@
|
||||
<string name="label_settings">ማስተካከያዎች</string>
|
||||
<string name="label_more">ተጨማሪ</string>
|
||||
<string name="name">ስም</string>
|
||||
<string name="custom_dir">ብጁ አካባቢ</string>
|
||||
<string name="pref_remove_bookmarked_chapters">ዕልባት የተደረገባቸውን ምዕራፎች ሰርዝ</string>
|
||||
<string name="pref_remove_after_read">ካነበብኩ በኋላ</string>
|
||||
<string name="pref_remove_after_marked_as_read">በእጅ እንደተነበበ ምልክት ከተደረገ በኋላ</string>
|
||||
<string name="pref_category_delete_chapters">ምዕራፎችን ሰርዝ</string>
|
||||
<string name="pref_download_directory">አካባቢን ያውርዱ</string>
|
||||
<string name="pref_webtoon_side_padding">የጎን ሽፋን</string>
|
||||
<string name="pref_category_reading">ንባብ</string>
|
||||
<string name="pref_category_reading_mode">የንባብ ሁነታ</string>
|
||||
@ -246,9 +244,7 @@
|
||||
<string name="color_filter_g_value">ኣ</string>
|
||||
<string name="invalid_backup_file">ልክ ያልሆነ የመጠባበቂያ ፋይል</string>
|
||||
<string name="backup_created">ምትኬ ተፈጥሯል</string>
|
||||
<string name="pref_backup_slots">ከፍተኛ መጠባበቂያዎች</string>
|
||||
<string name="pref_backup_interval">የመጠባበቂያ ድግግሞሽ</string>
|
||||
<string name="pref_backup_directory">የመጠባበቂያ ቦታ</string>
|
||||
<string name="pref_restore_backup_summ">ቤተ-መጽሐፍት ከመጠባበቂያ ፋይል ይመልሱ</string>
|
||||
<string name="pref_restore_backup">ምትኬ ወደነበረበት</string>
|
||||
<string name="pref_create_backup_summ">የአሁኑን ቤተ-መጽሐፍት ወደነበረበት ለመመለስ ሊያገለግል ይችላል</string>
|
||||
|
@ -116,10 +116,8 @@
|
||||
<string name="rotation_free">حر</string>
|
||||
<string name="rotation_force_portrait">الوضع الرأسي اﻹجباري</string>
|
||||
<string name="rotation_force_landscape">الوضع الأفقي الإجباري</string>
|
||||
<string name="pref_download_directory">موقع التنزيل</string>
|
||||
<string name="pref_remove_after_marked_as_read">بعد وضع علامة \"مقروءة\" يدوياً</string>
|
||||
<string name="pref_remove_after_read">الحذف تلقائيا بعد القراءة</string>
|
||||
<string name="custom_dir">مجلد مخصص</string>
|
||||
<string name="disabled">معطل</string>
|
||||
<string name="last_read_chapter">آخر فصل مقروء</string>
|
||||
<string name="second_to_last">من الفصل الثاني قبل الأخير</string>
|
||||
@ -132,9 +130,7 @@
|
||||
<string name="pref_create_backup_summ">يمكن استخدامها لإستعادة المكتبة الحالية</string>
|
||||
<string name="pref_restore_backup">إستعادة النسخة الإحتياطية</string>
|
||||
<string name="pref_restore_backup_summ">إستعادة مكتبة من ملف نسخة إحتياطية</string>
|
||||
<string name="pref_backup_directory">موقع النسخ الإحتياطي</string>
|
||||
<string name="pref_backup_interval">معدل النسخ الاحتياطي التلقائي</string>
|
||||
<string name="pref_backup_slots">أقصى عدد للنسخ الاحتياطية التلقائية</string>
|
||||
<string name="backup_created">أُنشئت نسخة احتياطية</string>
|
||||
<string name="restore_completed">اكتملت الاستعادة</string>
|
||||
<string name="backup_choice">ما الذي تريد نسخه احتياطيّاً؟</string>
|
||||
@ -350,7 +346,6 @@
|
||||
<string name="notification_chapters_multiple">الفصول %1$s</string>
|
||||
<string name="notification_chapters_single_and_more">الفصل %1$s و%2$d فصول أخرى</string>
|
||||
<string name="notification_chapters_single">الفصل %1$s</string>
|
||||
<string name="notification_check_updates">جارٍ التحقق من وجود فصول جديدة</string>
|
||||
<string name="recent_manga_time">الفصل %1$s - %2$s</string>
|
||||
<string name="updating_library">تُحدَّث المكتبة</string>
|
||||
<string name="viewer">وضع القراءة</string>
|
||||
@ -768,4 +763,10 @@
|
||||
<string name="no_scanlators_found">لم يُعثَر على مترجمين</string>
|
||||
<string name="scanlator">المترجم</string>
|
||||
<string name="exclude_scanlators">احجب بعض المترجمين</string>
|
||||
<string name="action_menu_overflow_description">خيارات أكثر</string>
|
||||
<string name="selected">محدَّد</string>
|
||||
<string name="not_selected">غير مُحدَّد</string>
|
||||
<string name="action_bar_up_description">اصعد</string>
|
||||
<string name="pref_storage_location">مكان التخزين</string>
|
||||
<string name="pref_storage_location_info">يُستخدَم في الاحتياط وتنزيل الفصول والمصدر المحليِّ.</string>
|
||||
</resources>
|
@ -288,12 +288,10 @@
|
||||
<string name="second_to_last">Перадапошняя частка</string>
|
||||
<string name="last_read_chapter">Апошняя прачытаная частка</string>
|
||||
<string name="disabled">Адключана</string>
|
||||
<string name="custom_dir">Карыстацкая дырэкторыя</string>
|
||||
<string name="pref_remove_bookmarked_chapters">Дазволіць выдаленне частак з закладкамі</string>
|
||||
<string name="pref_remove_after_read">Аўтаматычна пасля чытання</string>
|
||||
<string name="pref_remove_after_marked_as_read">Пасля таго, як пазначана як \"Прачытанае\"</string>
|
||||
<string name="pref_category_delete_chapters">Выдаліць часткі</string>
|
||||
<string name="pref_download_directory">Каталог загрузак</string>
|
||||
<string name="pref_lowest">Найнізкая</string>
|
||||
<string name="pref_low">Нізкая</string>
|
||||
<string name="pref_high">Высокая</string>
|
||||
|
@ -106,10 +106,8 @@
|
||||
<string name="color_filter_g_value">G</string>
|
||||
<string name="color_filter_b_value">B</string>
|
||||
<string name="color_filter_a_value">A</string>
|
||||
<string name="pref_download_directory">Директория на изтеглянията</string>
|
||||
<string name="pref_remove_after_marked_as_read">След маркиране като прочетено</string>
|
||||
<string name="pref_remove_after_read">След прочитане автоматично изтрийте</string>
|
||||
<string name="custom_dir">Персонализирана директория</string>
|
||||
<string name="disabled">Изключено</string>
|
||||
<string name="last_read_chapter">Последно прочетена глава</string>
|
||||
<string name="second_to_last">Предпоследна прочетена глава</string>
|
||||
@ -214,9 +212,7 @@
|
||||
<string name="pref_create_backup_summ">Може да се използва за възстановяване на текущата библиотека</string>
|
||||
<string name="pref_restore_backup">Възстанови резервно копие</string>
|
||||
<string name="pref_restore_backup_summ">Възстанови библиотеката от резервно копие</string>
|
||||
<string name="pref_backup_directory">Директория за резервното копие</string>
|
||||
<string name="pref_backup_interval">Честота на запазване</string>
|
||||
<string name="pref_backup_slots">Максимален брой копия</string>
|
||||
<string name="backup_created">Резервно копие създадено</string>
|
||||
<string name="restore_completed">Възстановяването завършено</string>
|
||||
<string name="backup_choice">Какво искате да запазите?</string>
|
||||
@ -310,7 +306,6 @@
|
||||
<string name="notification_chapters_multiple">Глави %1$s</string>
|
||||
<string name="notification_chapters_single_and_more">Глава %1$s и %2$d още</string>
|
||||
<string name="notification_chapters_single">Глава %1$s</string>
|
||||
<string name="notification_check_updates">Проверяване за нови глави</string>
|
||||
<string name="recent_manga_time">Гл. %1$s - %2$s</string>
|
||||
<string name="updating_library">Обновяване на библиотеката</string>
|
||||
<string name="add_tracking">Добави проследяване</string>
|
||||
|
@ -122,10 +122,8 @@
|
||||
<string name="color_filter_g_value">স</string>
|
||||
<string name="color_filter_b_value">নী</string>
|
||||
<string name="color_filter_a_value">আ</string>
|
||||
<string name="pref_download_directory">ডাউনলোডের স্থান</string>
|
||||
<string name="pref_remove_after_marked_as_read">পঠিত হিসেবে চিহ্নিত করার পর</string>
|
||||
<string name="pref_remove_after_read">পড়ার পর স্বয়ংক্রিয়ভাবে</string>
|
||||
<string name="custom_dir">স্বনির্ধারিত নির্দেশক</string>
|
||||
<string name="disabled">নিষ্ক্রিয়</string>
|
||||
<string name="last_read_chapter">শেষ পঠিত অধ্যায়</string>
|
||||
<string name="second_to_last">২য় থেকে শেষ অধ্যায়</string>
|
||||
@ -138,9 +136,7 @@
|
||||
<string name="pref_create_backup_summ">বর্তমান সংগ্রহশালা পুনরুদ্ধারের জন্য ব্যাবহার করা যাবে</string>
|
||||
<string name="pref_restore_backup">ব্যাকআপ পুনরুদ্ধার</string>
|
||||
<string name="pref_restore_backup_summ">ব্যাকআপ ফাইল থেকে সংগ্রহশালা পুনরুদ্ধার করুন</string>
|
||||
<string name="pref_backup_directory">ব্যাকআপের স্থান</string>
|
||||
<string name="pref_backup_interval">ব্যাকআপ ফ্রিকোয়েন্সি</string>
|
||||
<string name="pref_backup_slots">সর্বোচ্চ ব্যাকআপ</string>
|
||||
<string name="backup_created">ব্যাকআপ তৈরী হয়েছে</string>
|
||||
<string name="restore_completed">পুনরুদ্ধার সম্পন্ন হয়েছে</string>
|
||||
<string name="backup_choice">আপনি কি ব্যাকআপ করতে ইচ্ছুক?</string>
|
||||
@ -393,7 +389,6 @@
|
||||
<string name="notification_chapters_multiple">অধ্যায়গুলি %1$s</string>
|
||||
<string name="notification_chapters_single_and_more">অধ্যায় %1$s এবং %2$d আরও</string>
|
||||
<string name="notification_chapters_single">অধ্যায় %1$s</string>
|
||||
<string name="notification_check_updates">নতুন অধ্যায়ের জন্য অনুসন্ধান করা হচ্ছে</string>
|
||||
<string name="download_insufficient_space">কম সঞ্চয়স্থানের কারণে অধ্যায়গুলি ডাউনলোড করা যায়নি</string>
|
||||
<string name="recent_manga_time">অঃ %1$s - %2$s</string>
|
||||
<string name="updating_library">সংগ্রহশালার হালনাগাদ হচ্ছে</string>
|
||||
|
@ -2,66 +2,82 @@
|
||||
<resources>
|
||||
<plurals name="lock_after_mins">
|
||||
<item quantity="one">Després d’%1$s minut</item>
|
||||
<item quantity="many">Després de %1$s minuts</item>
|
||||
<item quantity="other">Després de %1$s minuts</item>
|
||||
</plurals>
|
||||
<plurals name="notification_chapters_generic">
|
||||
<item quantity="one">%1$d capítol nou</item>
|
||||
<item quantity="many">%1$d capítols nous</item>
|
||||
<item quantity="other">%1$d capítols nous</item>
|
||||
</plurals>
|
||||
<plurals name="notification_chapters_multiple_and_more">
|
||||
<item quantity="one">Capítols %1$s i 1 més</item>
|
||||
<item quantity="many">Capítols %1$s i %2$d més</item>
|
||||
<item quantity="other">Capítols %1$s i %2$d més</item>
|
||||
</plurals>
|
||||
<plurals name="notification_new_chapters_summary">
|
||||
<item quantity="one">Per a %d element</item>
|
||||
<item quantity="many">Per a %d elements</item>
|
||||
<item quantity="other">Per a %d elements</item>
|
||||
</plurals>
|
||||
<plurals name="update_check_notification_ext_updates">
|
||||
<item quantity="one">Hi ha una actualització d’una extensió</item>
|
||||
<item quantity="many">Hi ha actualitzacions de %d extensions</item>
|
||||
<item quantity="other">Hi ha actualitzacions de %d extensions</item>
|
||||
</plurals>
|
||||
<plurals name="download_queue_summary">
|
||||
<item quantity="one">En resta %1$s</item>
|
||||
<item quantity="many">En resten %1$s</item>
|
||||
<item quantity="other">En resten %1$s</item>
|
||||
</plurals>
|
||||
<plurals name="restore_completed_message">
|
||||
<item quantity="one">Fet en %1$s amb %2$s error</item>
|
||||
<item quantity="many">Fet en %1$s amb %2$s errors</item>
|
||||
<item quantity="other">Fet en %1$s amb %2$s errors</item>
|
||||
</plurals>
|
||||
<plurals name="num_categories">
|
||||
<item quantity="one">%d categoria</item>
|
||||
<item quantity="many">%d categories</item>
|
||||
<item quantity="other">%d categories</item>
|
||||
</plurals>
|
||||
<plurals name="manga_num_chapters">
|
||||
<item quantity="one">%1$s capítol</item>
|
||||
<item quantity="many">%1$s capítols</item>
|
||||
<item quantity="other">%1$s capítols</item>
|
||||
</plurals>
|
||||
<plurals name="num_trackers">
|
||||
<item quantity="one">%d servei de seguiment</item>
|
||||
<item quantity="many">%d serveis de seguiment</item>
|
||||
<item quantity="other">%d serveis de seguiment</item>
|
||||
</plurals>
|
||||
<plurals name="missing_chapters_warning">
|
||||
<item quantity="one">S’ha omès %d capítol. És possible que manqui a la font o que hagi estat filtrat</item>
|
||||
<item quantity="many">S’han omès %d capítols. És possible que manquin a la font o que hagin estat filtrats</item>
|
||||
<item quantity="other">S’han omès %d capítols. És possible que manquin a la font o que hagin estat filtrats</item>
|
||||
</plurals>
|
||||
<plurals name="relative_time">
|
||||
<item quantity="one">Ahir</item>
|
||||
<item quantity="many">Fa %1$d dies</item>
|
||||
<item quantity="other">Fa %1$d dies</item>
|
||||
</plurals>
|
||||
<plurals name="next_unread_chapters">
|
||||
<item quantity="one">El següent capítol no llegit</item>
|
||||
<item quantity="many">Els següents %d capítols no llegits</item>
|
||||
<item quantity="other">Els següents %d capítols no llegits</item>
|
||||
</plurals>
|
||||
<plurals name="download_amount">
|
||||
<item quantity="one">El següent capítol</item>
|
||||
<item quantity="many">Els següents %d capítols</item>
|
||||
<item quantity="other">Els següents %d capítols</item>
|
||||
</plurals>
|
||||
<plurals name="missing_chapters">
|
||||
<item quantity="one">Manca %1$s capítol</item>
|
||||
<item quantity="many">Manquen %1$s capítols</item>
|
||||
<item quantity="other">Manquen %1$s capítols</item>
|
||||
</plurals>
|
||||
<plurals name="day">
|
||||
<item quantity="one">1 dia</item>
|
||||
<item quantity="many">%d dies</item>
|
||||
<item quantity="other">%d dies</item>
|
||||
</plurals>
|
||||
</resources>
|
@ -144,11 +144,9 @@
|
||||
<string name="color_filter_g_value">G</string>
|
||||
<string name="color_filter_b_value">B</string>
|
||||
<string name="color_filter_a_value">A</string>
|
||||
<string name="pref_download_directory">Ubicació de les baixades</string>
|
||||
<string name="pref_remove_after_marked_as_read">Després de marcar com a llegit de manera manual</string>
|
||||
<string name="pref_remove_after_read">Suprimeix automàticament després de llegir</string>
|
||||
<string name="pref_double_tap_anim_speed">Velocitat de l’animació del doble toc</string>
|
||||
<string name="custom_dir">Ubicació personalitzada</string>
|
||||
<string name="disabled">Desactivat</string>
|
||||
<string name="last_read_chapter">Darrer capítol llegit</string>
|
||||
<string name="second_to_last">Penúltim capítol llegit</string>
|
||||
@ -161,9 +159,7 @@
|
||||
<string name="pref_create_backup_summ">Es pot utilitzar per a restaurar la biblioteca actual</string>
|
||||
<string name="pref_restore_backup">Restaura una còpia de seguretat</string>
|
||||
<string name="pref_restore_backup_summ">Restaura la biblioteca del fitxer de còpia de seguretat</string>
|
||||
<string name="pref_backup_directory">Ubicació de la còpia de seguretat</string>
|
||||
<string name="pref_backup_interval">Freqüència de la còpia de seguretat automàtica</string>
|
||||
<string name="pref_backup_slots">Màxim de còpies de seguretat automàtiques</string>
|
||||
<string name="backup_created">S’ha creat la còpia de seguretat</string>
|
||||
<string name="restore_completed">S’ha completat la restauració</string>
|
||||
<string name="backup_choice">De què voleu fer una còpia de seguretat\?</string>
|
||||
@ -327,7 +323,6 @@
|
||||
<string name="notification_chapters_single_and_more">Capítol %1$s i %2$d més</string>
|
||||
<string name="notification_chapters_multiple">Capítols %1$s</string>
|
||||
<string name="hide_notification_content">Amaga el contingut de les notificacions</string>
|
||||
<string name="notification_check_updates">S’està comprovant si hi ha capítols nous</string>
|
||||
<string name="pref_disable_battery_optimization">Desactiva l’optimització de la bateria</string>
|
||||
<string name="pref_disable_battery_optimization_summary">Fa que funcionin millor les actualitzacions de la biblioteca en segon pla i les còpies de seguretat</string>
|
||||
<string name="battery_optimization_disabled">L’optimització de la bateria ja està desactivada</string>
|
||||
@ -768,4 +763,10 @@
|
||||
<string name="action_sort_tracker_score">Puntuació del servei de seguiment</string>
|
||||
<string name="label_data_storage">Dades i emmagatzematge</string>
|
||||
<string name="exclude_scanlators">Exclou scanlators</string>
|
||||
<string name="selected">Seleccionat</string>
|
||||
<string name="not_selected">No seleccionat</string>
|
||||
<string name="pref_storage_location">Ubicació de l’emmagatzematge</string>
|
||||
<string name="pref_storage_location_info">S’utilitza per a les còpies de seguretat automàtiques, les baixades de capítols i la font local.</string>
|
||||
<string name="action_menu_overflow_description">Més opcions</string>
|
||||
<string name="action_bar_up_description">Navega cap amunt</string>
|
||||
</resources>
|
@ -297,13 +297,11 @@
|
||||
<string name="pref_category_reading">Pagbasa</string>
|
||||
<string name="pref_high">Taas</string>
|
||||
<string name="pref_low">Ubos</string>
|
||||
<string name="pref_download_directory">Lokasyon sa pag-download</string>
|
||||
<string name="pref_category_delete_chapters">Pagtangtang sa mga kapitulo</string>
|
||||
<string name="pref_remove_after_marked_as_read">Human gimarkahan sa mano-mano ingon nabasa na</string>
|
||||
<string name="pref_remove_after_read">Human sa pagbasa awtomatikong tangtangon</string>
|
||||
<string name="pref_remove_bookmarked_chapters">Tugoti ang pagtangtang sa gimarkahan nga mga kapitulo</string>
|
||||
<string name="pref_remove_exclude_categories">Wala iapil nga mga kategorya</string>
|
||||
<string name="custom_dir">Pasadya nga lokasyon</string>
|
||||
<string name="disabled">Nabaldado</string>
|
||||
<string name="fifth_to_last">Ikalima hangtod sa kataposang pagbasa sa kapitulo</string>
|
||||
<string name="pref_category_auto_download">Awtomatikong pag-download</string>
|
||||
@ -350,8 +348,6 @@
|
||||
<string name="pref_image_scale_type">Uri sa sukdanan sa hulagway</string>
|
||||
<string name="pref_restore_backup">Ibalik ang backup</string>
|
||||
<string name="pref_restore_backup_summ">Ibalik ang librarya gikan sa backup file</string>
|
||||
<string name="pref_backup_directory">Backup nga lokasyon</string>
|
||||
<string name="pref_backup_slots">Maximum nga pag-backup</string>
|
||||
<string name="backup_created">Gihimo ang backup</string>
|
||||
<string name="pref_backup_interval">Kadaghanon sa pag-backup</string>
|
||||
<string name="invalid_backup_file">Dili balido nga backup file</string>
|
||||
|
@ -84,10 +84,8 @@
|
||||
<string name="color_filter_g_value">G</string>
|
||||
<string name="color_filter_b_value">B</string>
|
||||
<string name="color_filter_a_value">A</string>
|
||||
<string name="pref_download_directory">Umístění pro stažení</string>
|
||||
<string name="pref_remove_after_marked_as_read">Po ručním označení jako přečtené</string>
|
||||
<string name="pref_remove_after_read">Po přečtení automaticky smazat</string>
|
||||
<string name="custom_dir">Vlastní umístění</string>
|
||||
<string name="pref_download_new">Stahovat nové kapitoly</string>
|
||||
<string name="username">Uživatelské jméno</string>
|
||||
<string name="password">Heslo</string>
|
||||
@ -207,7 +205,6 @@
|
||||
<string name="services">Sledovače</string>
|
||||
<string name="pref_create_backup">Vytvořit zálohu</string>
|
||||
<string name="pref_restore_backup">Obnovit zálohu</string>
|
||||
<string name="pref_backup_directory">Místo zálohy</string>
|
||||
<string name="pref_backup_interval">Frekvence automatických záloh</string>
|
||||
<string name="backup_created">Záloha vytvořena</string>
|
||||
<string name="restore_completed">Obnova dokončena</string>
|
||||
@ -258,7 +255,6 @@
|
||||
<string name="fifth_to_last">Pátá předposlední přečtená kapitola</string>
|
||||
<string name="pref_create_backup_summ">Lze použít k obnovení aktuální knihovny</string>
|
||||
<string name="pref_restore_backup_summ">Obnovit knihovnu ze záložního souboru</string>
|
||||
<string name="pref_backup_slots">Maximum automatických záloh</string>
|
||||
<string name="login_title">Přihlásit se do %1$s</string>
|
||||
<string name="show_title">Název zdroje</string>
|
||||
<string name="show_chapter_number">Číslo kapitoly</string>
|
||||
@ -420,7 +416,6 @@
|
||||
<string name="notification_chapters_multiple">Kapitoly %1$s</string>
|
||||
<string name="notification_chapters_single_and_more">Kapitola %1$s a %2$d dalších</string>
|
||||
<string name="notification_chapters_single">Kapitola %1$s</string>
|
||||
<string name="notification_check_updates">Hledám nové kapitoly</string>
|
||||
<string name="download_insufficient_space">Nelze stáhnout kapitoly kvůli nedostatku místa</string>
|
||||
<string name="migration_help_guide">Návod k přesunu zdrojů</string>
|
||||
<string name="clear_history_confirmation">Jste si jistý/á\? Všechna historie bude navždy ztracena.</string>
|
||||
|
@ -11,7 +11,6 @@
|
||||
<string name="last_read_chapter">Юлашки вуланӑ сыпăк</string>
|
||||
<string name="disabled">Сӳнтернӗ</string>
|
||||
<string name="pref_remove_after_read">Вуланӑ хыҫҫӑн</string>
|
||||
<string name="pref_download_directory">Тийев вырӑнӗ</string>
|
||||
<string name="pref_category_reading">Вулани</string>
|
||||
<string name="color_filter_b_value">Кӑвак</string>
|
||||
<string name="color_filter_g_value">Симӗс</string>
|
||||
@ -190,7 +189,6 @@
|
||||
<string name="fourth_to_last">Вуланӑ сыпӑкран тӑваттӑмӗшӗ</string>
|
||||
<string name="third_to_last">Вуланӑ сыпӑкран виҫҫӗмӗшӗ</string>
|
||||
<string name="second_to_last">Юлашкинчен маларахри</string>
|
||||
<string name="custom_dir">Усӑҫ палӑртнӑ вырӑнӗ</string>
|
||||
<string name="pref_remove_after_marked_as_read">Вуланӑ пек палӑртнӑ хыҫҫӑн катерт</string>
|
||||
<string name="scale_type_original_size">Хӑйӗн виҫе</string>
|
||||
<string name="pager_viewer">Елсерен</string>
|
||||
@ -275,7 +273,6 @@
|
||||
<string name="notification_cover_update_failed">Хуплашкана ҫӗнетеймерӗ</string>
|
||||
<string name="notification_chapters_single_and_more">%1$s сыпӑкӗ тата ытти %2$d</string>
|
||||
<string name="notification_chapters_multiple">%1$s сыпӑкӗсем</string>
|
||||
<string name="notification_check_updates">Ҫӗнӗ сыпӑксен пуррине тӗрӗслени</string>
|
||||
<string name="download_queue_error">Сыпӑксене тийесе илме пулмасть. Тийевсем пайӗнче ҫӗнӗрен хӑтланса пӑхма пултаратӑн</string>
|
||||
<string name="copy">Ӑтавла</string>
|
||||
<string name="migrate">Куҫар</string>
|
||||
@ -401,8 +398,6 @@
|
||||
<string name="pref_create_backup_summ">Хальхи вулавăша тавӑрма усӑ курма пулать</string>
|
||||
<string name="invalid_backup_file_missing_manga">Янтӑвра манкӑсем ҫук.</string>
|
||||
<string name="backup_created">Янтӑв тӑвӑннӑ</string>
|
||||
<string name="pref_backup_slots">Май килнӗ таран янтӑвсем</string>
|
||||
<string name="pref_backup_directory">Янтӑв вырнаҫни</string>
|
||||
<string name="pref_restore_backup_summ">Вулавӑша янтӑвран тавӑр</string>
|
||||
<string name="pref_restore_backup">Янтӑв тавӑр</string>
|
||||
<string name="pref_create_backup">Янтӑв ту</string>
|
||||
|
@ -286,7 +286,6 @@
|
||||
<string name="pref_category_reading">Læser</string>
|
||||
<string name="channel_ext_updates">Udvidelsesopdateringer</string>
|
||||
<string name="creating_backup_error">Sikkerhedskopiering mislykkedes</string>
|
||||
<string name="pref_backup_directory">Placering af sikkerhedskopi</string>
|
||||
<string name="rotation_free">Fri</string>
|
||||
<string name="channel_errors">Fejl</string>
|
||||
<string name="restore_completed">Gendannelse fuldført</string>
|
||||
@ -300,7 +299,6 @@
|
||||
<string name="pref_category_reading_mode">Læsetilstand</string>
|
||||
<string name="remove_manga">Du er ved at fjerne \"%s\" fra dit bibliotek</string>
|
||||
<string name="pref_highest">Højeste</string>
|
||||
<string name="pref_backup_slots">Maksimale antal automatiske sikkerhedskopier</string>
|
||||
<string name="pref_low">Lav</string>
|
||||
<string name="source_settings">Kildeindstillinger</string>
|
||||
<string name="app_settings">App-indstillinger</string>
|
||||
|
@ -118,10 +118,8 @@
|
||||
<string name="color_filter_g_value">G</string>
|
||||
<string name="color_filter_b_value">B</string>
|
||||
<string name="color_filter_a_value">A</string>
|
||||
<string name="pref_download_directory">Speicherort</string>
|
||||
<string name="pref_remove_after_marked_as_read">Nachdem manuell als gelesen markiert</string>
|
||||
<string name="pref_remove_after_read">Automatisch nach dem Lesen löschen</string>
|
||||
<string name="custom_dir">Eigener Speicherort</string>
|
||||
<string name="disabled">Deaktiviert</string>
|
||||
<string name="last_read_chapter">Ab zuletzt gelesenem Kapitel</string>
|
||||
<string name="second_to_last">Ab zweitletzt gelesenem Kapitel</string>
|
||||
@ -134,9 +132,7 @@
|
||||
<string name="pref_create_backup_summ">Kann benutzt werden, um die aktuelle Bibliothek wiederherzustellen</string>
|
||||
<string name="pref_restore_backup">Datensicherung wiederherstellen</string>
|
||||
<string name="pref_restore_backup_summ">Bibliothek mit Hilfe einer Datensicherung wiederherstellen</string>
|
||||
<string name="pref_backup_directory">Sicherungsspeicherort</string>
|
||||
<string name="pref_backup_interval">Automatische Datensicherungshäufigkeit</string>
|
||||
<string name="pref_backup_slots">Maximale Anzahl automatischer Datensicherungen</string>
|
||||
<string name="backup_created">Datensicherung erstellt</string>
|
||||
<string name="restore_completed">Wiederherstellen abgeschlossen</string>
|
||||
<string name="backup_choice">Was möchtest du sichern\?</string>
|
||||
@ -327,7 +323,6 @@
|
||||
<string name="notification_chapters_single_and_more">Kapitel %1$s und %2$d mehr</string>
|
||||
<string name="notification_chapters_multiple">Kapitel %1$s</string>
|
||||
<string name="hide_notification_content">Benachrichtigungsinhalt verbergen</string>
|
||||
<string name="notification_check_updates">Überprüfe auf neue Kapitel</string>
|
||||
<string name="pref_disable_battery_optimization">Akkuverbrauch-Optimierung deaktivieren</string>
|
||||
<string name="pref_disable_battery_optimization_summary">Hilft bei Bibliotheksaktualisierungen und -sicherungen im Hintergrund</string>
|
||||
<string name="battery_optimization_disabled">Akkuverbrauch-Optimierung ist bereits deaktiviert</string>
|
||||
@ -768,4 +763,10 @@
|
||||
<string name="pref_storage_usage">Speichernutzung</string>
|
||||
<string name="action_sort_tracker_score">Tracker-Bewertung</string>
|
||||
<string name="exclude_scanlators">Scanlatoren ausschließen</string>
|
||||
<string name="selected">Ausgewählt</string>
|
||||
<string name="not_selected">Nicht ausgewählt</string>
|
||||
<string name="pref_storage_location">Speicherort</string>
|
||||
<string name="pref_storage_location_info">Wird für automatische Datensicherungen, heruntergeladene Kapitel und lokale Quellen verwendet.</string>
|
||||
<string name="action_menu_overflow_description">Weitere Optionen</string>
|
||||
<string name="action_bar_up_description">Nach oben navigieren</string>
|
||||
</resources>
|
@ -145,10 +145,8 @@
|
||||
<string name="color_filter_g_value">G</string>
|
||||
<string name="color_filter_b_value">B</string>
|
||||
<string name="color_filter_a_value">A</string>
|
||||
<string name="pref_download_directory">Τοποθεσία λήψεων</string>
|
||||
<string name="pref_remove_after_marked_as_read">Αφού επισημανθεί χειροκίνητα ως αναγνωσμένο</string>
|
||||
<string name="pref_remove_after_read">Αυτόματη διαγραφή μετά την ανάγνωση</string>
|
||||
<string name="custom_dir">Προσαρμοσμένη τοποθεσία</string>
|
||||
<string name="disabled">Απενεργοποιημένο</string>
|
||||
<string name="last_read_chapter">Τελευταίο αναγνωσμένο κεφάλαιο</string>
|
||||
<string name="second_to_last">Προτελευταίο αναγνωσμένο κεφάλαιο</string>
|
||||
@ -161,9 +159,7 @@
|
||||
<string name="pref_create_backup_summ">Μπορεί να χρησιμοποιηθεί για επαναφορά τρέχουσας βιβλιοθήκης</string>
|
||||
<string name="pref_restore_backup">Επαναφορά αντιγράφου ασφαλείας</string>
|
||||
<string name="pref_restore_backup_summ">Επαναφορά βιβλιοθήκης από αρχείο αντιγράφου ασφαλείας</string>
|
||||
<string name="pref_backup_directory">Τοποθεσία αντιγράφων ασφαλείας</string>
|
||||
<string name="pref_backup_interval">Συχνότητα αυτόματων αντιγράφων ασφαλείας</string>
|
||||
<string name="pref_backup_slots">Μέγιστα αυτόματα αντίγραφα ασφαλείας</string>
|
||||
<string name="backup_created">Δημιουργήθηκε αντίγραφο ασφαλείας</string>
|
||||
<string name="restore_completed">Η επαναφορά ολοκληρώθηκε</string>
|
||||
<string name="backup_choice">Τι αντίγραφο ασφαλείας θέλετε να δημιουργήσετε;</string>
|
||||
@ -308,7 +304,6 @@
|
||||
<string name="notification_chapters_single_and_more">Κεφάλαιο %1$s και %2$d ακόμη</string>
|
||||
<string name="notification_chapters_multiple">Κεφάλαια %1$s</string>
|
||||
<string name="notification_chapters_single">Κεφάλαιο %1$s</string>
|
||||
<string name="notification_check_updates">Έλεγχος για νέα κεφάλαια</string>
|
||||
<string name="recent_manga_time">Κεφ. %1$s - %2$s</string>
|
||||
<string name="updating_library">Ενημέρωση βιβλιοθήκης</string>
|
||||
<string name="paused">Σε παύση</string>
|
||||
@ -768,4 +763,10 @@
|
||||
<string name="no_scanlators_found">Δε βρέθηκαν scanlators</string>
|
||||
<string name="scanlator">Scanlator</string>
|
||||
<string name="exclude_scanlators">Εξαίρεση scanlator</string>
|
||||
<string name="action_menu_overflow_description">Περισσότερες επιλογές</string>
|
||||
<string name="selected">Επιλεγμένο</string>
|
||||
<string name="not_selected">Μη επιλεγμένο</string>
|
||||
<string name="action_bar_up_description">Πλοήγηση προς τα πάνω</string>
|
||||
<string name="pref_storage_location">Τοποθεσία αποθήκευσης</string>
|
||||
<string name="pref_storage_location_info">Χρησιμοποιείται για αυτόματα αντίγραφα ασφαλείας, λήψη κεφαλαίων και τοπική πηγή.</string>
|
||||
</resources>
|
@ -108,12 +108,10 @@
|
||||
<string name="update_24hour">Ĉiutage</string>
|
||||
<string name="invalid_backup_file">Nevalida savkopia dosiero</string>
|
||||
<string name="backup_created">Savkopio kreita</string>
|
||||
<string name="pref_backup_directory">Savkopiejo</string>
|
||||
<string name="pref_create_backup">Krei savkopion</string>
|
||||
<string name="pref_download_new">Elŝuti novajn ĉapitrojn</string>
|
||||
<string name="disabled">Malŝaltita</string>
|
||||
<string name="pref_category_delete_chapters">Forigi ĉapitrojn</string>
|
||||
<string name="pref_download_directory">Elŝutejo</string>
|
||||
<string name="double_tap_anim_speed_0">Sen animacioj</string>
|
||||
<string name="scale_type_original_size">Originala grando</string>
|
||||
<string name="scale_type_stretch">Streĉi</string>
|
||||
@ -132,7 +130,6 @@
|
||||
<string name="in_library">En biblioteko</string>
|
||||
<string name="manga_added_library">Aldonita al biblioteko</string>
|
||||
<string name="add_to_library">Aldoni al biblioteko</string>
|
||||
<string name="custom_dir">Propra dosierujo</string>
|
||||
<string name="pref_remove_after_read">Aŭtomate post legado</string>
|
||||
<string name="pref_category_reading">Legada</string>
|
||||
<string name="pref_category_reading_mode">Legada reĝimo</string>
|
||||
@ -364,7 +361,6 @@
|
||||
<string name="channel_ext_updates">Kromaĵaj ĝisdatigoj</string>
|
||||
<string name="download_notifier_download_paused">Elŝutito paŭzigita</string>
|
||||
<string name="download_notifier_downloader_title">Elŝutilo</string>
|
||||
<string name="notification_check_updates">Kontrolas por trovi novajn ĉapitrojn</string>
|
||||
<string name="pref_category_for_this_series">Por ĉi-serion</string>
|
||||
<string name="custom_filter">Propra filtrilo</string>
|
||||
<string name="source_unsupported">Fonto ne subtenita</string>
|
||||
@ -386,7 +382,6 @@
|
||||
<string name="restoring_backup">Restaŭras savkopion</string>
|
||||
<string name="restore_completed">Restaŭrado kompletita</string>
|
||||
<string name="invalid_backup_file_missing_manga">Savkopio enhavas neniun mangaon.</string>
|
||||
<string name="pref_backup_slots">Maksimume savkopioj</string>
|
||||
<string name="rotation_force_landscape">Deviga horizontala</string>
|
||||
<string name="rotation_force_portrait">Deviga vertikala</string>
|
||||
<string name="rotation_portrait">Vertikala</string>
|
||||
|
@ -87,10 +87,8 @@
|
||||
<string name="rotation_free">Cualquier dirección</string>
|
||||
<string name="rotation_force_portrait">Forzar en vertical</string>
|
||||
<string name="rotation_force_landscape">Forzar en horizontal</string>
|
||||
<string name="pref_download_directory">Carpeta de descarga</string>
|
||||
<string name="pref_remove_after_marked_as_read">Borrarlos tras marcarlos como leídos de forma manual</string>
|
||||
<string name="pref_remove_after_read">Borrar capítulos terminados de forma automática</string>
|
||||
<string name="custom_dir">Ubicación personalizada</string>
|
||||
<string name="services">Servicios de seguimiento</string>
|
||||
<string name="pref_clear_chapter_cache">Vaciar la caché de capítulos</string>
|
||||
<string name="used_cache">Usado: %1$s</string>
|
||||
@ -205,9 +203,7 @@
|
||||
<string name="pref_create_backup_summ">Se puede utilizar para restaurar la biblioteca actual</string>
|
||||
<string name="pref_restore_backup">Restaurar copia de seguridad</string>
|
||||
<string name="pref_restore_backup_summ">Restaurar la biblioteca a partir de una copia de seguridad</string>
|
||||
<string name="pref_backup_directory">Ubicación de la copia de respaldo</string>
|
||||
<string name="pref_backup_interval">Frecuencia de la copia de seguridad automática</string>
|
||||
<string name="pref_backup_slots">Copias de seguridad automáticas máximas</string>
|
||||
<string name="pref_backup_interval">Frecuencia de respaldo automático</string>
|
||||
<string name="backup_created">Copia de seguridad creada</string>
|
||||
<string name="restore_completed">Restauración completada</string>
|
||||
<string name="backup_choice">¿De qué quieres hacer una copia de seguridad\?</string>
|
||||
@ -328,7 +324,6 @@
|
||||
<string name="notification_chapters_single_and_more">Capítulo %1$s y %2$d más</string>
|
||||
<string name="notification_chapters_multiple">Capítulos %1$s</string>
|
||||
<string name="hide_notification_content">Ocultar el contenido de las notificaciones</string>
|
||||
<string name="notification_check_updates">Buscando nuevos capítulos</string>
|
||||
<string name="pref_disable_battery_optimization">Desactivar la optimización de batería</string>
|
||||
<string name="email">Correo electrónico</string>
|
||||
<string name="pref_disable_battery_optimization_summary">Mejora la cadencia de las actualizaciones y las copias de respaldo que se hagan en segundo plano</string>
|
||||
@ -398,7 +393,7 @@
|
||||
<string name="loader_not_implemented_error">No se ha encontrado la fuente</string>
|
||||
<string name="action_disable">Desactivar</string>
|
||||
<string name="requires_app_restart">Es necesario reiniciar la aplicación para que surja efecto</string>
|
||||
<string name="label_network">Networking</string>
|
||||
<string name="label_network">Red</string>
|
||||
<string name="unknown_status">Estado desconocido</string>
|
||||
<string name="tapping_inverted_both">Ambos</string>
|
||||
<string name="tapping_inverted_vertical">Vertical</string>
|
||||
@ -486,7 +481,7 @@
|
||||
<string name="action_display_show_number_of_items">Mostrar el número de elementos</string>
|
||||
<string name="action_sort_chapter_fetch_date">Fecha de obtención del capítulo</string>
|
||||
<string name="rotation_type">Tipo de rotación</string>
|
||||
<string name="pref_create_folder_per_manga_summary">Crea carpetas según el título de las entradas</string>
|
||||
<string name="pref_create_folder_per_manga_summary">Crea carpetas según el título de la obra</string>
|
||||
<string name="pref_create_folder_per_manga">Guardar las páginas en carpetas independientes</string>
|
||||
<string name="pref_reader_actions">Acciones</string>
|
||||
<string name="pref_grayscale">Escala de grises</string>
|
||||
@ -554,7 +549,7 @@
|
||||
<string name="label_warning">Advertencia</string>
|
||||
<string name="notification_size_warning">Las actualizaciones grandes pueden implicar un mayor uso de la batería y que los distintos servicios bloqueen o ralenticen el acceso a tu dispositivo. Toca aquí para más información.</string>
|
||||
<string name="action_display_language_badge">Idioma</string>
|
||||
<string name="backup_info">También deberías guardar las copias de seguridad en otros lugares. Las copias de seguridad pueden contener datos confidenciales, incluidas las contraseñas almacenadas.</string>
|
||||
<string name="backup_info">Es una buena idea tener copias de respaldo fuera de tu dispositivo. También incluyen contraseñas y otros datos privados que seguramente no quieras compartir.</string>
|
||||
<string name="connected_to_wifi">Solo con Wi-Fi</string>
|
||||
<string name="update_72hour">Cada 3 días</string>
|
||||
<string name="download_queue_size_warning">Advertencia: Las descargas grandes pueden llevar a que las fuentes se vuelvan cada vez más lentas y en casos extremos que los servidores limiten o impidan el acceso a Tachiyomi. Toca aquí para más información.</string>
|
||||
@ -653,7 +648,7 @@
|
||||
<string name="pref_appearance_summary">Temas de colores y formatos de fecha</string>
|
||||
<string name="pref_advanced_summary">Volcar datos del cuelgue y estado de ahorro de batería</string>
|
||||
<string name="pref_security_summary">Pantalla segura y desbloqueo biométrico</string>
|
||||
<string name="pref_backup_summary">Copias de seguridad manuales y automáticas, y el espacio de almacenamiento</string>
|
||||
<string name="pref_backup_summary">Copias de seguridad manuales y automáticas, almacenamiento</string>
|
||||
<string name="pref_browse_summary">Fuentes, extensiones y búsqueda global</string>
|
||||
<string name="crash_screen_title">¡Vaya!</string>
|
||||
<string name="crash_screen_restart_application">Reiniciar la aplicación</string>
|
||||
@ -730,7 +725,7 @@
|
||||
<string name="action_filter_interval_custom">Intervalo de descarga personalizado</string>
|
||||
<string name="action_filter_interval_long">Comprobar de forma mensual (28 días)</string>
|
||||
<string name="action_ok">Aceptar</string>
|
||||
<string name="track_delete_title">¿Quitar el rastreo de %s\?</string>
|
||||
<string name="track_delete_title">¿Quieres desvincular %s?</string>
|
||||
<string name="track_delete_text">Esto eliminará el seguimiento localmente.</string>
|
||||
<string name="track_delete_remote_text">Quitar también de %s</string>
|
||||
<string name="delete_downloaded">Borrar los ya descargados</string>
|
||||
@ -754,18 +749,24 @@
|
||||
<string name="app_settings">Ajustes de la aplicación</string>
|
||||
<string name="action_sort_category">Ordenar categorías</string>
|
||||
<string name="sort_category_confirmation">¿Quieres ordenar las categorías de forma alfabética\?</string>
|
||||
<string name="file_null_uri_error">Ningún archivo seleccionado</string>
|
||||
<string name="file_null_uri_error">No has elegido ningún archivo</string>
|
||||
<string name="relative_time_span_never">Nunca</string>
|
||||
<string name="pref_flash_page_summ">Reducir el ghosting en las pantallas de tinta electrónica</string>
|
||||
<string name="last_auto_backup_info">Última copia de seguridad automática: %s</string>
|
||||
<string name="pref_flash_page">Parpadeo en blanco al cambiar de página</string>
|
||||
<string name="pref_flash_page_summ">Esta transición minimiza las manchas y el efecto de retención de imagen en pantallas de tinta electrónica</string>
|
||||
<string name="last_auto_backup_info">Última copia automática: %s</string>
|
||||
<string name="pref_flash_page">Parpadear a blanco al cambiar de página</string>
|
||||
<string name="label_data_storage">Datos y almacenamiento</string>
|
||||
<string name="pref_storage_usage">Almacenamiento utilizado</string>
|
||||
<string name="action_sort_tracker_score">Puntuación del rastreador</string>
|
||||
<string name="action_apply">Aplicar</string>
|
||||
<string name="action_revert_to_default">Volver a la configuración predeterminada</string>
|
||||
<string name="action_create">Crear</string>
|
||||
<string name="no_scanlators_found">Sin ningún scanlators</string>
|
||||
<string name="scanlator">Scanlator</string>
|
||||
<string name="exclude_scanlators">Omitir a los scanlators</string>
|
||||
<string name="no_scanlators_found">Sin escanducciones</string>
|
||||
<string name="scanlator">Escanductor</string>
|
||||
<string name="exclude_scanlators">Excluir escanducciones</string>
|
||||
<string name="selected">Seleccionado</string>
|
||||
<string name="not_selected">Sin seleccionar</string>
|
||||
<string name="action_menu_overflow_description">Más opciones</string>
|
||||
<string name="action_bar_up_description">Subir un nivel</string>
|
||||
<string name="pref_storage_location">Ubicación del almacenamiento</string>
|
||||
<string name="pref_storage_location_info">Se utiliza para las copias de seguridad automáticas, las descargas de capítulos y la fuente local.</string>
|
||||
</resources>
|
@ -118,7 +118,6 @@
|
||||
<string name="pref_webtoon_side_padding">Alboko betegarria</string>
|
||||
<string name="pref_always_show_chapter_transition">Erakutsi beti kapituluaren trantsizioa</string>
|
||||
<string name="last_read_chapter">Azkenik irakurritako kapitulua</string>
|
||||
<string name="pref_download_directory">Deskarga kokapena</string>
|
||||
<string name="pref_category_delete_chapters">Ezabatu kapituluak</string>
|
||||
<string name="fourth_to_last">Atzetik hasita laugarren irakurritako kapitulua</string>
|
||||
<string name="backup_restore_missing_trackers">Saioa hasi gabeko jarraitzaileak:</string>
|
||||
@ -223,7 +222,6 @@
|
||||
<string name="pref_remove_after_marked_as_read">Irakurria bezala eskuz markatu ondoren</string>
|
||||
<string name="pref_remove_bookmarked_chapters">Baimendu laster-markadun kapituluak ezabatzea</string>
|
||||
<string name="pref_remove_after_read">Irakurri ondoren automatikoki ezabatu</string>
|
||||
<string name="custom_dir">Kokapen pertsonalizatua</string>
|
||||
<string name="enhanced_services">Zerbitzu hobetuak</string>
|
||||
<string name="help_translate">Lagundu itzultzen</string>
|
||||
<string name="file_picker_error">Ez da aurkitu fitxategiak hautatzeko aplikaziorik</string>
|
||||
@ -431,7 +429,6 @@
|
||||
<string name="clear_history_confirmation">Ziur zaude\? Historia guztia galduko da.</string>
|
||||
<string name="migration_help_guide">Iturrien migrazio gida</string>
|
||||
<string name="migration_dialog_what_to_include">Hautatu sartu nahi dituzun datuak</string>
|
||||
<string name="notification_check_updates">Kapitulu berriak bilatzen</string>
|
||||
<string name="notification_new_chapters">Kapitulu berriak aurkituak</string>
|
||||
<string name="information_no_recent_manga">Ez da ezer irakurri azkenaldian</string>
|
||||
<string name="information_no_downloads">Deskargarik ez</string>
|
||||
@ -458,9 +455,7 @@
|
||||
<string name="pref_highest">Altuena</string>
|
||||
<string name="pref_restore_backup">Babeskopia erabili</string>
|
||||
<string name="pref_restore_backup_summ">Berreskuratu liburutegia babeskopia fitxategitik</string>
|
||||
<string name="pref_backup_directory">Babeskopiaren kokapena</string>
|
||||
<string name="pref_backup_interval">Babeskopien maiztasuna</string>
|
||||
<string name="pref_backup_slots">Gehienezko babeskopiak</string>
|
||||
<string name="action_sort_alpha">Alfabetikoki</string>
|
||||
<string name="label_warning">Oharra</string>
|
||||
<string name="confirm_lock_change">Autentifikatu aldaketa berresteko</string>
|
||||
|
@ -52,4 +52,16 @@
|
||||
<item quantity="one">قسمت خوانده نشده بعدی</item>
|
||||
<item quantity="other">%d قسمت خوانده نشده بعدی</item>
|
||||
</plurals>
|
||||
<plurals name="download_amount">
|
||||
<item quantity="one">قسمت بعدی</item>
|
||||
<item quantity="other">%d قسمت بعدی</item>
|
||||
</plurals>
|
||||
<plurals name="missing_chapters">
|
||||
<item quantity="one">%1$s قسمت گم شده</item>
|
||||
<item quantity="other">%1$s قسمت گم شده</item>
|
||||
</plurals>
|
||||
<plurals name="day">
|
||||
<item quantity="one">1 روز</item>
|
||||
<item quantity="other">%d روز</item>
|
||||
</plurals>
|
||||
</resources>
|
@ -14,7 +14,6 @@
|
||||
<string name="notification_chapters_single_and_more">قسمت %1$s و %2$d قسمت دیگر</string>
|
||||
<string name="notification_chapters_single">قسمت %1$s</string>
|
||||
<string name="notification_new_chapters">قسمتهای جدید پیدا شدند</string>
|
||||
<string name="notification_check_updates">درحال بررسی برای قسمتهای جدید</string>
|
||||
<string name="download_queue_error">دانلود قسمت ها با خطا مواجه شد. با مراجعه به بخش دانلودها می توانید دوباره تلاش کنید</string>
|
||||
<string name="copy">کپی</string>
|
||||
<string name="migrate">تغییر منبع</string>
|
||||
@ -120,9 +119,7 @@
|
||||
<string name="no_results_found">هیچ نتیجه ای یافت نشد</string>
|
||||
<string name="no_more_results">نتیجه بیشتری یافت نشد</string>
|
||||
<string name="tabs_header">تب ها</string>
|
||||
<string name="pref_backup_slots">حداکثر تعداد نسخههای پشتیبان</string>
|
||||
<string name="pref_backup_interval">زمان پشتیبان گیری</string>
|
||||
<string name="pref_backup_directory">محل پشتیبان گیری</string>
|
||||
<string name="pref_restore_backup_summ">بازگرداندن کتابخانه از فایل پشتیبان</string>
|
||||
<string name="pref_restore_backup">برگرداندن نسخه پشتیبان</string>
|
||||
<string name="pref_create_backup_summ">می تواند برای بازگرداندن کتابخانه فعلی استفاده شود</string>
|
||||
@ -144,8 +141,6 @@
|
||||
<string name="pref_category_for_this_series">برای این مجموعه</string>
|
||||
<string name="decode_image_error">بازکردن عکس با خطا مواجه شد</string>
|
||||
<string name="plan_to_read">قصد خواندن دارم(Plan to read)</string>
|
||||
<string name="custom_dir">مکان سفارشی</string>
|
||||
<string name="pref_download_directory">مکان دانلود</string>
|
||||
<string name="scale_type_smart_fit">هم اندازه حالت هوشمند</string>
|
||||
<string name="filter_mode_multiply">Multiply</string>
|
||||
<string name="filter_mode_overlay">Overlay</string>
|
||||
@ -601,4 +596,22 @@
|
||||
<string name="backup_info">شما باید از پشتیبانی ها در جا های دیگر هم کپی داشته باشید.</string>
|
||||
<string name="action_update_category">بروزرسانی دسته بندی</string>
|
||||
<string name="action_copy_to_clipboard">کپی کردن به کلیپبرد</string>
|
||||
<string name="loader_rar5_error">فرمت RARv5 پشتیبانی نشده</string>
|
||||
<string name="on_hiatus">متوقف شده</string>
|
||||
<string name="unlock_app_title">باز گشایی %s</string>
|
||||
<string name="delete_downloaded">پاک کردن قسمت های دانلود شده</string>
|
||||
<string name="action_apply">ذخیره</string>
|
||||
<string name="action_revert_to_default">باز نشانی به حالت اولیه</string>
|
||||
<string name="action_sort_category">منظم کردن دسته بندی ها</string>
|
||||
<string name="action_menu_overflow_description">گزینه های بیشتر</string>
|
||||
<string name="selected">انتخاب شده</string>
|
||||
<string name="not_selected">انتخاب نشده</string>
|
||||
<string name="action_move_to_bottom_all_for_series">مجموعه ها را به پایین منطقل کن</string>
|
||||
<string name="action_bar_up_description">برو به بالا</string>
|
||||
<string name="action_sort_tracker_score">امتیاز رهگیز</string>
|
||||
<string name="label_data_storage">داده های و ذخیره سازی</string>
|
||||
<string name="sort_category_confirmation">آیا مایلید که دسته بندی ها را به ترتیب الفبا منظم کنید؟</string>
|
||||
<string name="action_ok">باشه</string>
|
||||
<string name="action_sort_next_updated">به روز رسانی مورد انتظار بعدی</string>
|
||||
<string name="download_queue_size_warning">هشدار: حجم زیاد بارگیری ممکن است باعث اهسته تر شدن سرعت ویا مسدود کردن Tachiyomi از منبع شود. برای اطلاعات بیشتر لمس کنید.</string>
|
||||
</resources>
|
@ -192,10 +192,8 @@
|
||||
<string name="color_filter_g_value">Vihreä</string>
|
||||
<string name="color_filter_b_value">Sininen</string>
|
||||
<string name="color_filter_a_value">Alpha</string>
|
||||
<string name="pref_download_directory">Lataus kansio</string>
|
||||
<string name="pref_remove_after_marked_as_read">Manuaalisesti luetuksi merkitsemisen jälkeen</string>
|
||||
<string name="pref_remove_after_read">Lukemisen jälkeen</string>
|
||||
<string name="custom_dir">Mukautettu kansio</string>
|
||||
<string name="disabled">Pois käytöstä</string>
|
||||
<string name="last_read_chapter">Viimeksi luettu luku</string>
|
||||
<string name="second_to_last">Toiseksi viimeinen luku</string>
|
||||
@ -207,7 +205,6 @@
|
||||
<string name="pref_create_backup_summ">Voidaan käyttää nykyisen kirjaston palauttamiseen</string>
|
||||
<string name="pref_restore_backup_summ">Palauta kirjasto varmuuskopiointi-tiedostosta</string>
|
||||
<string name="pref_backup_interval">Varmuuskopioinnin tiheys</string>
|
||||
<string name="pref_backup_slots">Varmuuskopioiden enimmäismäärä</string>
|
||||
<string name="backup_created">Varmuuskopio luotu</string>
|
||||
<string name="restore_completed">Palautus valmis</string>
|
||||
<string name="backup_choice">Mitä haluat varmuuskopioida\?</string>
|
||||
@ -260,7 +257,6 @@
|
||||
<string name="snack_categories_deleted">Kategoriat poistettu</string>
|
||||
<string name="pref_create_backup">Luo varmuuskopio</string>
|
||||
<string name="pref_restore_backup">Palauta varmuuskopio</string>
|
||||
<string name="pref_backup_directory">Varmuuskopio kansio</string>
|
||||
<string name="local_source">Paikalliset lähteet</string>
|
||||
<string name="other_source">Muut</string>
|
||||
<string name="latest">Viimeisimmät</string>
|
||||
@ -323,7 +319,6 @@
|
||||
<string name="notification_chapters_single_and_more">Luku %1$s ja %2$d lisää</string>
|
||||
<string name="notification_chapters_multiple">Luvut %1$s</string>
|
||||
<string name="hide_notification_content">Piilota ilmoitusten sisältö</string>
|
||||
<string name="notification_check_updates">Etsitään uusia lukuja</string>
|
||||
<string name="lock_when_idle">Lukitse käyttämättömänä</string>
|
||||
<string name="secure_screen">Salaa näyttö</string>
|
||||
<string name="secure_screen_summary">Turvallinen ruutu piilottaa sovelluksen sisällön sovelluksia vaihdettaessa ja estää kuvakaappauksen ottamisen</string>
|
||||
|
@ -115,10 +115,8 @@
|
||||
<string name="second_to_last">Pangalawa sa huling nabasa</string>
|
||||
<string name="last_read_chapter">Huling nabasang kabanata</string>
|
||||
<string name="disabled">Sarado</string>
|
||||
<string name="custom_dir">Pinili kong lugar</string>
|
||||
<string name="pref_remove_after_marked_as_read">Pagkamarkahang nabasa na</string>
|
||||
<string name="pref_remove_after_read">Pagkatapos basahin, kusang burahin</string>
|
||||
<string name="pref_download_directory">Lokasyon sa pag-download</string>
|
||||
<string name="pref_webtoon_side_padding">Kapal ng gilid</string>
|
||||
<string name="pref_category_reading">Pagbabasa</string>
|
||||
<string name="pref_always_show_chapter_transition">Ipakita palagi ang paglipat-kabanata</string>
|
||||
@ -229,9 +227,7 @@
|
||||
<string name="invalid_backup_file_missing_manga">Hindi naglalaman ang backup ng kahit anong mga entry sa Aklatan.</string>
|
||||
<string name="invalid_backup_file">Invalid na backup</string>
|
||||
<string name="backup_created">Nai-backup na</string>
|
||||
<string name="pref_backup_slots">Pinakamarami na awtomatikong pag-backup</string>
|
||||
<string name="pref_backup_interval">Awtomatikong dalas ng pag-backup</string>
|
||||
<string name="pref_backup_directory">Lokasyon ng backup</string>
|
||||
<string name="pref_restore_backup_summ">I-restore ang Aklatan mula sa backup</string>
|
||||
<string name="pref_restore_backup">I-restore ang backup</string>
|
||||
<string name="pref_create_backup_summ">Magagamit para ma-restore ang kasalukuyang Aklatan</string>
|
||||
@ -276,7 +272,6 @@
|
||||
<string name="notification_chapters_single_and_more">Kabanata %1$s at karagdagang %2$d pa</string>
|
||||
<string name="notification_chapters_single">Kabanata %1$s</string>
|
||||
<string name="notification_new_chapters">May mga bagong kabanata</string>
|
||||
<string name="notification_check_updates">Naghahanap ng mga bagong kabanata</string>
|
||||
<string name="download_insufficient_space">Di ma-download ang mga kabanata dahil sa mababang espasyo</string>
|
||||
<string name="download_queue_error">Di ma-download ang mga kabanata. Subukan mo uli ito sa Dina-download</string>
|
||||
<string name="copy">Kopyahin</string>
|
||||
@ -768,4 +763,10 @@
|
||||
<string name="scanlator">Scanlator</string>
|
||||
<string name="exclude_scanlators">Ibukod ang mga scanlator</string>
|
||||
<string name="action_create">Lumikha</string>
|
||||
<string name="pref_storage_location">Lokasyon ng storage</string>
|
||||
<string name="pref_storage_location_info">Ginagamit para sa automatikong pa-backup, pag-download ng mga kabanata, at lokal na source.</string>
|
||||
<string name="action_menu_overflow_description">Ibang opsiyon</string>
|
||||
<string name="selected">Napili</string>
|
||||
<string name="not_selected">Di napili</string>
|
||||
<string name="action_bar_up_description">Mag-navigate pataas</string>
|
||||
</resources>
|
@ -105,7 +105,6 @@
|
||||
<string name="color_filter_g_value">V</string>
|
||||
<string name="color_filter_b_value">B</string>
|
||||
<string name="color_filter_a_value">O</string>
|
||||
<string name="pref_download_directory">Répertoire de téléchargement</string>
|
||||
<string name="pref_remove_after_read">Suppression automatique après lecture</string>
|
||||
<string name="disabled">Désactivé</string>
|
||||
<string name="last_read_chapter">Dernier chapitre lu</string>
|
||||
@ -186,7 +185,6 @@
|
||||
<string name="download_notifier_no_network">Aucune connexion disponible</string>
|
||||
<string name="clear_database_confirmation">Êtes-vous sûr(e) \? Les chapitres lus et la progression des entrées non présentes dans la bibliothèque seront perdues</string>
|
||||
<string name="confirm_delete_chapters">Supprimer les chapitres sélectionnés \?</string>
|
||||
<string name="custom_dir">Répertoire personnalisé</string>
|
||||
<string name="download_notifier_unknown_error">Impossible de télécharger le chapitre en raison d\'une erreur inattendue</string>
|
||||
<string name="fifth_to_last">Cinquième chapitre avant le dernier lu</string>
|
||||
<string name="login_success">Connecté</string>
|
||||
@ -208,7 +206,6 @@
|
||||
<string name="chapter_paused">En pause</string>
|
||||
<string name="action_open_log">Ouvrir le fichier</string>
|
||||
<string name="action_restore">Restaurer</string>
|
||||
<string name="pref_backup_directory">Dossier de sauvegarde</string>
|
||||
<string name="restore_completed">Restauration terminée</string>
|
||||
<string name="backup_choice">Que voulez-vous sauvegarder \?</string>
|
||||
<string name="delete_downloads_for_manga">Supprimer les chapitres téléchargés ?</string>
|
||||
@ -219,7 +216,6 @@
|
||||
<string name="pref_restore_backup">Restaurer une sauvegarde</string>
|
||||
<string name="pref_restore_backup_summ">Restaurer la bibliothèque à partir d\'un fichier de sauvegarde</string>
|
||||
<string name="pref_backup_interval">Fréquence de sauvegarde</string>
|
||||
<string name="pref_backup_slots">Nombre maximal de sauvegardes</string>
|
||||
<string name="backup_created">Sauvegarde créée</string>
|
||||
<string name="restoring_backup">Restauration de sauvegarde en cours</string>
|
||||
<string name="creating_backup">Création de sauvegarde en cours</string>
|
||||
@ -327,7 +323,6 @@
|
||||
<string name="notification_chapters_single_and_more">Chapitre %1$s et %2$d autres</string>
|
||||
<string name="notification_chapters_multiple">Chapitres %1$s</string>
|
||||
<string name="hide_notification_content">Cacher le contenu des notifications</string>
|
||||
<string name="notification_check_updates">Recherche de nouveaux chapitres</string>
|
||||
<string name="pref_disable_battery_optimization">Désactiver la fonction d\'optimisation de la batterie</string>
|
||||
<string name="pref_disable_battery_optimization_summary">Facilite les mises à jour et sauvegardes de la bibliothèque en arrière-plan</string>
|
||||
<string name="battery_optimization_disabled">La fonction d\'optimisation de la batterie est déjà désactivée</string>
|
||||
@ -742,4 +737,20 @@
|
||||
<string name="action_move_to_bottom_all_for_series">Déplacer la série vers le bas</string>
|
||||
<string name="track_delete_remote_text">Supprimez également de %s</string>
|
||||
<string name="exception_unknown_host">Impossible de joindre %s</string>
|
||||
<string name="app_settings">Paramètres de l\'application</string>
|
||||
<string name="delete_downloaded">Supprimer le(s) téléchargement(s)</string>
|
||||
<string name="action_apply">Appliquer</string>
|
||||
<string name="action_revert_to_default">Réintialiser les valeurs par défaut</string>
|
||||
<string name="action_sort_category">Trier les catégories</string>
|
||||
<string name="action_menu_overflow_description">Plus d\'options</string>
|
||||
<string name="selected">Sélectionné</string>
|
||||
<string name="not_selected">Pas sélectionné(e)</string>
|
||||
<string name="scanlator">Scanlator</string>
|
||||
<string name="pref_flash_page">Faire l\'écran clignoter sur le changement de page</string>
|
||||
<string name="action_bar_up_description">Naviguer vers le haut</string>
|
||||
<string name="action_sort_tracker_score">Score du service de suivi</string>
|
||||
<string name="label_data_storage">Données et stockage</string>
|
||||
<string name="sort_category_confirmation">Voulez-vous trier les catégories par ordre alphabétique ?</string>
|
||||
<string name="track_activity_name">Se connecter au service de suivi</string>
|
||||
<string name="pref_relative_format_summary">« %1$s » au lieu de « %2$s »</string>
|
||||
</resources>
|
@ -10,12 +10,10 @@
|
||||
<string name="label_download_queue">Cola de baixadas</string>
|
||||
<string name="last_read_chapter">Último capítulo lido</string>
|
||||
<string name="disabled">Deshabilitado</string>
|
||||
<string name="custom_dir">Ubicación personalizada</string>
|
||||
<string name="pref_remove_bookmarked_chapters">Permitir eliminar os capítulos marcados como favoritos</string>
|
||||
<string name="pref_remove_after_read">Eliminar automaticamente despois de ler</string>
|
||||
<string name="pref_remove_after_marked_as_read">Despois de marcar manualmente como lido</string>
|
||||
<string name="pref_category_delete_chapters">Eliminar capítulos</string>
|
||||
<string name="pref_download_directory">Localización das baixadas</string>
|
||||
<string name="pref_webtoon_side_padding">Recheo lateral</string>
|
||||
<string name="pref_category_reading">Lendo</string>
|
||||
<string name="pref_category_reading_mode">Modo de lectura</string>
|
||||
@ -274,7 +272,6 @@
|
||||
<string name="picture_saved">Imaxe gardada</string>
|
||||
<string name="pref_restore_backup">Restaurar a copia de seguridade</string>
|
||||
<string name="pref_backup_interval">Frecuencia das copias de seguridade</string>
|
||||
<string name="pref_backup_slots">Máximo de copias de seguridade</string>
|
||||
<string name="backup_restore_missing_sources">Fontes faltantes:</string>
|
||||
<string name="pref_invalidate_download_cache">Invalidar o índice de baixadas</string>
|
||||
<string name="pref_dump_crash_logs_summary">Garda os rexistros de erros nun ficheiro para compartilo cos desenvolvedores</string>
|
||||
@ -370,7 +367,6 @@
|
||||
<string name="ext_info_age_rating">Clasificación por idades</string>
|
||||
<string name="enhanced_services">Servizos mellorados</string>
|
||||
<string name="enhanced_tracking_info">Estes servizos proporcionan funcións melloradas para fontes concretas. Faise un seguemento automático dos elementos ao engadilos á biblioteca.</string>
|
||||
<string name="pref_backup_directory">Localización da copia de seguridade</string>
|
||||
<string name="backup_in_progress">Xa se está facendo unha copia de seguridade</string>
|
||||
<string name="pref_dump_crash_logs">Compartir os rexistros de erros</string>
|
||||
<string name="error_sharing_cover">Error ao compartir a portada</string>
|
||||
@ -592,7 +588,6 @@
|
||||
<string name="local_source">Fonte local</string>
|
||||
<string name="manga_tracking_tab">En seguimento</string>
|
||||
<string name="reading">Lendo</string>
|
||||
<string name="notification_check_updates">Procurando capítulos novos</string>
|
||||
<string name="download_notifier_text_only_wifi">Non hai ningunha conexión Wi-Fi dispoñible</string>
|
||||
<string name="crash_screen_description">%s pechouse por un problema inesperado. Aconsellámoste que compartas os rexistros de erros na canle de soporte no Discord (en inglés).</string>
|
||||
<string name="crash_screen_restart_application">Reinicia a aplicación</string>
|
||||
|
@ -27,7 +27,6 @@
|
||||
<string name="notification_chapters_single_and_more">פרק %1$s ו-%2$d נוספים</string>
|
||||
<string name="notification_chapters_single">פרק %1$s</string>
|
||||
<string name="notification_new_chapters">נמצאו פרקים חדשים</string>
|
||||
<string name="notification_check_updates">מחפש פרקים חדשים</string>
|
||||
<string name="download_queue_error">לא ניתן להוריד פרקים. אפשר לנסות שוב בדף ההורדות</string>
|
||||
<string name="copy">העתק</string>
|
||||
<string name="migrate">העברה</string>
|
||||
@ -206,9 +205,7 @@
|
||||
<string name="backup_choice">מה אתה רוצה לגבות\?</string>
|
||||
<string name="restore_completed">השחזור הושלם</string>
|
||||
<string name="backup_created">גיבוי נוצר</string>
|
||||
<string name="pref_backup_slots">מספר גיבויים מקסימלי</string>
|
||||
<string name="pref_backup_interval">תדירות גיבוי</string>
|
||||
<string name="pref_backup_directory">מיקום גיבוי</string>
|
||||
<string name="pref_restore_backup_summ">שחזר ספרייה מקובץ גיבוי</string>
|
||||
<string name="pref_restore_backup">שחזור גיבוי</string>
|
||||
<string name="pref_create_backup_summ">ניתן לשימוש על מנת לשחזר את הספרייה הנוכחית</string>
|
||||
@ -221,10 +218,8 @@
|
||||
<string name="third_to_last">הפרק השלישי מהסוף שנקרא</string>
|
||||
<string name="second_to_last">הפרק השני מהסוף שנקרא</string>
|
||||
<string name="last_read_chapter">פרק שנקרא בפעם האחרונה</string>
|
||||
<string name="custom_dir">מיקום מותאם אישית</string>
|
||||
<string name="pref_remove_after_read">אוטומטי לאחר סיום הקריאה</string>
|
||||
<string name="pref_remove_after_marked_as_read">אחרי שמסומן ידנית כנקרא</string>
|
||||
<string name="pref_download_directory">מיקום ההורדה</string>
|
||||
<string name="pref_always_show_chapter_transition">הצג תמיד מעברי פרקים</string>
|
||||
<string name="color_filter_a_value">אלפא</string>
|
||||
<string name="color_filter_b_value">כחול</string>
|
||||
|
@ -122,10 +122,8 @@
|
||||
<string name="color_filter_g_value">G</string>
|
||||
<string name="color_filter_b_value">B</string>
|
||||
<string name="color_filter_a_value">A</string>
|
||||
<string name="pref_download_directory">डाउनलोड निर्देशिका</string>
|
||||
<string name="pref_remove_after_marked_as_read">\'पढ़ें\' के रूप में खुद से चिह्नित करने के बाद</string>
|
||||
<string name="pref_remove_after_read">पढ़ने के बाद स्वचालित रूप से हटाएं</string>
|
||||
<string name="custom_dir">इच्छा अनुसार निर्देशिका</string>
|
||||
<string name="disabled">बंद करें</string>
|
||||
<string name="last_read_chapter">अंतिम पढ़ा अध्याय</string>
|
||||
<string name="second_to_last">दूसरा से अंतिम पढ़ा गया अध्याय</string>
|
||||
@ -138,9 +136,7 @@
|
||||
<string name="pref_create_backup_summ">वर्तमान पुस्तकालय को पुनर्स्थापित करने के लिए उपयोग किया जा सकता है</string>
|
||||
<string name="pref_restore_backup">बैकअप पुनर्स्थापित करे</string>
|
||||
<string name="pref_restore_backup_summ">बैकअप फ़ाइल से लाइब्रेरी पुनर्स्थापित करें</string>
|
||||
<string name="pref_backup_directory">बैकअप निर्देशिका</string>
|
||||
<string name="pref_backup_interval">बैकअप फ़्रीक्वेंसी</string>
|
||||
<string name="pref_backup_slots">अधिकतम बैकअप</string>
|
||||
<string name="backup_created">बैकअप बनाया गया है</string>
|
||||
<string name="restore_completed">पुनर्स्थापना पूर्ण हुआ</string>
|
||||
<string name="backup_choice">आप बैकअप के लिए क्या चाहते हैं?</string>
|
||||
@ -327,7 +323,6 @@
|
||||
<string name="notification_chapters_single_and_more">अध्याय %1$s और %2$d अधिक</string>
|
||||
<string name="notification_chapters_multiple">अध्याय %1$s</string>
|
||||
<string name="hide_notification_content">अधिसूचना सामग्री छुपाएं</string>
|
||||
<string name="notification_check_updates">नए अध्यायों के लिए जांच</string>
|
||||
<string name="pref_disable_battery_optimization">बैटरी अनुकूलन को अक्षम करना</string>
|
||||
<string name="pref_disable_battery_optimization_summary">पृष्ठभूमि पुस्तकालय अपडेट और बैकअप के साथ मदद करता है</string>
|
||||
<string name="battery_optimization_disabled">बैटरी अनुकूलन पहले से ही अक्षम है</string>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user