Migrate to multiplatform string resources (#10147)
* Migrate to multiplatform string resources * Move plurals translations into separate files * Fix lint check on generated files (cherry picked from commit 46e734fc8eefb8c06a880194e702559ca3fa769d) # Conflicts: # app/src/main/java/eu/kanade/presentation/browse/BrowseSourceScreen.kt # app/src/main/java/eu/kanade/presentation/browse/ExtensionDetailsScreen.kt # app/src/main/java/eu/kanade/presentation/browse/ExtensionsScreen.kt # app/src/main/java/eu/kanade/presentation/browse/SourcesScreen.kt # app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceDialogs.kt # app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceToolbar.kt # app/src/main/java/eu/kanade/presentation/category/components/CategoryDialogs.kt # app/src/main/java/eu/kanade/presentation/library/LibrarySettingsDialog.kt # app/src/main/java/eu/kanade/presentation/manga/components/MangaBottomActionMenu.kt # app/src/main/java/eu/kanade/presentation/manga/components/MangaDialogs.kt # app/src/main/java/eu/kanade/presentation/more/MoreScreen.kt # app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt # app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt # app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsLibraryScreen.kt # app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsMainScreen.kt # app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt # app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsSecurityScreen.kt # app/src/main/java/eu/kanade/presentation/more/settings/screen/about/AboutScreen.kt # app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt # app/src/main/java/eu/kanade/presentation/more/settings/screen/data/CreateBackupScreen.kt # app/src/main/java/eu/kanade/presentation/reader/ReaderPageActionsDialog.kt # app/src/main/java/eu/kanade/presentation/reader/appbars/BottomReaderBar.kt # app/src/main/java/eu/kanade/presentation/reader/appbars/ReaderAppBars.kt # app/src/main/java/eu/kanade/presentation/reader/components/ChapterNavigator.kt # app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt # app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt # app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt # app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt # app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/MigrationFlags.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/manga/MigrateMangaScreen.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateDialog.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrateSourceTab.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesTab.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt # app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterDialog.kt # app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt # app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt # app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt # app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt # app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt # app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ChapterLoader.kt # app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt # app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreen.kt # app/src/main/java/eu/kanade/tachiyomi/ui/updates/UpdatesTab.kt # build.gradle.kts # i18n/build.gradle.kts # i18n/src/commonMain/resources/MR/base/strings_sy.xml # i18n/src/commonMain/resources/MR/fr/strings_sy.xml # i18n/src/commonMain/resources/MR/in/strings_sy.xml # i18n/src/commonMain/resources/MR/pt-rBR/strings_sy.xml # i18n/src/commonMain/resources/MR/ru/strings_sy.xml # i18n/src/commonMain/resources/MR/zh-rCN/strings_sy.xml # i18n/src/commonMain/resources/MR/zh-rTW/strings_sy.xml
This commit is contained in:
parent
120ac6dbda
commit
1eccf9fad8
@ -140,6 +140,9 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation(project(":i18n"))
|
||||
// SY -->
|
||||
implementation(project(":i18n-sy"))
|
||||
// SY <--
|
||||
implementation(project(":core"))
|
||||
implementation(project(":core-metadata"))
|
||||
implementation(project(":source-api"))
|
||||
|
@ -1,12 +1,12 @@
|
||||
package eu.kanade.domain.base
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.StringRes
|
||||
import eu.kanade.tachiyomi.R
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.tachiyomi.util.system.isPreviewBuildType
|
||||
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
|
||||
import tachiyomi.core.preference.Preference
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.i18n.MR
|
||||
|
||||
class BasePreferences(
|
||||
val context: Context,
|
||||
@ -24,10 +24,10 @@ class BasePreferences(
|
||||
|
||||
fun acraEnabled() = preferenceStore.getBoolean("acra.enable", isPreviewBuildType || isReleaseBuildType)
|
||||
|
||||
enum class ExtensionInstaller(@StringRes val titleResId: Int) {
|
||||
LEGACY(R.string.ext_installer_legacy),
|
||||
PACKAGEINSTALLER(R.string.ext_installer_packageinstaller),
|
||||
SHIZUKU(R.string.ext_installer_shizuku),
|
||||
PRIVATE(R.string.ext_installer_private),
|
||||
enum class ExtensionInstaller(val titleRes: StringResource) {
|
||||
LEGACY(MR.strings.ext_installer_legacy),
|
||||
PACKAGEINSTALLER(MR.strings.ext_installer_packageinstaller),
|
||||
SHIZUKU(MR.strings.ext_installer_shizuku),
|
||||
PRIVATE(MR.strings.ext_installer_private),
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,20 @@
|
||||
package eu.kanade.domain.ui.model
|
||||
|
||||
import eu.kanade.tachiyomi.R
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import tachiyomi.i18n.MR
|
||||
|
||||
enum class AppTheme(val titleResId: Int?) {
|
||||
DEFAULT(R.string.label_default),
|
||||
MONET(R.string.theme_monet),
|
||||
GREEN_APPLE(R.string.theme_greenapple),
|
||||
LAVENDER(R.string.theme_lavender),
|
||||
MIDNIGHT_DUSK(R.string.theme_midnightdusk),
|
||||
STRAWBERRY_DAIQUIRI(R.string.theme_strawberrydaiquiri),
|
||||
TAKO(R.string.theme_tako),
|
||||
TEALTURQUOISE(R.string.theme_tealturquoise),
|
||||
TIDAL_WAVE(R.string.theme_tidalwave),
|
||||
YINYANG(R.string.theme_yinyang),
|
||||
YOTSUBA(R.string.theme_yotsuba),
|
||||
enum class AppTheme(val titleRes: StringResource?) {
|
||||
DEFAULT(MR.strings.label_default),
|
||||
MONET(MR.strings.theme_monet),
|
||||
GREEN_APPLE(MR.strings.theme_greenapple),
|
||||
LAVENDER(MR.strings.theme_lavender),
|
||||
MIDNIGHT_DUSK(MR.strings.theme_midnightdusk),
|
||||
STRAWBERRY_DAIQUIRI(MR.strings.theme_strawberrydaiquiri),
|
||||
TAKO(MR.strings.theme_tako),
|
||||
TEALTURQUOISE(MR.strings.theme_tealturquoise),
|
||||
TIDAL_WAVE(MR.strings.theme_tidalwave),
|
||||
YINYANG(MR.strings.theme_yinyang),
|
||||
YOTSUBA(MR.strings.theme_yotsuba),
|
||||
|
||||
// Deprecated
|
||||
DARK_BLUE(null),
|
||||
|
@ -1,10 +1,11 @@
|
||||
package eu.kanade.domain.ui.model
|
||||
|
||||
import eu.kanade.tachiyomi.R
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import tachiyomi.i18n.MR
|
||||
|
||||
enum class TabletUiMode(val titleResId: Int) {
|
||||
AUTOMATIC(R.string.automatic_background),
|
||||
ALWAYS(R.string.lock_always),
|
||||
LANDSCAPE(R.string.landscape),
|
||||
NEVER(R.string.lock_never),
|
||||
enum class TabletUiMode(val titleRes: StringResource) {
|
||||
AUTOMATIC(MR.strings.automatic_background),
|
||||
ALWAYS(MR.strings.lock_always),
|
||||
LANDSCAPE(MR.strings.landscape),
|
||||
NEVER(MR.strings.lock_never),
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.paging.LoadState
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import eu.kanade.presentation.browse.components.BrowseSourceComfortableGrid
|
||||
@ -23,17 +22,19 @@ import eu.kanade.presentation.browse.components.BrowseSourceEHentaiList
|
||||
import eu.kanade.presentation.browse.components.BrowseSourceList
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.util.formattedMessage
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import exh.metadata.metadata.RaisedSearchMetadata
|
||||
import exh.source.isEhBasedSource
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.model.StubSource
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.screens.EmptyScreenAction
|
||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||
@ -71,7 +72,7 @@ fun BrowseSourceContent(
|
||||
if (mangaList.itemCount > 0 && errorState != null && errorState is LoadState.Error) {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = getErrorMessage(errorState),
|
||||
actionLabel = context.getString(R.string.action_retry),
|
||||
actionLabel = context.localize(MR.strings.action_retry),
|
||||
duration = SnackbarDuration.Indefinite,
|
||||
)
|
||||
when (result) {
|
||||
@ -88,7 +89,7 @@ fun BrowseSourceContent(
|
||||
actions = if (source is LocalSource /* SY --> */ && onLocalSourceHelpClick != null /* SY <-- */) {
|
||||
persistentListOf(
|
||||
EmptyScreenAction(
|
||||
stringResId = R.string.local_source_help_guide,
|
||||
stringRes = MR.strings.local_source_help_guide,
|
||||
icon = Icons.AutoMirrored.Outlined.HelpOutline,
|
||||
onClick = onLocalSourceHelpClick,
|
||||
),
|
||||
@ -96,7 +97,7 @@ fun BrowseSourceContent(
|
||||
} else {
|
||||
listOfNotNull(
|
||||
EmptyScreenAction(
|
||||
stringResId = R.string.action_retry,
|
||||
stringRes = MR.strings.action_retry,
|
||||
icon = Icons.Outlined.Refresh,
|
||||
onClick = mangaList::refresh,
|
||||
),
|
||||
@ -191,7 +192,7 @@ internal fun MissingSourceScreen(
|
||||
},
|
||||
) { paddingValues ->
|
||||
EmptyScreen(
|
||||
message = stringResource(R.string.source_not_installed, source.toString()),
|
||||
message = localize(MR.strings.source_not_installed, source.toString()),
|
||||
modifier = Modifier.padding(paddingValues),
|
||||
)
|
||||
}
|
||||
|
@ -7,13 +7,13 @@ import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.browse.extension.ExtensionFilterState
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
|
||||
@Composable
|
||||
@ -25,7 +25,7 @@ fun ExtensionFilterScreen(
|
||||
Scaffold(
|
||||
topBar = { scrollBehavior ->
|
||||
AppBar(
|
||||
title = stringResource(R.string.label_extensions),
|
||||
title = localize(MR.strings.label_extensions),
|
||||
navigateUp = navigateUp,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
@ -33,7 +33,7 @@ fun ExtensionFilterScreen(
|
||||
) { contentPadding ->
|
||||
if (state.isEmpty) {
|
||||
EmptyScreen(
|
||||
textResource = R.string.empty_screen,
|
||||
stringRes = MR.strings.empty_screen,
|
||||
modifier = Modifier.padding(contentPadding),
|
||||
)
|
||||
return@Scaffold
|
||||
|
@ -7,9 +7,9 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.manga.components.BaseMangaListItem
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.browse.migration.manga.MigrateMangaScreenModel
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.FastScrollLazyColumn
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
@ -33,7 +33,7 @@ fun MigrateMangaScreen(
|
||||
) { contentPadding ->
|
||||
if (state.isEmpty) {
|
||||
EmptyScreen(
|
||||
textResource = R.string.empty_screen,
|
||||
stringRes = MR.strings.empty_screen,
|
||||
modifier = Modifier.padding(contentPadding),
|
||||
)
|
||||
return@Scaffold
|
||||
|
@ -22,21 +22,21 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import eu.kanade.domain.source.interactor.SetMigrateSorting
|
||||
import eu.kanade.presentation.browse.components.BaseSourceItem
|
||||
import eu.kanade.presentation.browse.components.SourceIcon
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.browse.migration.sources.MigrateSourceScreenModel
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import tachiyomi.domain.source.model.Source
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.Badge
|
||||
import tachiyomi.presentation.core.components.BadgeGroup
|
||||
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
||||
import tachiyomi.presentation.core.components.Scroller.STICKY_HEADER_KEY_PREFIX
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.components.material.topSmallPaddingValues
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||
import tachiyomi.presentation.core.theme.header
|
||||
@ -58,7 +58,7 @@ fun MigrateSourceScreen(
|
||||
when {
|
||||
state.isLoading -> LoadingScreen(Modifier.padding(contentPadding))
|
||||
state.isEmpty -> EmptyScreen(
|
||||
textResource = R.string.information_empty_library,
|
||||
stringRes = MR.strings.information_empty_library,
|
||||
modifier = Modifier.padding(contentPadding),
|
||||
)
|
||||
else ->
|
||||
@ -106,7 +106,7 @@ private fun MigrateSourceList(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.migration_selection_prompt),
|
||||
text = localize(MR.strings.migration_selection_prompt),
|
||||
modifier = Modifier.weight(1f),
|
||||
style = MaterialTheme.typography.header,
|
||||
)
|
||||
@ -115,11 +115,11 @@ private fun MigrateSourceList(
|
||||
when (sortingMode) {
|
||||
SetMigrateSorting.Mode.ALPHABETICAL -> Icon(
|
||||
Icons.Outlined.SortByAlpha,
|
||||
contentDescription = stringResource(R.string.action_sort_alpha),
|
||||
contentDescription = localize(MR.strings.action_sort_alpha),
|
||||
)
|
||||
SetMigrateSorting.Mode.TOTAL -> Icon(
|
||||
Icons.Outlined.Numbers,
|
||||
contentDescription = stringResource(R.string.action_sort_count),
|
||||
contentDescription = localize(MR.strings.action_sort_count),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -127,11 +127,11 @@ private fun MigrateSourceList(
|
||||
when (sortingDirection) {
|
||||
SetMigrateSorting.Direction.ASCENDING -> Icon(
|
||||
Icons.Outlined.ArrowUpward,
|
||||
contentDescription = stringResource(R.string.action_asc),
|
||||
contentDescription = localize(MR.strings.action_asc),
|
||||
)
|
||||
SetMigrateSorting.Direction.DESCENDING -> Icon(
|
||||
Icons.Outlined.ArrowDownward,
|
||||
contentDescription = stringResource(R.string.action_desc),
|
||||
contentDescription = localize(MR.strings.action_desc),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -216,7 +216,7 @@ private fun MigrateSourceItem(
|
||||
if (source.isStub) {
|
||||
Text(
|
||||
modifier = Modifier.secondaryItemAlpha(),
|
||||
text = stringResource(R.string.not_installed),
|
||||
text = localize(MR.strings.not_installed),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
|
@ -8,16 +8,16 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.browse.components.BaseSourceItem
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.more.settings.widget.SwitchPreferenceWidget
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.browse.source.SourcesFilterScreenModel
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
import tachiyomi.domain.source.model.Source
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.FastScrollLazyColumn
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
|
||||
@Composable
|
||||
@ -33,7 +33,7 @@ fun SourcesFilterScreen(
|
||||
Scaffold(
|
||||
topBar = { scrollBehavior ->
|
||||
AppBar(
|
||||
title = stringResource(R.string.label_sources),
|
||||
title = localize(MR.strings.label_sources),
|
||||
navigateUp = navigateUp,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
@ -41,7 +41,7 @@ fun SourcesFilterScreen(
|
||||
) { contentPadding ->
|
||||
if (state.isEmpty) {
|
||||
EmptyScreen(
|
||||
textResource = R.string.source_filter_empty_screen,
|
||||
stringRes = MR.strings.source_filter_empty_screen,
|
||||
modifier = Modifier.padding(contentPadding),
|
||||
)
|
||||
return@Scaffold
|
||||
|
@ -18,6 +18,8 @@ import androidx.compose.ui.window.DialogProperties
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun RemoveMangaDialog(
|
||||
@ -29,7 +31,7 @@ fun RemoveMangaDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
@ -39,14 +41,14 @@ fun RemoveMangaDialog(
|
||||
onConfirm()
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_remove))
|
||||
Text(text = localize(MR.strings.action_remove))
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Text(text = stringResource(R.string.are_you_sure))
|
||||
Text(text = localize(MR.strings.are_you_sure))
|
||||
},
|
||||
text = {
|
||||
Text(text = stringResource(R.string.remove_manga, mangaToRemove.title))
|
||||
Text(text = localize(MR.strings.remove_manga, mangaToRemove.title))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -12,19 +12,19 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.components.AppBarTitle
|
||||
import eu.kanade.presentation.components.DropdownMenu
|
||||
import eu.kanade.presentation.components.RadioMenuItem
|
||||
import eu.kanade.presentation.components.SearchToolbar
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import exh.source.anyIs
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.source.local.LocalSource
|
||||
|
||||
@Composable
|
||||
@ -111,7 +111,7 @@ fun BrowseSourceToolbar(
|
||||
if (isConfigurableSource) {
|
||||
add(
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.action_settings),
|
||||
title = localize(MR.strings.action_settings),
|
||||
onClick = onSettingsClick,
|
||||
),
|
||||
)
|
||||
@ -125,21 +125,21 @@ fun BrowseSourceToolbar(
|
||||
onDismissRequest = { selectingDisplayMode = false },
|
||||
) {
|
||||
RadioMenuItem(
|
||||
text = { Text(text = stringResource(R.string.action_display_comfortable_grid)) },
|
||||
text = { Text(text = localize(MR.strings.action_display_comfortable_grid)) },
|
||||
isChecked = displayMode == LibraryDisplayMode.ComfortableGrid,
|
||||
) {
|
||||
selectingDisplayMode = false
|
||||
onDisplayModeChange(LibraryDisplayMode.ComfortableGrid)
|
||||
}
|
||||
RadioMenuItem(
|
||||
text = { Text(text = stringResource(R.string.action_display_grid)) },
|
||||
text = { Text(text = localize(MR.strings.action_display_grid)) },
|
||||
isChecked = displayMode == LibraryDisplayMode.CompactGrid,
|
||||
) {
|
||||
selectingDisplayMode = false
|
||||
onDisplayModeChange(LibraryDisplayMode.CompactGrid)
|
||||
}
|
||||
RadioMenuItem(
|
||||
text = { Text(text = stringResource(R.string.action_display_list)) },
|
||||
text = { Text(text = localize(MR.strings.action_display_list)) },
|
||||
isChecked = displayMode == LibraryDisplayMode.List,
|
||||
) {
|
||||
selectingDisplayMode = false
|
||||
|
@ -13,15 +13,15 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.library.components.CommonMangaItemDefaults
|
||||
import eu.kanade.presentation.library.components.MangaComfortableGridItem
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.MangaCover
|
||||
import tachiyomi.domain.manga.model.asMangaCover
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun GlobalSearchCardRow(
|
||||
@ -78,7 +78,7 @@ private fun MangaItem(
|
||||
@Composable
|
||||
private fun EmptyResultItem() {
|
||||
Text(
|
||||
text = stringResource(R.string.no_results_found),
|
||||
text = localize(MR.strings.no_results_found),
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
horizontal = MaterialTheme.padding.medium,
|
||||
|
@ -23,11 +23,11 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun GlobalSearchResultItem(
|
||||
@ -112,7 +112,7 @@ fun GlobalSearchErrorResultItem(message: String?) {
|
||||
Icon(imageVector = Icons.Outlined.Error, contentDescription = null)
|
||||
Spacer(Modifier.height(4.dp))
|
||||
Text(
|
||||
text = message ?: stringResource(R.string.unknown_error),
|
||||
text = message ?: localize(MR.strings.unknown_error),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
|
@ -26,11 +26,11 @@ import androidx.compose.material3.VerticalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.components.SearchToolbar
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun GlobalSearchToolbar(
|
||||
@ -85,7 +85,7 @@ fun GlobalSearchToolbar(
|
||||
)
|
||||
},
|
||||
label = {
|
||||
Text(text = stringResource(id = R.string.pinned_sources))
|
||||
Text(text = localize(MR.strings.pinned_sources))
|
||||
},
|
||||
)
|
||||
FilterChip(
|
||||
@ -100,7 +100,7 @@ fun GlobalSearchToolbar(
|
||||
)
|
||||
},
|
||||
label = {
|
||||
Text(text = stringResource(id = R.string.all))
|
||||
Text(text = localize(MR.strings.all))
|
||||
},
|
||||
)
|
||||
|
||||
@ -118,7 +118,7 @@ fun GlobalSearchToolbar(
|
||||
)
|
||||
},
|
||||
label = {
|
||||
Text(text = stringResource(id = R.string.has_results))
|
||||
Text(text = localize(MR.strings.has_results))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -2,19 +2,20 @@ package eu.kanade.presentation.category
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
val Category.visualName: String
|
||||
@Composable
|
||||
get() = when {
|
||||
isSystemCategory -> stringResource(R.string.label_default)
|
||||
isSystemCategory -> localize(MR.strings.label_default)
|
||||
else -> name
|
||||
}
|
||||
|
||||
fun Category.visualName(context: Context): String =
|
||||
when {
|
||||
isSystemCategory -> context.getString(R.string.label_default)
|
||||
isSystemCategory -> context.localize(MR.strings.label_default)
|
||||
else -> name
|
||||
}
|
||||
|
@ -12,18 +12,18 @@ import androidx.compose.material.icons.outlined.SortByAlpha
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.category.components.CategoryFloatingActionButton
|
||||
import eu.kanade.presentation.category.components.CategoryListItem
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.category.CategoryScreenState
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.components.material.topSmallPaddingValues
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.util.plus
|
||||
|
||||
@ -42,13 +42,13 @@ fun CategoryScreen(
|
||||
Scaffold(
|
||||
topBar = { scrollBehavior ->
|
||||
AppBar(
|
||||
title = stringResource(R.string.action_edit_categories),
|
||||
title = localize(MR.strings.action_edit_categories),
|
||||
navigateUp = navigateUp,
|
||||
actions = {
|
||||
AppBarActions(
|
||||
persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_sort),
|
||||
title = localize(MR.strings.action_sort),
|
||||
icon = Icons.Outlined.SortByAlpha,
|
||||
onClick = onClickSortAlphabetically,
|
||||
),
|
||||
@ -67,7 +67,7 @@ fun CategoryScreen(
|
||||
) { paddingValues ->
|
||||
if (state.isEmpty) {
|
||||
EmptyScreen(
|
||||
textResource = R.string.information_empty_category,
|
||||
stringRes = MR.strings.information_empty_category,
|
||||
modifier = Modifier.padding(paddingValues),
|
||||
)
|
||||
return@Scaffold
|
||||
|
@ -6,9 +6,9 @@ import androidx.compose.material.icons.outlined.Add
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.isScrolledToEnd
|
||||
import tachiyomi.presentation.core.util.isScrollingUp
|
||||
|
||||
@ -18,7 +18,7 @@ fun CategoryFloatingActionButton(
|
||||
onCreate: () -> Unit,
|
||||
) {
|
||||
ExtendedFloatingActionButton(
|
||||
text = { Text(text = stringResource(R.string.action_add)) },
|
||||
text = { Text(text = localize(MR.strings.action_add)) },
|
||||
icon = { Icon(imageVector = Icons.Outlined.Add, contentDescription = null) },
|
||||
onClick = onCreate,
|
||||
expanded = lazyListState.isScrollingUp() || lazyListState.isScrolledToEnd(),
|
||||
|
@ -20,10 +20,10 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun CategoryListItem(
|
||||
@ -74,11 +74,11 @@ fun CategoryListItem(
|
||||
IconButton(onClick = onRename) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Edit,
|
||||
contentDescription = stringResource(R.string.action_rename_category),
|
||||
contentDescription = localize(MR.strings.action_rename_category),
|
||||
)
|
||||
}
|
||||
IconButton(onClick = onDelete) {
|
||||
Icon(imageVector = Icons.Outlined.Delete, contentDescription = stringResource(R.string.action_delete))
|
||||
Icon(imageVector = Icons.Outlined.Delete, contentDescription = localize(MR.strings.action_delete))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.clearFocusOnSoftKeyboardHide
|
||||
import tachiyomi.presentation.core.util.runOnEnterKeyPressed
|
||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
@ -133,7 +135,7 @@ fun AppBar(
|
||||
IconButton(onClick = onCancelActionMode) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Close,
|
||||
contentDescription = stringResource(R.string.action_cancel),
|
||||
contentDescription = localize(MR.strings.action_cancel),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@ -253,7 +255,7 @@ fun AppBarActions(
|
||||
/**
|
||||
* @param searchEnabled Set to false if you don't want to show search action.
|
||||
* @param searchQuery If null, use normal toolbar.
|
||||
* @param placeholderText If null, [R.string.action_search_hint] is used.
|
||||
* @param placeholderText If null, [MR.strings.action_search_hint] is used.
|
||||
*/
|
||||
@Composable
|
||||
fun SearchToolbar(
|
||||
@ -317,7 +319,7 @@ fun SearchToolbar(
|
||||
placeholder = {
|
||||
Text(
|
||||
modifier = Modifier.secondaryItemAlpha(),
|
||||
text = (placeholderText ?: stringResource(R.string.action_search_hint)),
|
||||
text = (placeholderText ?: localize(MR.strings.action_search_hint)),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.titleMedium.copy(
|
||||
@ -342,7 +344,7 @@ fun SearchToolbar(
|
||||
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
|
||||
tooltip = {
|
||||
PlainTooltip {
|
||||
Text(stringResource(R.string.action_search))
|
||||
Text(localize(MR.strings.action_search))
|
||||
}
|
||||
},
|
||||
state = rememberTooltipState(),
|
||||
@ -352,7 +354,7 @@ fun SearchToolbar(
|
||||
) {
|
||||
Icon(
|
||||
Icons.Outlined.Search,
|
||||
contentDescription = stringResource(R.string.action_search),
|
||||
contentDescription = localize(MR.strings.action_search),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -361,7 +363,7 @@ fun SearchToolbar(
|
||||
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
|
||||
tooltip = {
|
||||
PlainTooltip {
|
||||
Text(stringResource(R.string.action_reset))
|
||||
Text(localize(MR.strings.action_reset))
|
||||
}
|
||||
},
|
||||
state = rememberTooltipState(),
|
||||
@ -374,7 +376,7 @@ fun SearchToolbar(
|
||||
) {
|
||||
Icon(
|
||||
Icons.Outlined.Close,
|
||||
contentDescription = stringResource(R.string.action_reset),
|
||||
contentDescription = localize(MR.strings.action_reset),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package eu.kanade.presentation.components
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
@ -26,13 +25,14 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.SubcomposeLayout
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import androidx.compose.ui.util.fastMap
|
||||
import androidx.compose.ui.util.fastMaxBy
|
||||
import eu.kanade.tachiyomi.R
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
val DownloadedOnlyBannerBackgroundColor
|
||||
@Composable get() = MaterialTheme.colorScheme.tertiary
|
||||
@ -43,11 +43,11 @@ val IndexingBannerBackgroundColor
|
||||
|
||||
@Composable
|
||||
fun WarningBanner(
|
||||
@StringRes textRes: Int,
|
||||
textRes: StringResource,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(textRes),
|
||||
text = localize(textRes),
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.background(MaterialTheme.colorScheme.error)
|
||||
@ -127,7 +127,7 @@ fun AppStateBanners(
|
||||
@Composable
|
||||
private fun DownloadedOnlyModeBanner(modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
text = stringResource(R.string.label_downloaded_only),
|
||||
text = localize(MR.strings.label_downloaded_only),
|
||||
modifier = Modifier
|
||||
.background(DownloadedOnlyBannerBackgroundColor)
|
||||
.fillMaxWidth()
|
||||
@ -142,7 +142,7 @@ private fun DownloadedOnlyModeBanner(modifier: Modifier = Modifier) {
|
||||
@Composable
|
||||
private fun IncognitoModeBanner(modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
text = stringResource(R.string.pref_incognito_mode),
|
||||
text = localize(MR.strings.pref_incognito_mode),
|
||||
modifier = Modifier
|
||||
.background(IncognitoModeBannerBackgroundColor)
|
||||
.fillMaxWidth()
|
||||
@ -173,7 +173,7 @@ private fun IndexingDownloadBanner(modifier: Modifier = Modifier) {
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.download_notifier_cache_renewal),
|
||||
text = localize(MR.strings.download_notifier_cache_renewal),
|
||||
color = MaterialTheme.colorScheme.onSecondary,
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
|
@ -3,10 +3,10 @@ package eu.kanade.presentation.components
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.manga.DownloadAction
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.i18n.localizePlural
|
||||
|
||||
@Composable
|
||||
fun DownloadDropdownMenu(
|
||||
@ -19,11 +19,11 @@ fun DownloadDropdownMenu(
|
||||
onDismissRequest = onDismissRequest,
|
||||
) {
|
||||
listOfNotNull(
|
||||
DownloadAction.NEXT_1_CHAPTER to pluralStringResource(R.plurals.download_amount, 1, 1),
|
||||
DownloadAction.NEXT_5_CHAPTERS to pluralStringResource(R.plurals.download_amount, 5, 5),
|
||||
DownloadAction.NEXT_10_CHAPTERS to pluralStringResource(R.plurals.download_amount, 10, 10),
|
||||
DownloadAction.NEXT_25_CHAPTERS to pluralStringResource(R.plurals.download_amount, 25, 25),
|
||||
DownloadAction.UNREAD_CHAPTERS to stringResource(R.string.download_unread),
|
||||
DownloadAction.NEXT_1_CHAPTER to localizePlural(MR.plurals.download_amount, 1, 1),
|
||||
DownloadAction.NEXT_5_CHAPTERS to localizePlural(MR.plurals.download_amount, 5, 5),
|
||||
DownloadAction.NEXT_10_CHAPTERS to localizePlural(MR.plurals.download_amount, 10, 10),
|
||||
DownloadAction.NEXT_25_CHAPTERS to localizePlural(MR.plurals.download_amount, 25, 25),
|
||||
DownloadAction.UNREAD_CHAPTERS to localize(MR.strings.download_unread),
|
||||
).map { (downloadAction, string) ->
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = string) },
|
||||
|
@ -15,11 +15,11 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.PopupProperties
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import androidx.compose.material3.DropdownMenu as ComposeDropdownMenu
|
||||
|
||||
@Composable
|
||||
@ -54,13 +54,13 @@ fun RadioMenuItem(
|
||||
if (isChecked) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.RadioButtonChecked,
|
||||
contentDescription = stringResource(R.string.selected),
|
||||
contentDescription = localize(MR.strings.selected),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.RadioButtonUnchecked,
|
||||
contentDescription = stringResource(R.string.not_selected),
|
||||
contentDescription = localize(MR.strings.not_selected),
|
||||
)
|
||||
}
|
||||
},
|
||||
|
@ -2,14 +2,13 @@ package eu.kanade.presentation.components
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
|
||||
import androidx.compose.material.icons.outlined.HelpOutline
|
||||
import androidx.compose.material.icons.outlined.Refresh
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.screens.EmptyScreenAction
|
||||
|
||||
@ -19,7 +18,7 @@ private fun NoActionPreview() {
|
||||
TachiyomiTheme {
|
||||
Surface {
|
||||
EmptyScreen(
|
||||
textResource = R.string.empty_screen,
|
||||
stringRes = MR.strings.empty_screen,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -31,15 +30,15 @@ private fun WithActionPreview() {
|
||||
TachiyomiTheme {
|
||||
Surface {
|
||||
EmptyScreen(
|
||||
textResource = R.string.empty_screen,
|
||||
stringRes = MR.strings.empty_screen,
|
||||
actions = persistentListOf(
|
||||
EmptyScreenAction(
|
||||
stringResId = R.string.action_retry,
|
||||
stringRes = MR.strings.action_retry,
|
||||
icon = Icons.Outlined.Refresh,
|
||||
onClick = {},
|
||||
),
|
||||
EmptyScreenAction(
|
||||
stringResId = R.string.getting_started_guide,
|
||||
stringRes = MR.strings.getting_started_guide,
|
||||
icon = Icons.AutoMirrored.Outlined.HelpOutline,
|
||||
onClick = {},
|
||||
),
|
||||
|
@ -24,14 +24,14 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.HorizontalPager
|
||||
import tachiyomi.presentation.core.components.material.TabText
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
object TabbedDialogPaddings {
|
||||
val Horizontal = 24.dp
|
||||
@ -94,7 +94,7 @@ private fun MoreMenu(
|
||||
IconButton(onClick = { expanded = true }) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = stringResource(R.string.label_more),
|
||||
contentDescription = localize(MR.strings.label_more),
|
||||
)
|
||||
}
|
||||
DropdownMenu(
|
||||
|
@ -1,6 +1,5 @@
|
||||
package eu.kanade.presentation.components
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.calculateEndPadding
|
||||
@ -20,17 +19,18 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.presentation.core.components.HorizontalPager
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.components.material.TabText
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun TabbedScreen(
|
||||
@StringRes titleRes: Int,
|
||||
titleRes: StringResource,
|
||||
tabs: ImmutableList<TabContent>,
|
||||
startIndex: Int? = null,
|
||||
searchQuery: String? = null,
|
||||
@ -52,7 +52,7 @@ fun TabbedScreen(
|
||||
val searchEnabled = tab.searchEnabled
|
||||
|
||||
SearchToolbar(
|
||||
titleContent = { AppBarTitle(stringResource(titleRes)) },
|
||||
titleContent = { AppBarTitle(localize(titleRes)) },
|
||||
searchEnabled = searchEnabled,
|
||||
searchQuery = if (searchEnabled) searchQuery else null,
|
||||
onChangeSearchQuery = onChangeSearchQuery,
|
||||
@ -75,7 +75,7 @@ fun TabbedScreen(
|
||||
Tab(
|
||||
selected = state.currentPage == index,
|
||||
onClick = { scope.launch { state.animateScrollToPage(index) } },
|
||||
text = { TabText(text = stringResource(tab.titleRes), badgeCount = tab.badgeNumber) },
|
||||
text = { TabText(text = localize(tab.titleRes), badgeCount = tab.badgeNumber) },
|
||||
unselectedContentColor = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
@ -96,7 +96,7 @@ fun TabbedScreen(
|
||||
}
|
||||
|
||||
data class TabContent(
|
||||
@StringRes val titleRes: Int,
|
||||
val titleRes: StringResource,
|
||||
val badgeNumber: Int? = null,
|
||||
val searchEnabled: Boolean = false,
|
||||
val actions: ImmutableList<AppBar.Action> = persistentListOf(),
|
||||
|
@ -13,13 +13,13 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.CrashLogUtil
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.screens.InfoScreen
|
||||
|
||||
@Composable
|
||||
@ -32,15 +32,15 @@ fun CrashScreen(
|
||||
|
||||
InfoScreen(
|
||||
icon = Icons.Outlined.BugReport,
|
||||
headingText = stringResource(R.string.crash_screen_title),
|
||||
subtitleText = stringResource(R.string.crash_screen_description, stringResource(R.string.app_name)),
|
||||
acceptText = stringResource(R.string.pref_dump_crash_logs),
|
||||
headingText = localize(MR.strings.crash_screen_title),
|
||||
subtitleText = localize(MR.strings.crash_screen_description, localize(MR.strings.app_name)),
|
||||
acceptText = localize(MR.strings.pref_dump_crash_logs),
|
||||
onAcceptClick = {
|
||||
scope.launch {
|
||||
CrashLogUtil(context).dumpLogs()
|
||||
}
|
||||
},
|
||||
rejectText = stringResource(R.string.crash_screen_restart_application),
|
||||
rejectText = localize(MR.strings.crash_screen_restart_application),
|
||||
onRejectClick = onRestartClick,
|
||||
) {
|
||||
Box(
|
||||
|
@ -10,7 +10,6 @@ import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
@ -21,13 +20,14 @@ import eu.kanade.presentation.components.RelativeDateHeader
|
||||
import eu.kanade.presentation.components.SearchToolbar
|
||||
import eu.kanade.presentation.history.components.HistoryItem
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.history.HistoryScreenModel
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.core.preference.InMemoryPreferenceStore
|
||||
import tachiyomi.domain.history.model.HistoryWithRelations
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.FastScrollLazyColumn
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@ -47,14 +47,14 @@ fun HistoryScreen(
|
||||
Scaffold(
|
||||
topBar = { scrollBehavior ->
|
||||
SearchToolbar(
|
||||
titleContent = { AppBarTitle(stringResource(R.string.history)) },
|
||||
titleContent = { AppBarTitle(localize(MR.strings.history)) },
|
||||
searchQuery = state.searchQuery,
|
||||
onChangeSearchQuery = onSearchQueryChange,
|
||||
actions = {
|
||||
AppBarActions(
|
||||
persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.pref_clear_history),
|
||||
title = localize(MR.strings.pref_clear_history),
|
||||
icon = Icons.Outlined.DeleteSweep,
|
||||
onClick = {
|
||||
onDialogChange(HistoryScreenModel.Dialog.DeleteAll)
|
||||
@ -73,12 +73,12 @@ fun HistoryScreen(
|
||||
LoadingScreen(Modifier.padding(contentPadding))
|
||||
} else if (it.isEmpty()) {
|
||||
val msg = if (!state.searchQuery.isNullOrEmpty()) {
|
||||
R.string.no_results_found
|
||||
MR.strings.no_results_found
|
||||
} else {
|
||||
R.string.information_no_recent_manga
|
||||
MR.strings.information_no_recent_manga
|
||||
}
|
||||
EmptyScreen(
|
||||
textResource = msg,
|
||||
stringRes = msg,
|
||||
modifier = Modifier.padding(contentPadding),
|
||||
)
|
||||
} else {
|
||||
|
@ -10,12 +10,12 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun HistoryDeleteDialog(
|
||||
@ -26,16 +26,16 @@ fun HistoryDeleteDialog(
|
||||
|
||||
AlertDialog(
|
||||
title = {
|
||||
Text(text = stringResource(R.string.action_remove))
|
||||
Text(text = localize(MR.strings.action_remove))
|
||||
},
|
||||
text = {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Text(text = stringResource(R.string.dialog_with_checkbox_remove_description))
|
||||
Text(text = localize(MR.strings.dialog_with_checkbox_remove_description))
|
||||
|
||||
LabeledCheckbox(
|
||||
label = stringResource(R.string.dialog_with_checkbox_reset),
|
||||
label = localize(MR.strings.dialog_with_checkbox_reset),
|
||||
checked = removeEverything,
|
||||
onCheckedChange = { removeEverything = it },
|
||||
)
|
||||
@ -47,12 +47,12 @@ fun HistoryDeleteDialog(
|
||||
onDelete(removeEverything)
|
||||
onDismissRequest()
|
||||
}) {
|
||||
Text(text = stringResource(R.string.action_remove))
|
||||
Text(text = localize(MR.strings.action_remove))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
},
|
||||
)
|
||||
@ -65,10 +65,10 @@ fun HistoryDeleteAllDialog(
|
||||
) {
|
||||
AlertDialog(
|
||||
title = {
|
||||
Text(text = stringResource(R.string.action_remove_everything))
|
||||
Text(text = localize(MR.strings.action_remove_everything))
|
||||
},
|
||||
text = {
|
||||
Text(text = stringResource(R.string.clear_history_confirmation))
|
||||
Text(text = localize(MR.strings.clear_history_confirmation))
|
||||
},
|
||||
onDismissRequest = onDismissRequest,
|
||||
confirmButton = {
|
||||
@ -76,12 +76,12 @@ fun HistoryDeleteAllDialog(
|
||||
onDelete()
|
||||
onDismissRequest()
|
||||
}) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
Text(text = localize(MR.strings.action_ok))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -17,7 +17,6 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
@ -26,10 +25,11 @@ import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.manga.components.MangaCover
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.util.formatChapterNumber
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.lang.toTimestampString
|
||||
import tachiyomi.domain.history.model.HistoryWithRelations
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
private val HistoryItemHeight = 96.dp
|
||||
|
||||
@ -69,8 +69,8 @@ fun HistoryItem(
|
||||
val readAt = remember { history.readAt?.toTimestampString() ?: "" }
|
||||
Text(
|
||||
text = if (history.chapterNumber > -1) {
|
||||
stringResource(
|
||||
R.string.recent_manga_time,
|
||||
localize(
|
||||
MR.strings.recent_manga_time,
|
||||
formatChapterNumber(history.chapterNumber),
|
||||
readAt,
|
||||
)
|
||||
@ -85,7 +85,7 @@ fun HistoryItem(
|
||||
IconButton(onClick = onClickDelete) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Delete,
|
||||
contentDescription = stringResource(R.string.action_delete),
|
||||
contentDescription = localize(MR.strings.action_delete),
|
||||
tint = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
|
@ -9,10 +9,11 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.tachiyomi.R
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import tachiyomi.core.preference.CheckboxState
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun DeleteLibraryMangaDialog(
|
||||
@ -22,10 +23,10 @@ fun DeleteLibraryMangaDialog(
|
||||
) {
|
||||
var list by remember {
|
||||
mutableStateOf(
|
||||
buildList<CheckboxState.State<Int>> {
|
||||
add(CheckboxState.State.None(R.string.manga_from_library))
|
||||
buildList<CheckboxState.State<StringResource>> {
|
||||
add(CheckboxState.State.None(MR.strings.manga_from_library))
|
||||
if (!containsLocalManga) {
|
||||
add(CheckboxState.State.None(R.string.downloaded_chapters))
|
||||
add(CheckboxState.State.None(MR.strings.downloaded_chapters))
|
||||
}
|
||||
},
|
||||
)
|
||||
@ -34,7 +35,7 @@ fun DeleteLibraryMangaDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
@ -48,23 +49,23 @@ fun DeleteLibraryMangaDialog(
|
||||
)
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
Text(text = localize(MR.strings.action_ok))
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Text(text = stringResource(R.string.action_remove))
|
||||
Text(text = localize(MR.strings.action_remove))
|
||||
},
|
||||
text = {
|
||||
Column {
|
||||
list.forEach { state ->
|
||||
LabeledCheckbox(
|
||||
label = stringResource(state.value),
|
||||
label = localize(state.value),
|
||||
checked = state.isChecked,
|
||||
onCheckedChange = {
|
||||
val index = list.indexOf(state)
|
||||
if (index != -1) {
|
||||
val mutableList = list.toMutableList()
|
||||
mutableList[index] = state.next() as CheckboxState.State<Int>
|
||||
mutableList[index] = state.next() as CheckboxState.State<StringResource>
|
||||
list = mutableList.toList()
|
||||
}
|
||||
},
|
||||
|
@ -33,14 +33,14 @@ import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shadow
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import eu.kanade.presentation.manga.components.MangaCover
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.BadgeGroup
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.selectedBackground
|
||||
|
||||
object CommonMangaItemDefaults {
|
||||
@ -378,7 +378,7 @@ private fun ContinueReadingButton(
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.PlayArrow,
|
||||
contentDescription = stringResource(R.string.action_resume),
|
||||
contentDescription = localize(MR.strings.action_resume),
|
||||
modifier = Modifier.size(16.dp),
|
||||
)
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.zIndex
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
internal fun GlobalSearchItem(
|
||||
@ -19,7 +19,7 @@ internal fun GlobalSearchItem(
|
||||
onClick = onClick,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.action_global_search_query, searchQuery),
|
||||
text = localize(MR.strings.action_global_search_query, searchQuery),
|
||||
modifier = Modifier.zIndex(99f),
|
||||
)
|
||||
}
|
||||
|
@ -18,10 +18,10 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.core.preference.PreferenceMutableState
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.library.LibraryItem
|
||||
import tachiyomi.domain.library.model.LibraryDisplayMode
|
||||
import tachiyomi.domain.library.model.LibraryManga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.HorizontalPager
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.util.plus
|
||||
@ -124,9 +124,9 @@ private fun LibraryPagerEmptyScreen(
|
||||
onGlobalSearchClicked: () -> Unit,
|
||||
) {
|
||||
val msg = when {
|
||||
!searchQuery.isNullOrEmpty() -> R.string.no_results_found
|
||||
hasActiveFilters -> R.string.error_no_match
|
||||
else -> R.string.information_no_manga_category
|
||||
!searchQuery.isNullOrEmpty() -> MR.strings.no_results_found
|
||||
hasActiveFilters -> MR.strings.error_no_match
|
||||
else -> MR.strings.information_no_manga_category
|
||||
}
|
||||
|
||||
Column(
|
||||
@ -146,7 +146,7 @@ private fun LibraryPagerEmptyScreen(
|
||||
}
|
||||
|
||||
EmptyScreen(
|
||||
textResource = msg,
|
||||
stringRes = msg,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
|
@ -14,15 +14,15 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.sp
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.components.SearchToolbar
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.Pill
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.theme.active
|
||||
|
||||
@Composable
|
||||
@ -107,21 +107,21 @@ private fun LibraryRegularToolbar(
|
||||
AppBarActions(
|
||||
persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_filter),
|
||||
title = localize(MR.strings.action_filter),
|
||||
icon = Icons.Outlined.FilterList,
|
||||
iconTint = filterTint,
|
||||
onClick = onClickFilter,
|
||||
),
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.action_update_library),
|
||||
title = localize(MR.strings.action_update_library),
|
||||
onClick = onClickGlobalUpdate,
|
||||
),
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.action_update_category),
|
||||
title = localize(MR.strings.action_update_category),
|
||||
onClick = onClickRefresh,
|
||||
),
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.action_open_random_manga),
|
||||
title = localize(MR.strings.action_open_random_manga),
|
||||
onClick = onClickOpenRandomManga,
|
||||
),
|
||||
|
||||
@ -156,12 +156,12 @@ private fun LibrarySelectionToolbar(
|
||||
AppBarActions(
|
||||
persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_select_all),
|
||||
title = localize(MR.strings.action_select_all),
|
||||
icon = Icons.Outlined.SelectAll,
|
||||
onClick = onClickSelectAll,
|
||||
),
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_select_inverse),
|
||||
title = localize(MR.strings.action_select_inverse),
|
||||
icon = Icons.Outlined.FlipToBack,
|
||||
onClick = onClickInvertSelection,
|
||||
),
|
||||
|
@ -25,20 +25,20 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.domain.manga.model.downloadedFilter
|
||||
import eu.kanade.domain.manga.model.forceDownloaded
|
||||
import eu.kanade.presentation.components.TabbedDialog
|
||||
import eu.kanade.presentation.components.TabbedDialogPaddings
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.core.preference.TriState
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||
import tachiyomi.presentation.core.components.RadioItem
|
||||
import tachiyomi.presentation.core.components.SortItem
|
||||
import tachiyomi.presentation.core.components.TriStateItem
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.theme.active
|
||||
|
||||
@Composable
|
||||
@ -66,20 +66,20 @@ fun ChapterSettingsDialog(
|
||||
TabbedDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
tabTitles = persistentListOf(
|
||||
stringResource(R.string.action_filter),
|
||||
stringResource(R.string.action_sort),
|
||||
stringResource(R.string.action_display),
|
||||
localize(MR.strings.action_filter),
|
||||
localize(MR.strings.action_sort),
|
||||
localize(MR.strings.action_display),
|
||||
),
|
||||
tabOverflowMenuContent = { closeMenu ->
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.set_chapter_settings_as_default)) },
|
||||
text = { Text(localize(MR.strings.set_chapter_settings_as_default)) },
|
||||
onClick = {
|
||||
showSetAsDefaultDialog = true
|
||||
closeMenu()
|
||||
},
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.action_reset)) },
|
||||
text = { Text(localize(MR.strings.action_reset)) },
|
||||
onClick = {
|
||||
onResetToDefault()
|
||||
closeMenu()
|
||||
@ -136,17 +136,17 @@ private fun ColumnScope.FilterPage(
|
||||
onScanlatorFilterClicked: (() -> Unit),
|
||||
) {
|
||||
TriStateItem(
|
||||
label = stringResource(R.string.label_downloaded),
|
||||
label = localize(MR.strings.label_downloaded),
|
||||
state = downloadFilter,
|
||||
onClick = onDownloadFilterChanged,
|
||||
)
|
||||
TriStateItem(
|
||||
label = stringResource(R.string.action_filter_unread),
|
||||
label = localize(MR.strings.action_filter_unread),
|
||||
state = unreadFilter,
|
||||
onClick = onUnreadFilterChanged,
|
||||
)
|
||||
TriStateItem(
|
||||
label = stringResource(R.string.action_filter_bookmarked),
|
||||
label = localize(MR.strings.action_filter_bookmarked),
|
||||
state = bookmarkedFilter,
|
||||
onClick = onBookmarkedFilterChanged,
|
||||
)
|
||||
@ -179,7 +179,7 @@ fun ScanlatorFilterItem(
|
||||
},
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.scanlator),
|
||||
text = localize(MR.strings.scanlator),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
}
|
||||
@ -192,13 +192,13 @@ private fun ColumnScope.SortPage(
|
||||
onItemSelected: (Long) -> Unit,
|
||||
) {
|
||||
listOf(
|
||||
R.string.sort_by_source to Manga.CHAPTER_SORTING_SOURCE,
|
||||
R.string.sort_by_number to Manga.CHAPTER_SORTING_NUMBER,
|
||||
R.string.sort_by_upload_date to Manga.CHAPTER_SORTING_UPLOAD_DATE,
|
||||
R.string.action_sort_alpha to Manga.CHAPTER_SORTING_ALPHABET,
|
||||
MR.strings.sort_by_source to Manga.CHAPTER_SORTING_SOURCE,
|
||||
MR.strings.sort_by_number to Manga.CHAPTER_SORTING_NUMBER,
|
||||
MR.strings.sort_by_upload_date to Manga.CHAPTER_SORTING_UPLOAD_DATE,
|
||||
MR.strings.action_sort_alpha to Manga.CHAPTER_SORTING_ALPHABET,
|
||||
).map { (titleRes, mode) ->
|
||||
SortItem(
|
||||
label = stringResource(titleRes),
|
||||
label = localize(titleRes),
|
||||
sortDescending = sortDescending.takeIf { sortingMode == mode },
|
||||
onClick = { onItemSelected(mode) },
|
||||
)
|
||||
@ -211,11 +211,11 @@ private fun ColumnScope.DisplayPage(
|
||||
onItemSelected: (Long) -> Unit,
|
||||
) {
|
||||
listOf(
|
||||
R.string.show_title to Manga.CHAPTER_DISPLAY_NAME,
|
||||
R.string.show_chapter_number to Manga.CHAPTER_DISPLAY_NUMBER,
|
||||
MR.strings.show_title to Manga.CHAPTER_DISPLAY_NAME,
|
||||
MR.strings.show_chapter_number to Manga.CHAPTER_DISPLAY_NUMBER,
|
||||
).map { (titleRes, mode) ->
|
||||
RadioItem(
|
||||
label = stringResource(titleRes),
|
||||
label = localize(titleRes),
|
||||
selected = displayMode == mode,
|
||||
onClick = { onItemSelected(mode) },
|
||||
)
|
||||
@ -231,15 +231,15 @@ private fun SetAsDefaultDialog(
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
title = { Text(text = stringResource(R.string.chapter_settings)) },
|
||||
title = { Text(text = localize(MR.strings.chapter_settings)) },
|
||||
text = {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
Text(text = stringResource(R.string.confirm_set_chapter_settings))
|
||||
Text(text = localize(MR.strings.confirm_set_chapter_settings))
|
||||
|
||||
LabeledCheckbox(
|
||||
label = stringResource(R.string.also_set_chapter_settings_for_library),
|
||||
label = localize(MR.strings.also_set_chapter_settings_for_library),
|
||||
checked = optionalChecked,
|
||||
onCheckedChange = { optionalChecked = it },
|
||||
)
|
||||
@ -247,7 +247,7 @@ private fun SetAsDefaultDialog(
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
@ -257,7 +257,7 @@ private fun SetAsDefaultDialog(
|
||||
onDismissRequest()
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
Text(text = localize(MR.strings.action_ok))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -8,9 +8,9 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun DuplicateMangaDialog(
|
||||
@ -21,10 +21,10 @@ fun DuplicateMangaDialog(
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
title = {
|
||||
Text(text = stringResource(R.string.are_you_sure))
|
||||
Text(text = localize(MR.strings.are_you_sure))
|
||||
},
|
||||
text = {
|
||||
Text(text = stringResource(R.string.confirm_add_duplicate_manga))
|
||||
Text(text = localize(MR.strings.confirm_add_duplicate_manga))
|
||||
},
|
||||
confirmButton = {
|
||||
FlowRow(
|
||||
@ -36,13 +36,13 @@ fun DuplicateMangaDialog(
|
||||
onOpenManga()
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_show_manga))
|
||||
Text(text = localize(MR.strings.action_show_manga))
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
TextButton(
|
||||
onClick = {
|
||||
@ -50,7 +50,7 @@ fun DuplicateMangaDialog(
|
||||
onConfirm()
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_add))
|
||||
Text(text = localize(MR.strings.action_add))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -44,7 +44,6 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.util.fastAll
|
||||
import androidx.compose.ui.util.fastAny
|
||||
import androidx.compose.ui.util.fastMap
|
||||
@ -61,7 +60,6 @@ import eu.kanade.presentation.manga.components.MissingChapterCountListItem
|
||||
import eu.kanade.presentation.manga.components.PagePreviews
|
||||
import eu.kanade.presentation.manga.components.SearchMetadataChips
|
||||
import eu.kanade.presentation.util.formatChapterNumber
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.getNameForMangaInfo
|
||||
@ -94,11 +92,13 @@ import tachiyomi.domain.chapter.service.missingChaptersCount
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.model.StubSource
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.TwoPanelBox
|
||||
import tachiyomi.presentation.core.components.VerticalFastScroller
|
||||
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
|
||||
import tachiyomi.presentation.core.components.material.PullRefresh
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.isScrolledToEnd
|
||||
import tachiyomi.presentation.core.util.isScrollingUp
|
||||
import java.text.DateFormat
|
||||
@ -422,7 +422,7 @@ private fun MangaScreenSmallImpl(
|
||||
val isReading = remember(state.chapters) {
|
||||
state.chapters.fastAny { it.chapter.read }
|
||||
}
|
||||
Text(text = stringResource(if (isReading) R.string.action_resume else R.string.action_start))
|
||||
Text(text = localize(if (isReading) MR.strings.action_resume else MR.strings.action_start))
|
||||
},
|
||||
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
|
||||
onClick = onContinueReading,
|
||||
@ -758,7 +758,7 @@ fun MangaScreenLargeImpl(
|
||||
state.chapters.fastAny { it.chapter.read }
|
||||
}
|
||||
Text(
|
||||
text = stringResource(if (isReading) R.string.action_resume else R.string.action_start),
|
||||
text = localize(if (isReading) MR.strings.action_resume else MR.strings.action_start),
|
||||
)
|
||||
},
|
||||
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
|
||||
@ -977,8 +977,8 @@ private fun LazyListScope.sharedChapterItems(
|
||||
is ChapterList.Item -> {
|
||||
MangaChapterListItem(
|
||||
title = if (manga.displayMode == Manga.CHAPTER_DISPLAY_NUMBER) {
|
||||
stringResource(
|
||||
R.string.display_mode_chapter,
|
||||
localize(
|
||||
MR.strings.display_mode_chapter,
|
||||
formatChapterNumber(item.chapter.chapterNumber),
|
||||
)
|
||||
} else {
|
||||
@ -1002,8 +1002,8 @@ private fun LazyListScope.sharedChapterItems(
|
||||
readProgress = item.chapter.lastPageRead
|
||||
.takeIf { /* SY --> */(!item.chapter.read || alwaysShowReadingProgress)/* SY <-- */ && it > 0L }
|
||||
?.let {
|
||||
stringResource(
|
||||
R.string.chapter_progress,
|
||||
localize(
|
||||
MR.strings.chapter_progress,
|
||||
it + 1,
|
||||
)
|
||||
},
|
||||
|
@ -29,13 +29,14 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.components.DropdownMenu
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.IconButtonTokens
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
|
||||
enum class ChapterDownloadAction {
|
||||
@ -98,7 +99,7 @@ private fun NotDownloadedIndicator(
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_download_chapter_24dp),
|
||||
contentDescription = stringResource(R.string.manga_download),
|
||||
contentDescription = localize(MR.strings.manga_download),
|
||||
modifier = Modifier.size(IndicatorSize),
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@ -155,14 +156,14 @@ private fun DownloadingIndicator(
|
||||
}
|
||||
DropdownMenu(expanded = isMenuExpanded, onDismissRequest = { isMenuExpanded = false }) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(R.string.action_start_downloading_now)) },
|
||||
text = { Text(text = localize(MR.strings.action_start_downloading_now)) },
|
||||
onClick = {
|
||||
onClick(ChapterDownloadAction.START_NOW)
|
||||
isMenuExpanded = false
|
||||
},
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(R.string.action_cancel)) },
|
||||
text = { Text(text = localize(MR.strings.action_cancel)) },
|
||||
onClick = {
|
||||
onClick(ChapterDownloadAction.CANCEL)
|
||||
isMenuExpanded = false
|
||||
@ -203,7 +204,7 @@ private fun DownloadedIndicator(
|
||||
)
|
||||
DropdownMenu(expanded = isMenuExpanded, onDismissRequest = { isMenuExpanded = false }) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(R.string.action_delete)) },
|
||||
text = { Text(text = localize(MR.strings.action_delete)) },
|
||||
onClick = {
|
||||
onClick(ChapterDownloadAction.DELETE)
|
||||
isMenuExpanded = false
|
||||
@ -231,7 +232,7 @@ private fun ErrorIndicator(
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.ErrorOutline,
|
||||
contentDescription = stringResource(R.string.chapter_error),
|
||||
contentDescription = localize(MR.strings.chapter_error),
|
||||
modifier = Modifier.size(IndicatorSize),
|
||||
tint = MaterialTheme.colorScheme.error,
|
||||
)
|
||||
|
@ -9,12 +9,12 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.i18n.localizePlural
|
||||
|
||||
@Composable
|
||||
fun ChapterHeader(
|
||||
@ -35,9 +35,9 @@ fun ChapterHeader(
|
||||
) {
|
||||
Text(
|
||||
text = if (chapterCount == null) {
|
||||
stringResource(R.string.chapters)
|
||||
localize(MR.strings.chapters)
|
||||
} else {
|
||||
pluralStringResource(id = R.plurals.manga_num_chapters, count = chapterCount, chapterCount)
|
||||
localizePlural(MR.plurals.manga_num_chapters, count = chapterCount, chapterCount)
|
||||
},
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
@ -54,7 +54,7 @@ private fun MissingChaptersWarning(count: Int) {
|
||||
}
|
||||
|
||||
Text(
|
||||
text = pluralStringResource(id = R.plurals.missing_chapters, count = count, count),
|
||||
text = localizePlural(MR.plurals.missing_chapters, count = count, count),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
|
@ -42,23 +42,22 @@ import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.LocalViewConfiguration
|
||||
import androidx.compose.ui.platform.ViewConfiguration
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import me.saket.swipe.SwipeableActionsBox
|
||||
import me.saket.swipe.rememberSwipeableActionsState
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.ReadItemAlpha
|
||||
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.selectedBackground
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
@Composable
|
||||
fun MangaChapterListItem(
|
||||
modifier: Modifier = Modifier,
|
||||
title: String,
|
||||
date: String?,
|
||||
readProgress: String?,
|
||||
@ -78,6 +77,7 @@ fun MangaChapterListItem(
|
||||
onClick: () -> Unit,
|
||||
onDownloadClick: ((ChapterDownloadAction) -> Unit)?,
|
||||
onChapterSwipe: (LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val haptic = LocalHapticFeedback.current
|
||||
val density = LocalDensity.current
|
||||
@ -146,7 +146,7 @@ fun MangaChapterListItem(
|
||||
if (!read) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Circle,
|
||||
contentDescription = stringResource(R.string.unread),
|
||||
contentDescription = localize(MR.strings.unread),
|
||||
modifier = Modifier
|
||||
.height(8.dp)
|
||||
.padding(end = 4.dp),
|
||||
@ -156,7 +156,7 @@ fun MangaChapterListItem(
|
||||
if (bookmark) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Bookmark,
|
||||
contentDescription = stringResource(R.string.action_filter_bookmarked),
|
||||
contentDescription = localize(MR.strings.action_filter_bookmarked),
|
||||
modifier = Modifier
|
||||
.sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
|
@ -32,7 +32,6 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
@ -47,11 +46,12 @@ import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.components.DropdownMenu
|
||||
import eu.kanade.presentation.manga.EditCoverAction
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.clickableNoIndication
|
||||
|
||||
@Composable
|
||||
@ -85,7 +85,7 @@ fun MangaCoverDialog(
|
||||
IconButton(onClick = onDismissRequest) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Close,
|
||||
contentDescription = stringResource(R.string.action_close),
|
||||
contentDescription = localize(MR.strings.action_close),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -94,12 +94,12 @@ fun MangaCoverDialog(
|
||||
AppBarActions(
|
||||
actions = persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_share),
|
||||
title = localize(MR.strings.action_share),
|
||||
icon = Icons.Outlined.Share,
|
||||
onClick = onShareClick,
|
||||
),
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_save),
|
||||
title = localize(MR.strings.action_save),
|
||||
icon = Icons.Outlined.Save,
|
||||
onClick = onSaveClick,
|
||||
),
|
||||
@ -119,7 +119,7 @@ fun MangaCoverDialog(
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Edit,
|
||||
contentDescription = stringResource(R.string.action_edit_cover),
|
||||
contentDescription = localize(MR.strings.action_edit_cover),
|
||||
)
|
||||
}
|
||||
DropdownMenu(
|
||||
@ -128,14 +128,14 @@ fun MangaCoverDialog(
|
||||
offset = DpOffset(8.dp, 0.dp),
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(R.string.action_edit)) },
|
||||
text = { Text(text = localize(MR.strings.action_edit)) },
|
||||
onClick = {
|
||||
onEditClick(EditCoverAction.EDIT)
|
||||
expanded = false
|
||||
},
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(R.string.action_delete)) },
|
||||
text = { Text(text = localize(MR.strings.action_delete)) },
|
||||
onClick = {
|
||||
onEditClick(EditCoverAction.DELETE)
|
||||
expanded = false
|
||||
|
@ -65,8 +65,6 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.Layout
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.Constraints
|
||||
@ -79,8 +77,11 @@ import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.TextButton
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.i18n.localizePlural
|
||||
import tachiyomi.presentation.core.util.clickableNoIndication
|
||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
import kotlin.math.absoluteValue
|
||||
@ -180,9 +181,9 @@ fun MangaActionRow(
|
||||
Row(modifier = modifier.padding(start = 16.dp, top = 8.dp, end = 16.dp)) {
|
||||
MangaActionButton(
|
||||
title = if (favorite) {
|
||||
stringResource(R.string.in_library)
|
||||
localize(MR.strings.in_library)
|
||||
} else {
|
||||
stringResource(R.string.add_to_library)
|
||||
localize(MR.strings.add_to_library)
|
||||
},
|
||||
icon = if (favorite) Icons.Filled.Favorite else Icons.Outlined.FavoriteBorder,
|
||||
color = if (favorite) MaterialTheme.colorScheme.primary else defaultActionButtonColor,
|
||||
@ -191,8 +192,8 @@ fun MangaActionRow(
|
||||
)
|
||||
if (onEditIntervalClicked != null && fetchInterval != null) {
|
||||
MangaActionButton(
|
||||
title = pluralStringResource(
|
||||
id = R.plurals.day,
|
||||
title = localizePlural(
|
||||
MR.plurals.day,
|
||||
count = fetchInterval.absoluteValue,
|
||||
fetchInterval.absoluteValue,
|
||||
),
|
||||
@ -204,9 +205,9 @@ fun MangaActionRow(
|
||||
if (onTrackingClicked != null) {
|
||||
MangaActionButton(
|
||||
title = if (trackingCount == 0) {
|
||||
stringResource(R.string.manga_tracking_tab)
|
||||
localize(MR.strings.manga_tracking_tab)
|
||||
} else {
|
||||
pluralStringResource(id = R.plurals.num_trackers, count = trackingCount, trackingCount)
|
||||
localizePlural(MR.plurals.num_trackers, count = trackingCount, trackingCount)
|
||||
},
|
||||
icon = if (trackingCount == 0) Icons.Outlined.Sync else Icons.Outlined.Done,
|
||||
color = if (trackingCount == 0) defaultActionButtonColor else MaterialTheme.colorScheme.primary,
|
||||
@ -215,7 +216,7 @@ fun MangaActionRow(
|
||||
}
|
||||
if (onWebViewClicked != null) {
|
||||
MangaActionButton(
|
||||
title = stringResource(R.string.action_web_view),
|
||||
title = localize(MR.strings.action_web_view),
|
||||
icon = Icons.Outlined.Public,
|
||||
color = defaultActionButtonColor,
|
||||
onClick = onWebViewClicked,
|
||||
@ -253,7 +254,7 @@ fun ExpandableMangaDescription(
|
||||
mutableStateOf(defaultExpandState)
|
||||
}
|
||||
val desc =
|
||||
description.takeIf { !it.isNullOrBlank() } ?: stringResource(R.string.description_placeholder)
|
||||
description.takeIf { !it.isNullOrBlank() } ?: localize(MR.strings.description_placeholder)
|
||||
val trimmedDescription = remember(desc) {
|
||||
desc
|
||||
.replace(whitespaceLineRegex, "\n")
|
||||
@ -283,7 +284,7 @@ fun ExpandableMangaDescription(
|
||||
onDismissRequest = { showMenu = false },
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(R.string.action_search)) },
|
||||
text = { Text(text = localize(MR.strings.action_search)) },
|
||||
onClick = {
|
||||
onTagSearch(tagSelected)
|
||||
showMenu = false
|
||||
@ -299,7 +300,7 @@ fun ExpandableMangaDescription(
|
||||
)
|
||||
// SY <--
|
||||
DropdownMenuItem(
|
||||
text = { Text(text = stringResource(R.string.action_copy_to_clipboard)) },
|
||||
text = { Text(text = localize(MR.strings.action_copy_to_clipboard)) },
|
||||
onClick = {
|
||||
onCopyTagToClipboard(tagSelected)
|
||||
showMenu = false
|
||||
@ -378,7 +379,7 @@ private fun MangaAndSourceTitlesLarge(
|
||||
MangaCover.Book(
|
||||
modifier = Modifier.fillMaxWidth(0.65f),
|
||||
data = coverDataProvider(),
|
||||
contentDescription = stringResource(R.string.manga_cover),
|
||||
contentDescription = localize(MR.strings.manga_cover),
|
||||
onClick = onCoverClick,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
@ -420,7 +421,7 @@ private fun MangaAndSourceTitlesSmall(
|
||||
.sizeIn(maxWidth = 100.dp)
|
||||
.align(Alignment.Top),
|
||||
data = coverDataProvider(),
|
||||
contentDescription = stringResource(R.string.manga_cover),
|
||||
contentDescription = localize(MR.strings.manga_cover),
|
||||
onClick = onCoverClick,
|
||||
)
|
||||
Column(
|
||||
@ -452,7 +453,7 @@ private fun MangaContentInfo(
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
Text(
|
||||
text = title.ifBlank { stringResource(R.string.unknown_title) },
|
||||
text = title.ifBlank { localize(MR.strings.unknown_title) },
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier.clickableNoIndication(
|
||||
onLongClick = {
|
||||
@ -482,7 +483,7 @@ private fun MangaContentInfo(
|
||||
)
|
||||
Text(
|
||||
text = author?.takeIf { it.isNotBlank() }
|
||||
?: stringResource(R.string.unknown_author),
|
||||
?: localize(MR.strings.unknown_author),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
modifier = Modifier
|
||||
.clickableNoIndication(
|
||||
@ -548,13 +549,13 @@ private fun MangaContentInfo(
|
||||
ProvideTextStyle(MaterialTheme.typography.bodyMedium) {
|
||||
Text(
|
||||
text = when (status) {
|
||||
SManga.ONGOING.toLong() -> stringResource(R.string.ongoing)
|
||||
SManga.COMPLETED.toLong() -> stringResource(R.string.completed)
|
||||
SManga.LICENSED.toLong() -> stringResource(R.string.licensed)
|
||||
SManga.PUBLISHING_FINISHED.toLong() -> stringResource(R.string.publishing_finished)
|
||||
SManga.CANCELLED.toLong() -> stringResource(R.string.cancelled)
|
||||
SManga.ON_HIATUS.toLong() -> stringResource(R.string.on_hiatus)
|
||||
else -> stringResource(R.string.unknown)
|
||||
SManga.ONGOING.toLong() -> localize(MR.strings.ongoing)
|
||||
SManga.COMPLETED.toLong() -> localize(MR.strings.completed)
|
||||
SManga.LICENSED.toLong() -> localize(MR.strings.licensed)
|
||||
SManga.PUBLISHING_FINISHED.toLong() -> localize(MR.strings.publishing_finished)
|
||||
SManga.CANCELLED.toLong() -> localize(MR.strings.cancelled)
|
||||
SManga.ON_HIATUS.toLong() -> localize(MR.strings.on_hiatus)
|
||||
else -> localize(MR.strings.unknown)
|
||||
},
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
@ -628,8 +629,8 @@ private fun MangaSummary(
|
||||
val image = AnimatedImageVector.animatedVectorResource(R.drawable.anim_caret_down)
|
||||
Icon(
|
||||
painter = rememberAnimatedVectorPainter(image, !expanded),
|
||||
contentDescription = stringResource(
|
||||
if (expanded) R.string.manga_info_collapse else R.string.manga_info_expand,
|
||||
contentDescription = localize(
|
||||
if (expanded) MR.strings.manga_info_collapse else MR.strings.manga_info_expand,
|
||||
),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier.background(Brush.radialGradient(colors = colors.asReversed())),
|
||||
|
@ -21,7 +21,6 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
@ -29,8 +28,9 @@ import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.components.DownloadDropdownMenu
|
||||
import eu.kanade.presentation.components.UpIcon
|
||||
import eu.kanade.presentation.manga.DownloadAction
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.theme.active
|
||||
|
||||
@Composable
|
||||
@ -81,12 +81,12 @@ fun MangaToolbar(
|
||||
AppBarActions(
|
||||
persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_select_all),
|
||||
title = localize(MR.strings.action_select_all),
|
||||
icon = Icons.Outlined.SelectAll,
|
||||
onClick = onSelectAll,
|
||||
),
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_select_inverse),
|
||||
title = localize(MR.strings.action_select_inverse),
|
||||
icon = Icons.Outlined.FlipToBack,
|
||||
onClick = onInvertSelection,
|
||||
),
|
||||
@ -110,7 +110,7 @@ fun MangaToolbar(
|
||||
if (onClickDownload != null) {
|
||||
add(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.manga_download),
|
||||
title = localize(MR.strings.manga_download),
|
||||
icon = Icons.Outlined.Download,
|
||||
onClick = { downloadExpanded = !downloadExpanded },
|
||||
),
|
||||
@ -118,7 +118,7 @@ fun MangaToolbar(
|
||||
}
|
||||
add(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_filter),
|
||||
title = localize(MR.strings.action_filter),
|
||||
icon = Icons.Outlined.FilterList,
|
||||
iconTint = filterTint,
|
||||
onClick = onClickFilter,
|
||||
@ -126,14 +126,14 @@ fun MangaToolbar(
|
||||
)
|
||||
add(
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.action_webview_refresh),
|
||||
title = localize(MR.strings.action_webview_refresh),
|
||||
onClick = onClickRefresh,
|
||||
),
|
||||
)
|
||||
if (onClickEditCategory != null) {
|
||||
add(
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.action_edit_categories),
|
||||
title = localize(MR.strings.action_edit_categories),
|
||||
onClick = onClickEditCategory,
|
||||
),
|
||||
)
|
||||
@ -141,7 +141,7 @@ fun MangaToolbar(
|
||||
if (onClickMigrate != null) {
|
||||
add(
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.action_migrate),
|
||||
title = localize(MR.strings.action_migrate),
|
||||
onClick = onClickMigrate,
|
||||
),
|
||||
)
|
||||
@ -149,7 +149,7 @@ fun MangaToolbar(
|
||||
if (onClickShare != null) {
|
||||
add(
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.action_share),
|
||||
title = localize(MR.strings.action_share),
|
||||
onClick = onClickShare,
|
||||
),
|
||||
)
|
||||
|
@ -10,11 +10,11 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localizePlural
|
||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
|
||||
@Composable
|
||||
@ -34,7 +34,7 @@ fun MissingChapterCountListItem(
|
||||
) {
|
||||
HorizontalDivider(modifier = Modifier.weight(1f))
|
||||
Text(
|
||||
text = pluralStringResource(id = R.plurals.missing_chapters, count = count, count),
|
||||
text = localizePlural(MR.plurals.missing_chapters, count = count, count),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
HorizontalDivider(modifier = Modifier.weight(1f))
|
||||
|
@ -27,12 +27,12 @@ import androidx.compose.runtime.toMutableStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.TextButton
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.isScrolledToEnd
|
||||
import tachiyomi.presentation.core.util.isScrolledToStart
|
||||
|
||||
@ -49,10 +49,10 @@ fun ScanlatorFilterDialog(
|
||||
val mutableExcludedScanlators = remember(excludedScanlators) { excludedScanlators.toMutableStateList() }
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
title = { Text(text = stringResource(R.string.exclude_scanlators)) },
|
||||
title = { Text(text = localize(MR.strings.exclude_scanlators)) },
|
||||
text = textFunc@{
|
||||
if (sortedAvailableScanlators.isEmpty()) {
|
||||
Text(text = stringResource(R.string.no_scanlators_found))
|
||||
Text(text = localize(MR.strings.no_scanlators_found))
|
||||
return@textFunc
|
||||
}
|
||||
Box {
|
||||
@ -108,16 +108,16 @@ fun ScanlatorFilterDialog(
|
||||
confirmButton = {
|
||||
if (sortedAvailableScanlators.isEmpty()) {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
} else {
|
||||
FlowRow {
|
||||
TextButton(onClick = mutableExcludedScanlators::clear) {
|
||||
Text(text = stringResource(R.string.action_reset))
|
||||
Text(text = localize(MR.strings.action_reset))
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
TextButton(
|
||||
onClick = {
|
||||
@ -125,7 +125,7 @@ fun ScanlatorFilterDialog(
|
||||
onDismissRequest()
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
Text(text = localize(MR.strings.action_ok))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import com.halilibo.richtext.markdown.Markdown
|
||||
@ -22,8 +21,9 @@ import com.halilibo.richtext.ui.RichTextStyle
|
||||
import com.halilibo.richtext.ui.material3.Material3RichText
|
||||
import com.halilibo.richtext.ui.string.RichTextStringStyle
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.screens.InfoScreen
|
||||
|
||||
@Composable
|
||||
@ -36,11 +36,11 @@ fun NewUpdateScreen(
|
||||
) {
|
||||
InfoScreen(
|
||||
icon = Icons.Outlined.NewReleases,
|
||||
headingText = stringResource(R.string.update_check_notification_update_available),
|
||||
headingText = localize(MR.strings.update_check_notification_update_available),
|
||||
subtitleText = versionName,
|
||||
acceptText = stringResource(R.string.update_check_confirm),
|
||||
acceptText = localize(MR.strings.update_check_confirm),
|
||||
onAcceptClick = onAcceptUpdate,
|
||||
rejectText = stringResource(R.string.action_not_now),
|
||||
rejectText = localize(MR.strings.action_not_now),
|
||||
onRejectClick = onRejectUpdate,
|
||||
) {
|
||||
Material3RichText(
|
||||
@ -59,7 +59,7 @@ fun NewUpdateScreen(
|
||||
onClick = onOpenInBrowser,
|
||||
modifier = Modifier.padding(top = MaterialTheme.padding.small),
|
||||
) {
|
||||
Text(text = stringResource(R.string.update_check_open))
|
||||
Text(text = localize(MR.strings.update_check_open))
|
||||
Spacer(modifier = Modifier.width(MaterialTheme.padding.tiny))
|
||||
Icon(imageVector = Icons.AutoMirrored.Outlined.OpenInNew, contentDescription = null)
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ package eu.kanade.presentation.more.settings
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.core.preference.Preference as PreferenceData
|
||||
|
||||
sealed class Preference {
|
||||
@ -112,7 +112,7 @@ sealed class Preference {
|
||||
v.map { e[it] }
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?.joinToString()
|
||||
} ?: stringResource(R.string.none)
|
||||
} ?: localize(MR.strings.none)
|
||||
subtitle?.format(combined)
|
||||
},
|
||||
override val icon: ImageVector? = null,
|
||||
|
@ -1,15 +1,15 @@
|
||||
package eu.kanade.presentation.more.settings
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun PreferenceScaffold(
|
||||
@StringRes titleRes: Int,
|
||||
titleRes: StringResource,
|
||||
actions: @Composable RowScope.() -> Unit = {},
|
||||
onBackPressed: (() -> Unit)? = null,
|
||||
itemsProvider: @Composable () -> List<Preference>,
|
||||
@ -17,7 +17,7 @@ fun PreferenceScaffold(
|
||||
Scaffold(
|
||||
topBar = {
|
||||
AppBar(
|
||||
title = stringResource(titleRes),
|
||||
title = localize(titleRes),
|
||||
navigateUp = onBackPressed,
|
||||
actions = actions,
|
||||
scrollBehavior = it,
|
||||
|
@ -3,10 +3,10 @@ package eu.kanade.presentation.more.settings.screen
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.category.visualName
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
/**
|
||||
* Returns a string of categories name for settings subtitle
|
||||
@ -34,15 +34,15 @@ fun getCategoriesLabel(
|
||||
includedCategories.isNotEmpty() && includedCategories.size != allCategories.size ->
|
||||
includedCategories.joinToString { it.visualName(context) }
|
||||
// All explicitly selected
|
||||
includedCategories.size == allCategories.size -> stringResource(R.string.all)
|
||||
allExcluded -> stringResource(R.string.none)
|
||||
else -> stringResource(R.string.all)
|
||||
includedCategories.size == allCategories.size -> localize(MR.strings.all)
|
||||
allExcluded -> localize(MR.strings.none)
|
||||
else -> localize(MR.strings.all)
|
||||
}
|
||||
val excludedItemsText = when {
|
||||
excludedCategories.isEmpty() -> stringResource(R.string.none)
|
||||
allExcluded -> stringResource(R.string.all)
|
||||
excludedCategories.isEmpty() -> localize(MR.strings.none)
|
||||
allExcluded -> localize(MR.strings.all)
|
||||
else -> excludedCategories.joinToString { it.visualName(context) }
|
||||
}
|
||||
return stringResource(R.string.include, includedItemsText) + "\n" +
|
||||
stringResource(R.string.exclude, excludedItemsText)
|
||||
return localize(MR.strings.include, includedItemsText) + "\n" +
|
||||
localize(MR.strings.exclude, excludedItemsText)
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package eu.kanade.presentation.more.settings.screen
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.more.settings.PreferenceScaffold
|
||||
import eu.kanade.presentation.util.LocalBackPress
|
||||
@ -13,8 +13,7 @@ interface SearchableSettings : Screen {
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
@StringRes
|
||||
fun getTitleRes(): Int
|
||||
fun getTitleRes(): StringResource
|
||||
|
||||
@Composable
|
||||
fun getPreferences(): List<Preference>
|
||||
|
@ -3,7 +3,6 @@ package eu.kanade.presentation.more.settings.screen
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@ -13,7 +12,6 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.os.LocaleListCompat
|
||||
import eu.kanade.domain.ui.UiPreferences
|
||||
@ -29,6 +27,9 @@ import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@ -38,8 +39,7 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
|
||||
@ReadOnlyComposable
|
||||
@Composable
|
||||
@StringRes
|
||||
override fun getTitleRes() = R.string.pref_category_appearance
|
||||
override fun getTitleRes() = MR.strings.pref_category_appearance
|
||||
|
||||
@Composable
|
||||
override fun getPreferences(): List<Preference> {
|
||||
@ -80,26 +80,26 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
}
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.pref_category_theme),
|
||||
title = localize(MR.strings.pref_category_theme),
|
||||
preferenceItems = listOf(
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
pref = themeModePref,
|
||||
title = stringResource(R.string.pref_theme_mode),
|
||||
title = localize(MR.strings.pref_theme_mode),
|
||||
entries = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
mapOf(
|
||||
ThemeMode.SYSTEM to stringResource(R.string.theme_system),
|
||||
ThemeMode.LIGHT to stringResource(R.string.theme_light),
|
||||
ThemeMode.DARK to stringResource(R.string.theme_dark),
|
||||
ThemeMode.SYSTEM to localize(MR.strings.theme_system),
|
||||
ThemeMode.LIGHT to localize(MR.strings.theme_light),
|
||||
ThemeMode.DARK to localize(MR.strings.theme_dark),
|
||||
)
|
||||
} else {
|
||||
mapOf(
|
||||
ThemeMode.LIGHT to stringResource(R.string.theme_light),
|
||||
ThemeMode.DARK to stringResource(R.string.theme_dark),
|
||||
ThemeMode.LIGHT to localize(MR.strings.theme_light),
|
||||
ThemeMode.DARK to localize(MR.strings.theme_dark),
|
||||
)
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.CustomPreference(
|
||||
title = stringResource(R.string.pref_app_theme),
|
||||
title = localize(MR.strings.pref_app_theme),
|
||||
) { item ->
|
||||
val value by appThemePref.collectAsState()
|
||||
AppThemePreferenceWidget(
|
||||
@ -111,7 +111,7 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
},
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = amoledPref,
|
||||
title = stringResource(R.string.pref_dark_theme_pure_black),
|
||||
title = localize(MR.strings.pref_dark_theme_pure_black),
|
||||
enabled = themeMode != ThemeMode.LIGHT,
|
||||
),
|
||||
),
|
||||
@ -144,11 +144,11 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
}
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.pref_category_display),
|
||||
title = localize(MR.strings.pref_category_display),
|
||||
preferenceItems = listOf(
|
||||
Preference.PreferenceItem.BasicListPreference(
|
||||
value = currentLanguage,
|
||||
title = stringResource(R.string.pref_app_language),
|
||||
title = localize(MR.strings.pref_app_language),
|
||||
entries = langs,
|
||||
onValueChanged = { newValue ->
|
||||
currentLanguage = newValue
|
||||
@ -157,28 +157,28 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
pref = uiPreferences.tabletUiMode(),
|
||||
title = stringResource(R.string.pref_tablet_ui_mode),
|
||||
entries = TabletUiMode.entries.associateWith { stringResource(it.titleResId) },
|
||||
title = localize(MR.strings.pref_tablet_ui_mode),
|
||||
entries = TabletUiMode.entries.associateWith { localize(it.titleRes) },
|
||||
onValueChanged = {
|
||||
context.toast(R.string.requires_app_restart)
|
||||
context.toast(MR.strings.requires_app_restart)
|
||||
true
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
pref = uiPreferences.dateFormat(),
|
||||
title = stringResource(R.string.pref_date_format),
|
||||
title = localize(MR.strings.pref_date_format),
|
||||
entries = DateFormats
|
||||
.associateWith {
|
||||
val formattedDate = UiPreferences.dateFormat(it).format(now)
|
||||
"${it.ifEmpty { stringResource(R.string.label_default) }} ($formattedDate)"
|
||||
"${it.ifEmpty { localize(MR.strings.label_default) }} ($formattedDate)"
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = uiPreferences.relativeTime(),
|
||||
title = stringResource(R.string.pref_relative_format),
|
||||
subtitle = stringResource(
|
||||
R.string.pref_relative_format_summary,
|
||||
stringResource(R.string.relative_time_today),
|
||||
title = localize(MR.strings.pref_relative_format),
|
||||
subtitle = localize(
|
||||
MR.strings.pref_relative_format_summary,
|
||||
localize(MR.strings.relative_time_today),
|
||||
formattedNow,
|
||||
),
|
||||
),
|
||||
@ -205,7 +205,7 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
}
|
||||
|
||||
langs.sortBy { it.second }
|
||||
langs.add(0, Pair("", context.getString(R.string.label_default)))
|
||||
langs.add(0, Pair("", context.localize(MR.strings.label_default)))
|
||||
|
||||
return langs.toMap()
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import android.text.format.Formatter
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@ -27,7 +26,6 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
@ -36,7 +34,6 @@ import eu.kanade.presentation.more.settings.widget.BasePreferenceWidget
|
||||
import eu.kanade.presentation.more.settings.widget.PrefsHorizontalPadding
|
||||
import eu.kanade.presentation.permissions.PermissionRequestHelper
|
||||
import eu.kanade.presentation.util.relativeTimeSpanString
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.backup.BackupCreateJob
|
||||
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
|
||||
@ -47,11 +44,14 @@ import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.core.util.lang.launchNonCancellable
|
||||
import tachiyomi.core.util.lang.withUIContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.backup.service.BackupPreferences
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@ -60,8 +60,7 @@ object SettingsDataScreen : SearchableSettings {
|
||||
|
||||
@ReadOnlyComposable
|
||||
@Composable
|
||||
@StringRes
|
||||
override fun getTitleRes() = R.string.label_data_storage
|
||||
override fun getTitleRes() = MR.strings.label_data_storage
|
||||
|
||||
@Composable
|
||||
override fun getPreferences(): List<Preference> {
|
||||
@ -83,7 +82,7 @@ object SettingsDataScreen : SearchableSettings {
|
||||
val lastAutoBackup by backupPreferences.lastAutoBackupTimestamp().collectAsState()
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.label_backup),
|
||||
title = localize(MR.strings.label_backup),
|
||||
preferenceItems = listOf(
|
||||
// Manual actions
|
||||
getCreateBackupPref(),
|
||||
@ -92,14 +91,14 @@ object SettingsDataScreen : SearchableSettings {
|
||||
// Automatic backups
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
pref = backupIntervalPref,
|
||||
title = stringResource(R.string.pref_backup_interval),
|
||||
title = localize(MR.strings.pref_backup_interval),
|
||||
entries = mapOf(
|
||||
0 to stringResource(R.string.off),
|
||||
6 to stringResource(R.string.update_6hour),
|
||||
12 to stringResource(R.string.update_12hour),
|
||||
24 to stringResource(R.string.update_24hour),
|
||||
48 to stringResource(R.string.update_48hour),
|
||||
168 to stringResource(R.string.update_weekly),
|
||||
0 to localize(MR.strings.off),
|
||||
6 to localize(MR.strings.update_6hour),
|
||||
12 to localize(MR.strings.update_12hour),
|
||||
24 to localize(MR.strings.update_24hour),
|
||||
48 to localize(MR.strings.update_48hour),
|
||||
168 to localize(MR.strings.update_weekly),
|
||||
),
|
||||
onValueChanged = {
|
||||
BackupCreateJob.setupTask(context, it)
|
||||
@ -109,12 +108,12 @@ object SettingsDataScreen : SearchableSettings {
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
pref = backupPreferences.numberOfBackups(),
|
||||
enabled = backupInterval != 0,
|
||||
title = stringResource(R.string.pref_backup_slots),
|
||||
title = localize(MR.strings.pref_backup_slots),
|
||||
entries = listOf(2, 3, 4, 5).associateWith { it.toString() },
|
||||
),
|
||||
Preference.PreferenceItem.InfoPreference(
|
||||
stringResource(R.string.backup_info) + "\n\n" +
|
||||
stringResource(R.string.last_auto_backup_info, relativeTimeSpanString(lastAutoBackup)),
|
||||
localize(MR.strings.backup_info) + "\n\n" +
|
||||
localize(MR.strings.last_auto_backup_info, relativeTimeSpanString(lastAutoBackup)),
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -124,8 +123,8 @@ object SettingsDataScreen : SearchableSettings {
|
||||
private fun getCreateBackupPref(): Preference.PreferenceItem.TextPreference {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
return Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(R.string.pref_create_backup),
|
||||
subtitle = stringResource(R.string.pref_create_backup_summ),
|
||||
title = localize(MR.strings.pref_create_backup),
|
||||
subtitle = localize(MR.strings.pref_create_backup_summ),
|
||||
onClick = { navigator.push(CreateBackupScreen()) },
|
||||
)
|
||||
}
|
||||
@ -140,7 +139,7 @@ object SettingsDataScreen : SearchableSettings {
|
||||
is InvalidRestore -> {
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
title = { Text(text = stringResource(R.string.invalid_backup_file)) },
|
||||
title = { Text(text = localize(MR.strings.invalid_backup_file)) },
|
||||
text = { Text(text = listOfNotNull(err.uri, err.message).joinToString("\n\n")) },
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
@ -149,12 +148,12 @@ object SettingsDataScreen : SearchableSettings {
|
||||
onDismissRequest()
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_copy_to_clipboard))
|
||||
Text(text = localize(MR.strings.action_copy_to_clipboard))
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
Text(text = localize(MR.strings.action_ok))
|
||||
}
|
||||
},
|
||||
)
|
||||
@ -162,15 +161,15 @@ object SettingsDataScreen : SearchableSettings {
|
||||
is MissingRestoreComponents -> {
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
title = { Text(text = stringResource(R.string.pref_restore_backup)) },
|
||||
title = { Text(text = localize(MR.strings.pref_restore_backup)) },
|
||||
text = {
|
||||
Column(
|
||||
modifier = Modifier.verticalScroll(rememberScrollState()),
|
||||
) {
|
||||
val msg = buildString {
|
||||
append(stringResource(R.string.backup_restore_content_full))
|
||||
append(localize(MR.strings.backup_restore_content_full))
|
||||
if (err.sources.isNotEmpty()) {
|
||||
append("\n\n").append(stringResource(R.string.backup_restore_missing_sources))
|
||||
append("\n\n").append(localize(MR.strings.backup_restore_missing_sources))
|
||||
err.sources.joinTo(
|
||||
this,
|
||||
separator = "\n- ",
|
||||
@ -178,7 +177,7 @@ object SettingsDataScreen : SearchableSettings {
|
||||
)
|
||||
}
|
||||
if (err.trackers.isNotEmpty()) {
|
||||
append("\n\n").append(stringResource(R.string.backup_restore_missing_trackers))
|
||||
append("\n\n").append(localize(MR.strings.backup_restore_missing_trackers))
|
||||
err.trackers.joinTo(
|
||||
this,
|
||||
separator = "\n- ",
|
||||
@ -196,7 +195,7 @@ object SettingsDataScreen : SearchableSettings {
|
||||
onDismissRequest()
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_restore))
|
||||
Text(text = localize(MR.strings.action_restore))
|
||||
}
|
||||
},
|
||||
)
|
||||
@ -209,12 +208,12 @@ object SettingsDataScreen : SearchableSettings {
|
||||
object : ActivityResultContracts.GetContent() {
|
||||
override fun createIntent(context: Context, input: String): Intent {
|
||||
val intent = super.createIntent(context, input)
|
||||
return Intent.createChooser(intent, context.getString(R.string.file_select_backup))
|
||||
return Intent.createChooser(intent, context.localize(MR.strings.file_select_backup))
|
||||
}
|
||||
},
|
||||
) {
|
||||
if (it == null) {
|
||||
context.toast(R.string.file_null_uri_error)
|
||||
context.toast(MR.strings.file_null_uri_error)
|
||||
return@rememberLauncherForActivityResult
|
||||
}
|
||||
|
||||
@ -234,17 +233,17 @@ object SettingsDataScreen : SearchableSettings {
|
||||
}
|
||||
|
||||
return Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(R.string.pref_restore_backup),
|
||||
subtitle = stringResource(R.string.pref_restore_backup_summ),
|
||||
title = localize(MR.strings.pref_restore_backup),
|
||||
subtitle = localize(MR.strings.pref_restore_backup_summ),
|
||||
onClick = {
|
||||
if (!BackupRestoreJob.isRunning(context)) {
|
||||
if (DeviceUtil.isMiui && DeviceUtil.isMiuiOptimizationDisabled()) {
|
||||
context.toast(R.string.restore_miui_warning, Toast.LENGTH_LONG)
|
||||
context.toast(MR.strings.restore_miui_warning, Toast.LENGTH_LONG)
|
||||
}
|
||||
// no need to catch because it's wrapped with a chooser
|
||||
chooseBackup.launch("*/*")
|
||||
} else {
|
||||
context.toast(R.string.restore_in_progress)
|
||||
context.toast(MR.strings.restore_in_progress)
|
||||
}
|
||||
},
|
||||
)
|
||||
@ -267,24 +266,24 @@ object SettingsDataScreen : SearchableSettings {
|
||||
// SY <--
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.label_data),
|
||||
title = localize(MR.strings.label_data),
|
||||
preferenceItems = listOf(
|
||||
getStorageInfoPref(cacheReadableSize),
|
||||
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(R.string.pref_clear_chapter_cache),
|
||||
subtitle = stringResource(R.string.used_cache, cacheReadableSize),
|
||||
title = localize(MR.strings.pref_clear_chapter_cache),
|
||||
subtitle = localize(MR.strings.used_cache, cacheReadableSize),
|
||||
onClick = {
|
||||
scope.launchNonCancellable {
|
||||
try {
|
||||
val deletedFiles = chapterCache.clear()
|
||||
withUIContext {
|
||||
context.toast(context.getString(R.string.cache_deleted, deletedFiles))
|
||||
context.toast(context.localize(MR.strings.cache_deleted, deletedFiles))
|
||||
cacheReadableSizeSema++
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
logcat(LogPriority.ERROR, e)
|
||||
withUIContext { context.toast(R.string.cache_delete_error) }
|
||||
withUIContext { context.toast(MR.strings.cache_delete_error) }
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -311,7 +310,7 @@ object SettingsDataScreen : SearchableSettings {
|
||||
// SY <--
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = libraryPreferences.autoClearChapterCache(),
|
||||
title = stringResource(R.string.pref_auto_clear_chapter_cache),
|
||||
title = localize(MR.strings.pref_auto_clear_chapter_cache),
|
||||
),
|
||||
),
|
||||
)
|
||||
@ -330,10 +329,10 @@ object SettingsDataScreen : SearchableSettings {
|
||||
}
|
||||
|
||||
return Preference.PreferenceItem.CustomPreference(
|
||||
title = stringResource(R.string.pref_storage_usage),
|
||||
title = localize(MR.strings.pref_storage_usage),
|
||||
) {
|
||||
BasePreferenceWidget(
|
||||
title = stringResource(R.string.pref_storage_usage),
|
||||
title = localize(MR.strings.pref_storage_usage),
|
||||
subcomponent = {
|
||||
// TODO: downloads, SD cards, bar representation?, i18n
|
||||
Box(modifier = Modifier.padding(horizontal = PrefsHorizontalPadding)) {
|
||||
|
@ -4,7 +4,6 @@ import android.content.Intent
|
||||
import android.os.Environment
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
@ -14,19 +13,19 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.util.fastMap
|
||||
import androidx.core.net.toUri
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.presentation.category.visualName
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.more.settings.widget.TriStateListDialog
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.domain.download.service.DownloadPreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.i18n.localizePlural
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@ -36,8 +35,7 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
|
||||
@ReadOnlyComposable
|
||||
@Composable
|
||||
@StringRes
|
||||
override fun getTitleRes() = R.string.pref_category_downloads
|
||||
override fun getTitleRes() = MR.strings.pref_category_downloads
|
||||
|
||||
@Composable
|
||||
override fun getPreferences(): List<Preference> {
|
||||
@ -49,16 +47,16 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
getDownloadLocationPreference(downloadPreferences = downloadPreferences),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = downloadPreferences.downloadOnlyOverWifi(),
|
||||
title = stringResource(R.string.connected_to_wifi),
|
||||
title = localize(MR.strings.connected_to_wifi),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = downloadPreferences.saveChaptersAsCBZ(),
|
||||
title = stringResource(R.string.save_chapter_as_cbz),
|
||||
title = localize(MR.strings.save_chapter_as_cbz),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = downloadPreferences.splitTallImages(),
|
||||
title = stringResource(R.string.split_tall_images),
|
||||
subtitle = stringResource(R.string.split_tall_images_summary),
|
||||
title = localize(MR.strings.split_tall_images),
|
||||
subtitle = localize(MR.strings.split_tall_images_summary),
|
||||
),
|
||||
getDeleteChaptersGroup(
|
||||
downloadPreferences = downloadPreferences,
|
||||
@ -99,15 +97,15 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
|
||||
return Preference.PreferenceItem.ListPreference(
|
||||
pref = currentDirPref,
|
||||
title = stringResource(R.string.pref_download_directory),
|
||||
title = localize(MR.strings.pref_download_directory),
|
||||
subtitleProvider = { value, _ ->
|
||||
remember(value) {
|
||||
UniFile.fromUri(context, value.toUri())?.filePath
|
||||
} ?: stringResource(R.string.invalid_location, value)
|
||||
} ?: localize(MR.strings.invalid_location, value)
|
||||
},
|
||||
entries = mapOf(
|
||||
defaultDirPair,
|
||||
customDirEntryKey to stringResource(R.string.custom_dir),
|
||||
customDirEntryKey to localize(MR.strings.custom_dir),
|
||||
),
|
||||
onValueChanged = {
|
||||
val default = it == defaultDirPair.first
|
||||
@ -121,7 +119,7 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
|
||||
@Composable
|
||||
private fun rememberDefaultDownloadDir(): Pair<String, String> {
|
||||
val appName = stringResource(R.string.app_name)
|
||||
val appName = localize(MR.strings.app_name)
|
||||
return remember {
|
||||
val file = UniFile.fromFile(
|
||||
File(
|
||||
@ -139,27 +137,27 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
categories: List<Category>,
|
||||
): Preference.PreferenceGroup {
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.pref_category_delete_chapters),
|
||||
title = localize(MR.strings.pref_category_delete_chapters),
|
||||
preferenceItems = listOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = downloadPreferences.removeAfterMarkedAsRead(),
|
||||
title = stringResource(R.string.pref_remove_after_marked_as_read),
|
||||
title = localize(MR.strings.pref_remove_after_marked_as_read),
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
pref = downloadPreferences.removeAfterReadSlots(),
|
||||
title = stringResource(R.string.pref_remove_after_read),
|
||||
title = localize(MR.strings.pref_remove_after_read),
|
||||
entries = mapOf(
|
||||
-1 to stringResource(R.string.disabled),
|
||||
0 to stringResource(R.string.last_read_chapter),
|
||||
1 to stringResource(R.string.second_to_last),
|
||||
2 to stringResource(R.string.third_to_last),
|
||||
3 to stringResource(R.string.fourth_to_last),
|
||||
4 to stringResource(R.string.fifth_to_last),
|
||||
-1 to localize(MR.strings.disabled),
|
||||
0 to localize(MR.strings.last_read_chapter),
|
||||
1 to localize(MR.strings.second_to_last),
|
||||
2 to localize(MR.strings.third_to_last),
|
||||
3 to localize(MR.strings.fourth_to_last),
|
||||
4 to localize(MR.strings.fifth_to_last),
|
||||
),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = downloadPreferences.removeBookmarkedChapters(),
|
||||
title = stringResource(R.string.pref_remove_bookmarked_chapters),
|
||||
title = localize(MR.strings.pref_remove_bookmarked_chapters),
|
||||
),
|
||||
getExcludedCategoriesPreference(
|
||||
downloadPreferences = downloadPreferences,
|
||||
@ -176,7 +174,7 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
): Preference.PreferenceItem.MultiSelectListPreference {
|
||||
return Preference.PreferenceItem.MultiSelectListPreference(
|
||||
pref = downloadPreferences.removeExcludeCategories(),
|
||||
title = stringResource(R.string.pref_remove_exclude_categories),
|
||||
title = localize(MR.strings.pref_remove_exclude_categories),
|
||||
entries = categories().associate { it.id.toString() to it.visualName },
|
||||
)
|
||||
}
|
||||
@ -197,8 +195,8 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
var showDialog by rememberSaveable { mutableStateOf(false) }
|
||||
if (showDialog) {
|
||||
TriStateListDialog(
|
||||
title = stringResource(R.string.categories),
|
||||
message = stringResource(R.string.pref_download_new_categories_details),
|
||||
title = localize(MR.strings.categories),
|
||||
message = localize(MR.strings.pref_download_new_categories_details),
|
||||
items = allCategories,
|
||||
initialChecked = included.mapNotNull { id -> allCategories.find { it.id.toString() == id } },
|
||||
initialInversed = excluded.mapNotNull { id -> allCategories.find { it.id.toString() == id } },
|
||||
@ -213,14 +211,14 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
}
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.pref_category_auto_download),
|
||||
title = localize(MR.strings.pref_category_auto_download),
|
||||
preferenceItems = listOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = downloadNewChaptersPref,
|
||||
title = stringResource(R.string.pref_download_new),
|
||||
title = localize(MR.strings.pref_download_new),
|
||||
),
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(R.string.categories),
|
||||
title = localize(MR.strings.categories),
|
||||
subtitle = getCategoriesLabel(
|
||||
allCategories = allCategories,
|
||||
included = included,
|
||||
@ -238,20 +236,20 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
downloadPreferences: DownloadPreferences,
|
||||
): Preference.PreferenceGroup {
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.download_ahead),
|
||||
title = localize(MR.strings.download_ahead),
|
||||
preferenceItems = listOf(
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
pref = downloadPreferences.autoDownloadWhileReading(),
|
||||
title = stringResource(R.string.auto_download_while_reading),
|
||||
title = localize(MR.strings.auto_download_while_reading),
|
||||
entries = listOf(0, 2, 3, 5, 10).associateWith {
|
||||
if (it == 0) {
|
||||
stringResource(R.string.disabled)
|
||||
localize(MR.strings.disabled)
|
||||
} else {
|
||||
pluralStringResource(id = R.plurals.next_unread_chapters, count = it, it)
|
||||
localizePlural(MR.plurals.next_unread_chapters, count = it, it)
|
||||
}
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.download_ahead_info)),
|
||||
Preference.PreferenceItem.InfoPreference(localize(MR.strings.download_ahead_info)),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
@ -53,8 +52,9 @@ import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.presentation.components.UpIcon
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.util.runOnEnterKeyPressed
|
||||
import cafe.adriel.voyager.core.screen.Screen as VoyagerScreen
|
||||
@ -118,7 +118,7 @@ class SettingsSearchScreen : Screen() {
|
||||
decorationBox = {
|
||||
if (textFieldValue.text.isEmpty()) {
|
||||
Text(
|
||||
text = stringResource(R.string.action_search_settings),
|
||||
text = localize(MR.strings.action_search_settings),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
@ -215,7 +215,7 @@ private fun SearchResult(
|
||||
when {
|
||||
it == null -> {}
|
||||
it.isEmpty() -> {
|
||||
EmptyScreen(stringResource(R.string.no_results_found))
|
||||
EmptyScreen(localize(MR.strings.no_results_found))
|
||||
}
|
||||
else -> {
|
||||
LazyColumn(
|
||||
@ -264,7 +264,7 @@ private fun getIndex() = settingScreens
|
||||
// SY <--
|
||||
.map { screen ->
|
||||
SettingsData(
|
||||
title = stringResource(screen.getTitleRes()),
|
||||
title = localize(screen.getTitleRes()),
|
||||
route = screen,
|
||||
contents = screen.getPreferences(),
|
||||
)
|
||||
|
@ -1,7 +1,6 @@
|
||||
package eu.kanade.presentation.more.settings.screen
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@ -13,7 +12,6 @@ import androidx.compose.material.icons.automirrored.outlined.HelpOutline
|
||||
import androidx.compose.material.icons.filled.Visibility
|
||||
import androidx.compose.material.icons.filled.VisibilityOff
|
||||
import androidx.compose.material.icons.outlined.Close
|
||||
import androidx.compose.material.icons.outlined.HelpOutline
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
@ -34,7 +32,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
@ -42,9 +39,9 @@ import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.domain.track.service.TrackPreferences
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.EnhancedTracker
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
@ -57,7 +54,9 @@ import eu.kanade.tachiyomi.util.system.toast
|
||||
import tachiyomi.core.util.lang.launchIO
|
||||
import tachiyomi.core.util.lang.withUIContext
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@ -65,8 +64,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
|
||||
@ReadOnlyComposable
|
||||
@Composable
|
||||
@StringRes
|
||||
override fun getTitleRes() = R.string.pref_category_tracking
|
||||
override fun getTitleRes() = MR.strings.pref_category_tracking
|
||||
|
||||
@Composable
|
||||
override fun RowScope.AppBarAction() {
|
||||
@ -74,7 +72,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
IconButton(onClick = { uriHandler.openUri("https://tachiyomi.org/docs/guides/tracking") }) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Outlined.HelpOutline,
|
||||
contentDescription = stringResource(R.string.tracking_guide),
|
||||
contentDescription = localize(MR.strings.tracking_guide),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -111,10 +109,10 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
val acceptedSources = (service as EnhancedTracker).getAcceptedSources()
|
||||
sourceManager.getCatalogueSources().any { it::class.qualifiedName in acceptedSources }
|
||||
}
|
||||
var enhancedTrackerInfo = stringResource(R.string.enhanced_tracking_info)
|
||||
var enhancedTrackerInfo = localize(MR.strings.enhanced_tracking_info)
|
||||
if (enhancedTrackers.second.isNotEmpty()) {
|
||||
val missingSourcesInfo = stringResource(
|
||||
R.string.enhanced_services_not_installed,
|
||||
val missingSourcesInfo = localize(
|
||||
MR.strings.enhanced_services_not_installed,
|
||||
enhancedTrackers.second.joinToString { it.name },
|
||||
)
|
||||
enhancedTrackerInfo += "\n\n$missingSourcesInfo"
|
||||
@ -123,10 +121,10 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
return listOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
pref = trackPreferences.autoUpdateTrack(),
|
||||
title = stringResource(R.string.pref_auto_update_manga_sync),
|
||||
title = localize(MR.strings.pref_auto_update_manga_sync),
|
||||
),
|
||||
Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.services),
|
||||
title = localize(MR.strings.services),
|
||||
preferenceItems = listOf(
|
||||
Preference.PreferenceItem.TrackerPreference(
|
||||
title = trackerManager.myAnimeList.name,
|
||||
@ -143,13 +141,13 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
Preference.PreferenceItem.TrackerPreference(
|
||||
title = trackerManager.kitsu.name,
|
||||
tracker = trackerManager.kitsu,
|
||||
login = { dialog = LoginDialog(trackerManager.kitsu, R.string.email) },
|
||||
login = { dialog = LoginDialog(trackerManager.kitsu, MR.strings.email) },
|
||||
logout = { dialog = LogoutDialog(trackerManager.kitsu) },
|
||||
),
|
||||
Preference.PreferenceItem.TrackerPreference(
|
||||
title = trackerManager.mangaUpdates.name,
|
||||
tracker = trackerManager.mangaUpdates,
|
||||
login = { dialog = LoginDialog(trackerManager.mangaUpdates, R.string.username) },
|
||||
login = { dialog = LoginDialog(trackerManager.mangaUpdates, MR.strings.username) },
|
||||
logout = { dialog = LogoutDialog(trackerManager.mangaUpdates) },
|
||||
),
|
||||
Preference.PreferenceItem.TrackerPreference(
|
||||
@ -164,11 +162,11 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
login = { context.openInBrowser(BangumiApi.authUrl(), forceDefaultBrowser = true) },
|
||||
logout = { dialog = LogoutDialog(trackerManager.bangumi) },
|
||||
),
|
||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.tracking_info)),
|
||||
Preference.PreferenceItem.InfoPreference(localize(MR.strings.tracking_info)),
|
||||
),
|
||||
),
|
||||
Preference.PreferenceGroup(
|
||||
title = stringResource(R.string.enhanced_services),
|
||||
title = localize(MR.strings.enhanced_services),
|
||||
preferenceItems = enhancedTrackers.first
|
||||
.map { service ->
|
||||
Preference.PreferenceItem.TrackerPreference(
|
||||
@ -185,7 +183,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
@Composable
|
||||
private fun TrackingLoginDialog(
|
||||
tracker: Tracker,
|
||||
@StringRes uNameStringRes: Int,
|
||||
uNameStringRes: StringResource,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
@ -201,13 +199,13 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
title = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
text = stringResource(R.string.login_title, tracker.name),
|
||||
text = localize(MR.strings.login_title, tracker.name),
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
IconButton(onClick = onDismissRequest) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Close,
|
||||
contentDescription = stringResource(R.string.action_close),
|
||||
contentDescription = localize(MR.strings.action_close),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -218,7 +216,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = username,
|
||||
onValueChange = { username = it },
|
||||
label = { Text(text = stringResource(uNameStringRes)) },
|
||||
label = { Text(text = localize(uNameStringRes)) },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
||||
singleLine = true,
|
||||
isError = inputError && !processing,
|
||||
@ -229,7 +227,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = password,
|
||||
onValueChange = { password = it },
|
||||
label = { Text(text = stringResource(R.string.password)) },
|
||||
label = { Text(text = localize(MR.strings.password)) },
|
||||
trailingIcon = {
|
||||
IconButton(onClick = { hidePassword = !hidePassword }) {
|
||||
Icon(
|
||||
@ -275,8 +273,8 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
}
|
||||
},
|
||||
) {
|
||||
val id = if (processing) R.string.loading else R.string.login
|
||||
Text(text = stringResource(id))
|
||||
val id = if (processing) MR.strings.loading else MR.strings.login
|
||||
Text(text = localize(id))
|
||||
}
|
||||
},
|
||||
)
|
||||
@ -290,7 +288,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
): Boolean {
|
||||
return try {
|
||||
tracker.login(username, password)
|
||||
withUIContext { context.toast(R.string.login_success) }
|
||||
withUIContext { context.toast(MR.strings.login_success) }
|
||||
true
|
||||
} catch (e: Throwable) {
|
||||
tracker.logout()
|
||||
@ -309,7 +307,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
onDismissRequest = onDismissRequest,
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(R.string.logout_title, tracker.name),
|
||||
text = localize(MR.strings.logout_title, tracker.name),
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
@ -320,21 +318,21 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
modifier = Modifier.weight(1f),
|
||||
onClick = onDismissRequest,
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
Button(
|
||||
modifier = Modifier.weight(1f),
|
||||
onClick = {
|
||||
tracker.logout()
|
||||
onDismissRequest()
|
||||
context.toast(R.string.logout_success)
|
||||
context.toast(MR.strings.logout_success)
|
||||
},
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = MaterialTheme.colorScheme.error,
|
||||
contentColor = MaterialTheme.colorScheme.onError,
|
||||
),
|
||||
) {
|
||||
Text(text = stringResource(R.string.logout))
|
||||
Text(text = localize(MR.strings.logout))
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -344,7 +342,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
|
||||
private data class LoginDialog(
|
||||
val tracker: Tracker,
|
||||
@StringRes val uNameStringRes: Int,
|
||||
val uNameStringRes: StringResource,
|
||||
)
|
||||
|
||||
private data class LogoutDialog(
|
||||
|
@ -19,7 +19,6 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
@ -30,7 +29,6 @@ import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
|
||||
import eu.kanade.presentation.util.LocalBackPress
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.updater.AppUpdateChecker
|
||||
import eu.kanade.tachiyomi.ui.more.NewUpdateScreen
|
||||
import eu.kanade.tachiyomi.util.CrashLogUtil
|
||||
@ -45,9 +43,11 @@ import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.util.lang.withUIContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.release.interactor.GetApplicationRelease
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.LinkIcon
|
||||
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.icons.CustomIcons
|
||||
import tachiyomi.presentation.core.icons.Discord
|
||||
import tachiyomi.presentation.core.icons.Facebook
|
||||
@ -79,7 +79,7 @@ object AboutScreen : Screen() {
|
||||
Scaffold(
|
||||
topBar = { scrollBehavior ->
|
||||
AppBar(
|
||||
title = stringResource(R.string.pref_category_about),
|
||||
title = localize(MR.strings.pref_category_about),
|
||||
navigateUp = if (handleBack != null) handleBack::invoke else null,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
@ -94,7 +94,7 @@ object AboutScreen : Screen() {
|
||||
|
||||
item {
|
||||
TextPreferenceWidget(
|
||||
title = stringResource(R.string.version),
|
||||
title = localize(MR.strings.version),
|
||||
subtitle = getVersionName(withBuildDate = true),
|
||||
onPreferenceClick = {
|
||||
val deviceInfo = CrashLogUtil(context).getDebugInfo()
|
||||
@ -106,7 +106,7 @@ object AboutScreen : Screen() {
|
||||
if (BuildConfig.INCLUDE_UPDATER) {
|
||||
item {
|
||||
TextPreferenceWidget(
|
||||
title = stringResource(R.string.check_for_updates),
|
||||
title = localize(MR.strings.check_for_updates),
|
||||
widget = {
|
||||
AnimatedVisibility(visible = isCheckingUpdates) {
|
||||
CircularProgressIndicator(
|
||||
@ -145,7 +145,7 @@ object AboutScreen : Screen() {
|
||||
if (!BuildConfig.DEBUG) {
|
||||
item {
|
||||
TextPreferenceWidget(
|
||||
title = stringResource(R.string.whats_new),
|
||||
title = localize(MR.string.whats_new),
|
||||
// SY -->
|
||||
onPreferenceClick = { showWhatsNewDialog = true },
|
||||
// SY <--
|
||||
@ -155,21 +155,21 @@ object AboutScreen : Screen() {
|
||||
|
||||
item {
|
||||
TextPreferenceWidget(
|
||||
title = stringResource(R.string.help_translate),
|
||||
title = localize(MR.strings.help_translate),
|
||||
onPreferenceClick = { uriHandler.openUri("https://tachiyomi.org/docs/contribute#translation") },
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
TextPreferenceWidget(
|
||||
title = stringResource(R.string.licenses),
|
||||
title = localize(MR.strings.licenses),
|
||||
onPreferenceClick = { navigator.push(OpenSourceLicensesScreen()) },
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
TextPreferenceWidget(
|
||||
title = stringResource(R.string.privacy_policy),
|
||||
title = localize(MR.strings.privacy_policy),
|
||||
onPreferenceClick = { uriHandler.openUri("https://tachiyomi.org/privacy/") },
|
||||
)
|
||||
}
|
||||
@ -182,7 +182,7 @@ object AboutScreen : Screen() {
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
) {
|
||||
LinkIcon(
|
||||
label = stringResource(R.string.website),
|
||||
label = localize(MR.strings.website),
|
||||
icon = Icons.Outlined.Public,
|
||||
url = "https://tachiyomi.org",
|
||||
)
|
||||
@ -241,10 +241,10 @@ object AboutScreen : Screen() {
|
||||
onAvailableUpdate(result)
|
||||
}
|
||||
is GetApplicationRelease.Result.NoNewUpdate -> {
|
||||
context.toast(R.string.update_check_no_new_updates)
|
||||
context.toast(MR.strings.update_check_no_new_updates)
|
||||
}
|
||||
is GetApplicationRelease.Result.OsTooOld -> {
|
||||
context.toast(R.string.update_check_eol)
|
||||
context.toast(MR.strings.update_check_eol)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import androidx.compose.material.icons.filled.Public
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.text.HtmlCompat
|
||||
@ -19,9 +18,10 @@ import com.google.android.material.textview.MaterialTextView
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
class OpenSourceLibraryLicenseScreen(
|
||||
private val name: String,
|
||||
@ -44,7 +44,7 @@ class OpenSourceLibraryLicenseScreen(
|
||||
AppBarActions(
|
||||
persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.website),
|
||||
title = localize(MR.strings.website),
|
||||
icon = Icons.Default.Public,
|
||||
onClick = { uriHandler.openUri(website) },
|
||||
),
|
||||
|
@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import com.mikepenz.aboutlibraries.ui.compose.LibrariesContainer
|
||||
@ -12,8 +11,9 @@ import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults
|
||||
import com.mikepenz.aboutlibraries.ui.compose.util.htmlReadyLicenseContent
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
class OpenSourceLicensesScreen : Screen() {
|
||||
|
||||
@ -23,7 +23,7 @@ class OpenSourceLicensesScreen : Screen() {
|
||||
Scaffold(
|
||||
topBar = { scrollBehavior ->
|
||||
AppBar(
|
||||
title = stringResource(R.string.licenses),
|
||||
title = localize(MR.strings.licenses),
|
||||
navigateUp = navigator::pop,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
|
@ -10,7 +10,6 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.unit.dp
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
@ -18,12 +17,13 @@ import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.backup.models.Backup
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.serialization.protobuf.schema.ProtoBufSchemaGenerator
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
class BackupSchemaScreen : Screen() {
|
||||
|
||||
@ -47,7 +47,7 @@ class BackupSchemaScreen : Screen() {
|
||||
AppBarActions(
|
||||
persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_copy_to_clipboard),
|
||||
title = localize(MR.strings.action_copy_to_clipboard),
|
||||
icon = Icons.Default.ContentCopy,
|
||||
onClick = {
|
||||
context.copyToClipboard(title, schema)
|
||||
|
@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.WebViewUtil
|
||||
import kotlinx.coroutines.guava.await
|
||||
import tachiyomi.i18n.MR
|
||||
|
||||
class DebugInfoScreen : Screen() {
|
||||
|
||||
@ -24,7 +25,7 @@ class DebugInfoScreen : Screen() {
|
||||
override fun Content() {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
PreferenceScaffold(
|
||||
titleRes = R.string.pref_debug_info,
|
||||
titleRes = MR.strings.pref_debug_info,
|
||||
onBackPressed = navigator::pop,
|
||||
itemsProvider = {
|
||||
listOf(
|
||||
|
@ -15,7 +15,6 @@ import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
@ -30,14 +29,15 @@ import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.presentation.util.ioCoroutineScope
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.plus
|
||||
|
||||
class WorkerInfoScreen : Screen() {
|
||||
@ -65,7 +65,7 @@ class WorkerInfoScreen : Screen() {
|
||||
AppBarActions(
|
||||
persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_copy_to_clipboard),
|
||||
title = localize(MR.strings.action_copy_to_clipboard),
|
||||
icon = Icons.Default.ContentCopy,
|
||||
onClick = {
|
||||
context.copyToClipboard(title, enqueued + finished + running)
|
||||
|
@ -36,17 +36,17 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.domain.ui.model.AppTheme
|
||||
import eu.kanade.presentation.manga.components.MangaCover
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
|
||||
@Composable
|
||||
@ -76,7 +76,7 @@ private fun AppThemesList(
|
||||
) {
|
||||
val appThemes = remember {
|
||||
AppTheme.entries
|
||||
.filterNot { it.titleResId == null || (it == AppTheme.MONET && !DeviceUtil.isDynamicColorAvailable) }
|
||||
.filterNot { it.titleRes == null || (it == AppTheme.MONET && !DeviceUtil.isDynamicColorAvailable) }
|
||||
}
|
||||
LazyRow(
|
||||
contentPadding = PaddingValues(horizontal = PrefsHorizontalPadding),
|
||||
@ -104,7 +104,7 @@ private fun AppThemesList(
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
Text(
|
||||
text = stringResource(appTheme.titleResId!!),
|
||||
text = localize(appTheme.titleRes!!),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.secondaryItemAlpha(),
|
||||
@ -167,7 +167,7 @@ fun AppThemePreviewItem(
|
||||
if (selected) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.CheckCircle,
|
||||
contentDescription = stringResource(R.string.selected),
|
||||
contentDescription = localize(MR.strings.selected),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
|
@ -19,11 +19,11 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun EditTextPreferenceWidget(
|
||||
@ -83,12 +83,12 @@ fun EditTextPreferenceWidget(
|
||||
}
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
Text(text = localize(MR.strings.action_ok))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -11,11 +11,11 @@ import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
|
||||
@Composable
|
||||
@ -45,7 +45,7 @@ internal fun InfoWidget(text: String) {
|
||||
private fun InfoWidgetPreview() {
|
||||
TachiyomiTheme {
|
||||
Surface {
|
||||
InfoWidget(text = stringResource(R.string.download_ahead_info))
|
||||
InfoWidget(text = localize(MR.strings.download_ahead_info))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,10 +22,10 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.isScrolledToEnd
|
||||
import tachiyomi.presentation.core.util.isScrolledToStart
|
||||
|
||||
@ -75,7 +75,7 @@ fun <T> ListPreferenceWidget(
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = { isDialogShown = false }) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -10,11 +10,11 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.toMutableStateList
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.LabeledCheckbox
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun MultiSelectListPreferenceWidget(
|
||||
@ -70,12 +70,12 @@ fun MultiSelectListPreferenceWidget(
|
||||
isDialogShown = false
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
Text(text = localize(MR.strings.action_ok))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { isDialogShown = false }) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -15,12 +15,12 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.more.settings.LocalPreferenceHighlighted
|
||||
import eu.kanade.presentation.track.components.TrackLogoIcon
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun TrackingPreferenceWidget(
|
||||
@ -55,7 +55,7 @@ fun TrackingPreferenceWidget(
|
||||
.padding(4.dp)
|
||||
.size(32.dp),
|
||||
tint = Color(0xFF4CAF50),
|
||||
contentDescription = stringResource(R.string.login_success),
|
||||
contentDescription = localize(MR.strings.login_success),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ import androidx.compose.runtime.toMutableStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.isScrolledToEnd
|
||||
import tachiyomi.presentation.core.util.isScrolledToStart
|
||||
|
||||
@ -102,11 +102,11 @@ fun <T> TriStateListDialog(
|
||||
} else {
|
||||
MaterialTheme.colorScheme.primary
|
||||
},
|
||||
contentDescription = stringResource(
|
||||
contentDescription = localize(
|
||||
when (state) {
|
||||
State.UNCHECKED -> R.string.not_selected
|
||||
State.CHECKED -> R.string.selected
|
||||
State.INVERSED -> R.string.disabled
|
||||
State.UNCHECKED -> MR.strings.not_selected
|
||||
State.CHECKED -> MR.strings.selected
|
||||
State.INVERSED -> MR.strings.disabled
|
||||
},
|
||||
),
|
||||
)
|
||||
@ -130,7 +130,7 @@ fun <T> TriStateListDialog(
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
@ -145,7 +145,7 @@ fun <T> TriStateListDialog(
|
||||
onValueChanged(included, excluded)
|
||||
},
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
Text(text = localize(MR.strings.action_ok))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -13,14 +13,14 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.presentation.more.stats.components.StatsItem
|
||||
import eu.kanade.presentation.more.stats.components.StatsOverviewItem
|
||||
import eu.kanade.presentation.more.stats.components.StatsSection
|
||||
import eu.kanade.presentation.more.stats.data.StatsData
|
||||
import eu.kanade.presentation.util.toDurationString
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import java.util.Locale
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.toDuration
|
||||
@ -55,28 +55,28 @@ fun StatsScreenContent(
|
||||
private fun OverviewSection(
|
||||
data: StatsData.Overview,
|
||||
) {
|
||||
val none = stringResource(R.string.none)
|
||||
val none = localize(MR.strings.none)
|
||||
val context = LocalContext.current
|
||||
val readDurationString = remember(data.totalReadDuration) {
|
||||
data.totalReadDuration
|
||||
.toDuration(DurationUnit.MILLISECONDS)
|
||||
.toDurationString(context, fallback = none)
|
||||
}
|
||||
StatsSection(R.string.label_overview_section) {
|
||||
StatsSection(MR.strings.label_overview_section) {
|
||||
Row {
|
||||
StatsOverviewItem(
|
||||
title = data.libraryMangaCount.toString(),
|
||||
subtitle = stringResource(R.string.in_library),
|
||||
subtitle = localize(MR.strings.in_library),
|
||||
icon = Icons.Outlined.CollectionsBookmark,
|
||||
)
|
||||
StatsOverviewItem(
|
||||
title = data.completedMangaCount.toString(),
|
||||
subtitle = stringResource(R.string.label_completed_titles),
|
||||
subtitle = localize(MR.strings.label_completed_titles),
|
||||
icon = Icons.Outlined.LocalLibrary,
|
||||
)
|
||||
StatsOverviewItem(
|
||||
title = readDurationString,
|
||||
subtitle = stringResource(R.string.label_read_duration),
|
||||
subtitle = localize(MR.strings.label_read_duration),
|
||||
icon = Icons.Outlined.Schedule,
|
||||
)
|
||||
}
|
||||
@ -87,19 +87,19 @@ private fun OverviewSection(
|
||||
private fun TitlesStats(
|
||||
data: StatsData.Titles,
|
||||
) {
|
||||
StatsSection(R.string.label_titles_section) {
|
||||
StatsSection(MR.strings.label_titles_section) {
|
||||
Row {
|
||||
StatsItem(
|
||||
data.globalUpdateItemCount.toString(),
|
||||
stringResource(R.string.label_titles_in_global_update),
|
||||
localize(MR.strings.label_titles_in_global_update),
|
||||
)
|
||||
StatsItem(
|
||||
data.startedMangaCount.toString(),
|
||||
stringResource(R.string.label_started),
|
||||
localize(MR.strings.label_started),
|
||||
)
|
||||
StatsItem(
|
||||
data.localMangaCount.toString(),
|
||||
stringResource(R.string.label_local),
|
||||
localize(MR.strings.label_local),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -109,19 +109,19 @@ private fun TitlesStats(
|
||||
private fun ChapterStats(
|
||||
data: StatsData.Chapters,
|
||||
) {
|
||||
StatsSection(R.string.chapters) {
|
||||
StatsSection(MR.strings.chapters) {
|
||||
Row {
|
||||
StatsItem(
|
||||
data.totalChapterCount.toString(),
|
||||
stringResource(R.string.label_total_chapters),
|
||||
localize(MR.strings.label_total_chapters),
|
||||
)
|
||||
StatsItem(
|
||||
data.readChapterCount.toString(),
|
||||
stringResource(R.string.label_read_chapters),
|
||||
localize(MR.strings.label_read_chapters),
|
||||
)
|
||||
StatsItem(
|
||||
data.downloadCount.toString(),
|
||||
stringResource(R.string.label_downloaded),
|
||||
localize(MR.strings.label_downloaded),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -131,7 +131,7 @@ private fun ChapterStats(
|
||||
private fun TrackerStats(
|
||||
data: StatsData.Trackers,
|
||||
) {
|
||||
val notApplicable = stringResource(R.string.not_applicable)
|
||||
val notApplicable = localize(MR.strings.not_applicable)
|
||||
val meanScoreStr = remember(data.trackedTitleCount, data.meanScore) {
|
||||
if (data.trackedTitleCount > 0 && !data.meanScore.isNaN()) {
|
||||
// All other numbers are localized in English
|
||||
@ -140,19 +140,19 @@ private fun TrackerStats(
|
||||
notApplicable
|
||||
}
|
||||
}
|
||||
StatsSection(R.string.label_tracker_section) {
|
||||
StatsSection(MR.strings.label_tracker_section) {
|
||||
Row {
|
||||
StatsItem(
|
||||
data.trackedTitleCount.toString(),
|
||||
stringResource(R.string.label_tracked_titles),
|
||||
localize(MR.strings.label_tracked_titles),
|
||||
)
|
||||
StatsItem(
|
||||
meanScoreStr,
|
||||
stringResource(R.string.label_mean_score),
|
||||
localize(MR.strings.label_mean_score),
|
||||
)
|
||||
StatsItem(
|
||||
data.trackerCount.toString(),
|
||||
stringResource(R.string.label_used),
|
||||
localize(MR.strings.label_used),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package eu.kanade.presentation.more.stats.components
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@ -9,17 +8,18 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun StatsSection(
|
||||
@StringRes titleRes: Int,
|
||||
titleRes: StringResource,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = MaterialTheme.padding.extraLarge),
|
||||
text = stringResource(titleRes),
|
||||
text = localize(titleRes),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
)
|
||||
ElevatedCard(
|
||||
|
@ -26,8 +26,6 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.Placeholder
|
||||
import androidx.compose.ui.text.PlaceholderVerticalAlign
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
@ -36,13 +34,15 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
|
||||
import eu.kanade.tachiyomi.data.database.models.toDomainChapter
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||
import tachiyomi.domain.chapter.service.calculateChapterGap
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.i18n.localizePlural
|
||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
|
||||
@Composable
|
||||
@ -58,25 +58,25 @@ fun ChapterTransition(
|
||||
when (transition) {
|
||||
is ChapterTransition.Prev -> {
|
||||
TransitionText(
|
||||
topLabel = stringResource(R.string.transition_previous),
|
||||
topLabel = localize(MR.strings.transition_previous),
|
||||
topChapter = goingToChapter,
|
||||
topChapterDownloaded = goingToChapterDownloaded,
|
||||
bottomLabel = stringResource(R.string.transition_current),
|
||||
bottomLabel = localize(MR.strings.transition_current),
|
||||
bottomChapter = currChapter,
|
||||
bottomChapterDownloaded = currChapterDownloaded,
|
||||
fallbackLabel = stringResource(R.string.transition_no_previous),
|
||||
fallbackLabel = localize(MR.strings.transition_no_previous),
|
||||
chapterGap = calculateChapterGap(currChapter.toDomainChapter(), goingToChapter?.toDomainChapter()),
|
||||
)
|
||||
}
|
||||
is ChapterTransition.Next -> {
|
||||
TransitionText(
|
||||
topLabel = stringResource(R.string.transition_finished),
|
||||
topLabel = localize(MR.strings.transition_finished),
|
||||
topChapter = currChapter,
|
||||
topChapterDownloaded = currChapterDownloaded,
|
||||
bottomLabel = stringResource(R.string.transition_next),
|
||||
bottomLabel = localize(MR.strings.transition_next),
|
||||
bottomChapter = goingToChapter,
|
||||
bottomChapterDownloaded = goingToChapterDownloaded,
|
||||
fallbackLabel = stringResource(R.string.transition_no_next),
|
||||
fallbackLabel = localize(MR.strings.transition_no_next),
|
||||
chapterGap = calculateChapterGap(goingToChapter?.toDomainChapter(), currChapter.toDomainChapter()),
|
||||
)
|
||||
}
|
||||
@ -191,7 +191,7 @@ private fun ChapterGapWarning(
|
||||
)
|
||||
|
||||
Text(
|
||||
text = pluralStringResource(R.plurals.missing_chapters_warning, count = gapCount, gapCount),
|
||||
text = localizePlural(MR.plurals.missing_chapters_warning, count = gapCount, gapCount),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
}
|
||||
@ -245,7 +245,7 @@ private fun ChapterText(
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.CheckCircle,
|
||||
contentDescription = stringResource(R.string.label_downloaded),
|
||||
contentDescription = localize(MR.strings.label_downloaded),
|
||||
)
|
||||
},
|
||||
),
|
||||
|
@ -12,18 +12,19 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.domain.manga.model.readerOrientation
|
||||
import eu.kanade.presentation.components.AdaptiveSheet
|
||||
import eu.kanade.presentation.reader.components.ModeSelectionDialog
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.SettingsIconGrid
|
||||
import tachiyomi.presentation.core.components.material.IconToggleButton
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
private val ReaderOrientationsWithoutDefault = ReaderOrientation.entries - ReaderOrientation.DEFAULT
|
||||
|
||||
@ -31,7 +32,7 @@ private val ReaderOrientationsWithoutDefault = ReaderOrientation.entries - Reade
|
||||
fun OrientationSelectDialog(
|
||||
onDismissRequest: () -> Unit,
|
||||
screenModel: ReaderSettingsScreenModel,
|
||||
onChange: (Int) -> Unit,
|
||||
onChange: (StringResource) -> Unit,
|
||||
) {
|
||||
val manga by screenModel.mangaFlow.collectAsState()
|
||||
val orientation = remember(manga) { ReaderOrientation.fromPreference(manga?.readerOrientation?.toInt()) }
|
||||
@ -63,7 +64,7 @@ private fun DialogContent(
|
||||
}.takeIf { orientation != ReaderOrientation.DEFAULT },
|
||||
onApply = { onChangeOrientation(selected) },
|
||||
) {
|
||||
SettingsIconGrid(R.string.rotation_type) {
|
||||
SettingsIconGrid(MR.strings.rotation_type) {
|
||||
items(ReaderOrientationsWithoutDefault) { mode ->
|
||||
IconToggleButton(
|
||||
checked = mode == selected,
|
||||
@ -72,7 +73,7 @@ private fun DialogContent(
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
imageVector = ImageVector.vectorResource(mode.iconRes),
|
||||
title = stringResource(mode.stringRes),
|
||||
title = localize(mode.stringRes),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -12,18 +12,19 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.domain.manga.model.readingMode
|
||||
import eu.kanade.presentation.components.AdaptiveSheet
|
||||
import eu.kanade.presentation.reader.components.ModeSelectionDialog
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.SettingsIconGrid
|
||||
import tachiyomi.presentation.core.components.material.IconToggleButton
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
private val ReadingModesWithoutDefault = ReadingMode.entries - ReadingMode.DEFAULT
|
||||
|
||||
@ -31,7 +32,7 @@ private val ReadingModesWithoutDefault = ReadingMode.entries - ReadingMode.DEFAU
|
||||
fun ReadingModeSelectDialog(
|
||||
onDismissRequest: () -> Unit,
|
||||
screenModel: ReaderSettingsScreenModel,
|
||||
onChange: (Int) -> Unit,
|
||||
onChange: (StringResource) -> Unit,
|
||||
) {
|
||||
val manga by screenModel.mangaFlow.collectAsState()
|
||||
val readingMode = remember(manga) { ReadingMode.fromPreference(manga?.readingMode?.toInt()) }
|
||||
@ -59,7 +60,7 @@ private fun DialogContent(
|
||||
onUseDefault = { onChangeReadingMode(ReadingMode.DEFAULT) }.takeIf { readingMode != ReadingMode.DEFAULT },
|
||||
onApply = { onChangeReadingMode(selected) },
|
||||
) {
|
||||
SettingsIconGrid(R.string.pref_category_reading_mode) {
|
||||
SettingsIconGrid(MR.strings.pref_category_reading_mode) {
|
||||
items(ReadingModesWithoutDefault) { mode ->
|
||||
IconToggleButton(
|
||||
checked = mode == selected,
|
||||
@ -68,7 +69,7 @@ private fun DialogContent(
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
imageVector = ImageVector.vectorResource(mode.iconRes),
|
||||
title = stringResource(mode.stringRes),
|
||||
title = localize(mode.stringRes),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -17,12 +17,13 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderBottomButton
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun BottomReaderBar(
|
||||
@ -60,7 +61,7 @@ fun BottomReaderBar(
|
||||
IconButton(onClick = onClickChapterList) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.FormatListNumbered,
|
||||
contentDescription = stringResource(R.string.chapters),
|
||||
contentDescription = localize(MR.strings.chapters),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -69,7 +70,7 @@ fun BottomReaderBar(
|
||||
IconButton(onClick = onClickWebView) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Public,
|
||||
contentDescription = stringResource(R.string.action_open_in_web_view),
|
||||
contentDescription = localize(MR.strings.action_open_in_web_view),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -78,7 +79,7 @@ fun BottomReaderBar(
|
||||
IconButton(onClick = onClickShare) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Share,
|
||||
contentDescription = stringResource(R.string.action_share),
|
||||
contentDescription = localize(MR.strings.action_share),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -87,7 +88,7 @@ fun BottomReaderBar(
|
||||
IconButton(onClick = onClickReadingMode) {
|
||||
Icon(
|
||||
painter = painterResource(readingMode.iconRes),
|
||||
contentDescription = stringResource(R.string.viewer),
|
||||
contentDescription = localize(MR.strings.viewer),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -96,7 +97,7 @@ fun BottomReaderBar(
|
||||
IconButton(onClick = onClickOrientation) {
|
||||
Icon(
|
||||
painter = painterResource(orientation.iconRes),
|
||||
contentDescription = stringResource(R.string.pref_rotation_type),
|
||||
contentDescription = localize(MR.strings.pref_rotation_type),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -110,7 +111,7 @@ fun BottomReaderBar(
|
||||
IconButton(onClick = onClickCropBorder) {
|
||||
Icon(
|
||||
painter = painterResource(if (cropEnabled) R.drawable.ic_crop_24dp else R.drawable.ic_crop_off_24dp),
|
||||
contentDescription = stringResource(R.string.pref_crop_borders),
|
||||
contentDescription = localize(MR.strings.pref_crop_borders),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -123,7 +124,7 @@ fun BottomReaderBar(
|
||||
IconButton(onClick = onClickPageLayout) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_book_open_variant_24dp),
|
||||
contentDescription = stringResource(R.string.page_layout),
|
||||
contentDescription = localize(MR.strings.page_layout),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -132,7 +133,7 @@ fun BottomReaderBar(
|
||||
IconButton(onClick = onClickShiftPage) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_page_next_outline_24dp),
|
||||
contentDescription = stringResource(R.string.shift_double_pages),
|
||||
contentDescription = localize(MR.strings.shift_double_pages),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -140,7 +141,7 @@ fun BottomReaderBar(
|
||||
IconButton(onClick = onClickSettings) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Settings,
|
||||
contentDescription = stringResource(R.string.action_settings),
|
||||
contentDescription = localize(MR.stringss.action_settings),
|
||||
)
|
||||
}
|
||||
// SY <--
|
||||
|
@ -16,12 +16,12 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.SettingsItemsPaddings
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun ModeSelectionDialog(
|
||||
@ -40,7 +40,7 @@ fun ModeSelectionDialog(
|
||||
) {
|
||||
onUseDefault?.let {
|
||||
OutlinedButton(onClick = it) {
|
||||
Text(text = stringResource(R.string.action_revert_to_default))
|
||||
Text(text = localize(MR.strings.action_revert_to_default))
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ fun ModeSelectionDialog(
|
||||
imageVector = Icons.Outlined.Check,
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(text = stringResource(R.string.action_apply))
|
||||
Text(text = localize(MR.strings.action_apply))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,17 +6,17 @@ import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.core.graphics.alpha
|
||||
import androidx.core.graphics.blue
|
||||
import androidx.core.graphics.green
|
||||
import androidx.core.graphics.red
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
||||
import tachiyomi.core.preference.getAndSet
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.CheckboxItem
|
||||
import tachiyomi.presentation.core.components.SettingsChipRow
|
||||
import tachiyomi.presentation.core.components.SliderItem
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
|
||||
@Composable
|
||||
@ -24,25 +24,25 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
val colorFilterModes = buildList {
|
||||
addAll(
|
||||
listOf(
|
||||
R.string.label_default,
|
||||
R.string.filter_mode_multiply,
|
||||
R.string.filter_mode_screen,
|
||||
MR.strings.label_default,
|
||||
MR.strings.filter_mode_multiply,
|
||||
MR.strings.filter_mode_screen,
|
||||
),
|
||||
)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
addAll(
|
||||
listOf(
|
||||
R.string.filter_mode_overlay,
|
||||
R.string.filter_mode_lighten,
|
||||
R.string.filter_mode_darken,
|
||||
MR.strings.filter_mode_overlay,
|
||||
MR.strings.filter_mode_lighten,
|
||||
MR.strings.filter_mode_darken,
|
||||
),
|
||||
)
|
||||
}
|
||||
}.map { stringResource(it) }
|
||||
}.map { localize(it) }
|
||||
|
||||
val customBrightness by screenModel.preferences.customBrightness().collectAsState()
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_custom_brightness),
|
||||
label = localize(MR.strings.pref_custom_brightness),
|
||||
pref = screenModel.preferences.customBrightness(),
|
||||
)
|
||||
|
||||
@ -55,7 +55,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
if (customBrightness) {
|
||||
val customBrightnessValue by screenModel.preferences.customBrightnessValue().collectAsState()
|
||||
SliderItem(
|
||||
label = stringResource(R.string.pref_custom_brightness),
|
||||
label = localize(MR.strings.pref_custom_brightness),
|
||||
min = -75,
|
||||
max = 100,
|
||||
value = customBrightnessValue,
|
||||
@ -66,13 +66,13 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
|
||||
val colorFilter by screenModel.preferences.colorFilter().collectAsState()
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_custom_color_filter),
|
||||
label = localize(MR.strings.pref_custom_color_filter),
|
||||
pref = screenModel.preferences.colorFilter(),
|
||||
)
|
||||
if (colorFilter) {
|
||||
val colorFilterValue by screenModel.preferences.colorFilterValue().collectAsState()
|
||||
SliderItem(
|
||||
label = stringResource(R.string.color_filter_r_value),
|
||||
label = localize(MR.strings.color_filter_r_value),
|
||||
max = 255,
|
||||
value = colorFilterValue.red,
|
||||
valueText = colorFilterValue.red.toString(),
|
||||
@ -83,7 +83,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
},
|
||||
)
|
||||
SliderItem(
|
||||
label = stringResource(R.string.color_filter_g_value),
|
||||
label = localize(MR.strings.color_filter_g_value),
|
||||
max = 255,
|
||||
value = colorFilterValue.green,
|
||||
valueText = colorFilterValue.green.toString(),
|
||||
@ -94,7 +94,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
},
|
||||
)
|
||||
SliderItem(
|
||||
label = stringResource(R.string.color_filter_b_value),
|
||||
label = localize(MR.strings.color_filter_b_value),
|
||||
max = 255,
|
||||
value = colorFilterValue.blue,
|
||||
valueText = colorFilterValue.blue.toString(),
|
||||
@ -105,7 +105,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
},
|
||||
)
|
||||
SliderItem(
|
||||
label = stringResource(R.string.color_filter_a_value),
|
||||
label = localize(MR.strings.color_filter_a_value),
|
||||
max = 255,
|
||||
value = colorFilterValue.alpha,
|
||||
valueText = colorFilterValue.alpha.toString(),
|
||||
@ -117,7 +117,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
)
|
||||
|
||||
val colorFilterMode by screenModel.preferences.colorFilterMode().collectAsState()
|
||||
SettingsChipRow(R.string.pref_color_filter_mode) {
|
||||
SettingsChipRow(MR.strings.pref_color_filter_mode) {
|
||||
colorFilterModes.mapIndexed { index, it ->
|
||||
FilterChip(
|
||||
selected = colorFilterMode == index,
|
||||
@ -129,11 +129,11 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
}
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_grayscale),
|
||||
label = localize(MR.strings.pref_grayscale),
|
||||
pref = screenModel.preferences.grayscale(),
|
||||
)
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_inverted_colors),
|
||||
label = localize(MR.strings.pref_inverted_colors),
|
||||
pref = screenModel.preferences.invertedColors(),
|
||||
)
|
||||
}
|
||||
|
@ -11,13 +11,13 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.window.DialogWindowProvider
|
||||
import eu.kanade.presentation.components.TabbedDialog
|
||||
import eu.kanade.presentation.components.TabbedDialogPaddings
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun ReaderSettingsDialog(
|
||||
@ -27,9 +27,9 @@ fun ReaderSettingsDialog(
|
||||
screenModel: ReaderSettingsScreenModel,
|
||||
) {
|
||||
val tabTitles = persistentListOf(
|
||||
stringResource(R.string.pref_category_reading_mode),
|
||||
stringResource(R.string.pref_category_general),
|
||||
stringResource(R.string.custom_filter),
|
||||
localize(MR.strings.pref_category_reading_mode),
|
||||
localize(MR.strings.pref_category_general),
|
||||
localize(MR.strings.custom_filter),
|
||||
)
|
||||
val pagerState = rememberPagerState { tabTitles.size }
|
||||
|
||||
|
@ -7,45 +7,45 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.domain.manga.model.readerOrientation
|
||||
import eu.kanade.domain.manga.model.readingMode
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.CheckboxItem
|
||||
import tachiyomi.presentation.core.components.HeadingItem
|
||||
import tachiyomi.presentation.core.components.SettingsChipRow
|
||||
import tachiyomi.presentation.core.components.SliderItem
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import java.text.NumberFormat
|
||||
|
||||
@Composable
|
||||
internal fun ColumnScope.ReadingModePage(screenModel: ReaderSettingsScreenModel) {
|
||||
HeadingItem(R.string.pref_category_for_this_series)
|
||||
HeadingItem(MR.strings.pref_category_for_this_series)
|
||||
val manga by screenModel.mangaFlow.collectAsState()
|
||||
|
||||
val readingMode = remember(manga) { ReadingMode.fromPreference(manga?.readingMode?.toInt()) }
|
||||
SettingsChipRow(R.string.pref_category_reading_mode) {
|
||||
SettingsChipRow(MR.strings.pref_category_reading_mode) {
|
||||
ReadingMode.entries.map {
|
||||
FilterChip(
|
||||
selected = it == readingMode,
|
||||
onClick = { screenModel.onChangeReadingMode(it) },
|
||||
label = { Text(stringResource(it.stringRes)) },
|
||||
label = { Text(localize(it.stringRes)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val orientation = remember(manga) { ReaderOrientation.fromPreference(manga?.readerOrientation?.toInt()) }
|
||||
SettingsChipRow(R.string.rotation_type) {
|
||||
SettingsChipRow(MR.strings.rotation_type) {
|
||||
ReaderOrientation.entries.map {
|
||||
FilterChip(
|
||||
selected = it == orientation,
|
||||
onClick = { screenModel.onChangeOrientation(it) },
|
||||
label = { Text(stringResource(it.stringRes)) },
|
||||
label = { Text(localize(it.stringRes)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -63,7 +63,7 @@ internal fun ColumnScope.ReadingModePage(screenModel: ReaderSettingsScreenModel)
|
||||
|
||||
@Composable
|
||||
private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenModel) {
|
||||
HeadingItem(R.string.pager_viewer)
|
||||
HeadingItem(MR.strings.pager_viewer)
|
||||
|
||||
val navigationModePager by screenModel.preferences.navigationModePager().collectAsState()
|
||||
val pagerNavInverted by screenModel.preferences.pagerNavInverted().collectAsState()
|
||||
@ -75,23 +75,23 @@ private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenMod
|
||||
)
|
||||
|
||||
val imageScaleType by screenModel.preferences.imageScaleType().collectAsState()
|
||||
SettingsChipRow(R.string.pref_image_scale_type) {
|
||||
SettingsChipRow(MR.strings.pref_image_scale_type) {
|
||||
ReaderPreferences.ImageScaleType.mapIndexed { index, it ->
|
||||
FilterChip(
|
||||
selected = imageScaleType == index + 1,
|
||||
onClick = { screenModel.preferences.imageScaleType().set(index + 1) },
|
||||
label = { Text(stringResource(it)) },
|
||||
label = { Text(localize(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val zoomStart by screenModel.preferences.zoomStart().collectAsState()
|
||||
SettingsChipRow(R.string.pref_zoom_start) {
|
||||
SettingsChipRow(MR.strings.pref_zoom_start) {
|
||||
ReaderPreferences.ZoomStart.mapIndexed { index, it ->
|
||||
FilterChip(
|
||||
selected = zoomStart == index + 1,
|
||||
onClick = { screenModel.preferences.zoomStart().set(index + 1) },
|
||||
label = { Text(stringResource(it)) },
|
||||
label = { Text(localize(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -110,42 +110,42 @@ private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenMod
|
||||
// SY <--
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_crop_borders),
|
||||
label = localize(MR.strings.pref_crop_borders),
|
||||
pref = screenModel.preferences.cropBorders(),
|
||||
)
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_landscape_zoom),
|
||||
label = localize(MR.strings.pref_landscape_zoom),
|
||||
pref = screenModel.preferences.landscapeZoom(),
|
||||
)
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_navigate_pan),
|
||||
label = localize(MR.strings.pref_navigate_pan),
|
||||
pref = screenModel.preferences.navigateToPan(),
|
||||
)
|
||||
|
||||
val dualPageSplitPaged by screenModel.preferences.dualPageSplitPaged().collectAsState()
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_dual_page_split),
|
||||
label = localize(MR.strings.pref_dual_page_split),
|
||||
pref = screenModel.preferences.dualPageSplitPaged(),
|
||||
)
|
||||
|
||||
if (dualPageSplitPaged) {
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_dual_page_invert),
|
||||
label = localize(MR.strings.pref_dual_page_invert),
|
||||
pref = screenModel.preferences.dualPageInvertPaged(),
|
||||
)
|
||||
}
|
||||
|
||||
val dualPageRotateToFit by screenModel.preferences.dualPageRotateToFit().collectAsState()
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_page_rotate),
|
||||
label = localize(MR.strings.pref_page_rotate),
|
||||
pref = screenModel.preferences.dualPageRotateToFit(),
|
||||
)
|
||||
|
||||
if (dualPageRotateToFit) {
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_page_rotate_invert),
|
||||
label = localize(MR.strings.pref_page_rotate_invert),
|
||||
pref = screenModel.preferences.dualPageRotateToFitInvert(),
|
||||
)
|
||||
}
|
||||
@ -178,7 +178,7 @@ private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenMod
|
||||
private fun ColumnScope.WebtoonViewerSettings(screenModel: ReaderSettingsScreenModel) {
|
||||
val numberFormat = remember { NumberFormat.getPercentInstance() }
|
||||
|
||||
HeadingItem(R.string.webtoon_viewer)
|
||||
HeadingItem(MR.strings.webtoon_viewer)
|
||||
|
||||
val navigationModeWebtoon by screenModel.preferences.navigationModeWebtoon().collectAsState()
|
||||
val webtoonNavInverted by screenModel.preferences.webtoonNavInverted().collectAsState()
|
||||
@ -191,7 +191,7 @@ private fun ColumnScope.WebtoonViewerSettings(screenModel: ReaderSettingsScreenM
|
||||
|
||||
val webtoonSidePadding by screenModel.preferences.webtoonSidePadding().collectAsState()
|
||||
SliderItem(
|
||||
label = stringResource(R.string.pref_webtoon_side_padding),
|
||||
label = localize(MR.strings.pref_webtoon_side_padding),
|
||||
min = ReaderPreferences.WEBTOON_PADDING_MIN,
|
||||
max = ReaderPreferences.WEBTOON_PADDING_MAX,
|
||||
value = webtoonSidePadding,
|
||||
@ -202,7 +202,7 @@ private fun ColumnScope.WebtoonViewerSettings(screenModel: ReaderSettingsScreenM
|
||||
)
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_crop_borders),
|
||||
label = localize(MR.strings.pref_crop_borders),
|
||||
pref = screenModel.preferences.cropBordersWebtoon(),
|
||||
)
|
||||
|
||||
@ -225,19 +225,19 @@ private fun ColumnScope.WebtoonViewerSettings(screenModel: ReaderSettingsScreenM
|
||||
|
||||
val dualPageSplitWebtoon by screenModel.preferences.dualPageSplitWebtoon().collectAsState()
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_dual_page_split),
|
||||
label = localize(MR.strings.pref_dual_page_split),
|
||||
pref = screenModel.preferences.dualPageSplitWebtoon(),
|
||||
)
|
||||
|
||||
if (dualPageSplitWebtoon) {
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_dual_page_invert),
|
||||
label = localize(MR.strings.pref_dual_page_invert),
|
||||
pref = screenModel.preferences.dualPageInvertWebtoon(),
|
||||
)
|
||||
}
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(R.string.pref_double_tap_zoom),
|
||||
label = localize(MR.strings.pref_double_tap_zoom),
|
||||
pref = screenModel.preferences.webtoonDoubleTapZoomEnabled(),
|
||||
)
|
||||
}
|
||||
@ -261,23 +261,23 @@ private fun ColumnScope.TapZonesItems(
|
||||
invertMode: ReaderPreferences.TappingInvertMode,
|
||||
onSelectInvertMode: (ReaderPreferences.TappingInvertMode) -> Unit,
|
||||
) {
|
||||
SettingsChipRow(R.string.pref_viewer_nav) {
|
||||
SettingsChipRow(MR.strings.pref_viewer_nav) {
|
||||
ReaderPreferences.TapZones.mapIndexed { index, it ->
|
||||
FilterChip(
|
||||
selected = selected == index,
|
||||
onClick = { onSelect(index) },
|
||||
label = { Text(stringResource(it)) },
|
||||
label = { Text(localize(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (selected != 5) {
|
||||
SettingsChipRow(R.string.pref_read_with_tapping_inverted) {
|
||||
SettingsChipRow(MR.strings.pref_read_with_tapping_inverted) {
|
||||
ReaderPreferences.TappingInvertMode.entries.map {
|
||||
FilterChip(
|
||||
selected = it == invertMode,
|
||||
onClick = { onSelectInvertMode(it) },
|
||||
label = { Text(stringResource(it.titleResId)) },
|
||||
label = { Text(localize(it.titleRes)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package eu.kanade.presentation.track
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
@ -42,20 +41,21 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.domain.track.model.toDbTrack
|
||||
import eu.kanade.presentation.components.DropdownMenu
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.presentation.track.components.TrackLogoIcon
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.Tracker
|
||||
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import java.text.DateFormat
|
||||
|
||||
private const val UnsetStatusTextAlpha = 0.5F
|
||||
@ -131,7 +131,7 @@ fun TrackInfoDialogHome(
|
||||
private fun TrackInfoItem(
|
||||
title: String,
|
||||
tracker: Tracker,
|
||||
@StringRes status: Int?,
|
||||
status: StringResource?,
|
||||
onStatusClick: () -> Unit,
|
||||
chapters: String,
|
||||
onChaptersClick: () -> Unit,
|
||||
@ -194,7 +194,7 @@ private fun TrackInfoItem(
|
||||
Row(modifier = Modifier.height(IntrinsicSize.Min)) {
|
||||
TrackDetailsItem(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = status?.let { stringResource(it) } ?: "",
|
||||
text = status?.let { localize(it) } ?: "",
|
||||
onClick = onStatusClick,
|
||||
)
|
||||
VerticalDivider()
|
||||
@ -209,7 +209,7 @@ private fun TrackInfoItem(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.alpha(if (score == null) UnsetStatusTextAlpha else 1f),
|
||||
text = score ?: stringResource(R.string.score),
|
||||
text = score ?: localize(MR.strings.score),
|
||||
onClick = onScoreClick,
|
||||
)
|
||||
}
|
||||
@ -221,14 +221,14 @@ private fun TrackInfoItem(
|
||||
TrackDetailsItem(
|
||||
modifier = Modifier.weight(1F),
|
||||
text = startDate,
|
||||
placeholder = stringResource(R.string.track_started_reading_date),
|
||||
placeholder = localize(MR.strings.track_started_reading_date),
|
||||
onClick = onStartDateClick,
|
||||
)
|
||||
VerticalDivider()
|
||||
TrackDetailsItem(
|
||||
modifier = Modifier.weight(1F),
|
||||
text = endDate,
|
||||
placeholder = stringResource(R.string.track_finished_reading_date),
|
||||
placeholder = localize(MR.strings.track_finished_reading_date),
|
||||
onClick = onEndDateClick,
|
||||
)
|
||||
}
|
||||
@ -279,7 +279,7 @@ private fun TrackInfoItemEmpty(
|
||||
.padding(start = 16.dp)
|
||||
.weight(1f),
|
||||
) {
|
||||
Text(text = stringResource(R.string.add_tracking))
|
||||
Text(text = localize(MR.strings.add_tracking))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -294,7 +294,7 @@ private fun TrackInfoItemMenu(
|
||||
IconButton(onClick = { expanded = true }) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = stringResource(R.string.label_more),
|
||||
contentDescription = localize(MR.strings.label_more),
|
||||
)
|
||||
}
|
||||
DropdownMenu(
|
||||
@ -302,14 +302,14 @@ private fun TrackInfoItemMenu(
|
||||
onDismissRequest = { expanded = false },
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.action_open_in_browser)) },
|
||||
text = { Text(localize(MR.strings.action_open_in_browser)) },
|
||||
onClick = {
|
||||
onOpenInBrowser()
|
||||
expanded = false
|
||||
},
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.action_remove)) },
|
||||
text = { Text(localize(MR.strings.action_remove)) },
|
||||
onClick = {
|
||||
onRemoved()
|
||||
expanded = false
|
||||
|
@ -29,18 +29,19 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
||||
import tachiyomi.presentation.core.components.WheelNumberPicker
|
||||
import tachiyomi.presentation.core.components.WheelTextPicker
|
||||
import tachiyomi.presentation.core.components.material.AlertDialogContent
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.isScrolledToEnd
|
||||
import tachiyomi.presentation.core.util.isScrolledToStart
|
||||
|
||||
@ -48,12 +49,12 @@ import tachiyomi.presentation.core.util.isScrolledToStart
|
||||
fun TrackStatusSelector(
|
||||
selection: Int,
|
||||
onSelectionChange: (Int) -> Unit,
|
||||
selections: Map<Int, Int?>,
|
||||
selections: Map<Int, StringResource?>,
|
||||
onConfirm: () -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
BaseSelector(
|
||||
title = stringResource(R.string.status),
|
||||
title = localize(MR.strings.status),
|
||||
content = {
|
||||
val state = rememberLazyListState()
|
||||
ScrollbarLazyColumn(state = state) {
|
||||
@ -76,7 +77,7 @@ fun TrackStatusSelector(
|
||||
onClick = null,
|
||||
)
|
||||
Text(
|
||||
text = value?.let { stringResource(it) } ?: "",
|
||||
text = value?.let { localize(it) } ?: "",
|
||||
style = MaterialTheme.typography.bodyLarge.merge(),
|
||||
modifier = Modifier.padding(start = 24.dp),
|
||||
)
|
||||
@ -101,7 +102,7 @@ fun TrackChapterSelector(
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
BaseSelector(
|
||||
title = stringResource(R.string.chapters),
|
||||
title = localize(MR.strings.chapters),
|
||||
content = {
|
||||
WheelNumberPicker(
|
||||
items = range.toImmutableList(),
|
||||
@ -124,7 +125,7 @@ fun TrackScoreSelector(
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
BaseSelector(
|
||||
title = stringResource(R.string.score),
|
||||
title = localize(MR.strings.score),
|
||||
content = {
|
||||
WheelTextPicker(
|
||||
items = selections,
|
||||
@ -171,15 +172,15 @@ fun TrackDateSelector(
|
||||
) {
|
||||
if (onRemove != null) {
|
||||
TextButton(onClick = onRemove) {
|
||||
Text(text = stringResource(R.string.action_remove))
|
||||
Text(text = localize(MR.strings.action_remove))
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
TextButton(onClick = { onConfirm(pickerState.selectedDateMillis!!) }) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
Text(text = localize(MR.strings.action_ok))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -214,10 +215,10 @@ private fun BaseSelector(
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
TextButton(onClick = onConfirm) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
Text(text = localize(MR.strings.action_ok))
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -234,12 +235,12 @@ private fun TrackStatusSelectorPreviews() {
|
||||
onSelectionChange = {},
|
||||
selections = mapOf(
|
||||
// Anilist values
|
||||
1 to R.string.reading,
|
||||
2 to R.string.plan_to_read,
|
||||
3 to R.string.completed,
|
||||
4 to R.string.on_hold,
|
||||
5 to R.string.dropped,
|
||||
6 to R.string.repeating,
|
||||
1 to MR.strings.reading,
|
||||
2 to MR.strings.plan_to_read,
|
||||
3 to MR.strings.completed,
|
||||
4 to MR.strings.on_hold,
|
||||
5 to MR.strings.dropped,
|
||||
6 to MR.strings.repeating,
|
||||
),
|
||||
onConfirm = {},
|
||||
onDismissRequest = {},
|
||||
|
@ -29,7 +29,6 @@ import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.CheckCircle
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material3.Button
|
||||
@ -50,7 +49,6 @@ import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.capitalize
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
@ -62,11 +60,12 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.manga.components.MangaCover
|
||||
import eu.kanade.presentation.theme.TachiyomiTheme
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||
import tachiyomi.presentation.core.util.plus
|
||||
@ -121,7 +120,7 @@ fun TrackerSearch(
|
||||
decorationBox = {
|
||||
if (query.text.isEmpty()) {
|
||||
Text(
|
||||
text = stringResource(R.string.action_search_hint),
|
||||
text = localize(MR.strings.action_search_hint),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
@ -164,7 +163,7 @@ fun TrackerSearch(
|
||||
.fillMaxWidth(),
|
||||
elevation = ButtonDefaults.elevatedButtonElevation(),
|
||||
) {
|
||||
Text(text = stringResource(R.string.action_track))
|
||||
Text(text = localize(MR.strings.action_track))
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -177,7 +176,7 @@ fun TrackerSearch(
|
||||
if (availableTracks.isEmpty()) {
|
||||
EmptyScreen(
|
||||
modifier = Modifier.padding(innerPadding),
|
||||
textResource = R.string.no_results_found,
|
||||
stringRes = MR.strings.no_results_found,
|
||||
)
|
||||
} else {
|
||||
ScrollbarLazyColumn(
|
||||
@ -205,7 +204,7 @@ fun TrackerSearch(
|
||||
EmptyScreen(
|
||||
modifier = Modifier.padding(innerPadding),
|
||||
message = queryResult.exceptionOrNull()?.message
|
||||
?: stringResource(R.string.unknown_error),
|
||||
?: localize(MR.strings.unknown_error),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -264,19 +263,19 @@ private fun SearchResultItem(
|
||||
)
|
||||
if (type.isNotBlank()) {
|
||||
SearchResultItemDetails(
|
||||
title = stringResource(R.string.track_type),
|
||||
title = localize(MR.strings.track_type),
|
||||
text = type,
|
||||
)
|
||||
}
|
||||
if (startDate.isNotBlank()) {
|
||||
SearchResultItemDetails(
|
||||
title = stringResource(R.string.label_started),
|
||||
title = localize(MR.strings.label_started),
|
||||
text = startDate,
|
||||
)
|
||||
}
|
||||
if (status.isNotBlank()) {
|
||||
SearchResultItemDetails(
|
||||
title = stringResource(R.string.track_status),
|
||||
title = localize(MR.strings.track_status),
|
||||
text = status,
|
||||
)
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun UpdatesDeleteConfirmationDialog(
|
||||
@ -14,7 +14,7 @@ fun UpdatesDeleteConfirmationDialog(
|
||||
) {
|
||||
AlertDialog(
|
||||
text = {
|
||||
Text(text = stringResource(R.string.confirm_delete_chapters))
|
||||
Text(text = localize(MR.strings.confirm_delete_chapters))
|
||||
},
|
||||
onDismissRequest = onDismissRequest,
|
||||
confirmButton = {
|
||||
@ -22,12 +22,12 @@ fun UpdatesDeleteConfirmationDialog(
|
||||
onConfirm()
|
||||
onDismissRequest()
|
||||
}) {
|
||||
Text(text = stringResource(R.string.action_ok))
|
||||
Text(text = localize(MR.strings.action_ok))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismissRequest) {
|
||||
Text(text = stringResource(R.string.action_cancel))
|
||||
Text(text = localize(MR.strings.action_cancel))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -18,23 +18,23 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.util.fastAll
|
||||
import androidx.compose.ui.util.fastAny
|
||||
import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.manga.components.ChapterDownloadAction
|
||||
import eu.kanade.presentation.manga.components.MangaBottomActionMenu
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.ui.updates.UpdatesItem
|
||||
import eu.kanade.tachiyomi.ui.updates.UpdatesScreenModel
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.FastScrollLazyColumn
|
||||
import tachiyomi.presentation.core.components.material.PullRefresh
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.screens.EmptyScreen
|
||||
import tachiyomi.presentation.core.screens.LoadingScreen
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
@ -88,7 +88,7 @@ fun UpdateScreen(
|
||||
when {
|
||||
state.isLoading -> LoadingScreen(Modifier.padding(contentPadding))
|
||||
state.items.isEmpty() -> EmptyScreen(
|
||||
textResource = R.string.information_no_recent,
|
||||
stringRes = MR.strings.information_no_recent,
|
||||
modifier = Modifier.padding(contentPadding),
|
||||
)
|
||||
else -> {
|
||||
@ -146,12 +146,12 @@ private fun UpdatesAppBar(
|
||||
) {
|
||||
AppBar(
|
||||
modifier = modifier,
|
||||
title = stringResource(R.string.label_recent_updates),
|
||||
title = localize(MR.strings.label_recent_updates),
|
||||
actions = {
|
||||
AppBarActions(
|
||||
persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_update_library),
|
||||
title = localize(MR.strings.action_update_library),
|
||||
icon = Icons.Outlined.Refresh,
|
||||
onClick = onUpdateLibrary,
|
||||
),
|
||||
@ -164,12 +164,12 @@ private fun UpdatesAppBar(
|
||||
AppBarActions(
|
||||
persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_select_all),
|
||||
title = localize(MR.strings.action_select_all),
|
||||
icon = Icons.Outlined.SelectAll,
|
||||
onClick = onSelectAll,
|
||||
),
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_select_inverse),
|
||||
title = localize(MR.strings.action_select_inverse),
|
||||
icon = Icons.Outlined.FlipToBack,
|
||||
onClick = onInvertSelection,
|
||||
),
|
||||
|
@ -29,7 +29,6 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
@ -38,13 +37,14 @@ import eu.kanade.presentation.manga.components.ChapterDownloadIndicator
|
||||
import eu.kanade.presentation.manga.components.DotSeparatorText
|
||||
import eu.kanade.presentation.manga.components.MangaCover
|
||||
import eu.kanade.presentation.util.relativeTimeSpanString
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.ui.updates.UpdatesItem
|
||||
import tachiyomi.domain.updates.model.UpdatesWithRelations
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.ListGroupHeader
|
||||
import tachiyomi.presentation.core.components.material.ReadItemAlpha
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import tachiyomi.presentation.core.util.selectedBackground
|
||||
|
||||
internal fun LazyListScope.updatesLastUpdatedItem(
|
||||
@ -56,7 +56,7 @@ internal fun LazyListScope.updatesLastUpdatedItem(
|
||||
.padding(horizontal = MaterialTheme.padding.medium, vertical = MaterialTheme.padding.small),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.updates_last_update_info, relativeTimeSpanString(lastUpdated)),
|
||||
text = localize(MR.strings.updates_last_update_info, relativeTimeSpanString(lastUpdated)),
|
||||
fontStyle = FontStyle.Italic,
|
||||
)
|
||||
}
|
||||
@ -107,8 +107,8 @@ internal fun LazyListScope.updatesUiItems(
|
||||
)/* SY <-- */ && it > 0L
|
||||
}
|
||||
?.let {
|
||||
stringResource(
|
||||
R.string.chapter_progress,
|
||||
localize(
|
||||
MR.strings.chapter_progress,
|
||||
it + 1,
|
||||
)
|
||||
},
|
||||
@ -190,7 +190,7 @@ private fun UpdatesUiItem(
|
||||
if (!update.read) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Circle,
|
||||
contentDescription = stringResource(R.string.unread),
|
||||
contentDescription = localize(MR.strings.unread),
|
||||
modifier = Modifier
|
||||
.height(8.dp)
|
||||
.padding(end = 4.dp),
|
||||
@ -200,7 +200,7 @@ private fun UpdatesUiItem(
|
||||
if (update.bookmark) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Bookmark,
|
||||
contentDescription = stringResource(R.string.action_filter_bookmarked),
|
||||
contentDescription = localize(MR.strings.action_filter_bookmarked),
|
||||
modifier = Modifier
|
||||
.sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
|
@ -1,30 +1,31 @@
|
||||
package eu.kanade.presentation.util
|
||||
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.network.HttpException
|
||||
import eu.kanade.tachiyomi.source.online.LicensedMangaChaptersException
|
||||
import eu.kanade.tachiyomi.util.system.isOnline
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.data.source.NoResultsException
|
||||
import tachiyomi.domain.source.model.SourceNotInstalledException
|
||||
import tachiyomi.i18n.MR
|
||||
import java.net.UnknownHostException
|
||||
|
||||
context(Context)
|
||||
val Throwable.formattedMessage: String
|
||||
get() {
|
||||
when (this) {
|
||||
is HttpException -> return getString(R.string.exception_http, code)
|
||||
is HttpException -> return localize(MR.strings.exception_http, code)
|
||||
is UnknownHostException -> {
|
||||
return if (!isOnline()) {
|
||||
getString(R.string.exception_offline)
|
||||
localize(MR.strings.exception_offline)
|
||||
} else {
|
||||
getString(R.string.exception_unknown_host, message)
|
||||
localize(MR.strings.exception_unknown_host, message ?: "")
|
||||
}
|
||||
}
|
||||
|
||||
is NoResultsException -> return getString(R.string.no_results_found)
|
||||
is SourceNotInstalledException -> return getString(R.string.loader_not_implemented_error)
|
||||
is LicensedMangaChaptersException -> return getString(R.string.licensed_manga_chapters_error)
|
||||
is NoResultsException -> return localize(MR.strings.no_results_found)
|
||||
is SourceNotInstalledException -> return localize(MR.strings.loader_not_implemented_error)
|
||||
is LicensedMangaChaptersException -> return localize(MR.strings.licensed_manga_chapters_error)
|
||||
}
|
||||
return when (val className = this::class.simpleName) {
|
||||
"Exception", "IOException" -> message ?: className
|
||||
|
@ -4,8 +4,9 @@ import android.content.Context
|
||||
import android.text.format.DateUtils
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
import java.util.Date
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
@ -13,10 +14,10 @@ import kotlin.time.Duration.Companion.minutes
|
||||
fun Duration.toDurationString(context: Context, fallback: String): String {
|
||||
return toComponents { days, hours, minutes, seconds, _ ->
|
||||
buildList(4) {
|
||||
if (days != 0L) add(context.getString(R.string.day_short, days))
|
||||
if (hours != 0) add(context.getString(R.string.hour_short, hours))
|
||||
if (minutes != 0 && (days == 0L || hours == 0)) add(context.getString(R.string.minute_short, minutes))
|
||||
if (seconds != 0 && days == 0L && hours == 0) add(context.getString(R.string.seconds_short, seconds))
|
||||
if (days != 0L) add(context.localize(MR.strings.day_short, days))
|
||||
if (hours != 0) add(context.localize(MR.strings.hour_short, hours))
|
||||
if (minutes != 0 && (days == 0L || hours == 0)) add(context.localize(MR.strings.minute_short, minutes))
|
||||
if (seconds != 0 && days == 0L && hours == 0) add(context.localize(MR.strings.seconds_short, seconds))
|
||||
}.joinToString(" ").ifBlank { fallback }
|
||||
}
|
||||
}
|
||||
@ -26,8 +27,8 @@ fun Duration.toDurationString(context: Context, fallback: String): String {
|
||||
fun relativeTimeSpanString(epochMillis: Long): String {
|
||||
val now = Date().time
|
||||
return when {
|
||||
epochMillis <= 0L -> stringResource(R.string.relative_time_span_never)
|
||||
now - epochMillis < 1.minutes.inWholeMilliseconds -> stringResource(R.string.updates_last_update_info_just_now)
|
||||
epochMillis <= 0L -> localize(MR.strings.relative_time_span_never)
|
||||
now - epochMillis < 1.minutes.inWholeMilliseconds -> localize(MR.strings.updates_last_update_info_just_now)
|
||||
else -> DateUtils.getRelativeTimeSpanString(epochMillis, now, DateUtils.MINUTE_IN_MILLIS).toString()
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.outlined.ArrowForward
|
||||
import androidx.compose.material.icons.outlined.ArrowBack
|
||||
import androidx.compose.material.icons.outlined.ArrowForward
|
||||
import androidx.compose.material.icons.outlined.Close
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@ -29,7 +27,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.accompanist.web.AccompanistWebViewClient
|
||||
import com.google.accompanist.web.LoadingState
|
||||
@ -40,12 +37,13 @@ import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.presentation.components.WarningBanner
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.system.getHtml
|
||||
import eu.kanade.tachiyomi.util.system.setDefaultSettings
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.i18n.localize
|
||||
|
||||
@Composable
|
||||
fun WebViewScreenContent(
|
||||
@ -127,7 +125,7 @@ fun WebViewScreenContent(
|
||||
AppBarActions(
|
||||
persistentListOf(
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_webview_back),
|
||||
title = localize(MR.strings.action_webview_back),
|
||||
icon = Icons.AutoMirrored.Outlined.ArrowBack,
|
||||
onClick = {
|
||||
if (navigator.canGoBack) {
|
||||
@ -137,7 +135,7 @@ fun WebViewScreenContent(
|
||||
enabled = navigator.canGoBack,
|
||||
),
|
||||
AppBar.Action(
|
||||
title = stringResource(R.string.action_webview_forward),
|
||||
title = localize(MR.strings.action_webview_forward),
|
||||
icon = Icons.AutoMirrored.Outlined.ArrowForward,
|
||||
onClick = {
|
||||
if (navigator.canGoForward) {
|
||||
@ -147,19 +145,19 @@ fun WebViewScreenContent(
|
||||
enabled = navigator.canGoForward,
|
||||
),
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.action_webview_refresh),
|
||||
title = localize(MR.strings.action_webview_refresh),
|
||||
onClick = { navigator.reload() },
|
||||
),
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.action_share),
|
||||
title = localize(MR.strings.action_share),
|
||||
onClick = { onShare(currentUrl) },
|
||||
),
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.action_open_in_browser),
|
||||
title = localize(MR.strings.action_open_in_browser),
|
||||
onClick = { onOpenInBrowser(currentUrl) },
|
||||
),
|
||||
AppBar.OverflowAction(
|
||||
title = stringResource(R.string.pref_clear_cookies),
|
||||
title = localize(MR.strings.pref_clear_cookies),
|
||||
onClick = { onClearCookies(currentUrl) },
|
||||
),
|
||||
),
|
||||
@ -172,7 +170,7 @@ fun WebViewScreenContent(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
) {
|
||||
WarningBanner(
|
||||
textRes = R.string.information_cloudflare_help,
|
||||
textRes = MR.strings.information_cloudflare_help,
|
||||
modifier = Modifier
|
||||
.clip(MaterialTheme.shapes.small)
|
||||
.clickable {
|
||||
|
@ -68,7 +68,9 @@ import kotlinx.coroutines.flow.onEach
|
||||
import logcat.LogPriority
|
||||
import logcat.LogcatLogger
|
||||
import org.conscrypt.Conscrypt
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.widget.WidgetManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
@ -127,8 +129,8 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
|
||||
Notifications.ID_INCOGNITO_MODE,
|
||||
Notifications.CHANNEL_INCOGNITO_MODE,
|
||||
) {
|
||||
setContentTitle(getString(R.string.pref_incognito_mode))
|
||||
setContentText(getString(R.string.notification_incognito_text))
|
||||
setContentTitle(localize(MR.strings.pref_incognito_mode))
|
||||
setContentText(localize(MR.strings.notification_incognito_text))
|
||||
setSmallIcon(R.drawable.ic_glasses_24dp)
|
||||
setOngoing(true)
|
||||
|
||||
|
@ -27,6 +27,7 @@ import tachiyomi.core.preference.plusAssign
|
||||
import tachiyomi.domain.backup.service.BackupPreferences
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_COMPLETED
|
||||
import tachiyomi.i18n.MR
|
||||
import java.io.File
|
||||
|
||||
object Migrations {
|
||||
@ -148,7 +149,7 @@ object Migrations {
|
||||
// v53: switched from WebView to OAuth
|
||||
if (trackerManager.myAnimeList.isLoggedIn) {
|
||||
trackerManager.myAnimeList.logout()
|
||||
context.toast(R.string.myanimelist_relogin)
|
||||
context.toast(MR.strings.myanimelist_relogin)
|
||||
}
|
||||
}
|
||||
if (oldVersion < 57) {
|
||||
|
@ -4,7 +4,6 @@ import android.Manifest
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.backup.BackupCreateFlags.BACKUP_APP_PREFS
|
||||
import eu.kanade.tachiyomi.data.backup.BackupCreateFlags.BACKUP_CATEGORY
|
||||
import eu.kanade.tachiyomi.data.backup.BackupCreateFlags.BACKUP_CHAPTER
|
||||
@ -47,6 +46,7 @@ import logcat.LogPriority
|
||||
import okio.buffer
|
||||
import okio.gzip
|
||||
import okio.sink
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.core.preference.Preference
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.core.util.system.logcat
|
||||
@ -62,6 +62,7 @@ import tachiyomi.domain.manga.interactor.GetFlatMetadataById
|
||||
import tachiyomi.domain.manga.interactor.GetMergedManga
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.FileOutputStream
|
||||
@ -94,7 +95,7 @@ class BackupCreator(
|
||||
*/
|
||||
suspend fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean): String {
|
||||
if (!context.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||||
throw IllegalStateException(context.getString(R.string.missing_storage_permission))
|
||||
throw IllegalStateException(context.localize(MR.strings.missing_storage_permission))
|
||||
}
|
||||
|
||||
val databaseManga = getFavorites.await() /* SY --> */ +
|
||||
@ -137,7 +138,7 @@ class BackupCreator(
|
||||
UniFile.fromUri(context, uri)
|
||||
}
|
||||
)
|
||||
?: throw Exception(context.getString(R.string.create_backup_file_error))
|
||||
?: throw Exception(context.localize(MR.strings.create_backup_file_error))
|
||||
|
||||
if (!file.isFile) {
|
||||
throw IllegalStateException("Failed to get handle on a backup file")
|
||||
@ -145,7 +146,7 @@ class BackupCreator(
|
||||
|
||||
val byteArray = parser.encodeToByteArray(BackupSerializer, backup)
|
||||
if (byteArray.isEmpty()) {
|
||||
throw IllegalStateException(context.getString(R.string.empty_backup_error))
|
||||
throw IllegalStateException(context.localize(MR.strings.empty_backup_error))
|
||||
}
|
||||
|
||||
file.openOutputStream().also {
|
||||
|
@ -2,10 +2,11 @@ package eu.kanade.tachiyomi.data.backup
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.TrackerManager
|
||||
import eu.kanade.tachiyomi.util.BackupUtil
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@ -28,7 +29,7 @@ class BackupFileValidator(
|
||||
}
|
||||
|
||||
if (backup.backupManga.isEmpty()) {
|
||||
throw IllegalStateException(context.getString(R.string.invalid_backup_file_missing_manga))
|
||||
throw IllegalStateException(context.localize(MR.strings.invalid_backup_file_missing_manga))
|
||||
}
|
||||
|
||||
val sources = backup.backupSources.associate { it.sourceId to it.name }
|
||||
|
@ -12,6 +12,9 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||
import eu.kanade.tachiyomi.util.system.cancelNotification
|
||||
import eu.kanade.tachiyomi.util.system.notificationBuilder
|
||||
import eu.kanade.tachiyomi.util.system.notify
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.core.i18n.localizePlural
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
import java.util.concurrent.TimeUnit
|
||||
@ -44,7 +47,7 @@ class BackupNotifier(private val context: Context) {
|
||||
|
||||
fun showBackupProgress(): NotificationCompat.Builder {
|
||||
val builder = with(progressNotificationBuilder) {
|
||||
setContentTitle(context.getString(R.string.creating_backup))
|
||||
setContentTitle(context.localize(MR.strings.creating_backup))
|
||||
|
||||
setProgress(0, 0, true)
|
||||
}
|
||||
@ -58,7 +61,7 @@ class BackupNotifier(private val context: Context) {
|
||||
context.cancelNotification(Notifications.ID_BACKUP_PROGRESS)
|
||||
|
||||
with(completeNotificationBuilder) {
|
||||
setContentTitle(context.getString(R.string.creating_backup_error))
|
||||
setContentTitle(context.localize(MR.strings.creating_backup_error))
|
||||
setContentText(error)
|
||||
|
||||
show(Notifications.ID_BACKUP_COMPLETE)
|
||||
@ -69,13 +72,13 @@ class BackupNotifier(private val context: Context) {
|
||||
context.cancelNotification(Notifications.ID_BACKUP_PROGRESS)
|
||||
|
||||
with(completeNotificationBuilder) {
|
||||
setContentTitle(context.getString(R.string.backup_created))
|
||||
setContentTitle(context.localize(MR.strings.backup_created))
|
||||
setContentText(unifile.filePath ?: unifile.name)
|
||||
|
||||
clearActions()
|
||||
addAction(
|
||||
R.drawable.ic_share_24dp,
|
||||
context.getString(R.string.action_share),
|
||||
context.localize(MR.strings.action_share),
|
||||
NotificationReceiver.shareBackupPendingBroadcast(
|
||||
context,
|
||||
unifile.uri,
|
||||
@ -89,8 +92,8 @@ class BackupNotifier(private val context: Context) {
|
||||
|
||||
fun showRestoreProgress(
|
||||
content: String = "",
|
||||
contentTitle: String = context.getString(
|
||||
R.string.restoring_backup,
|
||||
contentTitle: String = context.localize(
|
||||
MR.strings.restoring_backup,
|
||||
),
|
||||
progress: Int = 0,
|
||||
maxAmount: Int = 100,
|
||||
@ -108,7 +111,7 @@ class BackupNotifier(private val context: Context) {
|
||||
clearActions()
|
||||
addAction(
|
||||
R.drawable.ic_close_24dp,
|
||||
context.getString(R.string.action_cancel),
|
||||
context.localize(MR.strings.action_cancel),
|
||||
NotificationReceiver.cancelRestorePendingBroadcast(context, Notifications.ID_RESTORE_PROGRESS),
|
||||
)
|
||||
}
|
||||
@ -122,7 +125,7 @@ class BackupNotifier(private val context: Context) {
|
||||
context.cancelNotification(Notifications.ID_RESTORE_PROGRESS)
|
||||
|
||||
with(completeNotificationBuilder) {
|
||||
setContentTitle(context.getString(R.string.restoring_backup_error))
|
||||
setContentTitle(context.localize(MR.strings.restoring_backup_error))
|
||||
setContentText(error)
|
||||
|
||||
show(Notifications.ID_RESTORE_COMPLETE)
|
||||
@ -134,14 +137,14 @@ class BackupNotifier(private val context: Context) {
|
||||
errorCount: Int,
|
||||
path: String?,
|
||||
file: String?,
|
||||
contentTitle: String = context.getString(
|
||||
R.string.restore_completed,
|
||||
contentTitle: String = context.localize(
|
||||
MR.strings.restore_completed,
|
||||
),
|
||||
) {
|
||||
context.cancelNotification(Notifications.ID_RESTORE_PROGRESS)
|
||||
|
||||
val timeString = context.getString(
|
||||
R.string.restore_duration,
|
||||
val timeString = context.localize(
|
||||
MR.strings.restore_duration,
|
||||
TimeUnit.MILLISECONDS.toMinutes(time),
|
||||
TimeUnit.MILLISECONDS.toSeconds(time) - TimeUnit.MINUTES.toSeconds(
|
||||
TimeUnit.MILLISECONDS.toMinutes(time),
|
||||
@ -151,8 +154,8 @@ class BackupNotifier(private val context: Context) {
|
||||
with(completeNotificationBuilder) {
|
||||
setContentTitle(contentTitle)
|
||||
setContentText(
|
||||
context.resources.getQuantityString(
|
||||
R.plurals.restore_completed_message,
|
||||
context.localizePlural(
|
||||
MR.plurals.restore_completed_message,
|
||||
errorCount,
|
||||
timeString,
|
||||
errorCount,
|
||||
@ -168,7 +171,7 @@ class BackupNotifier(private val context: Context) {
|
||||
setContentIntent(errorLogIntent)
|
||||
addAction(
|
||||
R.drawable.ic_folder_24dp,
|
||||
context.getString(R.string.action_show_errors),
|
||||
context.localize(MR.strings.action_show_errors),
|
||||
errorLogIntent,
|
||||
)
|
||||
}
|
||||
|
@ -9,14 +9,15 @@ import androidx.work.ForegroundInfo
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkerParameters
|
||||
import androidx.work.workDataOf
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.system.cancelNotification
|
||||
import eu.kanade.tachiyomi.util.system.isRunning
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.i18n.MR
|
||||
|
||||
class BackupRestoreJob(private val context: Context, workerParams: WorkerParameters) :
|
||||
CoroutineWorker(context, workerParams) {
|
||||
@ -40,7 +41,7 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
|
||||
Result.success()
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) {
|
||||
notifier.showRestoreError(context.getString(R.string.restoring_backup_canceled))
|
||||
notifier.showRestoreError(context.localize(MR.strings.restoring_backup_canceled))
|
||||
Result.success()
|
||||
} else {
|
||||
logcat(LogPriority.ERROR, e)
|
||||
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.backup
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupFlatMetadata
|
||||
import eu.kanade.tachiyomi.data.backup.models.BackupHistory
|
||||
@ -29,6 +28,7 @@ import exh.source.MERGED_SOURCE_ID
|
||||
import exh.util.nullIfBlank
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.isActive
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.core.preference.AndroidPreferenceStore
|
||||
import tachiyomi.core.preference.PreferenceStore
|
||||
import tachiyomi.data.DatabaseHandler
|
||||
@ -49,6 +49,7 @@ import tachiyomi.domain.manga.interactor.SetCustomMangaInfo
|
||||
import tachiyomi.domain.manga.model.CustomMangaInfo
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.track.model.Track
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
@ -111,7 +112,7 @@ class BackupRestorer(
|
||||
errors.size,
|
||||
logFile.parent,
|
||||
logFile.name,
|
||||
contentTitle = context.getString(R.string.library_sync_complete),
|
||||
contentTitle = context.localize(MR.strings.library_sync_complete),
|
||||
)
|
||||
} else {
|
||||
notifier.showRestoreComplete(time, errors.size, logFile.parent, logFile.name)
|
||||
@ -217,8 +218,8 @@ class BackupRestorer(
|
||||
showRestoreProgress(
|
||||
restoreProgress,
|
||||
restoreAmount,
|
||||
context.getString(R.string.categories),
|
||||
context.getString(R.string.restoring_backup),
|
||||
context.localize(MR.strings.categories),
|
||||
context.localize(MR.strings.restoring_backup),
|
||||
)
|
||||
}
|
||||
|
||||
@ -313,14 +314,14 @@ class BackupRestorer(
|
||||
restoreProgress,
|
||||
restoreAmount,
|
||||
manga.title,
|
||||
context.getString(R.string.syncing_library),
|
||||
context.localize(MR.strings.syncing_library),
|
||||
)
|
||||
} else {
|
||||
showRestoreProgress(
|
||||
restoreProgress,
|
||||
restoreAmount,
|
||||
manga.title,
|
||||
context.getString(R.string.restoring_backup),
|
||||
context.localize(MR.strings.restoring_backup),
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -821,8 +822,8 @@ class BackupRestorer(
|
||||
showRestoreProgress(
|
||||
restoreProgress,
|
||||
restoreAmount,
|
||||
context.getString(R.string.app_settings),
|
||||
context.getString(R.string.restoring_backup),
|
||||
context.localize(MR.strings.app_settings),
|
||||
context.localize(MR.strings.restoring_backup),
|
||||
)
|
||||
}
|
||||
|
||||
@ -836,8 +837,8 @@ class BackupRestorer(
|
||||
showRestoreProgress(
|
||||
restoreProgress,
|
||||
restoreAmount,
|
||||
context.getString(R.string.source_settings),
|
||||
context.getString(R.string.restoring_backup),
|
||||
context.localize(MR.strings.source_settings),
|
||||
context.localize(MR.strings.restoring_backup),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,8 @@ import eu.kanade.tachiyomi.util.lang.chop
|
||||
import eu.kanade.tachiyomi.util.system.cancelNotification
|
||||
import eu.kanade.tachiyomi.util.system.notificationBuilder
|
||||
import eu.kanade.tachiyomi.util.system.notify
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.util.regex.Pattern
|
||||
|
||||
@ -78,13 +80,13 @@ internal class DownloadNotifier(private val context: Context) {
|
||||
// Pause action
|
||||
addAction(
|
||||
R.drawable.ic_pause_24dp,
|
||||
context.getString(R.string.action_pause),
|
||||
context.localize(MR.strings.action_pause),
|
||||
NotificationReceiver.pauseDownloadsPendingBroadcast(context),
|
||||
)
|
||||
}
|
||||
|
||||
val downloadingProgressText = context.getString(
|
||||
R.string.chapter_downloading_progress,
|
||||
val downloadingProgressText = context.localize(
|
||||
MR.strings.chapter_downloading_progress,
|
||||
download.downloadedImages,
|
||||
download.pages!!.size,
|
||||
)
|
||||
@ -115,8 +117,8 @@ internal class DownloadNotifier(private val context: Context) {
|
||||
*/
|
||||
fun onPaused() {
|
||||
with(progressNotificationBuilder) {
|
||||
setContentTitle(context.getString(R.string.chapter_paused))
|
||||
setContentText(context.getString(R.string.download_notifier_download_paused))
|
||||
setContentTitle(context.localize(MR.strings.chapter_paused))
|
||||
setContentText(context.localize(MR.strings.download_notifier_download_paused))
|
||||
setSmallIcon(R.drawable.ic_pause_24dp)
|
||||
setProgress(0, 0, false)
|
||||
setOngoing(false)
|
||||
@ -126,13 +128,13 @@ internal class DownloadNotifier(private val context: Context) {
|
||||
// Resume action
|
||||
addAction(
|
||||
R.drawable.ic_play_arrow_24dp,
|
||||
context.getString(R.string.action_resume),
|
||||
context.localize(MR.strings.action_resume),
|
||||
NotificationReceiver.resumeDownloadsPendingBroadcast(context),
|
||||
)
|
||||
// Clear action
|
||||
addAction(
|
||||
R.drawable.ic_close_24dp,
|
||||
context.getString(R.string.action_cancel_all),
|
||||
context.localize(MR.strings.action_cancel_all),
|
||||
NotificationReceiver.clearDownloadsPendingBroadcast(context),
|
||||
)
|
||||
|
||||
@ -162,7 +164,7 @@ internal class DownloadNotifier(private val context: Context) {
|
||||
*/
|
||||
fun onWarning(reason: String, timeout: Long? = null, contentIntent: PendingIntent? = null) {
|
||||
with(errorNotificationBuilder) {
|
||||
setContentTitle(context.getString(R.string.download_notifier_downloader_title))
|
||||
setContentTitle(context.localize(MR.strings.download_notifier_downloader_title))
|
||||
setStyle(NotificationCompat.BigTextStyle().bigText(reason))
|
||||
setSmallIcon(R.drawable.ic_warning_white_24dp)
|
||||
setAutoCancel(true)
|
||||
@ -190,9 +192,9 @@ internal class DownloadNotifier(private val context: Context) {
|
||||
// Create notification
|
||||
with(errorNotificationBuilder) {
|
||||
setContentTitle(
|
||||
mangaTitle?.plus(": $chapter") ?: context.getString(R.string.download_notifier_downloader_title),
|
||||
mangaTitle?.plus(": $chapter") ?: context.localize(MR.strings.download_notifier_downloader_title),
|
||||
)
|
||||
setContentText(error ?: context.getString(R.string.download_notifier_unknown_error))
|
||||
setContentText(error ?: context.localize(MR.strings.download_notifier_unknown_error))
|
||||
setSmallIcon(R.drawable.ic_warning_white_24dp)
|
||||
clearActions()
|
||||
setContentIntent(NotificationHandler.openDownloadManagerPendingActivity(context))
|
||||
|
@ -3,17 +3,18 @@ package eu.kanade.tachiyomi.data.download
|
||||
import android.content.Context
|
||||
import androidx.core.net.toUri
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.chapter.model.Chapter
|
||||
import tachiyomi.domain.download.service.DownloadPreferences
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@ -58,7 +59,7 @@ class DownloadProvider(
|
||||
.createDirectory(getMangaDirName(mangaTitle))
|
||||
} catch (e: Throwable) {
|
||||
logcat(LogPriority.ERROR, e) { "Invalid download directory" }
|
||||
throw Exception(context.getString(R.string.invalid_location, downloadsDir))
|
||||
throw Exception(context.localize(MR.strings.invalid_location, downloadsDir))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,8 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import android.os.PowerManager
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import eu.kanade.tachiyomi.R
|
||||
import dev.icerock.moko.resources.StringResource
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.util.system.acquireWakeLock
|
||||
import eu.kanade.tachiyomi.util.system.isConnectedToWifi
|
||||
@ -27,9 +26,11 @@ import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import logcat.LogPriority
|
||||
import ru.beryukhov.reactivenetwork.ReactiveNetwork
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.core.util.lang.withUIContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.download.service.DownloadPreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
/**
|
||||
@ -111,8 +112,8 @@ class DownloadService : Service() {
|
||||
return null
|
||||
}
|
||||
|
||||
private fun downloaderStop(@StringRes string: Int) {
|
||||
downloadManager.downloaderStop(getString(string))
|
||||
private fun downloaderStop(string: StringResource) {
|
||||
downloadManager.downloaderStop(localize(string))
|
||||
}
|
||||
|
||||
private fun listenNetworkChanges() {
|
||||
@ -122,20 +123,20 @@ class DownloadService : Service() {
|
||||
withUIContext {
|
||||
if (isOnline()) {
|
||||
if (downloadPreferences.downloadOnlyOverWifi().get() && !isConnectedToWifi()) {
|
||||
downloaderStop(R.string.download_notifier_text_only_wifi)
|
||||
downloaderStop(MR.strings.download_notifier_text_only_wifi)
|
||||
} else {
|
||||
val started = downloadManager.downloaderStart()
|
||||
if (!started) stopSelf()
|
||||
}
|
||||
} else {
|
||||
downloaderStop(R.string.download_notifier_no_network)
|
||||
downloaderStop(MR.strings.download_notifier_no_network)
|
||||
}
|
||||
}
|
||||
}
|
||||
.catch { error ->
|
||||
withUIContext {
|
||||
logcat(LogPriority.ERROR, error)
|
||||
toast(R.string.download_queue_error)
|
||||
toast(MR.strings.download_queue_error)
|
||||
stopSelf()
|
||||
}
|
||||
}
|
||||
@ -144,7 +145,7 @@ class DownloadService : Service() {
|
||||
|
||||
private fun getPlaceholderNotification(): Notification {
|
||||
return notificationBuilder(Notifications.CHANNEL_DOWNLOADER_PROGRESS) {
|
||||
setContentTitle(getString(R.string.download_notifier_downloader_title))
|
||||
setContentTitle(localize(MR.strings.download_notifier_downloader_title))
|
||||
}.build()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,210 @@
|
||||
package eu.kanade.tachiyomi.data.library
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.ForegroundInfo
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkQuery
|
||||
import androidx.work.WorkerParameters
|
||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||
import eu.kanade.domain.manga.model.copyFrom
|
||||
import eu.kanade.domain.manga.model.toSManga
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import eu.kanade.tachiyomi.source.UnmeteredSource
|
||||
import eu.kanade.tachiyomi.util.prepUpdateCover
|
||||
import eu.kanade.tachiyomi.util.system.isRunning
|
||||
import eu.kanade.tachiyomi.util.system.workManager
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.lang.withIOContext
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.library.model.LibraryManga
|
||||
import tachiyomi.domain.manga.interactor.GetLibraryManga
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.toMangaUpdate
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.concurrent.CopyOnWriteArrayList
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
class MetadataUpdateJob(private val context: Context, workerParams: WorkerParameters) :
|
||||
CoroutineWorker(context, workerParams) {
|
||||
|
||||
private val sourceManager: SourceManager = Injekt.get()
|
||||
private val coverCache: CoverCache = Injekt.get()
|
||||
private val getLibraryManga: GetLibraryManga = Injekt.get()
|
||||
private val updateManga: UpdateManga = Injekt.get()
|
||||
|
||||
private val notifier = LibraryUpdateNotifier(context)
|
||||
|
||||
private var mangaToUpdate: List<LibraryManga> = mutableListOf()
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
try {
|
||||
setForeground(getForegroundInfo())
|
||||
} catch (e: IllegalStateException) {
|
||||
logcat(LogPriority.ERROR, e) { "Not allowed to set foreground job" }
|
||||
}
|
||||
|
||||
addMangaToQueue()
|
||||
|
||||
return withIOContext {
|
||||
try {
|
||||
updateMetadata()
|
||||
Result.success()
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) {
|
||||
// Assume success although cancelled
|
||||
Result.success()
|
||||
} else {
|
||||
logcat(LogPriority.ERROR, e)
|
||||
Result.failure()
|
||||
}
|
||||
} finally {
|
||||
notifier.cancelProgressNotification()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getForegroundInfo(): ForegroundInfo {
|
||||
val notifier = LibraryUpdateNotifier(context)
|
||||
return ForegroundInfo(
|
||||
Notifications.ID_LIBRARY_PROGRESS,
|
||||
notifier.progressNotificationBuilder.build(),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds list of manga to be updated.
|
||||
*/
|
||||
private fun addMangaToQueue() {
|
||||
mangaToUpdate = runBlocking { getLibraryManga.await() }
|
||||
|
||||
// Warn when excessively checking a single source
|
||||
val maxUpdatesFromSource = mangaToUpdate
|
||||
.groupBy { it.manga.source }
|
||||
.filterKeys { sourceManager.get(it) !is UnmeteredSource }
|
||||
.maxOfOrNull { it.value.size } ?: 0
|
||||
if (maxUpdatesFromSource > MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD) {
|
||||
notifier.showQueueSizeWarningNotification()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun updateMetadata() {
|
||||
val semaphore = Semaphore(5)
|
||||
val progressCount = AtomicInteger(0)
|
||||
val currentlyUpdatingManga = CopyOnWriteArrayList<Manga>()
|
||||
|
||||
coroutineScope {
|
||||
mangaToUpdate.groupBy { it.manga.source }
|
||||
.values
|
||||
.map { mangaInSource ->
|
||||
async {
|
||||
semaphore.withPermit {
|
||||
mangaInSource.forEach { libraryManga ->
|
||||
val manga = libraryManga.manga
|
||||
ensureActive()
|
||||
|
||||
withUpdateNotification(
|
||||
currentlyUpdatingManga,
|
||||
progressCount,
|
||||
manga,
|
||||
) {
|
||||
val source = sourceManager.get(manga.source) ?: return@withUpdateNotification
|
||||
try {
|
||||
val networkManga = source.getMangaDetails(manga.toSManga())
|
||||
val updatedManga = manga.prepUpdateCover(coverCache, networkManga, true)
|
||||
.copyFrom(networkManga)
|
||||
try {
|
||||
updateManga.await(updatedManga.toMangaUpdate())
|
||||
} catch (e: Exception) {
|
||||
logcat(LogPriority.ERROR) { "Manga doesn't exist anymore" }
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
// Ignore errors and continue
|
||||
logcat(LogPriority.ERROR, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.awaitAll()
|
||||
}
|
||||
|
||||
notifier.cancelProgressNotification()
|
||||
}
|
||||
|
||||
private suspend fun withUpdateNotification(
|
||||
updatingManga: CopyOnWriteArrayList<Manga>,
|
||||
completed: AtomicInteger,
|
||||
manga: Manga,
|
||||
block: suspend () -> Unit,
|
||||
) = coroutineScope {
|
||||
ensureActive()
|
||||
|
||||
updatingManga.add(manga)
|
||||
notifier.showProgressNotification(
|
||||
updatingManga,
|
||||
completed.get(),
|
||||
mangaToUpdate.size,
|
||||
)
|
||||
|
||||
block()
|
||||
|
||||
ensureActive()
|
||||
|
||||
updatingManga.remove(manga)
|
||||
completed.getAndIncrement()
|
||||
notifier.showProgressNotification(
|
||||
updatingManga,
|
||||
completed.get(),
|
||||
mangaToUpdate.size,
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MetadataUpdate"
|
||||
private const val WORK_NAME_MANUAL = "MetadataUpdate"
|
||||
|
||||
private const val MANGA_PER_SOURCE_QUEUE_WARNING_THRESHOLD = 60
|
||||
|
||||
fun startNow(context: Context): Boolean {
|
||||
val wm = context.workManager
|
||||
if (wm.isRunning(TAG)) {
|
||||
// Already running either as a scheduled or manual job
|
||||
return false
|
||||
}
|
||||
val request = OneTimeWorkRequestBuilder<MetadataUpdateJob>()
|
||||
.addTag(TAG)
|
||||
.addTag(WORK_NAME_MANUAL)
|
||||
.build()
|
||||
wm.enqueueUniqueWork(WORK_NAME_MANUAL, ExistingWorkPolicy.KEEP, request)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun stop(context: Context) {
|
||||
val wm = context.workManager
|
||||
val workQuery = WorkQuery.Builder.fromTags(listOf(TAG))
|
||||
.addStates(listOf(WorkInfo.State.RUNNING))
|
||||
.build()
|
||||
wm.getWorkInfos(workQuery).get()
|
||||
// Should only return one work but just in case
|
||||
.forEach {
|
||||
wm.cancelWorkById(it.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.core.net.toUri
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
@ -32,6 +31,7 @@ import tachiyomi.domain.download.service.DownloadPreferences
|
||||
import tachiyomi.domain.manga.interactor.GetManga
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.source.service.SourceManager
|
||||
import tachiyomi.i18n.MR
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
@ -173,7 +173,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
}
|
||||
context.startActivity(intent)
|
||||
} else {
|
||||
context.toast(R.string.chapter_error)
|
||||
context.toast(MR.strings.chapter_error)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,9 +5,10 @@ import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.app.NotificationManagerCompat.IMPORTANCE_DEFAULT
|
||||
import androidx.core.app.NotificationManagerCompat.IMPORTANCE_HIGH
|
||||
import androidx.core.app.NotificationManagerCompat.IMPORTANCE_LOW
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.system.buildNotificationChannel
|
||||
import eu.kanade.tachiyomi.util.system.buildNotificationChannelGroup
|
||||
import tachiyomi.core.i18n.localize
|
||||
import tachiyomi.i18n.MR
|
||||
|
||||
/**
|
||||
* Class to manage the basic information of all the notifications used in the app.
|
||||
@ -102,16 +103,16 @@ object Notifications {
|
||||
notificationManager.createNotificationChannelGroupsCompat(
|
||||
listOf(
|
||||
buildNotificationChannelGroup(GROUP_BACKUP_RESTORE) {
|
||||
setName(context.getString(R.string.label_backup))
|
||||
setName(context.localize(MR.strings.label_backup))
|
||||
},
|
||||
buildNotificationChannelGroup(GROUP_DOWNLOADER) {
|
||||
setName(context.getString(R.string.download_notifier_downloader_title))
|
||||
setName(context.localize(MR.strings.download_notifier_downloader_title))
|
||||
},
|
||||
buildNotificationChannelGroup(GROUP_LIBRARY) {
|
||||
setName(context.getString(R.string.label_library))
|
||||
setName(context.localize(MR.strings.label_library))
|
||||
},
|
||||
buildNotificationChannelGroup(GROUP_APK_UPDATES) {
|
||||
setName(context.getString(R.string.label_recent_updates))
|
||||
setName(context.localize(MR.strings.label_recent_updates))
|
||||
},
|
||||
),
|
||||
)
|
||||
@ -119,57 +120,57 @@ object Notifications {
|
||||
notificationManager.createNotificationChannelsCompat(
|
||||
listOf(
|
||||
buildNotificationChannel(CHANNEL_COMMON, IMPORTANCE_LOW) {
|
||||
setName(context.getString(R.string.channel_common))
|
||||
setName(context.localize(MR.strings.channel_common))
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_LIBRARY_PROGRESS, IMPORTANCE_LOW) {
|
||||
setName(context.getString(R.string.channel_progress))
|
||||
setName(context.localize(MR.strings.channel_progress))
|
||||
setGroup(GROUP_LIBRARY)
|
||||
setShowBadge(false)
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_LIBRARY_ERROR, IMPORTANCE_LOW) {
|
||||
setName(context.getString(R.string.channel_errors))
|
||||
setName(context.localize(MR.strings.channel_errors))
|
||||
setGroup(GROUP_LIBRARY)
|
||||
setShowBadge(false)
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_LIBRARY_SKIPPED, IMPORTANCE_LOW) {
|
||||
setName(context.getString(R.string.channel_skipped))
|
||||
setName(context.localize(MR.strings.channel_skipped))
|
||||
setGroup(GROUP_LIBRARY)
|
||||
setShowBadge(false)
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_NEW_CHAPTERS, IMPORTANCE_DEFAULT) {
|
||||
setName(context.getString(R.string.channel_new_chapters))
|
||||
setName(context.localize(MR.strings.channel_new_chapters))
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_DOWNLOADER_PROGRESS, IMPORTANCE_LOW) {
|
||||
setName(context.getString(R.string.channel_progress))
|
||||
setName(context.localize(MR.strings.channel_progress))
|
||||
setGroup(GROUP_DOWNLOADER)
|
||||
setShowBadge(false)
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_DOWNLOADER_ERROR, IMPORTANCE_LOW) {
|
||||
setName(context.getString(R.string.channel_errors))
|
||||
setName(context.localize(MR.strings.channel_errors))
|
||||
setGroup(GROUP_DOWNLOADER)
|
||||
setShowBadge(false)
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_BACKUP_RESTORE_PROGRESS, IMPORTANCE_LOW) {
|
||||
setName(context.getString(R.string.channel_progress))
|
||||
setName(context.localize(MR.strings.channel_progress))
|
||||
setGroup(GROUP_BACKUP_RESTORE)
|
||||
setShowBadge(false)
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_BACKUP_RESTORE_COMPLETE, IMPORTANCE_HIGH) {
|
||||
setName(context.getString(R.string.channel_complete))
|
||||
setName(context.localize(MR.strings.channel_complete))
|
||||
setGroup(GROUP_BACKUP_RESTORE)
|
||||
setShowBadge(false)
|
||||
setSound(null, null)
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_INCOGNITO_MODE, IMPORTANCE_LOW) {
|
||||
setName(context.getString(R.string.pref_incognito_mode))
|
||||
setName(context.localize(MR.strings.pref_incognito_mode))
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_APP_UPDATE, IMPORTANCE_DEFAULT) {
|
||||
setGroup(GROUP_APK_UPDATES)
|
||||
setName(context.getString(R.string.channel_app_updates))
|
||||
setName(context.localize(MR.strings.channel_app_updates))
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_EXTENSIONS_UPDATE, IMPORTANCE_DEFAULT) {
|
||||
setGroup(GROUP_APK_UPDATES)
|
||||
setName(context.getString(R.string.channel_ext_updates))
|
||||
setName(context.localize(MR.strings.channel_ext_updates))
|
||||
},
|
||||
),
|
||||
)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user