fix: merge conflict.

Signed-off-by: KaiserBh <kaiserbh@proton.me>
This commit is contained in:
KaiserBh 2023-11-14 14:09:17 +11:00
commit 0016f1e335
No known key found for this signature in database
GPG Key ID: 14D73B142042BBA9
81 changed files with 648 additions and 391 deletions

View File

@ -167,6 +167,7 @@ dependencies {
implementation(compose.accompanist.permissions) implementation(compose.accompanist.permissions)
implementation(compose.accompanist.themeadapter) implementation(compose.accompanist.themeadapter)
implementation(compose.accompanist.systemuicontroller) implementation(compose.accompanist.systemuicontroller)
lintChecks(compose.lintchecks)
implementation(androidx.paging.runtime) implementation(androidx.paging.runtime)
implementation(androidx.paging.compose) implementation(androidx.paging.compose)
@ -174,6 +175,7 @@ dependencies {
implementation(libs.bundles.sqlite) implementation(libs.bundles.sqlite)
implementation(kotlinx.reflect) implementation(kotlinx.reflect)
implementation(kotlinx.immutables)
implementation(platform(kotlinx.coroutines.bom)) implementation(platform(kotlinx.coroutines.bom))
implementation(kotlinx.bundles.coroutines) implementation(kotlinx.bundles.coroutines)

View File

@ -24,6 +24,7 @@ import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.util.formattedMessage import eu.kanade.presentation.util.formattedMessage
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import tachiyomi.domain.library.model.LibraryDisplayMode import tachiyomi.domain.library.model.LibraryDisplayMode
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
@ -76,7 +77,7 @@ fun BrowseSourceContent(
modifier = Modifier.padding(contentPadding), modifier = Modifier.padding(contentPadding),
message = getErrorMessage(errorState), message = getErrorMessage(errorState),
actions = if (source is LocalSource) { actions = if (source is LocalSource) {
listOf( persistentListOf(
EmptyScreenAction( EmptyScreenAction(
stringResId = R.string.local_source_help_guide, stringResId = R.string.local_source_help_guide,
icon = Icons.Outlined.HelpOutline, icon = Icons.Outlined.HelpOutline,
@ -84,7 +85,7 @@ fun BrowseSourceContent(
), ),
) )
} else { } else {
listOf( persistentListOf(
EmptyScreenAction( EmptyScreenAction(
stringResId = R.string.action_retry, stringResId = R.string.action_retry,
icon = Icons.Outlined.Refresh, icon = Icons.Outlined.Refresh,

View File

@ -94,8 +94,8 @@ fun SourcesScreen(
@Composable @Composable
private fun SourceHeader( private fun SourceHeader(
modifier: Modifier = Modifier,
language: String, language: String,
modifier: Modifier = Modifier,
) { ) {
val context = LocalContext.current val context = LocalContext.current
Text( Text(
@ -108,11 +108,11 @@ private fun SourceHeader(
@Composable @Composable
private fun SourceItem( private fun SourceItem(
modifier: Modifier = Modifier,
source: Source, source: Source,
onClickItem: (Source, Listing) -> Unit, onClickItem: (Source, Listing) -> Unit,
onLongClickItem: (Source) -> Unit, onLongClickItem: (Source) -> Unit,
onClickPin: (Source) -> Unit, onClickPin: (Source) -> Unit,
modifier: Modifier = Modifier,
) { ) {
BaseSourceItem( BaseSourceItem(
modifier = modifier, modifier = modifier,

View File

@ -8,6 +8,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewLightDark
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import kotlinx.collections.immutable.persistentListOf
import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.EmptyScreen
import tachiyomi.presentation.core.screens.EmptyScreenAction import tachiyomi.presentation.core.screens.EmptyScreenAction
@ -30,7 +31,7 @@ private fun WithActionPreview() {
Surface { Surface {
EmptyScreen( EmptyScreen(
textResource = R.string.empty_screen, textResource = R.string.empty_screen,
actions = listOf( actions = persistentListOf(
EmptyScreenAction( EmptyScreenAction(
stringResId = R.string.action_retry, stringResId = R.string.action_retry,
icon = Icons.Outlined.Refresh, icon = Icons.Outlined.Refresh,

View File

@ -16,6 +16,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import kotlinx.collections.immutable.toImmutableList
import tachiyomi.domain.manga.interactor.FetchInterval import tachiyomi.domain.manga.interactor.FetchInterval
import tachiyomi.presentation.core.components.WheelTextPicker import tachiyomi.presentation.core.components.WheelTextPicker
@ -67,16 +68,18 @@ fun SetIntervalDialog(
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
) { ) {
val size = DpSize(width = maxWidth / 2, height = 128.dp) val size = DpSize(width = maxWidth / 2, height = 128.dp)
val items = (0..FetchInterval.MAX_INTERVAL).map { val items = (0..FetchInterval.MAX_INTERVAL)
if (it == 0) { .map {
stringResource(R.string.label_default) if (it == 0) {
} else { stringResource(R.string.label_default)
it.toString() } else {
it.toString()
}
} }
} .toImmutableList()
WheelTextPicker( WheelTextPicker(
size = size,
items = items, items = items,
size = size,
startIndex = selectedInterval, startIndex = selectedInterval,
onSelectionChanged = { selectedInterval = it }, onSelectionChanged = { selectedInterval = it },
) )

View File

@ -85,12 +85,11 @@ fun PreferenceScreen(
private fun List<Preference>.findHighlightedIndex(highlightKey: String): Int { private fun List<Preference>.findHighlightedIndex(highlightKey: String): Int {
return flatMap { return flatMap {
if (it is Preference.PreferenceGroup) { if (it is Preference.PreferenceGroup) {
mutableListOf<String?>() buildList<String?> {
.apply { add(null) // Header
add(null) // Header addAll(it.preferenceItems.map { groupItem -> groupItem.title })
addAll(it.preferenceItems.map { groupItem -> groupItem.title }) add(null) // Spacer
add(null) // Spacer }
}
} else { } else {
listOf(it.title) listOf(it.title)
} }

View File

@ -36,6 +36,10 @@ import eu.kanade.tachiyomi.data.backup.BackupCreateJob
import eu.kanade.tachiyomi.data.backup.models.Backup import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.PersistentSet
import kotlinx.collections.immutable.minus
import kotlinx.collections.immutable.plus
import kotlinx.collections.immutable.toPersistentSet
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import tachiyomi.presentation.core.components.LabeledCheckbox import tachiyomi.presentation.core.components.LabeledCheckbox
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
@ -154,7 +158,7 @@ private class CreateBackupScreenModel : StateScreenModel<CreateBackupScreenModel
@Immutable @Immutable
data class State( data class State(
val flags: Set<Int> = BackupChoices.keys, val flags: PersistentSet<Int> = BackupChoices.keys.toPersistentSet(),
) )
} }

View File

@ -2,8 +2,8 @@ package eu.kanade.presentation.track
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import eu.kanade.tachiyomi.dev.preview.DummyTracker
import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.test.DummyTracker
import tachiyomi.domain.track.model.Track import tachiyomi.domain.track.model.Track
import java.text.DateFormat import java.text.DateFormat

View File

@ -34,6 +34,8 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.theme.TachiyomiTheme import eu.kanade.presentation.theme.TachiyomiTheme
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import tachiyomi.presentation.core.components.ScrollbarLazyColumn import tachiyomi.presentation.core.components.ScrollbarLazyColumn
import tachiyomi.presentation.core.components.WheelNumberPicker import tachiyomi.presentation.core.components.WheelNumberPicker
import tachiyomi.presentation.core.components.WheelTextPicker import tachiyomi.presentation.core.components.WheelTextPicker
@ -102,9 +104,9 @@ fun TrackChapterSelector(
title = stringResource(R.string.chapters), title = stringResource(R.string.chapters),
content = { content = {
WheelNumberPicker( WheelNumberPicker(
items = range.toImmutableList(),
modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.Center),
startIndex = selection, startIndex = selection,
items = range.toList(),
onSelectionChanged = { onSelectionChange(it) }, onSelectionChanged = { onSelectionChange(it) },
) )
}, },
@ -117,7 +119,7 @@ fun TrackChapterSelector(
fun TrackScoreSelector( fun TrackScoreSelector(
selection: String, selection: String,
onSelectionChange: (String) -> Unit, onSelectionChange: (String) -> Unit,
selections: List<String>, selections: ImmutableList<String>,
onConfirm: () -> Unit, onConfirm: () -> Unit,
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
) { ) {
@ -125,9 +127,9 @@ fun TrackScoreSelector(
title = stringResource(R.string.score), title = stringResource(R.string.score),
content = { content = {
WheelTextPicker( WheelTextPicker(
items = selections,
modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.Center),
startIndex = selections.indexOf(selection).takeIf { it > 0 } ?: (selections.size / 2), startIndex = selections.indexOf(selection).takeIf { it > 0 } ?: (selections.size / 2),
items = selections,
onSelectionChanged = { onSelectionChange(selections[it]) }, onSelectionChanged = { onSelectionChange(selections[it]) },
) )
}, },

View File

@ -4,7 +4,7 @@ import android.graphics.Color
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.dev.preview.DummyTracker import eu.kanade.test.DummyTracker
internal class TrackLogoIconPreviewProvider : PreviewParameterProvider<Tracker> { internal class TrackLogoIconPreviewProvider : PreviewParameterProvider<Tracker> {

View File

@ -34,6 +34,8 @@ import eu.kanade.tachiyomi.data.coil.MangaCoverKeyer
import eu.kanade.tachiyomi.data.coil.MangaKeyer import eu.kanade.tachiyomi.data.coil.MangaKeyer
import eu.kanade.tachiyomi.data.coil.TachiyomiImageDecoder import eu.kanade.tachiyomi.data.coil.TachiyomiImageDecoder
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.di.AppModule
import eu.kanade.tachiyomi.di.PreferenceModule
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.network.NetworkPreferences
import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate
@ -54,7 +56,7 @@ import org.acra.ktx.initAcra
import org.acra.sender.HttpSender import org.acra.sender.HttpSender
import org.conscrypt.Conscrypt import org.conscrypt.Conscrypt
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.presentation.widget.TachiyomiWidgetManager import tachiyomi.presentation.widget.WidgetManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -125,7 +127,7 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
setAppCompatDelegateThemeMode(Injekt.get<UiPreferences>().themeMode().get()) setAppCompatDelegateThemeMode(Injekt.get<UiPreferences>().themeMode().get())
// Updates widget update // Updates widget update
with(TachiyomiWidgetManager(Injekt.get(), Injekt.get())) { with(WidgetManager(Injekt.get(), Injekt.get())) {
init(ProcessLifecycleOwner.get().lifecycleScope) init(ProcessLifecycleOwner.get().lifecycleScope)
} }

View File

@ -6,6 +6,7 @@ import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.collections.immutable.ImmutableList
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
interface Tracker { interface Tracker {
@ -36,7 +37,7 @@ interface Tracker {
fun getCompletionStatus(): Int fun getCompletionStatus(): Int
fun getScoreList(): List<String> fun getScoreList(): ImmutableList<String>
// TODO: Store all scores as 10 point in the future maybe? // TODO: Store all scores as 10 point in the future maybe?
fun get10PointScore(track: tachiyomi.domain.track.model.Track): Double fun get10PointScore(track: tachiyomi.domain.track.model.Track): Double

View File

@ -7,6 +7,9 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.BaseTracker import eu.kanade.tachiyomi.data.track.BaseTracker
import eu.kanade.tachiyomi.data.track.DeletableTracker import eu.kanade.tachiyomi.data.track.DeletableTracker
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -74,18 +77,18 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
override fun getCompletionStatus(): Int = COMPLETED override fun getCompletionStatus(): Int = COMPLETED
override fun getScoreList(): List<String> { override fun getScoreList(): ImmutableList<String> {
return when (scorePreference.get()) { return when (scorePreference.get()) {
// 10 point // 10 point
POINT_10 -> IntRange(0, 10).map(Int::toString) POINT_10 -> IntRange(0, 10).map(Int::toString).toImmutableList()
// 100 point // 100 point
POINT_100 -> IntRange(0, 100).map(Int::toString) POINT_100 -> IntRange(0, 100).map(Int::toString).toImmutableList()
// 5 stars // 5 stars
POINT_5 -> IntRange(0, 5).map { "$it" } POINT_5 -> IntRange(0, 5).map { "$it" }.toImmutableList()
// Smiley // Smiley
POINT_3 -> listOf("-", "😦", "😐", "😊") POINT_3 -> persistentListOf("-", "😦", "😐", "😊")
// 10 point decimal // 10 point decimal
POINT_10_DECIMAL -> IntRange(0, 100).map { (it / 10f).toString() } POINT_10_DECIMAL -> IntRange(0, 100).map { (it / 10f).toString() }.toImmutableList()
else -> throw Exception("Unknown score type") else -> throw Exception("Unknown score type")
} }
} }

View File

@ -6,6 +6,8 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.BaseTracker import eu.kanade.tachiyomi.data.track.BaseTracker
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -18,9 +20,7 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
private val api by lazy { BangumiApi(id, client, interceptor) } private val api by lazy { BangumiApi(id, client, interceptor) }
override fun getScoreList(): List<String> { override fun getScoreList(): ImmutableList<String> = SCORE_LIST
return IntRange(0, 10).map(Int::toString)
}
override fun displayScore(track: Track): String { override fun displayScore(track: Track): String {
return track.score.toInt().toString() return track.score.toInt().toString()
@ -141,5 +141,9 @@ class Bangumi(id: Long) : BaseTracker(id, "Bangumi") {
const val ON_HOLD = 4 const val ON_HOLD = 4
const val DROPPED = 5 const val DROPPED = 5
const val PLAN_TO_READ = 1 const val PLAN_TO_READ = 1
private val SCORE_LIST = IntRange(0, 10)
.map(Int::toString)
.toImmutableList()
} }
} }

View File

@ -10,6 +10,8 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.sourcePreferences import eu.kanade.tachiyomi.source.sourcePreferences
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -51,7 +53,7 @@ class Kavita(id: Long) : BaseTracker(id, "Kavita"), EnhancedTracker {
override fun getCompletionStatus(): Int = COMPLETED override fun getCompletionStatus(): Int = COMPLETED
override fun getScoreList(): List<String> = emptyList() override fun getScoreList(): ImmutableList<String> = persistentListOf()
override fun displayScore(track: Track): String = "" override fun displayScore(track: Track): String = ""

View File

@ -7,6 +7,8 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.BaseTracker import eu.kanade.tachiyomi.data.track.BaseTracker
import eu.kanade.tachiyomi.data.track.DeletableTracker import eu.kanade.tachiyomi.data.track.DeletableTracker
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -54,9 +56,9 @@ class Kitsu(id: Long) : BaseTracker(id, "Kitsu"), DeletableTracker {
override fun getCompletionStatus(): Int = COMPLETED override fun getCompletionStatus(): Int = COMPLETED
override fun getScoreList(): List<String> { override fun getScoreList(): ImmutableList<String> {
val df = DecimalFormat("0.#") val df = DecimalFormat("0.#")
return listOf("0") + IntRange(2, 20).map { df.format(it / 2f) } return (listOf("0") + IntRange(2, 20).map { df.format(it / 2f) }).toImmutableList()
} }
override fun indexToScore(index: Int): Float { override fun indexToScore(index: Int): Float {

View File

@ -8,6 +8,8 @@ import eu.kanade.tachiyomi.data.track.BaseTracker
import eu.kanade.tachiyomi.data.track.EnhancedTracker import eu.kanade.tachiyomi.data.track.EnhancedTracker
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import okhttp3.Dns import okhttp3.Dns
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
@ -48,7 +50,7 @@ class Komga(id: Long) : BaseTracker(id, "Komga"), EnhancedTracker {
override fun getCompletionStatus(): Int = COMPLETED override fun getCompletionStatus(): Int = COMPLETED
override fun getScoreList(): List<String> = emptyList() override fun getScoreList(): ImmutableList<String> = persistentListOf()
override fun displayScore(track: Track): String = "" override fun displayScore(track: Track): String = ""

View File

@ -9,6 +9,8 @@ import eu.kanade.tachiyomi.data.track.DeletableTracker
import eu.kanade.tachiyomi.data.track.mangaupdates.dto.copyTo import eu.kanade.tachiyomi.data.track.mangaupdates.dto.copyTo
import eu.kanade.tachiyomi.data.track.mangaupdates.dto.toTrackSearch import eu.kanade.tachiyomi.data.track.mangaupdates.dto.toTrackSearch
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker { class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker {
@ -18,6 +20,12 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker
const val COMPLETE_LIST = 2 const val COMPLETE_LIST = 2
const val UNFINISHED_LIST = 3 const val UNFINISHED_LIST = 3
const val ON_HOLD_LIST = 4 const val ON_HOLD_LIST = 4
private val SCORE_LIST = (
(0..9)
.flatMap { i -> (0..9).map { j -> "$i.$j" } } + listOf("10.0")
)
.toImmutableList()
} }
private val interceptor by lazy { MangaUpdatesInterceptor(this) } private val interceptor by lazy { MangaUpdatesInterceptor(this) }
@ -48,11 +56,9 @@ class MangaUpdates(id: Long) : BaseTracker(id, "MangaUpdates"), DeletableTracker
override fun getCompletionStatus(): Int = COMPLETE_LIST override fun getCompletionStatus(): Int = COMPLETE_LIST
private val _scoreList = (0..9).flatMap { i -> (0..9).map { j -> "$i.$j" } } + listOf("10.0") override fun getScoreList(): ImmutableList<String> = SCORE_LIST
override fun getScoreList(): List<String> = _scoreList override fun indexToScore(index: Int): Float = SCORE_LIST[index].toFloat()
override fun indexToScore(index: Int): Float = _scoreList[index].toFloat()
override fun displayScore(track: Track): String = track.score.toString() override fun displayScore(track: Track): String = track.score.toString()

View File

@ -7,6 +7,8 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.BaseTracker import eu.kanade.tachiyomi.data.track.BaseTracker
import eu.kanade.tachiyomi.data.track.DeletableTracker import eu.kanade.tachiyomi.data.track.DeletableTracker
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -23,6 +25,10 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
private const val SEARCH_ID_PREFIX = "id:" private const val SEARCH_ID_PREFIX = "id:"
private const val SEARCH_LIST_PREFIX = "my:" private const val SEARCH_LIST_PREFIX = "my:"
private val SCORE_LIST = IntRange(0, 10)
.map(Int::toString)
.toImmutableList()
} }
private val json: Json by injectLazy() private val json: Json by injectLazy()
@ -57,9 +63,7 @@ class MyAnimeList(id: Long) : BaseTracker(id, "MyAnimeList"), DeletableTracker {
override fun getCompletionStatus(): Int = COMPLETED override fun getCompletionStatus(): Int = COMPLETED
override fun getScoreList(): List<String> { override fun getScoreList(): ImmutableList<String> = SCORE_LIST
return IntRange(0, 10).map(Int::toString)
}
override fun displayScore(track: Track): String { override fun displayScore(track: Track): String {
return track.score.toInt().toString() return track.score.toInt().toString()

View File

@ -7,6 +7,8 @@ import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.BaseTracker import eu.kanade.tachiyomi.data.track.BaseTracker
import eu.kanade.tachiyomi.data.track.DeletableTracker import eu.kanade.tachiyomi.data.track.DeletableTracker
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
@ -20,6 +22,10 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
const val DROPPED = 4 const val DROPPED = 4
const val PLAN_TO_READ = 5 const val PLAN_TO_READ = 5
const val REREADING = 6 const val REREADING = 6
private val SCORE_LIST = IntRange(0, 10)
.map(Int::toString)
.toImmutableList()
} }
private val json: Json by injectLazy() private val json: Json by injectLazy()
@ -28,9 +34,7 @@ class Shikimori(id: Long) : BaseTracker(id, "Shikimori"), DeletableTracker {
private val api by lazy { ShikimoriApi(id, client, interceptor) } private val api by lazy { ShikimoriApi(id, client, interceptor) }
override fun getScoreList(): List<String> { override fun getScoreList(): ImmutableList<String> = SCORE_LIST
return IntRange(0, 10).map(Int::toString)
}
override fun displayScore(track: Track): String { override fun displayScore(track: Track): String {
return track.score.toInt().toString() return track.score.toInt().toString()

View File

@ -8,6 +8,8 @@ import eu.kanade.tachiyomi.data.track.BaseTracker
import eu.kanade.tachiyomi.data.track.EnhancedTracker import eu.kanade.tachiyomi.data.track.EnhancedTracker
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import tachiyomi.domain.manga.model.Manga as DomainManga import tachiyomi.domain.manga.model.Manga as DomainManga
import tachiyomi.domain.track.model.Track as DomainTrack import tachiyomi.domain.track.model.Track as DomainTrack
@ -41,7 +43,7 @@ class Suwayomi(id: Long) : BaseTracker(id, "Suwayomi"), EnhancedTracker {
override fun getCompletionStatus(): Int = COMPLETED override fun getCompletionStatus(): Int = COMPLETED
override fun getScoreList(): List<String> = emptyList() override fun getScoreList(): ImmutableList<String> = persistentListOf()
override fun displayScore(track: Track): String = "" override fun displayScore(track: Track): String = ""

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi package eu.kanade.tachiyomi.di
import android.app.Application import android.app.Application
import android.os.Build import android.os.Build
@ -7,12 +7,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import app.cash.sqldelight.db.SqlDriver import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.driver.android.AndroidSqliteDriver import app.cash.sqldelight.driver.android.AndroidSqliteDriver
import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.domain.track.service.TrackPreferences
import eu.kanade.domain.track.store.DelayedTrackingStore import eu.kanade.domain.track.store.DelayedTrackingStore
import eu.kanade.domain.ui.UiPreferences import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.download.DownloadCache import eu.kanade.tachiyomi.data.download.DownloadCache
@ -24,19 +20,12 @@ import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.network.JavaScriptEngine import eu.kanade.tachiyomi.network.JavaScriptEngine
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.NetworkPreferences
import eu.kanade.tachiyomi.source.AndroidSourceManager import eu.kanade.tachiyomi.source.AndroidSourceManager
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.util.system.isDevFlavor
import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import nl.adaptivity.xmlutil.XmlDeclMode import nl.adaptivity.xmlutil.XmlDeclMode
import nl.adaptivity.xmlutil.core.XmlVersion import nl.adaptivity.xmlutil.core.XmlVersion
import nl.adaptivity.xmlutil.serialization.XML import nl.adaptivity.xmlutil.serialization.XML
import tachiyomi.core.preference.AndroidPreferenceStore
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.provider.AndroidBackupFolderProvider
import tachiyomi.core.provider.AndroidDownloadFolderProvider
import tachiyomi.data.AndroidDatabaseHandler import tachiyomi.data.AndroidDatabaseHandler
import tachiyomi.data.Database import tachiyomi.data.Database
import tachiyomi.data.DatabaseHandler import tachiyomi.data.DatabaseHandler
@ -45,11 +34,7 @@ import tachiyomi.data.History
import tachiyomi.data.Mangas import tachiyomi.data.Mangas
import tachiyomi.data.StringListColumnAdapter import tachiyomi.data.StringListColumnAdapter
import tachiyomi.data.UpdateStrategyColumnAdapter import tachiyomi.data.UpdateStrategyColumnAdapter
import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.download.service.DownloadPreferences
import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
import tachiyomi.domain.sync.SyncPreferences
import tachiyomi.source.local.image.LocalCoverManager import tachiyomi.source.local.image.LocalCoverManager
import tachiyomi.source.local.io.LocalSourceFileSystem import tachiyomi.source.local.io.LocalSourceFileSystem
import uy.kohesive.injekt.api.InjektModule import uy.kohesive.injekt.api.InjektModule
@ -156,59 +141,3 @@ class AppModule(val app: Application) : InjektModule {
addSingletonFactory { GoogleDriveService(app) } addSingletonFactory { GoogleDriveService(app) }
} }
} }
class PreferenceModule(val application: Application) : InjektModule {
override fun InjektRegistrar.registerInjectables() {
addSingletonFactory<PreferenceStore> {
AndroidPreferenceStore(application)
}
addSingletonFactory {
NetworkPreferences(
preferenceStore = get(),
verboseLogging = isDevFlavor,
)
}
addSingletonFactory {
SourcePreferences(get())
}
addSingletonFactory {
SecurityPreferences(get())
}
addSingletonFactory {
LibraryPreferences(get())
}
addSingletonFactory {
ReaderPreferences(get())
}
addSingletonFactory {
TrackPreferences(get())
}
addSingletonFactory {
AndroidDownloadFolderProvider(application)
}
addSingletonFactory {
DownloadPreferences(
folderProvider = get<AndroidDownloadFolderProvider>(),
preferenceStore = get(),
)
}
addSingletonFactory {
AndroidBackupFolderProvider(application)
}
addSingletonFactory {
BackupPreferences(
folderProvider = get<AndroidBackupFolderProvider>(),
preferenceStore = get(),
)
}
addSingletonFactory {
SyncPreferences(get())
}
addSingletonFactory {
UiPreferences(get())
}
addSingletonFactory {
BasePreferences(application, get())
}
}
}

View File

@ -0,0 +1,81 @@
package eu.kanade.tachiyomi.di
import android.app.Application
import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.domain.track.service.TrackPreferences
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.network.NetworkPreferences
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.util.system.isDevFlavor
import tachiyomi.core.preference.AndroidPreferenceStore
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.provider.AndroidBackupFolderProvider
import tachiyomi.core.provider.AndroidDownloadFolderProvider
import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.download.service.DownloadPreferences
import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.sync.SyncPreferences
import uy.kohesive.injekt.api.InjektModule
import uy.kohesive.injekt.api.InjektRegistrar
import uy.kohesive.injekt.api.addSingletonFactory
import uy.kohesive.injekt.api.get
class PreferenceModule(val app: Application) : InjektModule {
override fun InjektRegistrar.registerInjectables() {
addSingletonFactory<PreferenceStore> {
AndroidPreferenceStore(app)
}
addSingletonFactory {
NetworkPreferences(
preferenceStore = get(),
verboseLogging = isDevFlavor,
)
}
addSingletonFactory {
SourcePreferences(get())
}
addSingletonFactory {
SecurityPreferences(get())
}
addSingletonFactory {
LibraryPreferences(get())
}
addSingletonFactory {
ReaderPreferences(get())
}
addSingletonFactory {
TrackPreferences(get())
}
addSingletonFactory {
AndroidDownloadFolderProvider(app)
}
addSingletonFactory {
DownloadPreferences(
folderProvider = get<AndroidDownloadFolderProvider>(),
preferenceStore = get(),
)
}
addSingletonFactory {
AndroidBackupFolderProvider(app)
}
addSingletonFactory {
BackupPreferences(
folderProvider = get<AndroidBackupFolderProvider>(),
preferenceStore = get(),
)
}
addSingletonFactory {
UiPreferences(get())
}
addSingletonFactory {
BasePreferences(app, get())
}
addSingletonFactory {
SyncPreferences(get())
}
}
}

View File

@ -56,7 +56,7 @@ class AndroidSourceManager(
extensions.forEach { extension -> extensions.forEach { extension ->
extension.sources.forEach { extension.sources.forEach {
mutableMap[it.id] = it mutableMap[it.id] = it
registerStubSource(it.toStubSource()) registerStubSource(StubSource.from(it))
} }
} }
sourcesMapFlow.value = mutableMap sourcesMapFlow.value = mutableMap

View File

@ -1,17 +1,11 @@
package eu.kanade.tachiyomi.source package eu.kanade.tachiyomi.source
import android.graphics.drawable.Drawable
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.tachiyomi.extension.ExtensionManager
import tachiyomi.domain.source.model.StubSource import tachiyomi.domain.source.model.StubSource
import tachiyomi.source.local.isLocal import tachiyomi.source.local.isLocal
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
fun Source.icon(): Drawable? = Injekt.get<ExtensionManager>().getAppIconForSource(this.id)
fun Source.toStubSource(): StubSource = StubSource(id = id, lang = lang, name = name)
fun Source.getNameForMangaInfo(): String { fun Source.getNameForMangaInfo(): String {
val preferences = Injekt.get<SourcePreferences>() val preferences = Injekt.get<SourcePreferences>()
val enabledLanguages = preferences.enabledLanguages().get() val enabledLanguages = preferences.enabledLanguages().get()

View File

@ -1,11 +0,0 @@
package eu.kanade.tachiyomi.source.model
import tachiyomi.data.Chapters
fun SChapter.copyFrom(other: Chapters) {
name = other.name
url = other.url
date_upload = other.date_upload
chapter_number = other.chapter_number.toFloat()
scanlator = other.scanlator
}

View File

@ -3,58 +3,14 @@ package eu.kanade.tachiyomi.source.model
import tachiyomi.data.Mangas import tachiyomi.data.Mangas
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
fun SManga.copyFrom(other: Mangas) {
if (other.author != null) {
author = other.author
}
if (other.artist != null) {
artist = other.artist
}
if (other.description != null) {
description = other.description
}
if (other.genre != null) {
genre = other.genre!!.joinToString(separator = ", ")
}
if (other.thumbnail_url != null) {
thumbnail_url = other.thumbnail_url
}
status = other.status.toInt()
if (!initialized) {
initialized = other.initialized
}
}
fun Manga.copyFrom(other: Mangas): Manga { fun Manga.copyFrom(other: Mangas): Manga {
var manga = this var manga = this
if (other.author != null) { other.author?.let { manga = manga.copy(author = it) }
manga = manga.copy(author = other.author) other.artist?.let { manga = manga.copy(artist = it) }
} other.description?.let { manga = manga.copy(description = it) }
other.genre?.let { manga = manga.copy(genre = it) }
if (other.artist != null) { other.thumbnail_url?.let { manga = manga.copy(thumbnailUrl = it) }
manga = manga.copy(artist = other.artist)
}
if (other.description != null) {
manga = manga.copy(description = other.description)
}
if (other.genre != null) {
manga = manga.copy(genre = other.genre)
}
if (other.thumbnail_url != null) {
manga = manga.copy(thumbnailUrl = other.thumbnail_url)
}
manga = manga.copy(status = other.status) manga = manga.copy(status = other.status)
if (!initialized) { if (!initialized) {
manga = manga.copy(initialized = other.initialized) manga = manga.copy(initialized = other.initialized)
} }

View File

@ -6,6 +6,11 @@ import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.domain.extension.interactor.GetExtensionLanguages import eu.kanade.domain.extension.interactor.GetExtensionLanguages
import eu.kanade.domain.source.interactor.ToggleLanguage import eu.kanade.domain.source.interactor.ToggleLanguage
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.persistentSetOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toImmutableSet
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
@ -41,8 +46,8 @@ class ExtensionFilterScreenModel(
.collectLatest { (extensionLanguages, enabledLanguages) -> .collectLatest { (extensionLanguages, enabledLanguages) ->
mutableState.update { mutableState.update {
ExtensionFilterState.Success( ExtensionFilterState.Success(
languages = extensionLanguages, languages = extensionLanguages.toImmutableList(),
enabledLanguages = enabledLanguages, enabledLanguages = enabledLanguages.toImmutableSet(),
) )
} }
} }
@ -65,8 +70,8 @@ sealed interface ExtensionFilterState {
@Immutable @Immutable
data class Success( data class Success(
val languages: List<String>, val languages: ImmutableList<String>,
val enabledLanguages: Set<String> = emptySet(), val enabledLanguages: ImmutableSet<String> = persistentSetOf(),
) : ExtensionFilterState { ) : ExtensionFilterState {
val isEmpty: Boolean val isEmpty: Boolean

View File

@ -12,6 +12,9 @@ import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
@ -75,10 +78,10 @@ class ExtensionDetailsScreenModel(
} }
.catch { throwable -> .catch { throwable ->
logcat(LogPriority.ERROR, throwable) logcat(LogPriority.ERROR, throwable)
mutableState.update { it.copy(_sources = emptyList()) } mutableState.update { it.copy(_sources = persistentListOf()) }
} }
.collectLatest { sources -> .collectLatest { sources ->
mutableState.update { it.copy(_sources = sources) } mutableState.update { it.copy(_sources = sources.toImmutableList()) }
} }
} }
} }
@ -164,11 +167,11 @@ class ExtensionDetailsScreenModel(
@Immutable @Immutable
data class State( data class State(
val extension: Extension.Installed? = null, val extension: Extension.Installed? = null,
private val _sources: List<ExtensionSourceItem>? = null, private val _sources: ImmutableList<ExtensionSourceItem>? = null,
) { ) {
val sources: List<ExtensionSourceItem> val sources: ImmutableList<ExtensionSourceItem>
get() = _sources.orEmpty() get() = _sources ?: persistentListOf()
val isLoading: Boolean val isLoading: Boolean
get() = extension == null || _sources == null get() = extension == null || _sources == null

View File

@ -4,6 +4,9 @@ import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.screenModelScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
@ -40,11 +43,13 @@ class MigrateMangaScreenModel(
logcat(LogPriority.ERROR, it) logcat(LogPriority.ERROR, it)
_events.send(MigrationMangaEvent.FailedFetchingFavorites) _events.send(MigrationMangaEvent.FailedFetchingFavorites)
mutableState.update { state -> mutableState.update { state ->
state.copy(titleList = emptyList()) state.copy(titleList = persistentListOf())
} }
} }
.map { manga -> .map { manga ->
manga.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.title }) manga
.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.title })
.toImmutableList()
} }
.collectLatest { list -> .collectLatest { list ->
mutableState.update { it.copy(titleList = list) } mutableState.update { it.copy(titleList = list) }
@ -55,11 +60,11 @@ class MigrateMangaScreenModel(
@Immutable @Immutable
data class State( data class State(
val source: Source? = null, val source: Source? = null,
private val titleList: List<Manga>? = null, private val titleList: ImmutableList<Manga>? = null,
) { ) {
val titles: List<Manga> val titles: ImmutableList<Manga>
get() = titleList.orEmpty() get() = titleList ?: persistentListOf()
val isLoading: Boolean val isLoading: Boolean
get() = source == null || titleList == null get() = source == null || titleList == null

View File

@ -6,6 +6,9 @@ import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount
import eu.kanade.domain.source.interactor.SetMigrateSorting import eu.kanade.domain.source.interactor.SetMigrateSorting
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@ -40,7 +43,7 @@ class MigrateSourceScreenModel(
mutableState.update { mutableState.update {
it.copy( it.copy(
isLoading = false, isLoading = false,
items = sources, items = sources.toImmutableList(),
) )
} }
} }
@ -80,7 +83,7 @@ class MigrateSourceScreenModel(
@Immutable @Immutable
data class State( data class State(
val isLoading: Boolean = true, val isLoading: Boolean = true,
val items: List<Pair<Source, Long>> = emptyList(), val items: ImmutableList<Pair<Source, Long>> = persistentListOf(),
val sortingMode: SetMigrateSorting.Mode = SetMigrateSorting.Mode.ALPHABETICAL, val sortingMode: SetMigrateSorting.Mode = SetMigrateSorting.Mode.ALPHABETICAL,
val sortingDirection: SetMigrateSorting.Direction = SetMigrateSorting.Direction.ASCENDING, val sortingDirection: SetMigrateSorting.Direction = SetMigrateSorting.Direction.ASCENDING,
) { ) {

View File

@ -7,6 +7,9 @@ import eu.kanade.domain.source.interactor.GetEnabledSources
import eu.kanade.domain.source.interactor.ToggleSource import eu.kanade.domain.source.interactor.ToggleSource
import eu.kanade.domain.source.interactor.ToggleSourcePin import eu.kanade.domain.source.interactor.ToggleSourcePin
import eu.kanade.presentation.browse.SourceUiModel import eu.kanade.presentation.browse.SourceUiModel
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@ -65,14 +68,16 @@ class SourcesScreenModel(
state.copy( state.copy(
isLoading = false, isLoading = false,
items = byLang.flatMap { items = byLang
listOf( .flatMap {
SourceUiModel.Header(it.key), listOf(
*it.value.map { source -> SourceUiModel.Header(it.key),
SourceUiModel.Item(source) *it.value.map { source ->
}.toTypedArray(), SourceUiModel.Item(source)
) }.toTypedArray(),
}, )
}
.toImmutableList(),
) )
} }
} }
@ -103,7 +108,7 @@ class SourcesScreenModel(
data class State( data class State(
val dialog: Dialog? = null, val dialog: Dialog? = null,
val isLoading: Boolean = true, val isLoading: Boolean = true,
val items: List<SourceUiModel> = emptyList(), val items: ImmutableList<SourceUiModel> = persistentListOf(),
) { ) {
val isEmpty = items.isEmpty() val isEmpty = items.isEmpty()
} }

View File

@ -9,6 +9,10 @@ import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.presentation.util.ioCoroutineScope import eu.kanade.presentation.util.ioCoroutineScope
import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.mutate
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toPersistentMap
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.async import kotlinx.coroutines.async
@ -125,9 +129,17 @@ abstract class SearchScreenModel(
// Reuse previous results if possible // Reuse previous results if possible
if (sameQuery) { if (sameQuery) {
val existingResults = state.value.items val existingResults = state.value.items
updateItems(sources.associateWith { existingResults[it] ?: SearchItemResult.Loading }) updateItems(
sources
.associateWith { existingResults[it] ?: SearchItemResult.Loading }
.toPersistentMap(),
)
} else { } else {
updateItems(sources.associateWith { SearchItemResult.Loading }) updateItems(
sources
.associateWith { SearchItemResult.Loading }
.toPersistentMap(),
)
} }
searchJob = ioCoroutineScope.launch { searchJob = ioCoroutineScope.launch {
@ -160,14 +172,21 @@ abstract class SearchScreenModel(
} }
} }
private fun updateItems(items: Map<CatalogueSource, SearchItemResult>) { private fun updateItems(items: PersistentMap<CatalogueSource, SearchItemResult>) {
mutableState.update { it.copy(items = items.toSortedMap(sortComparator(items))) } mutableState.update {
it.copy(
items = items
.toSortedMap(sortComparator(items))
.toPersistentMap(),
)
}
} }
private fun updateItem(source: CatalogueSource, result: SearchItemResult) { private fun updateItem(source: CatalogueSource, result: SearchItemResult) {
val mutableItems = state.value.items.toMutableMap() val newItems = state.value.items.mutate {
mutableItems[source] = result it[source] = result
updateItems(mutableItems) }
updateItems(newItems)
} }
@Immutable @Immutable
@ -176,7 +195,7 @@ abstract class SearchScreenModel(
val searchQuery: String? = null, val searchQuery: String? = null,
val sourceFilter: SourceFilter = SourceFilter.PinnedOnly, val sourceFilter: SourceFilter = SourceFilter.PinnedOnly,
val onlyShowHasResults: Boolean = false, val onlyShowHasResults: Boolean = false,
val items: Map<CatalogueSource, SearchItemResult> = emptyMap(), val items: PersistentMap<CatalogueSource, SearchItemResult> = persistentMapOf(),
) { ) {
val progress: Int = items.count { it.value !is SearchItemResult.Loading } val progress: Int = items.count { it.value !is SearchItemResult.Loading }
val total: Int = items.size val total: Int = items.size

View File

@ -5,6 +5,8 @@ import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.screenModelScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow
@ -36,7 +38,9 @@ class CategoryScreenModel(
.collectLatest { categories -> .collectLatest { categories ->
mutableState.update { mutableState.update {
CategoryScreenState.Success( CategoryScreenState.Success(
categories = categories.filterNot(Category::isSystemCategory), categories = categories
.filterNot(Category::isSystemCategory)
.toImmutableList(),
) )
} }
} }
@ -135,7 +139,7 @@ sealed interface CategoryScreenState {
@Immutable @Immutable
data class Success( data class Success(
val categories: List<Category>, val categories: ImmutableList<Category>,
val dialog: CategoryDialog? = null, val dialog: CategoryDialog? = null,
) : CategoryScreenState { ) : CategoryScreenState {

View File

@ -28,6 +28,9 @@ import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.chapter.getNextUnread import eu.kanade.tachiyomi.util.chapter.getNextUnread
import eu.kanade.tachiyomi.util.removeCovers import eu.kanade.tachiyomi.util.removeCovers
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.mutate
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
@ -562,16 +565,16 @@ class LibraryScreenModel(
} }
fun clearSelection() { fun clearSelection() {
mutableState.update { it.copy(selection = emptyList()) } mutableState.update { it.copy(selection = persistentListOf()) }
} }
fun toggleSelection(manga: LibraryManga) { fun toggleSelection(manga: LibraryManga) {
mutableState.update { state -> mutableState.update { state ->
val newSelection = state.selection.toMutableList().apply { val newSelection = state.selection.mutate { list ->
if (fastAny { it.id == manga.id }) { if (list.fastAny { it.id == manga.id }) {
removeAll { it.id == manga.id } list.removeAll { it.id == manga.id }
} else { } else {
add(manga) list.add(manga)
} }
} }
state.copy(selection = newSelection) state.copy(selection = newSelection)
@ -584,11 +587,11 @@ class LibraryScreenModel(
*/ */
fun toggleRangeSelection(manga: LibraryManga) { fun toggleRangeSelection(manga: LibraryManga) {
mutableState.update { state -> mutableState.update { state ->
val newSelection = state.selection.toMutableList().apply { val newSelection = state.selection.mutate { list ->
val lastSelected = lastOrNull() val lastSelected = list.lastOrNull()
if (lastSelected?.category != manga.category) { if (lastSelected?.category != manga.category) {
add(manga) list.add(manga)
return@apply return@mutate
} }
val items = state.getLibraryItemsByCategoryId(manga.category) val items = state.getLibraryItemsByCategoryId(manga.category)
@ -596,17 +599,17 @@ class LibraryScreenModel(
val lastMangaIndex = items.indexOf(lastSelected) val lastMangaIndex = items.indexOf(lastSelected)
val curMangaIndex = items.indexOf(manga) val curMangaIndex = items.indexOf(manga)
val selectedIds = fastMap { it.id } val selectedIds = list.fastMap { it.id }
val selectionRange = when { val selectionRange = when {
lastMangaIndex < curMangaIndex -> IntRange(lastMangaIndex, curMangaIndex) lastMangaIndex < curMangaIndex -> IntRange(lastMangaIndex, curMangaIndex)
curMangaIndex < lastMangaIndex -> IntRange(curMangaIndex, lastMangaIndex) curMangaIndex < lastMangaIndex -> IntRange(curMangaIndex, lastMangaIndex)
// We shouldn't reach this point // We shouldn't reach this point
else -> return@apply else -> return@mutate
} }
val newSelections = selectionRange.mapNotNull { index -> val newSelections = selectionRange.mapNotNull { index ->
items[index].takeUnless { it.id in selectedIds } items[index].takeUnless { it.id in selectedIds }
} }
addAll(newSelections) list.addAll(newSelections)
} }
state.copy(selection = newSelection) state.copy(selection = newSelection)
} }
@ -614,14 +617,14 @@ class LibraryScreenModel(
fun selectAll(index: Int) { fun selectAll(index: Int) {
mutableState.update { state -> mutableState.update { state ->
val newSelection = state.selection.toMutableList().apply { val newSelection = state.selection.mutate { list ->
val categoryId = state.categories.getOrNull(index)?.id ?: -1 val categoryId = state.categories.getOrNull(index)?.id ?: -1
val selectedIds = fastMap { it.id } val selectedIds = list.fastMap { it.id }
state.getLibraryItemsByCategoryId(categoryId) state.getLibraryItemsByCategoryId(categoryId)
?.fastMapNotNull { item -> ?.fastMapNotNull { item ->
item.libraryManga.takeUnless { it.id in selectedIds } item.libraryManga.takeUnless { it.id in selectedIds }
} }
?.let { addAll(it) } ?.let { list.addAll(it) }
} }
state.copy(selection = newSelection) state.copy(selection = newSelection)
} }
@ -629,14 +632,14 @@ class LibraryScreenModel(
fun invertSelection(index: Int) { fun invertSelection(index: Int) {
mutableState.update { state -> mutableState.update { state ->
val newSelection = state.selection.toMutableList().apply { val newSelection = state.selection.mutate { list ->
val categoryId = state.categories[index].id val categoryId = state.categories[index].id
val items = state.getLibraryItemsByCategoryId(categoryId)?.fastMap { it.libraryManga }.orEmpty() val items = state.getLibraryItemsByCategoryId(categoryId)?.fastMap { it.libraryManga }.orEmpty()
val selectedIds = fastMap { it.id } val selectedIds = list.fastMap { it.id }
val (toRemove, toAdd) = items.fastPartition { it.id in selectedIds } val (toRemove, toAdd) = items.fastPartition { it.id in selectedIds }
val toRemoveIds = toRemove.fastMap { it.id } val toRemoveIds = toRemove.fastMap { it.id }
removeAll { it.id in toRemoveIds } list.removeAll { it.id in toRemoveIds }
addAll(toAdd) list.addAll(toAdd)
} }
state.copy(selection = newSelection) state.copy(selection = newSelection)
} }
@ -703,7 +706,7 @@ class LibraryScreenModel(
val isLoading: Boolean = true, val isLoading: Boolean = true,
val library: LibraryMap = emptyMap(), val library: LibraryMap = emptyMap(),
val searchQuery: String? = null, val searchQuery: String? = null,
val selection: List<LibraryManga> = emptyList(), val selection: PersistentList<LibraryManga> = persistentListOf(),
val hasActiveFilters: Boolean = false, val hasActiveFilters: Boolean = false,
val showCategoryTabs: Boolean = false, val showCategoryTabs: Boolean = false,
val showMangaCount: Boolean = false, val showMangaCount: Boolean = false,

View File

@ -43,6 +43,7 @@ import eu.kanade.tachiyomi.ui.home.HomeScreen
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaScreen import eu.kanade.tachiyomi.ui.manga.MangaScreen
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow
@ -154,7 +155,7 @@ object LibraryTab : Tab {
EmptyScreen( EmptyScreen(
textResource = R.string.information_empty_library, textResource = R.string.information_empty_library,
modifier = Modifier.padding(contentPadding), modifier = Modifier.padding(contentPadding),
actions = listOf( actions = persistentListOf(
EmptyScreenAction( EmptyScreenAction(
stringResId = R.string.getting_started_guide, stringResId = R.string.getting_started_guide,
icon = Icons.Outlined.HelpOutline, icon = Icons.Outlined.HelpOutline,

View File

@ -58,6 +58,7 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone import eu.kanade.tachiyomi.util.lang.convertEpochMillisZone
import eu.kanade.tachiyomi.util.system.openInBrowser import eu.kanade.tachiyomi.util.system.openInBrowser
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
@ -398,7 +399,7 @@ private data class TrackScoreSelectorScreen(
private val tracker: Tracker, private val tracker: Tracker,
) : StateScreenModel<Model.State>(State(tracker.displayScore(track.toDbTrack()))) { ) : StateScreenModel<Model.State>(State(tracker.displayScore(track.toDbTrack()))) {
fun getSelections(): List<String> { fun getSelections(): ImmutableList<String> {
return tracker.getScoreList() return tracker.getScoreList()
} }

View File

@ -21,6 +21,10 @@ import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.util.lang.toDateKey import eu.kanade.tachiyomi.util.lang.toDateKey
import eu.kanade.tachiyomi.util.lang.toRelativeString import eu.kanade.tachiyomi.util.lang.toRelativeString
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.mutate
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
@ -106,27 +110,29 @@ class UpdatesScreenModel(
} }
} }
private fun List<UpdatesWithRelations>.toUpdateItems(): List<UpdatesItem> { private fun List<UpdatesWithRelations>.toUpdateItems(): PersistentList<UpdatesItem> {
return this.map { update -> return this
val activeDownload = downloadManager.getQueuedDownloadOrNull(update.chapterId) .map { update ->
val downloaded = downloadManager.isChapterDownloaded( val activeDownload = downloadManager.getQueuedDownloadOrNull(update.chapterId)
update.chapterName, val downloaded = downloadManager.isChapterDownloaded(
update.scanlator, update.chapterName,
update.mangaTitle, update.scanlator,
update.sourceId, update.mangaTitle,
) update.sourceId,
val downloadState = when { )
activeDownload != null -> activeDownload.status val downloadState = when {
downloaded -> Download.State.DOWNLOADED activeDownload != null -> activeDownload.status
else -> Download.State.NOT_DOWNLOADED downloaded -> Download.State.DOWNLOADED
else -> Download.State.NOT_DOWNLOADED
}
UpdatesItem(
update = update,
downloadStateProvider = { downloadState },
downloadProgressProvider = { activeDownload?.progress ?: 0 },
selected = update.chapterId in selectedChapterIds,
)
} }
UpdatesItem( .toPersistentList()
update = update,
downloadStateProvider = { downloadState },
downloadProgressProvider = { activeDownload?.progress ?: 0 },
selected = update.chapterId in selectedChapterIds,
)
}
} }
fun updateLibrary(): Boolean { fun updateLibrary(): Boolean {
@ -144,17 +150,14 @@ class UpdatesScreenModel(
*/ */
private fun updateDownloadState(download: Download) { private fun updateDownloadState(download: Download) {
mutableState.update { state -> mutableState.update { state ->
val newItems = state.items.toMutableList().apply { val newItems = state.items.mutate { list ->
val modifiedIndex = indexOfFirst { it.update.chapterId == download.chapter.id } val modifiedIndex = list.indexOfFirst { it.update.chapterId == download.chapter.id }
if (modifiedIndex < 0) return@apply if (modifiedIndex < 0) return@mutate
val item = get(modifiedIndex) val item = list[modifiedIndex]
set( list[modifiedIndex] = item.copy(
modifiedIndex, downloadStateProvider = { download.status },
item.copy( downloadProgressProvider = { download.progress },
downloadStateProvider = { download.status },
downloadProgressProvider = { download.progress },
),
) )
} }
state.copy(items = newItems) state.copy(items = newItems)
@ -330,7 +333,7 @@ class UpdatesScreenModel(
} }
} }
} }
state.copy(items = newItems) state.copy(items = newItems.toPersistentList())
} }
} }
@ -340,7 +343,7 @@ class UpdatesScreenModel(
selectedChapterIds.addOrRemove(it.update.chapterId, selected) selectedChapterIds.addOrRemove(it.update.chapterId, selected)
it.copy(selected = selected) it.copy(selected = selected)
} }
state.copy(items = newItems) state.copy(items = newItems.toPersistentList())
} }
selectedPositions[0] = -1 selectedPositions[0] = -1
@ -353,7 +356,7 @@ class UpdatesScreenModel(
selectedChapterIds.addOrRemove(it.update.chapterId, !it.selected) selectedChapterIds.addOrRemove(it.update.chapterId, !it.selected)
it.copy(selected = !it.selected) it.copy(selected = !it.selected)
} }
state.copy(items = newItems) state.copy(items = newItems.toPersistentList())
} }
selectedPositions[0] = -1 selectedPositions[0] = -1
selectedPositions[1] = -1 selectedPositions[1] = -1
@ -370,7 +373,7 @@ class UpdatesScreenModel(
@Immutable @Immutable
data class State( data class State(
val isLoading: Boolean = true, val isLoading: Boolean = true,
val items: List<UpdatesItem> = emptyList(), val items: PersistentList<UpdatesItem> = persistentListOf(),
val dialog: Dialog? = null, val dialog: Dialog? = null,
) { ) {
val selected = items.filter { it.selected } val selected = items.filter { it.selected }

View File

@ -1,9 +1,11 @@
package eu.kanade.tachiyomi.dev.preview package eu.kanade.test
import android.graphics.Color import android.graphics.Color
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.track.Tracker import eu.kanade.tachiyomi.data.track.Tracker
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import tachiyomi.domain.track.model.Track import tachiyomi.domain.track.model.Track
@ -18,7 +20,7 @@ data class DummyTracker(
val valReadingStatus: Int = 1, val valReadingStatus: Int = 1,
val valRereadingStatus: Int = 1, val valRereadingStatus: Int = 1,
val valCompletionStatus: Int = 2, val valCompletionStatus: Int = 2,
val valScoreList: List<String> = (0..10).map(Int::toString), val valScoreList: ImmutableList<String> = (0..10).map(Int::toString).toImmutableList(),
val val10PointScore: Double = 5.4, val val10PointScore: Double = 5.4,
val valSearchResults: List<TrackSearch> = listOf(), val valSearchResults: List<TrackSearch> = listOf(),
) : Tracker { ) : Tracker {
@ -48,7 +50,7 @@ data class DummyTracker(
override fun getCompletionStatus(): Int = valCompletionStatus override fun getCompletionStatus(): Int = valCompletionStatus
override fun getScoreList(): List<String> = valScoreList override fun getScoreList(): ImmutableList<String> = valScoreList
override fun get10PointScore(track: Track): Double = val10PointScore override fun get10PointScore(track: Track): Double = val10PointScore

View File

@ -80,7 +80,7 @@ class EpubFile(file: File) : Closeable {
/** /**
* Returns all the pages from the epub. * Returns all the pages from the epub.
*/ */
fun getPagesFromDocument(document: Document): List<String> { private fun getPagesFromDocument(document: Document): List<String> {
val pages = document.select("manifest > item") val pages = document.select("manifest > item")
.filter { node -> "application/xhtml+xml" == node.attr("media-type") } .filter { node -> "application/xhtml+xml" == node.attr("media-type") }
.associateBy { it.attr("id") } .associateBy { it.attr("id") }
@ -102,10 +102,9 @@ class EpubFile(file: File) : Closeable {
val imageBasePath = getParentDirectory(entryPath) val imageBasePath = getParentDirectory(entryPath)
document.allElements.forEach { document.allElements.forEach {
if (it.tagName() == "img") { when (it.tagName()) {
result.add(resolveZipPath(imageBasePath, it.attr("src"))) "img" -> result.add(resolveZipPath(imageBasePath, it.attr("src")))
} else if (it.tagName() == "image") { "image" -> result.add(resolveZipPath(imageBasePath, it.attr("xlink:href")))
result.add(resolveZipPath(imageBasePath, it.attr("xlink:href")))
} }
} }
} }

View File

@ -23,6 +23,12 @@ class StubSource(
override fun toString(): String = override fun toString(): String =
if (isInvalid.not()) "$name (${lang.uppercase()})" else id.toString() if (isInvalid.not()) "$name (${lang.uppercase()})" else id.toString()
companion object {
fun from(source: Source): StubSource {
return StubSource(id = source.id, lang = source.lang, name = source.name)
}
}
} }
class SourceNotInstalledException : Exception() class SourceNotInstalledException : Exception()

View File

@ -14,7 +14,6 @@ corektx = "androidx.core:core-ktx:1.12.0"
splashscreen = "androidx.core:core-splashscreen:1.0.1" splashscreen = "androidx.core:core-splashscreen:1.0.1"
recyclerview = "androidx.recyclerview:recyclerview:1.3.2" recyclerview = "androidx.recyclerview:recyclerview:1.3.2"
viewpager = "androidx.viewpager:viewpager:1.1.0-alpha01" viewpager = "androidx.viewpager:viewpager:1.1.0-alpha01"
glance = "androidx.glance:glance-appwidget:1.0.0"
profileinstaller = "androidx.profileinstaller:profileinstaller:1.3.1" profileinstaller = "androidx.profileinstaller:profileinstaller:1.3.1"
lifecycle-common = { module = "androidx.lifecycle:lifecycle-common", version.ref = "lifecycle_version" } lifecycle-common = { module = "androidx.lifecycle:lifecycle-common", version.ref = "lifecycle_version" }

View File

@ -19,7 +19,11 @@ material-icons = { module = "androidx.compose.material:material-icons-extended"
# Some components aren't available in Material3 # Some components aren't available in Material3
material-core = { module = "androidx.compose.material:material" } material-core = { module = "androidx.compose.material:material" }
glance = "androidx.glance:glance-appwidget:1.0.0"
accompanist-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "accompanist" } accompanist-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "accompanist" }
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" } accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" }
accompanist-themeadapter = { module = "com.google.accompanist:accompanist-themeadapter-material3", version.ref = "accompanist" } accompanist-themeadapter = { module = "com.google.accompanist:accompanist-themeadapter-material3", version.ref = "accompanist" }
accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist" } accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist" }
lintchecks = { module = "com.slack.lint.compose:compose-lint-checks", version = "1.2.0" }

View File

@ -7,6 +7,8 @@ xml_serialization_version = "0.86.2"
reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin_version" } reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin_version" }
gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin_version" } gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin_version" }
immutables = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version = "0.3.6" }
coroutines-bom = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-bom", version = "1.7.3" } coroutines-bom = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-bom", version = "1.7.3" }
coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core" } coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core" }
coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android" } coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android" }

View File

@ -5,7 +5,7 @@ shizuku_version = "12.2.0"
sqlite = "2.4.0" sqlite = "2.4.0"
sqldelight = "2.0.0" sqldelight = "2.0.0"
leakcanary = "2.12" leakcanary = "2.12"
voyager = "1.0.0-rc09" voyager = "1.0.0-rc10"
richtext = "0.17.0" richtext = "0.17.0"
[libraries] [libraries]

View File

@ -566,8 +566,8 @@
<string name="rotation_portrait">رأسي</string> <string name="rotation_portrait">رأسي</string>
<string name="rotation_type">التدوير</string> <string name="rotation_type">التدوير</string>
<string name="automatic_background">تلقائيًّا</string> <string name="automatic_background">تلقائيًّا</string>
<string name="pref_create_folder_per_manga_summary">إنشاء مجلدات وفقا لعنوان الإدخالات</string> <string name="pref_create_folder_per_manga_summary">يُنشِئ مجلدات وفقًا لعناوين المدخلات</string>
<string name="pref_create_folder_per_manga">حفظ الصفحات في مجلدات منفصلة</string> <string name="pref_create_folder_per_manga">احفظ الصفحات في مجلدات منفصلة</string>
<string name="pref_reader_actions">الإجراءات</string> <string name="pref_reader_actions">الإجراءات</string>
<string name="pref_grayscale">تدرج رمادي</string> <string name="pref_grayscale">تدرج رمادي</string>
<string name="exclude">إستثناء: %s</string> <string name="exclude">إستثناء: %s</string>
@ -882,11 +882,18 @@
<string name="sort_category_confirmation">أتريد ترتيب الفئات حسب الحروف؟</string> <string name="sort_category_confirmation">أتريد ترتيب الفئات حسب الحروف؟</string>
<string name="source_settings">إعدادات المصادر</string> <string name="source_settings">إعدادات المصادر</string>
<string name="app_settings">إعدادات التطبيق</string> <string name="app_settings">إعدادات التطبيق</string>
<string name="file_null_uri_error">ما استطاع محدِّد الملفات من إدخال الملف في التطبيق</string> <string name="file_null_uri_error">لا ملفات حُدِّدت</string>
<string name="label_data_storage">البيانات والتخزين</string> <string name="label_data_storage">البيانات والتخزين</string>
<string name="relative_time_span_never">أبدًا</string> <string name="relative_time_span_never">أبدًا</string>
<string name="pref_flash_page_summ">يخفِّف الحرق في شاشات الحبر</string> <string name="pref_flash_page_summ">يخفِّف الحرق في شاشات الحبر</string>
<string name="last_auto_backup_info">آخر احتياط تلقائي: %s</string> <string name="last_auto_backup_info">آخر احتياط تلقائي: %s</string>
<string name="pref_flash_page">أشرق الشاشة بِيضًا إذا تغيرت الصفحة</string> <string name="pref_flash_page">أشرق الشاشة بِيضًا إذا تغيرت الصفحة</string>
<string name="pref_storage_usage">التخزين</string> <string name="pref_storage_usage">التخزين</string>
<string name="action_sort_tracker_score">نقاط المتتبع</string>
<string name="action_create">أنشئ</string>
<string name="action_apply">نفِّذ</string>
<string name="action_revert_to_default">صفِّر</string>
<string name="no_scanlators_found">لم يُعثَر على مترجمين</string>
<string name="scanlator">المترجم</string>
<string name="exclude_scanlators">احجب بعض المترجمين</string>
</resources> </resources>

View File

@ -271,7 +271,7 @@
<string name="action_start">Iniciar</string> <string name="action_start">Iniciar</string>
<string name="action_retry">Reintentar</string> <string name="action_retry">Reintentar</string>
<string name="pref_clear_cookies">Borrar cookies</string> <string name="pref_clear_cookies">Borrar cookies</string>
<string name="label_network">Red</string> <string name="label_network">Redes</string>
<string name="restoring_backup_canceled">Se canceló la restauración</string> <string name="restoring_backup_canceled">Se canceló la restauración</string>
<string name="restoring_backup_error">La restauración de la copia de seguridad falló</string> <string name="restoring_backup_error">La restauración de la copia de seguridad falló</string>
<string name="restoring_backup">Restaurando copia de seguridad</string> <string name="restoring_backup">Restaurando copia de seguridad</string>
@ -291,8 +291,8 @@
<string name="invalid_backup_file_missing_manga">La copia de seguridad no contiene ningún manga.</string> <string name="invalid_backup_file_missing_manga">La copia de seguridad no contiene ningún manga.</string>
<string name="invalid_backup_file">Archivo de copia de seguridad invalido</string> <string name="invalid_backup_file">Archivo de copia de seguridad invalido</string>
<string name="backup_created">Copia de seguridad creada</string> <string name="backup_created">Copia de seguridad creada</string>
<string name="pref_backup_slots">Máximo de copias de seguridad</string> <string name="pref_backup_slots">Máximo de copias de seguridad automáticas</string>
<string name="pref_backup_interval">Frecuencia de respaldo</string> <string name="pref_backup_interval">Frecuencia de respaldo automático</string>
<string name="pref_backup_directory">Directorio de copia de seguridad</string> <string name="pref_backup_directory">Directorio de copia de seguridad</string>
<string name="pref_restore_backup_summ">Restaurar biblioteca desde archivo de copia de seguridad</string> <string name="pref_restore_backup_summ">Restaurar biblioteca desde archivo de copia de seguridad</string>
<string name="cache_deleted">Caché borrada. %1$d archivos se han eliminado</string> <string name="cache_deleted">Caché borrada. %1$d archivos se han eliminado</string>
@ -523,7 +523,7 @@
<string name="rotation_type">Rotación</string> <string name="rotation_type">Rotación</string>
<string name="nav_zone_right">Derecha</string> <string name="nav_zone_right">Derecha</string>
<string name="nav_zone_left">Izquierda</string> <string name="nav_zone_left">Izquierda</string>
<string name="pref_create_folder_per_manga_summary">Crea carpetas según el título del manga</string> <string name="pref_create_folder_per_manga_summary">Crear carpetas según el título del manga</string>
<string name="pref_grayscale">Escala de grises</string> <string name="pref_grayscale">Escala de grises</string>
<string name="update_check_eol">Está versión de Android ya no está soportada</string> <string name="update_check_eol">Está versión de Android ya no está soportada</string>
<string name="clipboard_copy_error">Falló al copiar en el portapapeles</string> <string name="clipboard_copy_error">Falló al copiar en el portapapeles</string>
@ -708,7 +708,7 @@
<string name="pref_reader_summary">Modo lectura, apariencia, navegación</string> <string name="pref_reader_summary">Modo lectura, apariencia, navegación</string>
<string name="pref_downloads_summary">Descargas automáticas y por adelantado</string> <string name="pref_downloads_summary">Descargas automáticas y por adelantado</string>
<string name="pref_browse_summary">Fuentes, extensiones, búsqueda global</string> <string name="pref_browse_summary">Fuentes, extensiones, búsqueda global</string>
<string name="pref_backup_summary">Respaldo manual y automático</string> <string name="pref_backup_summary">Respaldo manual y automático, espacio de almacenamiento</string>
<string name="pref_security_summary">Bloqueo de aplicación, pantalla de seguridad</string> <string name="pref_security_summary">Bloqueo de aplicación, pantalla de seguridad</string>
<string name="pref_advanced_summary">Guardar registros de fallo, optimizaciones de bateria</string> <string name="pref_advanced_summary">Guardar registros de fallo, optimizaciones de bateria</string>
<string name="pref_tracking_summary">Sincronización de progreso unidireccional, sincronización mejorada</string> <string name="pref_tracking_summary">Sincronización de progreso unidireccional, sincronización mejorada</string>
@ -747,7 +747,7 @@
<string name="unknown_title">Título desconocido</string> <string name="unknown_title">Título desconocido</string>
<string name="download_notifier_cache_renewal">Comprobando descargas</string> <string name="download_notifier_cache_renewal">Comprobando descargas</string>
<string name="invalid_location">Ubicación incorrecta: %s</string> <string name="invalid_location">Ubicación incorrecta: %s</string>
<string name="pref_reset_user_agent_string">Reestablecer el nombre del navegador</string> <string name="pref_reset_user_agent_string">Restablecer el nombre del navegador</string>
<string name="update_already_running">Una actualización está actualmente en curso</string> <string name="update_already_running">Una actualización está actualmente en curso</string>
<string name="are_you_sure">¿Estás seguro\?</string> <string name="are_you_sure">¿Estás seguro\?</string>
<string name="label_titles_section">Manga</string> <string name="label_titles_section">Manga</string>
@ -834,5 +834,18 @@
<string name="sort_category_confirmation">¿Quieres ordenar las categorías de forma alfabética\?</string> <string name="sort_category_confirmation">¿Quieres ordenar las categorías de forma alfabética\?</string>
<string name="source_settings">Configuraciónes de fuente</string> <string name="source_settings">Configuraciónes de fuente</string>
<string name="app_settings">Configuraciones</string> <string name="app_settings">Configuraciones</string>
<string name="file_null_uri_error">El selector de archivos no pudo devolver el archivo a la aplicación</string> <string name="file_null_uri_error">Ningún archivo seleccionado</string>
<string name="action_create">Crear</string>
<string name="relative_time_span_never">Nunca</string>
<string name="pref_flash_page_summ">Reducir el ghosting en pantallas de tinta electrónica</string>
<string name="action_apply">Aplicar</string>
<string name="action_revert_to_default">Restablecer configuración predeterminada</string>
<string name="last_auto_backup_info">Última copia de seguridad automática: %s</string>
<string name="no_scanlators_found">No se encontraron scanlators</string>
<string name="scanlator">Scanlator</string>
<string name="pref_flash_page">Destello blanco al cambiar de página</string>
<string name="pref_storage_usage">Uso de almacenamiento</string>
<string name="action_sort_tracker_score">Puntuación del rastreador</string>
<string name="label_data_storage">Datos y almacenamiento</string>
<string name="exclude_scanlators">Excluir scanlators</string>
</resources> </resources>

View File

@ -162,8 +162,8 @@
<string name="pref_restore_backup">Restaura una còpia de seguretat</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_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_directory">Ubicació de la còpia de seguretat</string>
<string name="pref_backup_interval">Freqüència 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</string> <string name="pref_backup_slots">Màxim de còpies de seguretat automàtiques</string>
<string name="backup_created">Sha creat la còpia de seguretat</string> <string name="backup_created">Sha creat la còpia de seguretat</string>
<string name="restore_completed">Sha completat la restauració</string> <string name="restore_completed">Sha completat la restauració</string>
<string name="backup_choice">De què voleu fer una còpia de seguretat\?</string> <string name="backup_choice">De què voleu fer una còpia de seguretat\?</string>
@ -317,6 +317,7 @@
<string name="lock_never">Mai</string> <string name="lock_never">Mai</string>
<plurals name="lock_after_mins"> <plurals name="lock_after_mins">
<item quantity="one">Després d%1$s minut</item> <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> <item quantity="other">Després de %1$s minuts</item>
</plurals> </plurals>
<string name="secure_screen">Mode discret</string> <string name="secure_screen">Mode discret</string>
@ -329,6 +330,7 @@
<string name="pref_category_display">Visualització</string> <string name="pref_category_display">Visualització</string>
<plurals name="notification_chapters_generic"> <plurals name="notification_chapters_generic">
<item quantity="one">%1$d capítol nou</item> <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> <item quantity="other">%1$d capítols nous</item>
</plurals> </plurals>
<string name="notification_chapters_single">Capítol %1$s</string> <string name="notification_chapters_single">Capítol %1$s</string>
@ -336,6 +338,7 @@
<string name="notification_chapters_multiple">Capítols %1$s</string> <string name="notification_chapters_multiple">Capítols %1$s</string>
<plurals name="notification_chapters_multiple_and_more"> <plurals name="notification_chapters_multiple_and_more">
<item quantity="one">Capítols %1$s i 1 més</item> <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> <item quantity="other">Capítols %1$s i %2$d més</item>
</plurals> </plurals>
<string name="hide_notification_content">Amaga el contingut de les notificacions</string> <string name="hide_notification_content">Amaga el contingut de les notificacions</string>
@ -347,6 +350,7 @@
<string name="pref_always_show_chapter_transition">Mostra sempre la transició de capítol</string> <string name="pref_always_show_chapter_transition">Mostra sempre la transició de capítol</string>
<plurals name="notification_new_chapters_summary"> <plurals name="notification_new_chapters_summary">
<item quantity="one">Per a %d element</item> <item quantity="one">Per a %d element</item>
<item quantity="many">Per a %d elements</item>
<item quantity="other">Per a %d elements</item> <item quantity="other">Per a %d elements</item>
</plurals> </plurals>
<string name="action_menu">Menú</string> <string name="action_menu">Menú</string>
@ -356,6 +360,7 @@
<string name="action_move_to_bottom">Mou a sota de tot</string> <string name="action_move_to_bottom">Mou a sota de tot</string>
<plurals name="update_check_notification_ext_updates"> <plurals name="update_check_notification_ext_updates">
<item quantity="one">Hi ha una actualització duna extensió</item> <item quantity="one">Hi ha una actualització duna extensió</item>
<item quantity="many">Hi ha actualitzacions de %d extensions</item>
<item quantity="other">Hi ha actualitzacions de %d extensions</item> <item quantity="other">Hi ha actualitzacions de %d extensions</item>
</plurals> </plurals>
<string name="channel_ext_updates">Actualitzacions dextensions</string> <string name="channel_ext_updates">Actualitzacions dextensions</string>
@ -391,6 +396,7 @@
<string name="downloaded_only_summary">Filtra tots els elements de la vostra biblioteca</string> <string name="downloaded_only_summary">Filtra tots els elements de la vostra biblioteca</string>
<plurals name="download_queue_summary"> <plurals name="download_queue_summary">
<item quantity="one">En resta %1$s</item> <item quantity="one">En resta %1$s</item>
<item quantity="many">En resten %1$s</item>
<item quantity="other">En resten %1$s</item> <item quantity="other">En resten %1$s</item>
</plurals> </plurals>
<string name="gray_background">Gris</string> <string name="gray_background">Gris</string>
@ -399,11 +405,13 @@
<string name="battery_optimization_setting_activity_not_found">No sha pogut obrir la configuració del dispositiu</string> <string name="battery_optimization_setting_activity_not_found">No sha pogut obrir la configuració del dispositiu</string>
<plurals name="restore_completed_message"> <plurals name="restore_completed_message">
<item quantity="one">Fet en %1$s amb %2$s error</item> <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> <item quantity="other">Fet en %1$s amb %2$s errors</item>
</plurals> </plurals>
<string name="pref_true_color_summary">Redueix les bandes de colors, però pot afectar el rendiment</string> <string name="pref_true_color_summary">Redueix les bandes de colors, però pot afectar el rendiment</string>
<plurals name="num_categories"> <plurals name="num_categories">
<item quantity="one">%d categoria</item> <item quantity="one">%d categoria</item>
<item quantity="many">%d categories</item>
<item quantity="other">%d categories</item> <item quantity="other">%d categories</item>
</plurals> </plurals>
<string name="tracking_info">La sincronització és unidireccional per a actualitzar el progrés dels capítols als serveis de seguiment externs. Configureu el seguiment delements individuals al seu botó de seguiment.</string> <string name="tracking_info">La sincronització és unidireccional per a actualitzar el progrés dels capítols als serveis de seguiment externs. Configureu el seguiment delements individuals al seu botó de seguiment.</string>
@ -433,6 +441,7 @@
<string name="loader_not_implemented_error">No sha trobat la font</string> <string name="loader_not_implemented_error">No sha trobat la font</string>
<plurals name="manga_num_chapters"> <plurals name="manga_num_chapters">
<item quantity="one">%1$s capítol</item> <item quantity="one">%1$s capítol</item>
<item quantity="many">%1$s capítols</item>
<item quantity="other">%1$s capítols</item> <item quantity="other">%1$s capítols</item>
</plurals> </plurals>
<string name="unknown_status">Estat desconegut</string> <string name="unknown_status">Estat desconegut</string>
@ -451,6 +460,7 @@
<string name="action_sort_date_added">Data dincorporació</string> <string name="action_sort_date_added">Data dincorporació</string>
<plurals name="num_trackers"> <plurals name="num_trackers">
<item quantity="one">%d servei de seguiment</item> <item quantity="one">%d servei de seguiment</item>
<item quantity="many">%d serveis de seguiment</item>
<item quantity="other">%d serveis de seguiment</item> <item quantity="other">%d serveis de seguiment</item>
</plurals> </plurals>
<string name="no_pinned_sources">No teniu cap origen fixat</string> <string name="no_pinned_sources">No teniu cap origen fixat</string>
@ -465,6 +475,7 @@
<string name="parental_controls_info">Això no evita que les extensions no oficials o possiblement mal etiquetades puguin mostrar contingut NSFW (+18) a laplicació.</string> <string name="parental_controls_info">Això no evita que les extensions no oficials o possiblement mal etiquetades puguin mostrar contingut NSFW (+18) a laplicació.</string>
<plurals name="missing_chapters_warning"> <plurals name="missing_chapters_warning">
<item quantity="one">Sha omès %d capítol. És possible que manqui a la font o que hagi estat filtrat</item> <item quantity="one">Sha omès %d capítol. És possible que manqui a la font o que hagi estat filtrat</item>
<item quantity="many">Shan omès %d capítols. És possible que manquin a la font o que hagin estat filtrats</item>
<item quantity="other">Shan omès %d capítols. És possible que manquin a la font o que hagin estat filtrats</item> <item quantity="other">Shan omès %d capítols. És possible que manquin a la font o que hagin estat filtrats</item>
</plurals> </plurals>
<string name="no_chapters_error">No sha trobat cap capítol</string> <string name="no_chapters_error">No sha trobat cap capítol</string>
@ -563,6 +574,7 @@
<string name="enhanced_services">Serveis de seguiment millorats</string> <string name="enhanced_services">Serveis de seguiment millorats</string>
<plurals name="relative_time"> <plurals name="relative_time">
<item quantity="one">Ahir</item> <item quantity="one">Ahir</item>
<item quantity="many">Fa %1$d dies</item>
<item quantity="other">Fa %1$d dies</item> <item quantity="other">Fa %1$d dies</item>
</plurals> </plurals>
<string name="relative_time_today">Avui</string> <string name="relative_time_today">Avui</string>
@ -692,11 +704,12 @@
<string name="crash_screen_description">Sha produït un error inesperat al %s. Us suggerim que compartiu el registre derrors al nostre canal dassistència al Discord.</string> <string name="crash_screen_description">Sha produït un error inesperat al %s. Us suggerim que compartiu el registre derrors al nostre canal dassistència al Discord.</string>
<plurals name="next_unread_chapters"> <plurals name="next_unread_chapters">
<item quantity="one">El següent capítol no llegit</item> <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> <item quantity="other">Els següents %d capítols no llegits</item>
</plurals> </plurals>
<string name="missing_storage_permission">No shan concedit permisos demmagatzematge</string> <string name="missing_storage_permission">No shan concedit permisos demmagatzematge</string>
<string name="popular">Populars</string> <string name="popular">Populars</string>
<string name="pref_backup_summary">Còpies de seguretat automàtiques i manuals</string> <string name="pref_backup_summary">Còpies de seguretat automàtiques i manuals i espai demmagatzematge</string>
<string name="pref_reader_summary">Mode de lectura, visualització i navegació</string> <string name="pref_reader_summary">Mode de lectura, visualització i navegació</string>
<string name="pref_downloads_summary">Baixades automàtiques i per avançat</string> <string name="pref_downloads_summary">Baixades automàtiques i per avançat</string>
<string name="multi_lang">Múltiples</string> <string name="multi_lang">Múltiples</string>
@ -750,6 +763,7 @@
<string name="information_required_plain">*obligatori</string> <string name="information_required_plain">*obligatori</string>
<plurals name="download_amount"> <plurals name="download_amount">
<item quantity="one">El següent capítol</item> <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> <item quantity="other">Els següents %d capítols</item>
</plurals> </plurals>
<string name="information_no_manga_category">La categoria és buida</string> <string name="information_no_manga_category">La categoria és buida</string>
@ -773,6 +787,7 @@
<string name="pref_page_rotate">Rota les pàgines amples perquè sajustin a la pantalla</string> <string name="pref_page_rotate">Rota les pàgines amples perquè sajustin a la pantalla</string>
<plurals name="missing_chapters"> <plurals name="missing_chapters">
<item quantity="one">Manca %1$s capítol</item> <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> <item quantity="other">Manquen %1$s capítols</item>
</plurals> </plurals>
<string name="pref_debug_info">Informació de depuració</string> <string name="pref_debug_info">Informació de depuració</string>
@ -781,6 +796,7 @@
<string name="action_sort_next_updated">Pròxima actualització prevista</string> <string name="action_sort_next_updated">Pròxima actualització prevista</string>
<plurals name="day"> <plurals name="day">
<item quantity="one">1 dia</item> <item quantity="one">1 dia</item>
<item quantity="many">%d dies</item>
<item quantity="other">%d dies</item> <item quantity="other">%d dies</item>
</plurals> </plurals>
<string name="action_filter_interval_long">Obtén mensualment (28 dies)</string> <string name="action_filter_interval_long">Obtén mensualment (28 dies)</string>
@ -818,5 +834,18 @@
<string name="sort_category_confirmation">Voleu ordenar les categories alfabèticament\?</string> <string name="sort_category_confirmation">Voleu ordenar les categories alfabèticament\?</string>
<string name="source_settings">Configuració de la font</string> <string name="source_settings">Configuració de la font</string>
<string name="app_settings">Configuració de laplicació</string> <string name="app_settings">Configuració de laplicació</string>
<string name="file_null_uri_error">El selector de fitxers no ha retornat cap fitxer a laplicació</string> <string name="file_null_uri_error">No sha seleccionat cap fitxer</string>
<string name="action_create">Crea</string>
<string name="relative_time_span_never">Mai</string>
<string name="pref_flash_page_summ">Redueix lefecte fantasma en pantalles de tinta electrònica</string>
<string name="action_apply">Aplica</string>
<string name="action_revert_to_default">Torna a la configuració per defecte</string>
<string name="last_auto_backup_info">Darrera còpia de seguretat automàtica: %s</string>
<string name="no_scanlators_found">No sha trobat cap scanlator</string>
<string name="scanlator">Scanlator</string>
<string name="pref_flash_page">Centelleig blanc en canviar de pàgina</string>
<string name="pref_storage_usage">Ús de lemmagatzematge</string>
<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>
</resources> </resources>

View File

@ -162,8 +162,8 @@
<string name="pref_restore_backup">Επαναφορά αντιγράφου ασφαλείας</string> <string name="pref_restore_backup">Επαναφορά αντιγράφου ασφαλείας</string>
<string name="pref_restore_backup_summ">Επαναφορά βιβλιοθήκης από αρχείο αντιγράφου ασφαλείας</string> <string name="pref_restore_backup_summ">Επαναφορά βιβλιοθήκης από αρχείο αντιγράφου ασφαλείας</string>
<string name="pref_backup_directory">Τοποθεσία αντιγράφων ασφαλείας</string> <string name="pref_backup_directory">Τοποθεσία αντιγράφων ασφαλείας</string>
<string name="pref_backup_interval">Συχνότητα αντίγραφου ασφάλειας</string> <string name="pref_backup_interval">Συχνότητα αυτόματων αντιγράφων ασφαλείας</string>
<string name="pref_backup_slots">Μέγιστα αντίγραφα ασφαλείας</string> <string name="pref_backup_slots">Μέγιστα αυτόματα αντίγραφα ασφαλείας</string>
<string name="backup_created">Δημιουργήθηκε αντίγραφο ασφαλείας</string> <string name="backup_created">Δημιουργήθηκε αντίγραφο ασφαλείας</string>
<string name="restore_completed">Η επαναφορά ολοκληρώθηκε</string> <string name="restore_completed">Η επαναφορά ολοκληρώθηκε</string>
<string name="backup_choice">Τι αντίγραφο ασφαλείας θέλετε να δημιουργήσετε;</string> <string name="backup_choice">Τι αντίγραφο ασφαλείας θέλετε να δημιουργήσετε;</string>
@ -703,7 +703,7 @@
<string name="pref_library_summary">Κατηγορίες, καθολική ενημέρωση, σύρσιμο κεφαλαίου</string> <string name="pref_library_summary">Κατηγορίες, καθολική ενημέρωση, σύρσιμο κεφαλαίου</string>
<string name="pref_reader_summary">Λειτουργία ανάγνωσης, οθόνη, πλοήγηση</string> <string name="pref_reader_summary">Λειτουργία ανάγνωσης, οθόνη, πλοήγηση</string>
<string name="pref_tracking_summary">Μονόδρομος συγχρονισμός προόδου, ενισχυμένος συγχρονισμός</string> <string name="pref_tracking_summary">Μονόδρομος συγχρονισμός προόδου, ενισχυμένος συγχρονισμός</string>
<string name="pref_backup_summary">Χειροκίνητα &amp; αυτόματα αντίγραφα ασφαλείας</string> <string name="pref_backup_summary">Χειροκίνητα &amp; αυτόματα αντίγραφα ασφαλείας, χώρος αποθήκευσης</string>
<string name="pref_security_summary">Κλείδωμα εφαρμογής, ασφαλής οθόνη</string> <string name="pref_security_summary">Κλείδωμα εφαρμογής, ασφαλής οθόνη</string>
<string name="crash_screen_restart_application">Επανεκκίνηση της εφαρμογής</string> <string name="crash_screen_restart_application">Επανεκκίνηση της εφαρμογής</string>
<string name="pref_downloads_summary">Αυτόματη λήψη, λήψη εκ των προτέρων</string> <string name="pref_downloads_summary">Αυτόματη λήψη, λήψη εκ των προτέρων</string>
@ -818,5 +818,18 @@
<string name="notification_updating_progress">Ενημέρωση βιβλιοθήκης… (%s)</string> <string name="notification_updating_progress">Ενημέρωση βιβλιοθήκης… (%s)</string>
<string name="sort_category_confirmation">Θέλετε να ταξινομήσετε τις κατηγορίες αλφαβητικά;</string> <string name="sort_category_confirmation">Θέλετε να ταξινομήσετε τις κατηγορίες αλφαβητικά;</string>
<string name="source_settings">Ρυθμίσεις πηγών</string> <string name="source_settings">Ρυθμίσεις πηγών</string>
<string name="file_null_uri_error">Το πρόγραμμα επιλογής αρχείων απέτυχε να επιστρέψει το αρχείο στην εφαρμογή</string> <string name="file_null_uri_error">Δεν έχει επιλεγεί αρχείο</string>
<string name="relative_time_span_never">Ποτέ</string>
<string name="pref_flash_page_summ">Μειώνει το ghosting σε οθόνες e-ink</string>
<string name="last_auto_backup_info">Τελευταία αυτόματη δημιουργία αντιγράφων ασφαλείας: %s</string>
<string name="pref_flash_page">Λευκό φλας κατά την αλλαγή σελίδας</string>
<string name="pref_storage_usage">Χρήση αποθηκευτικού χώρου</string>
<string name="action_sort_tracker_score">Σκορ tracker</string>
<string name="label_data_storage">Δεδομένα και χώρος αποθήκευσης</string>
<string name="action_create">Δημιουργία</string>
<string name="action_apply">Υποβολή</string>
<string name="action_revert_to_default">Επαναφορά προεπιλογής</string>
<string name="no_scanlators_found">Δε βρέθηκαν scanlators</string>
<string name="scanlator">Scanlator</string>
<string name="exclude_scanlators">Εξαίρεση scanlator</string>
</resources> </resources>

View File

@ -572,8 +572,8 @@
<string name="action_display_show_number_of_items">Mostrar el número de elementos</string> <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="action_sort_chapter_fetch_date">Fecha de obtención del capítulo</string>
<string name="rotation_type">Tipo de rotación</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 los elementos</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">Guardar páginas en carpetas separadas</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_reader_actions">Acciones</string>
<string name="pref_grayscale">Escala de grises</string> <string name="pref_grayscale">Escala de grises</string>
<string name="restore_miui_warning">Es posible que las funciones de copia de respaldo y restauración no funcionen correctamente si la opción «Optimización de MIUI» está desactivada.</string> <string name="restore_miui_warning">Es posible que las funciones de copia de respaldo y restauración no funcionen correctamente si la opción «Optimización de MIUI» está desactivada.</string>
@ -865,11 +865,18 @@
<string name="app_settings">Ajustes de la aplicación</string> <string name="app_settings">Ajustes de la aplicación</string>
<string name="action_sort_category">Ordenar categorías</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="sort_category_confirmation">¿Quieres ordenar las categorías de forma alfabética\?</string>
<string name="file_null_uri_error">La pantalla de selección de archivos no ha devuelto ningún archivo</string> <string name="file_null_uri_error">Ningún archivo seleccionado</string>
<string name="relative_time_span_never">Nunca</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="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="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">Parpadeo en blanco al cambiar de página</string>
<string name="label_data_storage">Datos y almacenamiento</string> <string name="label_data_storage">Datos y almacenamiento</string>
<string name="pref_storage_usage">Almacenamiento utilizado</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>
</resources> </resources>

View File

@ -15,8 +15,8 @@
<string name="action_oldest">Pinakaluma</string> <string name="action_oldest">Pinakaluma</string>
<string name="action_newest">Pinakabago</string> <string name="action_newest">Pinakabago</string>
<string name="action_sort">Ayusin</string> <string name="action_sort">Ayusin</string>
<string name="action_cancel_all">Ikansela lahat</string> <string name="action_cancel_all">Kanselahin lahat</string>
<string name="action_cancel">Ikansela</string> <string name="action_cancel">Kanselahin</string>
<string name="action_unpin">I-unpin</string> <string name="action_unpin">I-unpin</string>
<string name="action_pin">I-pin</string> <string name="action_pin">I-pin</string>
<string name="action_disable">Isara</string> <string name="action_disable">Isara</string>
@ -380,7 +380,7 @@
<string name="unknown_author">Di alam ang may-akda</string> <string name="unknown_author">Di alam ang may-akda</string>
<string name="unknown">Di alam</string> <string name="unknown">Di alam</string>
<string name="ongoing">Patuloy</string> <string name="ongoing">Patuloy</string>
<string name="local_source_help_guide">Gabay sa Lokal na Source</string> <string name="local_source_help_guide">Gabay sa Lokal na source</string>
<string name="browse">Maghanap</string> <string name="browse">Maghanap</string>
<string name="latest">Pinakabago</string> <string name="latest">Pinakabago</string>
<string name="action_global_search_query">Hinanap ang \"%1$s\" sa lahat</string> <string name="action_global_search_query">Hinanap ang \"%1$s\" sa lahat</string>
@ -388,7 +388,7 @@
<string name="pinned_sources">Naka-pin</string> <string name="pinned_sources">Naka-pin</string>
<string name="last_used_source">Huling ginamit</string> <string name="last_used_source">Huling ginamit</string>
<string name="other_source">Iba pa</string> <string name="other_source">Iba pa</string>
<string name="local_source">Lokal na Source</string> <string name="local_source">Lokal na source</string>
<string name="no_results_found">Walang nakitang resulta</string> <string name="no_results_found">Walang nakitang resulta</string>
<string name="no_more_results">Wala na\'ng resulta</string> <string name="no_more_results">Wala na\'ng resulta</string>
<string name="tabs_header">Mga Tab</string> <string name="tabs_header">Mga Tab</string>
@ -453,7 +453,7 @@
<item quantity="one">%d tracker</item> <item quantity="one">%d tracker</item>
<item quantity="other">%d na mga tracker</item> <item quantity="other">%d na mga tracker</item>
</plurals> </plurals>
<string name="no_pinned_sources">Wala kang naka-pin na pinagkukunan</string> <string name="no_pinned_sources">Wala kang naka-pin na source</string>
<string name="channel_complete">Tapos na</string> <string name="channel_complete">Tapos na</string>
<string name="channel_errors">Mga error</string> <string name="channel_errors">Mga error</string>
<string name="channel_progress">Takbo</string> <string name="channel_progress">Takbo</string>
@ -482,11 +482,11 @@
<string name="pref_clear_history">Linisin ang nakaraan</string> <string name="pref_clear_history">Linisin ang nakaraan</string>
<string name="clear_history_completed">Nalinis na ang nakaraan</string> <string name="clear_history_completed">Nalinis na ang nakaraan</string>
<string name="clear_history_confirmation">Sigurado ka ba talaga\? Mawawala ang buong nakaraan.</string> <string name="clear_history_confirmation">Sigurado ka ba talaga\? Mawawala ang buong nakaraan.</string>
<string name="migration_help_guide">Gabay sa Paglipat ng Source</string> <string name="migration_help_guide">Gabay sa Paglipat ng source</string>
<string name="spen_next_page">Abante</string> <string name="spen_next_page">Abante</string>
<string name="spen_previous_page">Balik</string> <string name="spen_previous_page">Balik</string>
<string name="file_picker_error">Walang nakitang app para makapili</string> <string name="file_picker_error">Walang nakitang app para makapili</string>
<string name="pref_show_nsfw_source">Ipakita sa mga source at extension</string> <string name="pref_show_nsfw_source">Ipakita sa mga listahan ng source at extension</string>
<string name="pref_category_nsfw_content">Mga source na NSFW (18+)</string> <string name="pref_category_nsfw_content">Mga source na NSFW (18+)</string>
<string name="myanimelist_relogin">Mag-login muli po sa MAL</string> <string name="myanimelist_relogin">Mag-login muli po sa MAL</string>
<string name="track_finished_reading_date">Natapos basahin</string> <string name="track_finished_reading_date">Natapos basahin</string>
@ -504,7 +504,7 @@
<string name="action_filter_tracked">Sinundan</string> <string name="action_filter_tracked">Sinundan</string>
<string name="right_and_left_nav">Kaliwa at Kanan</string> <string name="right_and_left_nav">Kaliwa at Kanan</string>
<string name="pref_dual_page_split">Hatiin ang mga malalapad na pahina</string> <string name="pref_dual_page_split">Hatiin ang mga malalapad na pahina</string>
<string name="action_display_show_number_of_items">Ipakita ang dami</string> <string name="action_display_show_number_of_items">Ipakita ang bilang ng mga item</string>
<string name="pref_dual_page_invert_summary">Kung sakaling hindi sumasakto sa direksyon ng pagbabasa ang paghahati sa malalapad na pahina</string> <string name="pref_dual_page_invert_summary">Kung sakaling hindi sumasakto sa direksyon ng pagbabasa ang paghahati sa malalapad na pahina</string>
<string name="pref_dual_page_invert">Baligtarin ang paghahati sa pahina</string> <string name="pref_dual_page_invert">Baligtarin ang paghahati sa pahina</string>
<string name="backup_restore_content_full">Ire-restore ang mga datos mula sa backup file. <string name="backup_restore_content_full">Ire-restore ang mga datos mula sa backup file.
@ -535,8 +535,8 @@
<string name="rotation_type">Pag-ikot</string> <string name="rotation_type">Pag-ikot</string>
<string name="pref_grayscale">Maabo</string> <string name="pref_grayscale">Maabo</string>
<string name="notification_incognito_text">Isara ang incognito</string> <string name="notification_incognito_text">Isara ang incognito</string>
<string name="automatic_background">Kusa</string> <string name="automatic_background">Awto</string>
<string name="cancel_all_for_series">Ikansela lahat para sa seryeng ito</string> <string name="cancel_all_for_series">Kanselahin lahat para sa seryeng ito</string>
<string name="local_filter_order_by">Ayusin ayon sa</string> <string name="local_filter_order_by">Ayusin ayon sa</string>
<string name="restrictions">Restriksyon: %s</string> <string name="restrictions">Restriksyon: %s</string>
<string name="error_no_match">Walang nahanap na kapares</string> <string name="error_no_match">Walang nahanap na kapares</string>
@ -608,7 +608,7 @@
<string name="download_queue_size_warning">Babala: maaaring humantong sa pagbagal at/o pagharang ng mga source sa Tachiyomi ang mga malalaking maramihang pag-download. I-tap para matuto pa.</string> <string name="download_queue_size_warning">Babala: maaaring humantong sa pagbagal at/o pagharang ng mga source sa Tachiyomi ang mga malalaking maramihang pag-download. I-tap para matuto pa.</string>
<string name="channel_app_updates">Mga update sa app</string> <string name="channel_app_updates">Mga update sa app</string>
<string name="ext_update_all">I-update lahat</string> <string name="ext_update_all">I-update lahat</string>
<string name="clear_database_source_item_count">%1$d na entry sa database na wala sa Aklatan</string> <string name="clear_database_source_item_count">%1$d na entry sa database na wala sa aklatan</string>
<string name="pref_auto_clear_chapter_cache">Linisin ang cache ng kabanata sa paglulunsad ng app</string> <string name="pref_auto_clear_chapter_cache">Linisin ang cache ng kabanata sa paglulunsad ng app</string>
<string name="database_clean">Walang malilinis</string> <string name="database_clean">Walang malilinis</string>
<string name="extension_api_error">Bigong makuha ang listahan ng mga extension</string> <string name="extension_api_error">Bigong makuha ang listahan ng mga extension</string>
@ -780,7 +780,7 @@
<string name="action_filter_interval_custom">Ipasadya ang fetch interval</string> <string name="action_filter_interval_custom">Ipasadya ang fetch interval</string>
<string name="action_filter_interval_late">Huling 10+ pagsusuri</string> <string name="action_filter_interval_late">Huling 10+ pagsusuri</string>
<string name="action_sort_next_updated">Susunod na inaasahang update</string> <string name="action_sort_next_updated">Susunod na inaasahang update</string>
<string name="action_filter_interval_dropped">Nawala\? or Nahulog\? (depending on the context, \"Nahulog\" means dropped or dropped something, and \"Nawala\" means Gone/Vanished) Nahuling 20+ at 2 buwan</string> <string name="action_filter_interval_dropped">Itinigil\? Huli ng 20+ at 2 buwan</string>
<string name="action_filter_interval_passed">Lumipas ang check period</string> <string name="action_filter_interval_passed">Lumipas ang check period</string>
<string name="action_filter_interval_long">Kunin kada buwan (kada ika-28 na araw)</string> <string name="action_filter_interval_long">Kunin kada buwan (kada ika-28 na araw)</string>
<plurals name="day"> <plurals name="day">
@ -816,7 +816,7 @@
<string name="action_sort_category">Mag-ayos ng kategorya</string> <string name="action_sort_category">Mag-ayos ng kategorya</string>
<string name="notification_updating_progress">Nag-a-update ang aklatan... (%s)</string> <string name="notification_updating_progress">Nag-a-update ang aklatan... (%s)</string>
<string name="sort_category_confirmation">Gusto mo bang mag-ayos ng kategorya ayon sa alpabeto\?</string> <string name="sort_category_confirmation">Gusto mo bang mag-ayos ng kategorya ayon sa alpabeto\?</string>
<string name="source_settings">Mga setting ng pinagmula</string> <string name="source_settings">Mga setting ng source</string>
<string name="app_settings">Mga setting ng app</string> <string name="app_settings">Mga setting ng app</string>
<string name="file_null_uri_error">Ang file picker ay nabigo na ibalik ang file sa app</string> <string name="file_null_uri_error">Ang file picker ay nabigo na ibalik ang file sa app</string>
<string name="label_data_storage">Data at storage</string> <string name="label_data_storage">Data at storage</string>
@ -825,4 +825,11 @@
<string name="relative_time_span_never">Hindi kailanman</string> <string name="relative_time_span_never">Hindi kailanman</string>
<string name="last_auto_backup_info">Huling awtomatikong na-back up: %s</string> <string name="last_auto_backup_info">Huling awtomatikong na-back up: %s</string>
<string name="pref_storage_usage">Paggamit ng storage</string> <string name="pref_storage_usage">Paggamit ng storage</string>
<string name="action_sort_tracker_score">Iskor sa tracker</string>
<string name="action_apply">Gamitin</string>
<string name="action_revert_to_default">Ibalik sa default</string>
<string name="no_scanlators_found">Walang scanlator ang nahanap</string>
<string name="scanlator">Scanlator</string>
<string name="exclude_scanlators">Ibukod ang mga scanlator</string>
<string name="action_create">Lumikha</string>
</resources> </resources>

View File

@ -544,7 +544,7 @@
<string name="notification_incognito_text">Deaktiviraj anonimni modus</string> <string name="notification_incognito_text">Deaktiviraj anonimni modus</string>
<string name="rotation_type">Okretanje</string> <string name="rotation_type">Okretanje</string>
<string name="automatic_background">Automatski</string> <string name="automatic_background">Automatski</string>
<string name="pref_create_folder_per_manga_summary">Stvara mape prema naslovu unosa</string> <string name="pref_create_folder_per_manga_summary">Stvara mape na osnovi naslova unosa</string>
<string name="pref_create_folder_per_manga">Spremi stranice u zasebne mape</string> <string name="pref_create_folder_per_manga">Spremi stranice u zasebne mape</string>
<string name="pref_reader_actions">Radnje</string> <string name="pref_reader_actions">Radnje</string>
<string name="cancel_all_for_series">Prekini sve za ovu seriju</string> <string name="cancel_all_for_series">Prekini sve za ovu seriju</string>
@ -832,7 +832,7 @@
<string name="action_sort_category">Razvrstaj kategorije</string> <string name="action_sort_category">Razvrstaj kategorije</string>
<string name="notification_updating_progress">Aktualiziranje biblioteke … (%s)</string> <string name="notification_updating_progress">Aktualiziranje biblioteke … (%s)</string>
<string name="sort_category_confirmation">Želiš li razvrstati kategorije po abecedi\?</string> <string name="sort_category_confirmation">Želiš li razvrstati kategorije po abecedi\?</string>
<string name="file_null_uri_error">Program za biranje datoteka nije uspio vratiti datoteku u aplikaciju</string> <string name="file_null_uri_error">Nije odabrana nijedna datoteka</string>
<string name="source_settings">Postavke izvora</string> <string name="source_settings">Postavke izvora</string>
<string name="app_settings">Postavke aplikacije</string> <string name="app_settings">Postavke aplikacije</string>
<string name="label_data_storage">Podaci i spremište</string> <string name="label_data_storage">Podaci i spremište</string>
@ -840,4 +840,12 @@
<string name="pref_flash_page_summ">Smanjuje artefakte na ekranima s e-tintom</string> <string name="pref_flash_page_summ">Smanjuje artefakte na ekranima s e-tintom</string>
<string name="last_auto_backup_info">Zadnja automatska sigurnosna kopija: %s</string> <string name="last_auto_backup_info">Zadnja automatska sigurnosna kopija: %s</string>
<string name="pref_flash_page">Zabljesni prilikom mijenjanja stranice</string> <string name="pref_flash_page">Zabljesni prilikom mijenjanja stranice</string>
<string name="action_create">Stvori</string>
<string name="action_apply">Primijeni</string>
<string name="action_revert_to_default">Obnovi standardne vrijednosti</string>
<string name="no_scanlators_found">Nije pronađen nijedan amaterski prevoditelj</string>
<string name="scanlator">Amaterski prevoditelj</string>
<string name="pref_storage_usage">Korištenje memorije</string>
<string name="action_sort_tracker_score">Rezultat tragača</string>
<string name="exclude_scanlators">Isključi amaterske prevoditelje</string>
</resources> </resources>

View File

@ -135,8 +135,8 @@
<string name="pref_restore_backup">Pulihkan cadangan</string> <string name="pref_restore_backup">Pulihkan cadangan</string>
<string name="pref_restore_backup_summ">Pulihkan isi pustaka dari berkas cadangan</string> <string name="pref_restore_backup_summ">Pulihkan isi pustaka dari berkas cadangan</string>
<string name="pref_backup_directory">Tempat pencadangan</string> <string name="pref_backup_directory">Tempat pencadangan</string>
<string name="pref_backup_interval">Frekuensi cadangan dibuat</string> <string name="pref_backup_interval">Frekuensi pencadangan otomatis</string>
<string name="pref_backup_slots">Jumlah maksimum cadangan</string> <string name="pref_backup_slots">Jumlah maksimum pencadangan otomatis</string>
<string name="backup_created">Cadangan dibuat</string> <string name="backup_created">Cadangan dibuat</string>
<string name="restore_completed">Pemulihan selesai</string> <string name="restore_completed">Pemulihan selesai</string>
<string name="backup_choice">Apa saja yang ingin Anda cadangkan\?</string> <string name="backup_choice">Apa saja yang ingin Anda cadangkan\?</string>
@ -499,8 +499,8 @@
<string name="nav_zone_next">Lanjut</string> <string name="nav_zone_next">Lanjut</string>
<string name="nav_zone_prev">Sblm</string> <string name="nav_zone_prev">Sblm</string>
<string name="automatic_background">Otomatis</string> <string name="automatic_background">Otomatis</string>
<string name="pref_create_folder_per_manga">Simpan halaman di folder terpisah</string> <string name="pref_create_folder_per_manga">Menyimpan halaman ke dalam folder terpisah</string>
<string name="pref_create_folder_per_manga_summary">Membuat folder sesuai dengan judul entri</string> <string name="pref_create_folder_per_manga_summary">Membuat folder menurut judul entri</string>
<string name="exclude">Kecuali: %s</string> <string name="exclude">Kecuali: %s</string>
<string name="include">Termasuk: %s</string> <string name="include">Termasuk: %s</string>
<string name="pref_dual_page_split">Membagi halaman lebar</string> <string name="pref_dual_page_split">Membagi halaman lebar</string>
@ -692,7 +692,7 @@
<string name="pref_security_summary">Kunci aplikasi, layar aman</string> <string name="pref_security_summary">Kunci aplikasi, layar aman</string>
<string name="pref_appearance_summary">Tema, format tanggal &amp; waktu</string> <string name="pref_appearance_summary">Tema, format tanggal &amp; waktu</string>
<string name="pref_library_summary">Kategori, pembaruan global, geser chapter</string> <string name="pref_library_summary">Kategori, pembaruan global, geser chapter</string>
<string name="pref_backup_summary">Pencadangan manual &amp; otomatis</string> <string name="pref_backup_summary">Pencadangan manual &amp; otomatis, ruang penyimpanan</string>
<string name="pref_advanced_summary">Buat log kerusakan, pengoptimalan baterai</string> <string name="pref_advanced_summary">Buat log kerusakan, pengoptimalan baterai</string>
<string name="crash_screen_title">Aduh!</string> <string name="crash_screen_title">Aduh!</string>
<string name="crash_screen_restart_application">Mulai ulang aplikasi</string> <string name="crash_screen_restart_application">Mulai ulang aplikasi</string>
@ -800,7 +800,20 @@
<string name="action_sort_category">Mengurutkan kategori</string> <string name="action_sort_category">Mengurutkan kategori</string>
<string name="notification_updating_progress">Memperbarui pustaka... (%s)</string> <string name="notification_updating_progress">Memperbarui pustaka... (%s)</string>
<string name="sort_category_confirmation">Apakah Anda ingin mengurutkan kategori menurut abjad\?</string> <string name="sort_category_confirmation">Apakah Anda ingin mengurutkan kategori menurut abjad\?</string>
<string name="file_null_uri_error">Pemilih file gagal mengembalikan file ke aplikasi</string> <string name="file_null_uri_error">Tidak ada file yang dipilih</string>
<string name="source_settings">Pengaturan sumber</string> <string name="source_settings">Pengaturan sumber</string>
<string name="app_settings">Pengaturan aplikasi</string> <string name="app_settings">Pengaturan aplikasi</string>
<string name="action_create">Buat</string>
<string name="relative_time_span_never">Tidak pernah</string>
<string name="pref_flash_page_summ">Mengurangi ghosting pada tampilan e-ink</string>
<string name="action_apply">Terapkan</string>
<string name="action_revert_to_default">Kembalikan ke default</string>
<string name="last_auto_backup_info">Terakhir dicadangkan secara otomatis: %s</string>
<string name="no_scanlators_found">Tidak ditemukan pemindai</string>
<string name="scanlator">Pemindai</string>
<string name="pref_flash_page">Berkedip putih pada perubahan halaman</string>
<string name="pref_storage_usage">Penggunaan penyimpanan</string>
<string name="action_sort_tracker_score">Skor pelacak</string>
<string name="label_data_storage">Data dan penyimpanan</string>
<string name="exclude_scanlators">Kecualikan pemindai</string>
</resources> </resources>

View File

@ -802,11 +802,18 @@
<string name="sort_category_confirmation">カテゴリをアルファベット順で並べ替えますか?</string> <string name="sort_category_confirmation">カテゴリをアルファベット順で並べ替えますか?</string>
<string name="source_settings">ソース設定</string> <string name="source_settings">ソース設定</string>
<string name="app_settings">アプリ設定</string> <string name="app_settings">アプリ設定</string>
<string name="file_null_uri_error">ファイルピッカーはアプリにファイルを返せませんでした</string> <string name="file_null_uri_error">選択したファイルがありません</string>
<string name="relative_time_span_never">なし</string> <string name="relative_time_span_never">なし</string>
<string name="pref_flash_page_summ">Eインク画面の焼き付きを軽減</string> <string name="pref_flash_page_summ">Eインク画面の焼き付きを軽減</string>
<string name="last_auto_backup_info">前回の自動バックアップ: %s</string> <string name="last_auto_backup_info">前回の自動バックアップ: %s</string>
<string name="pref_flash_page">ページめくりの時、画面を点滅させる</string> <string name="pref_flash_page">ページめくりの時、画面を点滅させる</string>
<string name="pref_storage_usage">使用中のストレージ領域</string> <string name="pref_storage_usage">使用中のストレージ領域</string>
<string name="label_data_storage">データとストレージ</string> <string name="label_data_storage">データとストレージ</string>
<string name="action_sort_tracker_score">トラッカーの評価点数</string>
<string name="action_create">作成</string>
<string name="action_apply">適用</string>
<string name="action_revert_to_default">デフォルトに戻す</string>
<string name="no_scanlators_found">スキャンレーターが見つかりませんでした</string>
<string name="scanlator">スキャンレーター</string>
<string name="exclude_scanlators">スキャンレーターを除外</string>
</resources> </resources>

View File

@ -834,8 +834,18 @@
<string name="source_settings">Configurações das fontes</string> <string name="source_settings">Configurações das fontes</string>
<string name="action_sort_category">Ordenar as categorias</string> <string name="action_sort_category">Ordenar as categorias</string>
<string name="sort_category_confirmation">Você deseja ordenar as categorias alfabeticamente\?</string> <string name="sort_category_confirmation">Você deseja ordenar as categorias alfabeticamente\?</string>
<string name="file_null_uri_error">O seletor de arquivos não retornou o arquivo para o aplicativo</string> <string name="file_null_uri_error">Nenhum arquivo selecionado</string>
<string name="label_data_storage">Dados e armazenamento</string> <string name="label_data_storage">Dados e armazenamento</string>
<string name="pref_flash_page_summ">Reduz o efeito fantasma em telas e-ink</string> <string name="pref_flash_page_summ">Reduz o efeito fantasma em telas e-ink</string>
<string name="pref_flash_page">Flash branco ao mudar de página</string> <string name="pref_flash_page">Flash branco ao mudar de página</string>
<string name="action_sort_tracker_score">Avaliação no monitorador</string>
<string name="relative_time_span_never">Nunca</string>
<string name="last_auto_backup_info">Último backup automático feito em: %s</string>
<string name="pref_storage_usage">Uso de armazenamento</string>
<string name="action_apply">Aplicar</string>
<string name="action_revert_to_default">Reverter para o padrão</string>
<string name="no_scanlators_found">Nenhum scanlator encontrado</string>
<string name="scanlator">Scanlator</string>
<string name="exclude_scanlators">Excluir scanlators</string>
<string name="action_create">Criar</string>
</resources> </resources>

View File

@ -850,11 +850,18 @@
<string name="notification_updating_progress">Обновление библиотеки... (%s)</string> <string name="notification_updating_progress">Обновление библиотеки... (%s)</string>
<string name="action_sort_category">Сортировать категории</string> <string name="action_sort_category">Сортировать категории</string>
<string name="sort_category_confirmation">Хотите ли вы сортировать категории по алфавиту\?</string> <string name="sort_category_confirmation">Хотите ли вы сортировать категории по алфавиту\?</string>
<string name="file_null_uri_error">Приложению для выбора файлов не удалось вернуть путь файла в Tachiyomi</string> <string name="file_null_uri_error">Файл не выбран</string>
<string name="label_data_storage">Данные и хранение</string> <string name="label_data_storage">Данные и хранение</string>
<string name="relative_time_span_never">Никогда</string> <string name="relative_time_span_never">Никогда</string>
<string name="pref_flash_page_summ">Уменьшает артефакты у экранов e-ink</string> <string name="pref_flash_page_summ">Уменьшает артефакты у экранов e-ink</string>
<string name="last_auto_backup_info">Последнее автоматическое резервное копирование: %s</string> <string name="last_auto_backup_info">Последнее автоматическое резервное копирование: %s</string>
<string name="pref_flash_page">Мигать экраном при смене страницы</string> <string name="pref_flash_page">Мигать экраном при смене страницы</string>
<string name="pref_storage_usage">Использование хранилища</string> <string name="pref_storage_usage">Использование хранилища</string>
<string name="action_sort_tracker_score">Оценка сервиса отслеживания</string>
<string name="action_create">Создать</string>
<string name="action_apply">Применить</string>
<string name="action_revert_to_default">Сбросить настройки</string>
<string name="no_scanlators_found">Переводчики не найдены</string>
<string name="scanlator">Переводчик</string>
<string name="exclude_scanlators">Исключить переводчиков</string>
</resources> </resources>

View File

@ -301,8 +301,8 @@
<string name="l_nav">รูปตัว L</string> <string name="l_nav">รูปตัว L</string>
<string name="automatic_background">อัตโนมัติ</string> <string name="automatic_background">อัตโนมัติ</string>
<string name="gray_background">เทา</string> <string name="gray_background">เทา</string>
<string name="pref_create_folder_per_manga_summary">สร้างโฟลเดอร์ตามชื่อเรื่อง</string> <string name="pref_create_folder_per_manga_summary">สร้างโฟลเดอร์ตามชื่อเรื่องของรายการ</string>
<string name="pref_create_folder_per_manga">บันทึกหน้าลงในโฟลเดอร์ที่แยกต่างหาก</string> <string name="pref_create_folder_per_manga">บันทึกแต่ละหน้าลงในโฟลเดอร์ที่แยกต่างหาก</string>
<string name="pref_reader_actions">การกระทำ</string> <string name="pref_reader_actions">การกระทำ</string>
<string name="tapping_inverted_both">ทั้งสอง</string> <string name="tapping_inverted_both">ทั้งสอง</string>
<string name="tapping_inverted_vertical">แนวตั้ง</string> <string name="tapping_inverted_vertical">แนวตั้ง</string>
@ -564,7 +564,7 @@
<string name="enhanced_services">ตัวติดตามขั้นสูง</string> <string name="enhanced_services">ตัวติดตามขั้นสูง</string>
<string name="backup_info">ควรเก็บสำเนาของข้อมูลสำรองไว้ที่อื่นด้วยเช่นกัน การสำรองข้อมูลอาจมีข้อมูลที่ละเอียดอ่อนรวมถึงรหัสผ่านที่เก็บไว้ ควรระวังหากแบ่งปันสำเนา</string> <string name="backup_info">ควรเก็บสำเนาของข้อมูลสำรองไว้ที่อื่นด้วยเช่นกัน การสำรองข้อมูลอาจมีข้อมูลที่ละเอียดอ่อนรวมถึงรหัสผ่านที่เก็บไว้ ควรระวังหากแบ่งปันสำเนา</string>
<string name="pref_verbose_logging_summary">บันทึกบันทึกอย่างละเอียดไปยังบันทึกของระบบ (ลดประสิทธิภาพของแอป)</string> <string name="pref_verbose_logging_summary">บันทึกบันทึกอย่างละเอียดไปยังบันทึกของระบบ (ลดประสิทธิภาพของแอป)</string>
<string name="help_translate">ช่วยแปล</string> <string name="help_translate">แปลเป็นภาษาไทยโดย altqx</string>
<string name="local_invalid_format">รูปแบบตอนไม่ถูกต้อง</string> <string name="local_invalid_format">รูปแบบตอนไม่ถูกต้อง</string>
<string name="manga_cover">ปก</string> <string name="manga_cover">ปก</string>
<string name="unread">ยังไม่ได้อ่าน</string> <string name="unread">ยังไม่ได้อ่าน</string>
@ -802,11 +802,18 @@
<string name="sort_category_confirmation">ต้องการจัดเรียงหมวดหมู่ตามตัวอักษรหรือไม่\?</string> <string name="sort_category_confirmation">ต้องการจัดเรียงหมวดหมู่ตามตัวอักษรหรือไม่\?</string>
<string name="source_settings">การตั้งค่าแหล่งที่มา</string> <string name="source_settings">การตั้งค่าแหล่งที่มา</string>
<string name="app_settings">การตั้งค่าแอป</string> <string name="app_settings">การตั้งค่าแอป</string>
<string name="file_null_uri_error">เครื่องมือเลือกไฟล์ไม่สามารถส่งต่อไฟล์ไปยังแอปได</string> <string name="file_null_uri_error">ไม่มีไฟล์ถูกเลือกไว</string>
<string name="relative_time_span_never">ไม่เลย</string> <string name="relative_time_span_never">ไม่เลย</string>
<string name="pref_flash_page_summ">ลดภาพซ้อนบนจอแสดงผล E-Ink</string> <string name="pref_flash_page_summ">ลดภาพซ้อนบนจอแสดงผล E-Ink</string>
<string name="last_auto_backup_info">สำรองข้อมูลอัตโนมัติครั้งล่าสุด: %s</string> <string name="last_auto_backup_info">สำรองข้อมูลอัตโนมัติครั้งล่าสุด: %s</string>
<string name="pref_flash_page">แฟลชสีขาวเมื่อเปลี่ยนหน้า</string> <string name="pref_flash_page">แฟลชสีขาวเมื่อเปลี่ยนหน้า</string>
<string name="pref_storage_usage">การใช้พื้นที่เก็บข้อมูล</string> <string name="pref_storage_usage">การใช้พื้นที่เก็บข้อมูล</string>
<string name="label_data_storage">ข้อมูลและการจัดเก็บข้อมูล</string> <string name="label_data_storage">ข้อมูลและการจัดเก็บข้อมูล</string>
<string name="action_create">สร้าง</string>
<string name="action_apply">นำไปใช้</string>
<string name="action_revert_to_default">ย้อนกลับไปเป็นค่าเริ่มต้น</string>
<string name="no_scanlators_found">ไม่พบผู้แปล</string>
<string name="scanlator">ผู้แปล</string>
<string name="action_sort_tracker_score">คะแนนจากตัวติดตาม</string>
<string name="exclude_scanlators">ผู้แปลที่เว้นไว้</string>
</resources> </resources>

View File

@ -162,8 +162,8 @@
<string name="pref_restore_backup">Yedeği geri yükle</string> <string name="pref_restore_backup">Yedeği geri yükle</string>
<string name="pref_restore_backup_summ">Kitaplığı yedek dosyasından geri yükle</string> <string name="pref_restore_backup_summ">Kitaplığı yedek dosyasından geri yükle</string>
<string name="pref_backup_directory">Yedekleme konumu</string> <string name="pref_backup_directory">Yedekleme konumu</string>
<string name="pref_backup_interval">Yedekleme sıklığı</string> <string name="pref_backup_interval">Kendiliğinden yedekleme sıklığı</string>
<string name="pref_backup_slots">Maksimum yedek</string> <string name="pref_backup_slots">En fazla kendiliğinden yedek</string>
<string name="backup_created">Yedek oluşturuldu</string> <string name="backup_created">Yedek oluşturuldu</string>
<string name="restore_completed">Geri yükleme tamamlandı</string> <string name="restore_completed">Geri yükleme tamamlandı</string>
<string name="backup_choice">Neyi yedeklemek istiyorsunuz?</string> <string name="backup_choice">Neyi yedeklemek istiyorsunuz?</string>
@ -375,7 +375,7 @@
<string name="manga_info_collapse">Daha az</string> <string name="manga_info_collapse">Daha az</string>
<string name="manga_info_expand">Daha fazla</string> <string name="manga_info_expand">Daha fazla</string>
<string name="website">Web sitesi</string> <string name="website">Web sitesi</string>
<string name="information_webview_required">Web Görünümü, uygulamanın işlevselliği için gereklidir</string> <string name="information_webview_required">WebView, uygulamanın işlevselliği için gereklidir</string>
<string name="licenses">ık kaynak lisansları</string> <string name="licenses">ık kaynak lisansları</string>
<string name="label_downloaded_only">Yalnızca indirilen</string> <string name="label_downloaded_only">Yalnızca indirilen</string>
<string name="recent_manga_time">Böl. %1$s - %2$s</string> <string name="recent_manga_time">Böl. %1$s - %2$s</string>
@ -434,7 +434,7 @@
<item quantity="other">%1$s bölüm</item> <item quantity="other">%1$s bölüm</item>
</plurals> </plurals>
<string name="requires_app_restart">Etkili olması için uygulamanın yeniden başlatılmasını gerektirir</string> <string name="requires_app_restart">Etkili olması için uygulamanın yeniden başlatılmasını gerektirir</string>
<string name="label_network"></string> <string name="label_network"> oluşturma</string>
<string name="tapping_inverted_none">Yok</string> <string name="tapping_inverted_none">Yok</string>
<string name="pref_read_with_tapping_inverted">Dokunma bölgelerini ters çevir</string> <string name="pref_read_with_tapping_inverted">Dokunma bölgelerini ters çevir</string>
<string name="tapping_inverted_both">İkisi de</string> <string name="tapping_inverted_both">İkisi de</string>
@ -697,7 +697,7 @@
<string name="missing_storage_permission">Depolama izinleri verilmedi</string> <string name="missing_storage_permission">Depolama izinleri verilmedi</string>
<string name="skipped_reason_not_always_update">Dizi güncelleme gerektirmediği için atlandı</string> <string name="skipped_reason_not_always_update">Dizi güncelleme gerektirmediği için atlandı</string>
<string name="action_search_hint">Ara…</string> <string name="action_search_hint">Ara…</string>
<string name="pref_backup_summary">Elle ve kendiliğinden yedeklemeler</string> <string name="pref_backup_summary">Elle ve kendiliğinden yedeklemeler, depolama alanı</string>
<string name="pref_security_summary">Uygulama kilidi, güvenli ekran</string> <string name="pref_security_summary">Uygulama kilidi, güvenli ekran</string>
<string name="pref_advanced_summary">Çökme günlükleri dökümü, pil iyileştirmeleri</string> <string name="pref_advanced_summary">Çökme günlükleri dökümü, pil iyileştirmeleri</string>
<string name="pref_library_summary">Kategoriler, genel güncelleme, bölüm kaydırma</string> <string name="pref_library_summary">Kategoriler, genel güncelleme, bölüm kaydırma</string>
@ -806,7 +806,7 @@
<string name="exception_unknown_host">%s verisine erişilemedi</string> <string name="exception_unknown_host">%s verisine erişilemedi</string>
<string name="track_activity_name">İzleyici girişi</string> <string name="track_activity_name">İzleyici girişi</string>
<string name="library_sync_complete">Kitaplık eşleşmesi tamamlandı</string> <string name="library_sync_complete">Kitaplık eşleşmesi tamamlandı</string>
<string name="exception_http">HTTP %d, siteyi Web Görünümünde denetle</string> <string name="exception_http">HTTP %d, siteyi WebView\'de denetle</string>
<string name="exception_offline">Genel ağ bağlantısı yok</string> <string name="exception_offline">Genel ağ bağlantısı yok</string>
<string name="syncing_library">Kitaplık eşleştiriliyor</string> <string name="syncing_library">Kitaplık eşleştiriliyor</string>
<string name="unlock_app_title">Aç: %s</string> <string name="unlock_app_title">Aç: %s</string>
@ -819,4 +819,16 @@
<string name="app_settings">Uygulama ayarları</string> <string name="app_settings">Uygulama ayarları</string>
<string name="pref_relative_format">Göreli zaman damgaları</string> <string name="pref_relative_format">Göreli zaman damgaları</string>
<string name="pref_relative_format_summary">\"%1$s\" yerine \"%2$s</string> <string name="pref_relative_format_summary">\"%1$s\" yerine \"%2$s</string>
<string name="relative_time_span_never">Asla</string>
<string name="pref_flash_page_summ">E-ink görüntülerinde gölgelenmeyi azaltır</string>
<string name="action_apply">Uygula</string>
<string name="action_revert_to_default">Varsayılana dön</string>
<string name="last_auto_backup_info">En son şu tarihte kendi yedekledi: %s</string>
<string name="no_scanlators_found">Tareviriler bulunamadı</string>
<string name="scanlator">Tareviri</string>
<string name="pref_flash_page">Sayfa değişiminde beyaz ışık çak</string>
<string name="pref_storage_usage">Depolama kullanımı</string>
<string name="action_sort_tracker_score">İzleyici notu</string>
<string name="label_data_storage">Veri ve depolama</string>
<string name="exclude_scanlators">Tarevirileri hariç tut</string>
</resources> </resources>

View File

@ -846,4 +846,11 @@
<string name="pref_relative_format_summary">\"%1$s\" замість \"%2$s\"</string> <string name="pref_relative_format_summary">\"%1$s\" замість \"%2$s\"</string>
<string name="source_settings">Налаштування джерела</string> <string name="source_settings">Налаштування джерела</string>
<string name="app_settings">Налаштування застосунку</string> <string name="app_settings">Налаштування застосунку</string>
<string name="action_apply">Застосувати</string>
<string name="action_revert_to_default">Повернути за замовчуванням</string>
<string name="action_sort_category">Сортувати категорії</string>
<string name="scanlator">Сканлейтор</string>
<string name="action_sort_tracker_score">Оцінка трекера</string>
<string name="label_data_storage">Дані та сховище</string>
<string name="sort_category_confirmation">Ви хочете сортувати категорії алфавітно?</string>
</resources> </resources>

View File

@ -156,14 +156,14 @@
<string name="fourth_to_last">倒数第四已读章节</string> <string name="fourth_to_last">倒数第四已读章节</string>
<string name="fifth_to_last">倒数第五已读章节</string> <string name="fifth_to_last">倒数第五已读章节</string>
<string name="pref_download_new">自动下载新章节</string> <string name="pref_download_new">自动下载新章节</string>
<string name="services">平台</string> <string name="services">记录平台</string>
<string name="pref_create_backup">创建备份</string> <string name="pref_create_backup">创建备份</string>
<string name="pref_create_backup_summ">可用于还原当前书架数据</string> <string name="pref_create_backup_summ">可用于还原当前书架数据</string>
<string name="pref_restore_backup">还原备份</string> <string name="pref_restore_backup">还原备份</string>
<string name="pref_restore_backup_summ">从备份文件中还原</string> <string name="pref_restore_backup_summ">从备份文件中还原</string>
<string name="pref_backup_directory">备份路径</string> <string name="pref_backup_directory">备份路径</string>
<string name="pref_backup_interval">备份频率</string> <string name="pref_backup_interval">自动备份频率</string>
<string name="pref_backup_slots">最大备份数</string> <string name="pref_backup_slots">最大自动备份数</string>
<string name="backup_created">已创建备份</string> <string name="backup_created">已创建备份</string>
<string name="restore_completed">还原完毕</string> <string name="restore_completed">还原完毕</string>
<string name="backup_choice">需要备份什么?</string> <string name="backup_choice">需要备份什么?</string>
@ -365,7 +365,7 @@
<string name="vertical_plus_viewer">条漫(页间有空隙)</string> <string name="vertical_plus_viewer">条漫(页间有空隙)</string>
<string name="action_select_inverse">反选</string> <string name="action_select_inverse">反选</string>
<string name="add_tracking">添加进度记录</string> <string name="add_tracking">添加进度记录</string>
<string name="information_webview_required">Tachiyomi 依赖于 WebView</string> <string name="information_webview_required">app依赖WebView实现其功能</string>
<string name="manga_info_collapse">收起</string> <string name="manga_info_collapse">收起</string>
<string name="manga_info_expand">展开</string> <string name="manga_info_expand">展开</string>
<string name="licenses">开源许可证</string> <string name="licenses">开源许可证</string>
@ -556,7 +556,7 @@
<string name="theme_greenapple">青苹果</string> <string name="theme_greenapple">青苹果</string>
<string name="pref_app_theme">应用主题</string> <string name="pref_app_theme">应用主题</string>
<string name="enhanced_tracking_info">为特定图源提供增强功能。作品在添加到书架时会自动同步进度。</string> <string name="enhanced_tracking_info">为特定图源提供增强功能。作品在添加到书架时会自动同步进度。</string>
<string name="enhanced_services">增强平台</string> <string name="enhanced_services">增强型记录平台</string>
<string name="theme_monet">动态</string> <string name="theme_monet">动态</string>
<string name="label_background_activity">后台活动</string> <string name="label_background_activity">后台活动</string>
<string name="pref_lowest">最低</string> <string name="pref_lowest">最低</string>
@ -589,7 +589,7 @@
<string name="pref_verbose_logging">详细日志记录</string> <string name="pref_verbose_logging">详细日志记录</string>
<string name="label_warning">警告</string> <string name="label_warning">警告</string>
<string name="action_display_language_badge">语言</string> <string name="action_display_language_badge">语言</string>
<string name="backup_info">你应该将备份数据保存到多个地方。</string> <string name="backup_info">你应该将备份数据保存到多个地方。备份可能存有包括所有已存储密码在内的敏感数据;请谨慎分享。</string>
<string name="notification_size_warning">大量更新会损害图源,并可能导致更新变慢、耗电增加。点击了解详情。</string> <string name="notification_size_warning">大量更新会损害图源,并可能导致更新变慢、耗电增加。点击了解详情。</string>
<string name="connected_to_wifi">仅连接至 Wi-Fi 时</string> <string name="connected_to_wifi">仅连接至 Wi-Fi 时</string>
<string name="update_72hour">每 3 天</string> <string name="update_72hour">每 3 天</string>
@ -769,7 +769,7 @@
<string name="delete_downloaded">删除已下载章节</string> <string name="delete_downloaded">删除已下载章节</string>
<string name="action_filter_interval_custom">自定义更新间隔</string> <string name="action_filter_interval_custom">自定义更新间隔</string>
<string name="action_set_interval">设定间隔</string> <string name="action_set_interval">设定间隔</string>
<string name="action_filter_interval_dropped">放弃\? 延迟 20+ 和 2个月</string> <string name="action_filter_interval_dropped">放弃延迟 20+ 和 2个月</string>
<string name="action_filter_interval_passed">通过检查期</string> <string name="action_filter_interval_passed">通过检查期</string>
<string name="action_sort_next_updated">下次预期更新</string> <string name="action_sort_next_updated">下次预期更新</string>
<string name="action_filter_interval_long">每月更新28天</string> <string name="action_filter_interval_long">每月更新28天</string>
@ -781,7 +781,7 @@
<string name="manga_display_interval_title">估计每个</string> <string name="manga_display_interval_title">估计每个</string>
<string name="manga_display_modified_interval_title">设定更新为每</string> <string name="manga_display_modified_interval_title">设定更新为每</string>
<string name="manga_modify_calculated_interval_title">自定义间隔</string> <string name="manga_modify_calculated_interval_title">自定义间隔</string>
<string name="skipped_reason_not_in_release_period">跳过、今天预期没有新发布</string> <string name="skipped_reason_not_in_release_period">跳过,因为预计今天没有新发布</string>
<string name="has_results">有结果</string> <string name="has_results">有结果</string>
<string name="syncing_library">正在同步书架</string> <string name="syncing_library">正在同步书架</string>
<string name="library_sync_complete">书架同步完成</string> <string name="library_sync_complete">书架同步完成</string>
@ -800,7 +800,7 @@
<string name="action_move_to_bottom_all_for_series">将作品移到底部</string> <string name="action_move_to_bottom_all_for_series">将作品移到底部</string>
<string name="notification_updating_progress">书架更新中…(%s)</string> <string name="notification_updating_progress">书架更新中…(%s)</string>
<string name="sort_category_confirmation">是否按字母顺序对分类进行排序?</string> <string name="sort_category_confirmation">是否按字母顺序对分类进行排序?</string>
<string name="file_null_uri_error">文件选择器无法将文件恢复至应用</string> <string name="file_null_uri_error">没有文件被选中</string>
<string name="pref_relative_format">相对时间戳</string> <string name="pref_relative_format">相对时间戳</string>
<string name="pref_relative_format_summary">以\"%1$s\" 表示 \"%2$s\"</string> <string name="pref_relative_format_summary">以\"%1$s\" 表示 \"%2$s\"</string>
<string name="relative_time_span_never">从不</string> <string name="relative_time_span_never">从不</string>
@ -809,4 +809,11 @@
<string name="pref_flash_page">切页时闪烁白屏</string> <string name="pref_flash_page">切页时闪烁白屏</string>
<string name="label_data_storage">数据与存储</string> <string name="label_data_storage">数据与存储</string>
<string name="pref_storage_usage">存储占用</string> <string name="pref_storage_usage">存储占用</string>
<string name="action_create">创建</string>
<string name="action_apply">应用</string>
<string name="action_revert_to_default">恢复默认</string>
<string name="no_scanlators_found">未找到扫译者</string>
<string name="scanlator">扫译者</string>
<string name="action_sort_tracker_score">记录平台评分</string>
<string name="exclude_scanlators">排除的扫译者</string>
</resources> </resources>

View File

@ -400,7 +400,7 @@
<item quantity="other">%d 個類別</item> <item quantity="other">%d 個類別</item>
</plurals> </plurals>
<string name="requires_app_restart">需要重新啟動應用程式以套用</string> <string name="requires_app_restart">需要重新啟動應用程式以套用</string>
<string name="label_network">網路設定</string> <string name="label_network">網路</string>
<string name="tapping_inverted_both">全部</string> <string name="tapping_inverted_both">全部</string>
<string name="tapping_inverted_vertical">垂直</string> <string name="tapping_inverted_vertical">垂直</string>
<string name="tapping_inverted_horizontal">水平</string> <string name="tapping_inverted_horizontal">水平</string>
@ -639,7 +639,7 @@
<string name="split_tall_images_summary">用以改善閱讀器效能</string> <string name="split_tall_images_summary">用以改善閱讀器效能</string>
<string name="download_notifier_split_page_path_not_found">找不到第 %d 頁的檔案路徑</string> <string name="download_notifier_split_page_path_not_found">找不到第 %d 頁的檔案路徑</string>
<string name="pref_reset_viewer_flags">重設個別閱讀器設定</string> <string name="pref_reset_viewer_flags">重設個別閱讀器設定</string>
<string name="pref_reset_viewer_flags_summary">將所有作品的閱讀模式和螢幕方向恢復為預設值</string> <string name="pref_reset_viewer_flags_summary">將所有作品的閱讀模式和螢幕方向還原為預設值</string>
<string name="pref_reset_viewer_flags_success">已重設所有閱讀器設定</string> <string name="pref_reset_viewer_flags_success">已重設所有閱讀器設定</string>
<string name="pref_reset_viewer_flags_error">無法重設閱讀器設定</string> <string name="pref_reset_viewer_flags_error">無法重設閱讀器設定</string>
<string name="empty_screen">呃…尷尬了</string> <string name="empty_screen">呃…尷尬了</string>
@ -802,11 +802,18 @@
<string name="notification_updating_progress">正在更新書櫃… (%s)</string> <string name="notification_updating_progress">正在更新書櫃… (%s)</string>
<string name="sort_category_confirmation">欲依照字母順序排列類別嗎?</string> <string name="sort_category_confirmation">欲依照字母順序排列類別嗎?</string>
<string name="source_settings">來源設定</string> <string name="source_settings">來源設定</string>
<string name="file_null_uri_error">無法將選定的檔案傳回給應用程式</string> <string name="file_null_uri_error">未選擇檔案</string>
<string name="relative_time_span_never">永不</string> <string name="relative_time_span_never">永不</string>
<string name="pref_flash_page_summ">減少電子墨水螢幕上的殘影</string> <string name="pref_flash_page_summ">減少電子墨水螢幕上的殘影</string>
<string name="last_auto_backup_info">最後一次自動備份:%s</string> <string name="last_auto_backup_info">最後一次自動備份:%s</string>
<string name="pref_flash_page">頁面轉換時閃白</string> <string name="pref_flash_page">頁面轉換時閃白</string>
<string name="label_data_storage">資料與儲存空間</string> <string name="label_data_storage">資料與儲存空間</string>
<string name="pref_storage_usage">儲存空間佔用</string> <string name="pref_storage_usage">儲存空間使用情形</string>
<string name="action_sort_tracker_score">歷程平台評分</string>
<string name="action_apply">套用</string>
<string name="action_revert_to_default">還原為預設值</string>
<string name="no_scanlators_found">沒有掃譯者</string>
<string name="scanlator">掃譯者</string>
<string name="exclude_scanlators">排除掃譯者</string>
<string name="action_create">建立</string>
</resources> </resources>

View File

@ -35,6 +35,9 @@ dependencies {
debugImplementation(compose.ui.tooling) debugImplementation(compose.ui.tooling)
implementation(compose.ui.tooling.preview) implementation(compose.ui.tooling.preview)
implementation(compose.ui.util) implementation(compose.ui.util)
lintChecks(compose.lintchecks)
implementation(kotlinx.immutables)
} }
tasks { tasks {

View File

@ -14,10 +14,10 @@ import androidx.compose.ui.unit.dp
@Composable @Composable
fun ActionButton( fun ActionButton(
modifier: Modifier = Modifier,
title: String, title: String,
icon: ImageVector, icon: ImageVector,
onClick: () -> Unit, onClick: () -> Unit,
modifier: Modifier = Modifier,
) { ) {
TextButton( TextButton(
modifier = modifier, modifier = modifier,

View File

@ -56,11 +56,11 @@ private val sheetAnimationSpec = tween<Float>(durationMillis = 350)
@Composable @Composable
fun AdaptiveSheet( fun AdaptiveSheet(
modifier: Modifier = Modifier,
isTabletUi: Boolean, isTabletUi: Boolean,
tonalElevation: Dp, tonalElevation: Dp,
enableSwipeDismiss: Boolean, enableSwipeDismiss: Boolean,
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
modifier: Modifier = Modifier,
content: @Composable () -> Unit, content: @Composable () -> Unit,
) { ) {
val density = LocalDensity.current val density = LocalDensity.current

View File

@ -36,13 +36,14 @@ fun BadgeGroup(
@Composable @Composable
fun Badge( fun Badge(
text: String, text: String,
modifier: Modifier = Modifier,
color: Color = MaterialTheme.colorScheme.secondary, color: Color = MaterialTheme.colorScheme.secondary,
textColor: Color = MaterialTheme.colorScheme.onSecondary, textColor: Color = MaterialTheme.colorScheme.onSecondary,
shape: Shape = RectangleShape, shape: Shape = RectangleShape,
) { ) {
Text( Text(
text = text, text = text,
modifier = Modifier modifier = modifier
.clip(shape) .clip(shape)
.background(color) .background(color)
.padding(horizontal = 3.dp, vertical = 1.dp), .padding(horizontal = 3.dp, vertical = 1.dp),
@ -56,6 +57,7 @@ fun Badge(
@Composable @Composable
fun Badge( fun Badge(
imageVector: ImageVector, imageVector: ImageVector,
modifier: Modifier = Modifier,
color: Color = MaterialTheme.colorScheme.secondary, color: Color = MaterialTheme.colorScheme.secondary,
iconColor: Color = MaterialTheme.colorScheme.onSecondary, iconColor: Color = MaterialTheme.colorScheme.onSecondary,
shape: Shape = RectangleShape, shape: Shape = RectangleShape,
@ -86,7 +88,7 @@ fun Badge(
Text( Text(
text = text, text = text,
inlineContent = inlineContent, inlineContent = inlineContent,
modifier = Modifier modifier = modifier
.clip(shape) .clip(shape)
.background(color) .background(color)
.padding(horizontal = 3.dp, vertical = 1.dp), .padding(horizontal = 3.dp, vertical = 1.dp),

View File

@ -23,7 +23,10 @@ import androidx.compose.ui.unit.dp
import tachiyomi.presentation.core.theme.header import tachiyomi.presentation.core.theme.header
@Composable @Composable
fun CollapsibleBox(heading: String, content: @Composable () -> Unit) { fun CollapsibleBox(
heading: String,
content: @Composable () -> Unit,
) {
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) }
Column { Column {

View File

@ -17,10 +17,10 @@ import androidx.compose.ui.unit.dp
@Composable @Composable
fun LabeledCheckbox( fun LabeledCheckbox(
modifier: Modifier = Modifier,
label: String, label: String,
checked: Boolean, checked: Boolean,
onCheckedChange: (Boolean) -> Unit, onCheckedChange: (Boolean) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true, enabled: Boolean = true,
) { ) {
Row( Row(

View File

@ -11,7 +11,12 @@ import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@Composable @Composable
fun LinkIcon(modifier: Modifier = Modifier, label: String, icon: ImageVector, url: String) { fun LinkIcon(
label: String,
icon: ImageVector,
url: String,
modifier: Modifier = Modifier,
) {
val uriHandler = LocalUriHandler.current val uriHandler = LocalUriHandler.current
IconButton( IconButton(
modifier = modifier.padding(4.dp), modifier = modifier.padding(4.dp),

View File

@ -9,7 +9,10 @@ import androidx.compose.ui.text.font.FontWeight
import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.padding
@Composable @Composable
fun ListGroupHeader(modifier: Modifier = Modifier, text: String) { fun ListGroupHeader(
text: String,
modifier: Modifier = Modifier,
) {
Text( Text(
text = text, text = text,
modifier = modifier modifier = modifier

View File

@ -156,11 +156,11 @@ fun RadioItem(label: String, selected: Boolean, onClick: () -> Unit) {
@Composable @Composable
fun SliderItem( fun SliderItem(
label: String, label: String,
min: Int = 0,
max: Int,
value: Int, value: Int,
valueText: String, valueText: String,
onChange: (Int) -> Unit, onChange: (Int) -> Unit,
max: Int,
min: Int = 0,
) { ) {
val haptic = LocalHapticFeedback.current val haptic = LocalHapticFeedback.current

View File

@ -17,10 +17,10 @@ import androidx.compose.ui.unit.dp
@Composable @Composable
fun TwoPanelBox( fun TwoPanelBox(
modifier: Modifier = Modifier,
contentWindowInsets: WindowInsets = WindowInsets(0),
startContent: @Composable BoxScope.() -> Unit, startContent: @Composable BoxScope.() -> Unit,
endContent: @Composable BoxScope.() -> Unit, endContent: @Composable BoxScope.() -> Unit,
modifier: Modifier = Modifier,
contentWindowInsets: WindowInsets = WindowInsets(0),
) { ) {
val direction = LocalLayoutDirection.current val direction = LocalLayoutDirection.current
val padding = contentWindowInsets.asPaddingValues() val padding = contentWindowInsets.asPaddingValues()

View File

@ -41,6 +41,7 @@ import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.drop
@ -54,9 +55,9 @@ import kotlin.math.absoluteValue
@Composable @Composable
fun WheelNumberPicker( fun WheelNumberPicker(
items: ImmutableList<Number>,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
startIndex: Int = 0, startIndex: Int = 0,
items: List<Number>,
size: DpSize = DpSize(128.dp, 128.dp), size: DpSize = DpSize(128.dp, 128.dp),
onSelectionChanged: (index: Int) -> Unit = {}, onSelectionChanged: (index: Int) -> Unit = {},
backgroundContent: (@Composable (size: DpSize) -> Unit)? = { backgroundContent: (@Composable (size: DpSize) -> Unit)? = {
@ -78,9 +79,9 @@ fun WheelNumberPicker(
@Composable @Composable
fun WheelTextPicker( fun WheelTextPicker(
items: ImmutableList<String>,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
startIndex: Int = 0, startIndex: Int = 0,
items: List<String>,
size: DpSize = DpSize(128.dp, 128.dp), size: DpSize = DpSize(128.dp, 128.dp),
onSelectionChanged: (index: Int) -> Unit = {}, onSelectionChanged: (index: Int) -> Unit = {},
backgroundContent: (@Composable (size: DpSize) -> Unit)? = { backgroundContent: (@Composable (size: DpSize) -> Unit)? = {
@ -101,9 +102,9 @@ fun WheelTextPicker(
@Composable @Composable
private fun <T> WheelPicker( private fun <T> WheelPicker(
items: ImmutableList<T>,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
startIndex: Int = 0, startIndex: Int = 0,
items: List<T>,
size: DpSize = DpSize(128.dp, 128.dp), size: DpSize = DpSize(128.dp, 128.dp),
onSelectionChanged: (index: Int) -> Unit = {}, onSelectionChanged: (index: Int) -> Unit = {},
manualInputType: KeyboardType? = null, manualInputType: KeyboardType? = null,

View File

@ -46,7 +46,10 @@ fun ExtendedFloatingActionButton(
contentColor: Color = contentColorFor(containerColor), contentColor: Color = contentColorFor(containerColor),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(), elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
) { ) {
val minWidth by animateDpAsState(if (expanded) ExtendedFabMinimumWidth else FabContainerWidth) val minWidth by animateDpAsState(
targetValue = if (expanded) ExtendedFabMinimumWidth else FabContainerWidth,
label = "minWidth",
)
FloatingActionButton( FloatingActionButton(
modifier = modifier.sizeIn(minWidth = minWidth), modifier = modifier.sizeIn(minWidth = minWidth),
onClick = onClick, onClick = onClick,
@ -56,8 +59,14 @@ fun ExtendedFloatingActionButton(
contentColor = contentColor, contentColor = contentColor,
elevation = elevation, elevation = elevation,
) { ) {
val startPadding by animateDpAsState(if (expanded) ExtendedFabIconSize / 2 else 0.dp) val startPadding by animateDpAsState(
val endPadding by animateDpAsState(if (expanded) ExtendedFabTextPadding else 0.dp) targetValue = if (expanded) ExtendedFabIconSize / 2 else 0.dp,
label = "startPadding",
)
val endPadding by animateDpAsState(
targetValue = if (expanded) ExtendedFabTextPadding else 0.dp,
label = "endPadding",
)
Row( Row(
modifier = Modifier.padding(start = startPadding, end = endPadding), modifier = Modifier.padding(start = startPadding, end = endPadding),

View File

@ -20,9 +20,9 @@ import androidx.compose.ui.unit.dp
fun IconToggleButton( fun IconToggleButton(
checked: Boolean, checked: Boolean,
onCheckedChange: (Boolean) -> Unit, onCheckedChange: (Boolean) -> Unit,
modifier: Modifier = Modifier,
imageVector: ImageVector, imageVector: ImageVector,
title: String, title: String,
modifier: Modifier = Modifier,
) { ) {
FilledIconToggleButton( FilledIconToggleButton(
checked = checked, checked = checked,

View File

@ -36,10 +36,12 @@ private fun Modifier.tabIndicatorOffset(
val currentTabWidth by animateDpAsState( val currentTabWidth by animateDpAsState(
targetValue = currentTabPosition.width, targetValue = currentTabPosition.width,
animationSpec = spring(stiffness = Spring.StiffnessMediumLow), animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
label = "currentTabWidth",
) )
val offset by animateDpAsState( val offset by animateDpAsState(
targetValue = currentTabPosition.left + (currentTabWidth * currentPageOffsetFraction), targetValue = currentTabPosition.left + (currentTabWidth * currentPageOffsetFraction),
animationSpec = spring(stiffness = Spring.StiffnessMediumLow), animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
label = "offset",
) )
Modifier Modifier
.offset { IntOffset(x = offset.roundToPx(), y = 0) } .offset { IntOffset(x = offset.roundToPx(), y = 0) }

View File

@ -23,6 +23,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastForEach
import kotlinx.collections.immutable.ImmutableList
import tachiyomi.presentation.core.components.ActionButton import tachiyomi.presentation.core.components.ActionButton
import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.util.secondaryItemAlpha import tachiyomi.presentation.core.util.secondaryItemAlpha
@ -38,7 +39,7 @@ data class EmptyScreenAction(
fun EmptyScreen( fun EmptyScreen(
@StringRes textResource: Int, @StringRes textResource: Int,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
actions: List<EmptyScreenAction>? = null, actions: ImmutableList<EmptyScreenAction>? = null,
) { ) {
EmptyScreen( EmptyScreen(
message = stringResource(textResource), message = stringResource(textResource),
@ -51,7 +52,7 @@ fun EmptyScreen(
fun EmptyScreen( fun EmptyScreen(
message: String, message: String,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
actions: List<EmptyScreenAction>? = null, actions: ImmutableList<EmptyScreenAction>? = null,
) { ) {
val face = remember { getRandomErrorFace() } val face = remember { getRandomErrorFace() }
Column( Column(
@ -98,7 +99,7 @@ fun EmptyScreen(
} }
} }
private val ERROR_FACES = listOf( private val ErrorFaces = listOf(
"(・o・;)", "(・o・;)",
"Σ(ಠ_ಠ)", "Σ(ಠ_ಠ)",
"ಥ_ಥ", "ಥ_ಥ",
@ -108,5 +109,5 @@ private val ERROR_FACES = listOf(
) )
private fun getRandomErrorFace(): String { private fun getRandomErrorFace(): String {
return ERROR_FACES[Random.nextInt(ERROR_FACES.size)] return ErrorFaces[Random.nextInt(ErrorFaces.size)]
} }

View File

@ -25,7 +25,10 @@ dependencies {
implementation(project(":domain")) implementation(project(":domain"))
implementation(project(":presentation-core")) implementation(project(":presentation-core"))
implementation(androidx.glance) implementation(compose.glance)
lintChecks(compose.lintchecks)
implementation(kotlinx.immutables)
implementation(platform(libs.coil.bom)) implementation(platform(libs.coil.bom))
implementation(libs.coil.core) implementation(libs.coil.core)

View File

@ -30,6 +30,8 @@ import coil.size.Scale
import coil.transform.RoundedCornersTransformation import coil.transform.RoundedCornersTransformation
import eu.kanade.tachiyomi.core.security.SecurityPreferences import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.dpToPx
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withIOContext
import tachiyomi.domain.manga.model.MangaCover import tachiyomi.domain.manga.model.MangaCover
@ -95,10 +97,10 @@ abstract class BaseUpdatesGridGlanceWidget(
val data by flow.collectAsState(initial = null) val data by flow.collectAsState(initial = null)
UpdatesWidget( UpdatesWidget(
data = data, data = data,
modifier = containerModifier,
contentColor = foreground, contentColor = foreground,
topPadding = topPadding, topPadding = topPadding,
bottomPadding = bottomPadding, bottomPadding = bottomPadding,
modifier = containerModifier,
) )
} }
} }
@ -106,7 +108,7 @@ abstract class BaseUpdatesGridGlanceWidget(
private suspend fun List<UpdatesWithRelations>.prepareData( private suspend fun List<UpdatesWithRelations>.prepareData(
rowCount: Int, rowCount: Int,
columnCount: Int, columnCount: Int,
): List<Pair<Long, Bitmap?>> { ): ImmutableList<Pair<Long, Bitmap?>> {
// Resize to cover size // Resize to cover size
val widthPx = CoverWidth.value.toInt().dpToPx val widthPx = CoverWidth.value.toInt().dpToPx
val heightPx = CoverHeight.value.toInt().dpToPx val heightPx = CoverHeight.value.toInt().dpToPx
@ -140,6 +142,7 @@ abstract class BaseUpdatesGridGlanceWidget(
.build() .build()
Pair(updatesView.mangaId, context.imageLoader.executeBlocking(request).drawable?.toBitmap()) Pair(updatesView.mangaId, context.imageLoader.executeBlocking(request).drawable?.toBitmap())
} }
.toImmutableList()
} }
} }

View File

@ -12,7 +12,7 @@ import logcat.LogPriority
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.domain.updates.interactor.GetUpdates import tachiyomi.domain.updates.interactor.GetUpdates
class TachiyomiWidgetManager( class WidgetManager(
private val getUpdates: GetUpdates, private val getUpdates: GetUpdates,
private val securityPreferences: SecurityPreferences, private val securityPreferences: SecurityPreferences,
) { ) {

View File

@ -17,7 +17,10 @@ val CoverWidth = 58.dp
val CoverHeight = 87.dp val CoverHeight = 87.dp
@Composable @Composable
fun UpdatesMangaCover(modifier: GlanceModifier = GlanceModifier, cover: Bitmap?) { fun UpdatesMangaCover(
cover: Bitmap?,
modifier: GlanceModifier = GlanceModifier,
) {
Box( Box(
modifier = modifier modifier = modifier
.size(width = CoverWidth, height = CoverHeight) .size(width = CoverWidth, height = CoverHeight)

View File

@ -21,6 +21,7 @@ import androidx.glance.layout.padding
import androidx.glance.text.Text import androidx.glance.text.Text
import androidx.glance.text.TextStyle import androidx.glance.text.TextStyle
import androidx.glance.unit.ColorProvider import androidx.glance.unit.ColorProvider
import kotlinx.collections.immutable.ImmutableList
import tachiyomi.core.Constants import tachiyomi.core.Constants
import tachiyomi.presentation.widget.R import tachiyomi.presentation.widget.R
import tachiyomi.presentation.widget.util.calculateRowAndColumnCount import tachiyomi.presentation.widget.util.calculateRowAndColumnCount
@ -28,11 +29,11 @@ import tachiyomi.presentation.widget.util.stringResource
@Composable @Composable
fun UpdatesWidget( fun UpdatesWidget(
data: List<Pair<Long, Bitmap?>>?, data: ImmutableList<Pair<Long, Bitmap?>>?,
modifier: GlanceModifier = GlanceModifier,
contentColor: ColorProvider, contentColor: ColorProvider,
topPadding: Dp, topPadding: Dp,
bottomPadding: Dp, bottomPadding: Dp,
modifier: GlanceModifier = GlanceModifier,
) { ) {
Box( Box(
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
@ -83,8 +84,8 @@ fun UpdatesWidget(
addCategory(mangaId.toString()) addCategory(mangaId.toString())
} }
UpdatesMangaCover( UpdatesMangaCover(
modifier = GlanceModifier.clickable(actionStartActivity(intent)),
cover = cover, cover = cover,
modifier = GlanceModifier.clickable(actionStartActivity(intent)),
) )
} }
} }