Replace preference getter functions with properties (#3091)

This commit is contained in:
AntsyLich
2026-03-20 14:57:01 +06:00
committed by GitHub
parent 2f9edb551f
commit 87665736a9
126 changed files with 816 additions and 722 deletions
@@ -9,19 +9,22 @@ import tachiyomi.i18n.MR
class BasePreferences( class BasePreferences(
val context: Context, val context: Context,
private val preferenceStore: PreferenceStore, preferenceStore: PreferenceStore,
) { ) {
fun downloadedOnly() = preferenceStore.getBoolean( val downloadedOnly: Preference<Boolean> = preferenceStore.getBoolean(
Preference.appStateKey("pref_downloaded_only"), Preference.appStateKey("pref_downloaded_only"),
false, false,
) )
fun incognitoMode() = preferenceStore.getBoolean(Preference.appStateKey("incognito_mode"), false) val incognitoMode: Preference<Boolean> = preferenceStore.getBoolean(Preference.appStateKey("incognito_mode"), false)
fun extensionInstaller() = ExtensionInstallerPreference(context, preferenceStore) val extensionInstaller: ExtensionInstallerPreference = ExtensionInstallerPreference(context, preferenceStore)
fun shownOnboardingFlow() = preferenceStore.getBoolean(Preference.appStateKey("onboarding_complete"), false) val shownOnboardingFlow: Preference<Boolean> = preferenceStore.getBoolean(
Preference.appStateKey("onboarding_complete"),
false,
)
enum class ExtensionInstaller(val titleRes: StringResource, val requiresSystemPermission: Boolean) { enum class ExtensionInstaller(val titleRes: StringResource, val requiresSystemPermission: Boolean) {
LEGACY(MR.strings.ext_installer_legacy, true), LEGACY(MR.strings.ext_installer_legacy, true),
@@ -30,11 +33,17 @@ class BasePreferences(
PRIVATE(MR.strings.ext_installer_private, false), PRIVATE(MR.strings.ext_installer_private, false),
} }
fun displayProfile() = preferenceStore.getString("pref_display_profile_key", "") val displayProfile: Preference<String> = preferenceStore.getString("pref_display_profile_key", "")
fun hardwareBitmapThreshold() = preferenceStore.getInt("pref_hardware_bitmap_threshold", GLUtil.SAFE_TEXTURE_LIMIT) val hardwareBitmapThreshold: Preference<Int> = preferenceStore.getInt(
"pref_hardware_bitmap_threshold",
GLUtil.SAFE_TEXTURE_LIMIT,
)
fun alwaysDecodeLongStripWithSSIV() = preferenceStore.getBoolean("pref_always_decode_long_strip_with_ssiv", false) val alwaysDecodeLongStripWithSSIV: Preference<Boolean> = preferenceStore.getBoolean(
"pref_always_decode_long_strip_with_ssiv",
false,
)
fun installationId() = preferenceStore.getString(Preference.appStateKey("installation_id"), "") val installationId: Preference<String> = preferenceStore.getString(Preference.appStateKey("installation_id"), "")
} }
@@ -46,7 +46,7 @@ class SetReadStatus(
return@withNonCancellableContext Result.InternalError(e) return@withNonCancellableContext Result.InternalError(e)
} }
if (read && downloadPreferences.removeAfterMarkedAsRead().get()) { if (read && downloadPreferences.removeAfterMarkedAsRead.get()) {
chaptersToUpdate chaptersToUpdate
.groupBy { it.mangaId } .groupBy { it.mangaId }
.forEach { (mangaId, chapters) -> .forEach { (mangaId, chapters) ->
@@ -171,7 +171,7 @@ class SyncChaptersWithSource(
val deletedChapterNumberDateFetchMap = removedChapters.sortedByDescending { it.dateFetch } val deletedChapterNumberDateFetchMap = removedChapters.sortedByDescending { it.dateFetch }
.associate { it.chapterNumber to it.dateFetch } .associate { it.chapterNumber to it.dateFetch }
val markDuplicateAsRead = libraryPreferences.markDuplicateReadChapterAsRead().get() val markDuplicateAsRead = libraryPreferences.markDuplicateReadChapterAsRead.get()
.contains(LibraryPreferences.MARK_DUPLICATE_CHAPTER_READ_NEW) .contains(LibraryPreferences.MARK_DUPLICATE_CHAPTER_READ_NEW)
// Date fetch is set in such a way that the upper ones will have bigger value than the lower ones // Date fetch is set in such a way that the upper ones will have bigger value than the lower ones
@@ -12,7 +12,7 @@ class GetExtensionLanguages(
) { ) {
fun subscribe(): Flow<List<String>> { fun subscribe(): Flow<List<String>> {
return combine( return combine(
preferences.enabledLanguages().changes(), preferences.enabledLanguages.changes(),
extensionManager.availableExtensionsFlow, extensionManager.availableExtensionsFlow,
) { enabledLanguage, availableExtensions -> ) { enabledLanguage, availableExtensions ->
availableExtensions availableExtensions
@@ -15,7 +15,7 @@ class GetExtensionSources(
val isMultiLangSingleSource = val isMultiLangSingleSource =
isMultiSource && extension.sources.map { it.name }.distinct().size == 1 isMultiSource && extension.sources.map { it.name }.distinct().size == 1
return preferences.disabledSources().changes().map { disabledSources -> return preferences.disabledSources.changes().map { disabledSources ->
fun Source.isEnabled() = id.toString() !in disabledSources fun Source.isEnabled() = id.toString() !in disabledSources
extension.sources extension.sources
@@ -13,10 +13,10 @@ class GetExtensionsByType(
) { ) {
fun subscribe(): Flow<Extensions> { fun subscribe(): Flow<Extensions> {
val showNsfwSources = preferences.showNsfwSource().get() val showNsfwSources = preferences.showNsfwSource.get()
return combine( return combine(
preferences.enabledLanguages().changes(), preferences.enabledLanguages.changes(),
extensionManager.installedExtensionsFlow, extensionManager.installedExtensionsFlow,
extensionManager.untrustedExtensionsFlow, extensionManager.untrustedExtensionsFlow,
extensionManager.availableExtensionsFlow, extensionManager.availableExtensionsFlow,
@@ -14,11 +14,11 @@ class TrustExtension(
suspend fun isTrusted(pkgInfo: PackageInfo, fingerprints: List<String>): Boolean { suspend fun isTrusted(pkgInfo: PackageInfo, fingerprints: List<String>): Boolean {
val trustedFingerprints = extensionRepoRepository.getAll().map { it.signingKeyFingerprint }.toHashSet() val trustedFingerprints = extensionRepoRepository.getAll().map { it.signingKeyFingerprint }.toHashSet()
val key = "${pkgInfo.packageName}:${PackageInfoCompat.getLongVersionCode(pkgInfo)}:${fingerprints.last()}" val key = "${pkgInfo.packageName}:${PackageInfoCompat.getLongVersionCode(pkgInfo)}:${fingerprints.last()}"
return trustedFingerprints.any { fingerprints.contains(it) } || key in preferences.trustedExtensions().get() return trustedFingerprints.any { fingerprints.contains(it) } || key in preferences.trustedExtensions.get()
} }
fun trust(pkgName: String, versionCode: Long, signatureHash: String) { fun trust(pkgName: String, versionCode: Long, signatureHash: String) {
preferences.trustedExtensions().getAndSet { exts -> preferences.trustedExtensions.getAndSet { exts ->
// Remove previously trusted versions // Remove previously trusted versions
val removed = exts.filterNot { it.startsWith("$pkgName:") }.toMutableSet() val removed = exts.filterNot { it.startsWith("$pkgName:") }.toMutableSet()
@@ -27,6 +27,6 @@ class TrustExtension(
} }
fun revokeAll() { fun revokeAll() {
preferences.trustedExtensions().delete() preferences.trustedExtensions.delete()
} }
} }
@@ -44,7 +44,7 @@ class UpdateManga(
// if the manga isn't a favorite (or 'update titles' preference is enabled), set its title from source and update in db // if the manga isn't a favorite (or 'update titles' preference is enabled), set its title from source and update in db
val title = val title =
if (remoteTitle.isNotEmpty() && (!localManga.favorite || libraryPreferences.updateMangaTitles().get())) { if (remoteTitle.isNotEmpty() && (!localManga.favorite || libraryPreferences.updateMangaTitles.get())) {
remoteTitle remoteTitle
} else { } else {
null null
@@ -22,7 +22,7 @@ val Manga.readerOrientation: Long
val Manga.downloadedFilter: TriState val Manga.downloadedFilter: TriState
get() { get() {
if (Injekt.get<BasePreferences>().downloadedOnly().get()) return TriState.ENABLED_IS if (Injekt.get<BasePreferences>().downloadedOnly.get()) return TriState.ENABLED_IS
return when (downloadedFilterRaw) { return when (downloadedFilterRaw) {
Manga.CHAPTER_SHOW_DOWNLOADED -> TriState.ENABLED_IS Manga.CHAPTER_SHOW_DOWNLOADED -> TriState.ENABLED_IS
Manga.CHAPTER_SHOW_NOT_DOWNLOADED -> TriState.ENABLED_NOT Manga.CHAPTER_SHOW_NOT_DOWNLOADED -> TriState.ENABLED_NOT
@@ -17,10 +17,10 @@ class GetEnabledSources(
fun subscribe(): Flow<List<Source>> { fun subscribe(): Flow<List<Source>> {
return combine( return combine(
preferences.pinnedSources().changes(), preferences.pinnedSources.changes(),
preferences.enabledLanguages().changes(), preferences.enabledLanguages.changes(),
preferences.disabledSources().changes(), preferences.disabledSources.changes(),
preferences.lastUsedSource().changes(), preferences.lastUsedSource.changes(),
repository.getSources(), repository.getSources(),
) { pinnedSourceIds, enabledLanguages, disabledSources, lastUsedSource, sources -> ) { pinnedSourceIds, enabledLanguages, disabledSources, lastUsedSource, sources ->
sources sources
@@ -13,19 +13,19 @@ class GetIncognitoState(
private val extensionManager: ExtensionManager, private val extensionManager: ExtensionManager,
) { ) {
fun await(sourceId: Long?): Boolean { fun await(sourceId: Long?): Boolean {
if (basePreferences.incognitoMode().get()) return true if (basePreferences.incognitoMode.get()) return true
if (sourceId == null) return false if (sourceId == null) return false
val extensionPackage = extensionManager.getExtensionPackage(sourceId) ?: return false val extensionPackage = extensionManager.getExtensionPackage(sourceId) ?: return false
return extensionPackage in sourcePreferences.incognitoExtensions().get() return extensionPackage in sourcePreferences.incognitoExtensions.get()
} }
fun subscribe(sourceId: Long?): Flow<Boolean> { fun subscribe(sourceId: Long?): Flow<Boolean> {
if (sourceId == null) return basePreferences.incognitoMode().changes() if (sourceId == null) return basePreferences.incognitoMode.changes()
return combine( return combine(
basePreferences.incognitoMode().changes(), basePreferences.incognitoMode.changes(),
sourcePreferences.incognitoExtensions().changes(), sourcePreferences.incognitoExtensions.changes(),
extensionManager.getExtensionPackageAsFlow(sourceId), extensionManager.getExtensionPackageAsFlow(sourceId),
) { incognito, incognitoExtensions, extensionPackage -> ) { incognito, incognitoExtensions, extensionPackage ->
incognito || (extensionPackage in incognitoExtensions) incognito || (extensionPackage in incognitoExtensions)
@@ -15,8 +15,8 @@ class GetLanguagesWithSources(
fun subscribe(): Flow<SortedMap<String, List<Source>>> { fun subscribe(): Flow<SortedMap<String, List<Source>>> {
return combine( return combine(
preferences.enabledLanguages().changes(), preferences.enabledLanguages.changes(),
preferences.disabledSources().changes(), preferences.disabledSources.changes(),
repository.getOnlineSources(), repository.getOnlineSources(),
) { enabledLanguage, disabledSource, onlineSources -> ) { enabledLanguage, disabledSource, onlineSources ->
val sortedSources = onlineSources.sortedWith( val sortedSources = onlineSources.sortedWith(
@@ -16,8 +16,8 @@ class GetSourcesWithFavoriteCount(
fun subscribe(): Flow<List<Pair<Source, Long>>> { fun subscribe(): Flow<List<Pair<Source, Long>>> {
return combine( return combine(
preferences.migrationSortingDirection().changes(), preferences.migrationSortingDirection.changes(),
preferences.migrationSortingMode().changes(), preferences.migrationSortingMode.changes(),
repository.getSourcesWithFavoriteCount(), repository.getSourcesWithFavoriteCount(),
) { direction, mode, list -> ) { direction, mode, list ->
list list
@@ -7,8 +7,8 @@ class SetMigrateSorting(
) { ) {
fun await(mode: Mode, direction: Direction) { fun await(mode: Mode, direction: Direction) {
preferences.migrationSortingMode().set(mode) preferences.migrationSortingMode.set(mode)
preferences.migrationSortingDirection().set(direction) preferences.migrationSortingDirection.set(direction)
} }
enum class Mode { enum class Mode {
@@ -7,7 +7,7 @@ class ToggleIncognito(
private val preferences: SourcePreferences, private val preferences: SourcePreferences,
) { ) {
fun await(extensions: String, enable: Boolean) { fun await(extensions: String, enable: Boolean) {
preferences.incognitoExtensions().getAndSet { preferences.incognitoExtensions.getAndSet {
if (enable) it.plus(extensions) else it.minus(extensions) if (enable) it.plus(extensions) else it.minus(extensions)
} }
} }
@@ -8,8 +8,8 @@ class ToggleLanguage(
) { ) {
fun await(language: String) { fun await(language: String) {
val isEnabled = language in preferences.enabledLanguages().get() val isEnabled = language in preferences.enabledLanguages.get()
preferences.enabledLanguages().getAndSet { enabled -> preferences.enabledLanguages.getAndSet { enabled ->
if (isEnabled) enabled.minus(language) else enabled.plus(language) if (isEnabled) enabled.minus(language) else enabled.plus(language)
} }
} }
@@ -13,19 +13,19 @@ class ToggleSource(
} }
fun await(sourceId: Long, enable: Boolean = isEnabled(sourceId)) { fun await(sourceId: Long, enable: Boolean = isEnabled(sourceId)) {
preferences.disabledSources().getAndSet { disabled -> preferences.disabledSources.getAndSet { disabled ->
if (enable) disabled.minus("$sourceId") else disabled.plus("$sourceId") if (enable) disabled.minus("$sourceId") else disabled.plus("$sourceId")
} }
} }
fun await(sourceIds: List<Long>, enable: Boolean) { fun await(sourceIds: List<Long>, enable: Boolean) {
val transformedSourceIds = sourceIds.map { it.toString() } val transformedSourceIds = sourceIds.map { it.toString() }
preferences.disabledSources().getAndSet { disabled -> preferences.disabledSources.getAndSet { disabled ->
if (enable) disabled.minus(transformedSourceIds) else disabled.plus(transformedSourceIds) if (enable) disabled.minus(transformedSourceIds) else disabled.plus(transformedSourceIds)
} }
} }
private fun isEnabled(sourceId: Long): Boolean { private fun isEnabled(sourceId: Long): Boolean {
return sourceId.toString() in preferences.disabledSources().get() return sourceId.toString() in preferences.disabledSources.get()
} }
} }
@@ -9,8 +9,8 @@ class ToggleSourcePin(
) { ) {
fun await(source: Source) { fun await(source: Source) {
val isPinned = source.id.toString() in preferences.pinnedSources().get() val isPinned = source.id.toString() in preferences.pinnedSources.get()
preferences.pinnedSources().getAndSet { pinned -> preferences.pinnedSources.getAndSet { pinned ->
if (isPinned) pinned.minus("${source.id}") else pinned.plus("${source.id}") if (isPinned) pinned.minus("${source.id}") else pinned.plus("${source.id}")
} }
} }
@@ -10,68 +10,80 @@ import tachiyomi.core.common.preference.getLongArray
import tachiyomi.domain.library.model.LibraryDisplayMode import tachiyomi.domain.library.model.LibraryDisplayMode
class SourcePreferences( class SourcePreferences(
private val preferenceStore: PreferenceStore, preferenceStore: PreferenceStore,
) { ) {
fun sourceDisplayMode() = preferenceStore.getObjectFromString( val sourceDisplayMode: Preference<LibraryDisplayMode> = preferenceStore.getObjectFromString(
"pref_display_mode_catalogue", "pref_display_mode_catalogue",
LibraryDisplayMode.default, LibraryDisplayMode.default,
LibraryDisplayMode.Serializer::serialize, LibraryDisplayMode.Serializer::serialize,
LibraryDisplayMode.Serializer::deserialize, LibraryDisplayMode.Serializer::deserialize,
) )
fun enabledLanguages() = preferenceStore.getStringSet("source_languages", LocaleHelper.getDefaultEnabledLanguages()) val enabledLanguages: Preference<Set<String>> = preferenceStore.getStringSet(
"source_languages",
LocaleHelper.getDefaultEnabledLanguages(),
)
fun disabledSources() = preferenceStore.getStringSet("hidden_catalogues", emptySet()) val disabledSources: Preference<Set<String>> = preferenceStore.getStringSet("hidden_catalogues", emptySet())
fun incognitoExtensions() = preferenceStore.getStringSet("incognito_extensions", emptySet()) val incognitoExtensions: Preference<Set<String>> = preferenceStore.getStringSet("incognito_extensions", emptySet())
fun pinnedSources() = preferenceStore.getStringSet("pinned_catalogues", emptySet()) val pinnedSources: Preference<Set<String>> = preferenceStore.getStringSet("pinned_catalogues", emptySet())
fun lastUsedSource() = preferenceStore.getLong( val lastUsedSource: Preference<Long> = preferenceStore.getLong(
Preference.appStateKey("last_catalogue_source"), Preference.appStateKey("last_catalogue_source"),
-1, -1,
) )
fun showNsfwSource() = preferenceStore.getBoolean("show_nsfw_source", true) val showNsfwSource: Preference<Boolean> = preferenceStore.getBoolean("show_nsfw_source", true)
fun migrationSortingMode() = preferenceStore.getEnum("pref_migration_sorting", SetMigrateSorting.Mode.ALPHABETICAL) val migrationSortingMode: Preference<SetMigrateSorting.Mode> = preferenceStore.getEnum(
"pref_migration_sorting",
SetMigrateSorting.Mode.ALPHABETICAL,
)
fun migrationSortingDirection() = preferenceStore.getEnum( val migrationSortingDirection: Preference<SetMigrateSorting.Direction> = preferenceStore.getEnum(
"pref_migration_direction", "pref_migration_direction",
SetMigrateSorting.Direction.ASCENDING, SetMigrateSorting.Direction.ASCENDING,
) )
fun hideInLibraryItems() = preferenceStore.getBoolean("browse_hide_in_library_items", false) val hideInLibraryItems: Preference<Boolean> = preferenceStore.getBoolean("browse_hide_in_library_items", false)
fun extensionRepos() = preferenceStore.getStringSet("extension_repos", emptySet()) val extensionRepos: Preference<Set<String>> = preferenceStore.getStringSet("extension_repos", emptySet())
fun extensionUpdatesCount() = preferenceStore.getInt("ext_updates_count", 0) val extensionUpdatesCount: Preference<Int> = preferenceStore.getInt("ext_updates_count", 0)
fun trustedExtensions() = preferenceStore.getStringSet( val trustedExtensions: Preference<Set<String>> = preferenceStore.getStringSet(
Preference.appStateKey("trusted_extensions"), Preference.appStateKey("trusted_extensions"),
emptySet(), emptySet(),
) )
fun globalSearchFilterState() = preferenceStore.getBoolean( val globalSearchFilterState: Preference<Boolean> = preferenceStore.getBoolean(
Preference.appStateKey("has_filters_toggle_state"), Preference.appStateKey("has_filters_toggle_state"),
false, false,
) )
fun migrationSources() = preferenceStore.getLongArray("migration_sources", emptyList()) val migrationSources: Preference<List<Long>> = preferenceStore.getLongArray("migration_sources", emptyList())
fun migrationFlags() = preferenceStore.getObjectFromInt( val migrationFlags: Preference<Set<MigrationFlag>> = preferenceStore.getObjectFromInt(
key = "migration_flags", key = "migration_flags",
defaultValue = MigrationFlag.entries.toSet(), defaultValue = MigrationFlag.entries.toSet(),
serializer = { MigrationFlag.toBit(it) }, serializer = { MigrationFlag.toBit(it) },
deserializer = { value: Int -> MigrationFlag.fromBit(value) }, deserializer = { value: Int -> MigrationFlag.fromBit(value) },
) )
fun migrationDeepSearchMode() = preferenceStore.getBoolean("migration_deep_search", false) val migrationDeepSearchMode: Preference<Boolean> = preferenceStore.getBoolean("migration_deep_search", false)
fun migrationPrioritizeByChapters() = preferenceStore.getBoolean("migration_prioritize_by_chapters", false) val migrationPrioritizeByChapters: Preference<Boolean> = preferenceStore.getBoolean(
"migration_prioritize_by_chapters",
false,
)
fun migrationHideUnmatched() = preferenceStore.getBoolean("migration_hide_unmatched", false) val migrationHideUnmatched: Preference<Boolean> = preferenceStore.getBoolean("migration_hide_unmatched", false)
fun migrationHideWithoutUpdates() = preferenceStore.getBoolean("migration_hide_without_updates", false) val migrationHideWithoutUpdates: Preference<Boolean> = preferenceStore.getBoolean(
"migration_hide_without_updates",
false,
)
} }
@@ -34,11 +34,11 @@ class TrackPreferences(
fun trackToken(tracker: Tracker) = preferenceStore.getString(Preference.privateKey("track_token_${tracker.id}"), "") fun trackToken(tracker: Tracker) = preferenceStore.getString(Preference.privateKey("track_token_${tracker.id}"), "")
fun anilistScoreType() = preferenceStore.getString("anilist_score_type", Anilist.POINT_10) val anilistScoreType: Preference<String> = preferenceStore.getString("anilist_score_type", Anilist.POINT_10)
fun autoUpdateTrack() = preferenceStore.getBoolean("pref_auto_update_manga_sync_key", true) val autoUpdateTrack: Preference<Boolean> = preferenceStore.getBoolean("pref_auto_update_manga_sync_key", true)
fun autoUpdateTrackOnMarkRead() = preferenceStore.getEnum( val autoUpdateTrackOnMarkRead: Preference<AutoTrackState> = preferenceStore.getEnum(
"pref_auto_update_manga_on_mark_read", "pref_auto_update_manga_on_mark_read",
AutoTrackState.ALWAYS, AutoTrackState.ALWAYS,
) )
@@ -5,6 +5,7 @@ import eu.kanade.domain.ui.model.TabletUiMode
import eu.kanade.domain.ui.model.ThemeMode import eu.kanade.domain.ui.model.ThemeMode
import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable
import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.preference.PreferenceStore import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.core.common.preference.getEnum import tachiyomi.core.common.preference.getEnum
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
@@ -12,12 +13,12 @@ import java.time.format.FormatStyle
import java.util.Locale import java.util.Locale
class UiPreferences( class UiPreferences(
private val preferenceStore: PreferenceStore, preferenceStore: PreferenceStore,
) { ) {
fun themeMode() = preferenceStore.getEnum("pref_theme_mode_key", ThemeMode.SYSTEM) val themeMode: Preference<ThemeMode> = preferenceStore.getEnum("pref_theme_mode_key", ThemeMode.SYSTEM)
fun appTheme() = preferenceStore.getEnum( val appTheme: Preference<AppTheme> = preferenceStore.getEnum(
"pref_app_theme", "pref_app_theme",
if (DeviceUtil.isDynamicColorAvailable) { if (DeviceUtil.isDynamicColorAvailable) {
AppTheme.MONET AppTheme.MONET
@@ -26,15 +27,15 @@ class UiPreferences(
}, },
) )
fun themeDarkAmoled() = preferenceStore.getBoolean("pref_theme_dark_amoled_key", false) val themeDarkAmoled: Preference<Boolean> = preferenceStore.getBoolean("pref_theme_dark_amoled_key", false)
fun relativeTime() = preferenceStore.getBoolean("relative_time_v2", true) val relativeTime: Preference<Boolean> = preferenceStore.getBoolean("relative_time_v2", true)
fun dateFormat() = preferenceStore.getString("app_date_format", "") val dateFormat: Preference<String> = preferenceStore.getString("app_date_format", "")
fun tabletUiMode() = preferenceStore.getEnum("tablet_ui_mode", TabletUiMode.AUTOMATIC) val tabletUiMode: Preference<TabletUiMode> = preferenceStore.getEnum("tablet_ui_mode", TabletUiMode.AUTOMATIC)
fun imagesInDescription() = preferenceStore.getBoolean("pref_render_images_description", true) val imagesInDescription: Preference<Boolean> = preferenceStore.getBoolean("pref_render_images_description", true)
companion object { companion object {
fun dateFormat(format: String): DateTimeFormatter = when (format) { fun dateFormat(format: String): DateTimeFormatter = when (format) {
@@ -33,8 +33,8 @@ fun relativeDateText(
val context = LocalContext.current val context = LocalContext.current
val preferences = remember { Injekt.get<UiPreferences>() } val preferences = remember { Injekt.get<UiPreferences>() }
val relativeTime = remember { preferences.relativeTime().get() } val relativeTime = remember { preferences.relativeTime.get() }
val dateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat().get()) } val dateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat.get()) }
return localDate?.toRelativeString( return localDate?.toRelativeString(
context = context, context = context,
@@ -78,9 +78,9 @@ fun LibrarySettingsDialog(
private fun ColumnScope.FilterPage( private fun ColumnScope.FilterPage(
screenModel: LibrarySettingsScreenModel, screenModel: LibrarySettingsScreenModel,
) { ) {
val filterDownloaded by screenModel.libraryPreferences.filterDownloaded().collectAsState() val filterDownloaded by screenModel.libraryPreferences.filterDownloaded.collectAsState()
val downloadedOnly by screenModel.preferences.downloadedOnly().collectAsState() val downloadedOnly by screenModel.preferences.downloadedOnly.collectAsState()
val autoUpdateMangaRestrictions by screenModel.libraryPreferences.autoUpdateMangaRestrictions().collectAsState() val autoUpdateMangaRestrictions by screenModel.libraryPreferences.autoUpdateMangaRestrictions.collectAsState()
TriStateItem( TriStateItem(
label = stringResource(MR.strings.label_downloaded), label = stringResource(MR.strings.label_downloaded),
@@ -92,25 +92,25 @@ private fun ColumnScope.FilterPage(
enabled = !downloadedOnly, enabled = !downloadedOnly,
onClick = { screenModel.toggleFilter(LibraryPreferences::filterDownloaded) }, onClick = { screenModel.toggleFilter(LibraryPreferences::filterDownloaded) },
) )
val filterUnread by screenModel.libraryPreferences.filterUnread().collectAsState() val filterUnread by screenModel.libraryPreferences.filterUnread.collectAsState()
TriStateItem( TriStateItem(
label = stringResource(MR.strings.action_filter_unread), label = stringResource(MR.strings.action_filter_unread),
state = filterUnread, state = filterUnread,
onClick = { screenModel.toggleFilter(LibraryPreferences::filterUnread) }, onClick = { screenModel.toggleFilter(LibraryPreferences::filterUnread) },
) )
val filterStarted by screenModel.libraryPreferences.filterStarted().collectAsState() val filterStarted by screenModel.libraryPreferences.filterStarted.collectAsState()
TriStateItem( TriStateItem(
label = stringResource(MR.strings.label_started), label = stringResource(MR.strings.label_started),
state = filterStarted, state = filterStarted,
onClick = { screenModel.toggleFilter(LibraryPreferences::filterStarted) }, onClick = { screenModel.toggleFilter(LibraryPreferences::filterStarted) },
) )
val filterBookmarked by screenModel.libraryPreferences.filterBookmarked().collectAsState() val filterBookmarked by screenModel.libraryPreferences.filterBookmarked.collectAsState()
TriStateItem( TriStateItem(
label = stringResource(MR.strings.action_filter_bookmarked), label = stringResource(MR.strings.action_filter_bookmarked),
state = filterBookmarked, state = filterBookmarked,
onClick = { screenModel.toggleFilter(LibraryPreferences::filterBookmarked) }, onClick = { screenModel.toggleFilter(LibraryPreferences::filterBookmarked) },
) )
val filterCompleted by screenModel.libraryPreferences.filterCompleted().collectAsState() val filterCompleted by screenModel.libraryPreferences.filterCompleted.collectAsState()
TriStateItem( TriStateItem(
label = stringResource(MR.strings.completed), label = stringResource(MR.strings.completed),
state = filterCompleted, state = filterCompleted,
@@ -118,7 +118,7 @@ private fun ColumnScope.FilterPage(
) )
// TODO: re-enable when custom intervals are ready for stable // TODO: re-enable when custom intervals are ready for stable
if ((!isReleaseBuildType) && LibraryPreferences.MANGA_OUTSIDE_RELEASE_PERIOD in autoUpdateMangaRestrictions) { if ((!isReleaseBuildType) && LibraryPreferences.MANGA_OUTSIDE_RELEASE_PERIOD in autoUpdateMangaRestrictions) {
val filterIntervalCustom by screenModel.libraryPreferences.filterIntervalCustom().collectAsState() val filterIntervalCustom by screenModel.libraryPreferences.filterIntervalCustom.collectAsState()
TriStateItem( TriStateItem(
label = stringResource(MR.strings.action_filter_interval_custom), label = stringResource(MR.strings.action_filter_interval_custom),
state = filterIntervalCustom, state = filterIntervalCustom,
@@ -229,7 +229,7 @@ private val displayModes = listOf(
private fun ColumnScope.DisplayPage( private fun ColumnScope.DisplayPage(
screenModel: LibrarySettingsScreenModel, screenModel: LibrarySettingsScreenModel,
) { ) {
val displayMode by screenModel.libraryPreferences.displayMode().collectAsState() val displayMode by screenModel.libraryPreferences.displayMode.collectAsState()
SettingsChipRow(MR.strings.action_display_mode) { SettingsChipRow(MR.strings.action_display_mode) {
displayModes.map { (titleRes, mode) -> displayModes.map { (titleRes, mode) ->
FilterChip( FilterChip(
@@ -244,9 +244,9 @@ private fun ColumnScope.DisplayPage(
val configuration = LocalConfiguration.current val configuration = LocalConfiguration.current
val columnPreference = remember { val columnPreference = remember {
if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) { if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
screenModel.libraryPreferences.landscapeColumns() screenModel.libraryPreferences.landscapeColumns
} else { } else {
screenModel.libraryPreferences.portraitColumns() screenModel.libraryPreferences.portraitColumns
} }
} }
@@ -268,32 +268,32 @@ private fun ColumnScope.DisplayPage(
HeadingItem(MR.strings.overlay_header) HeadingItem(MR.strings.overlay_header)
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.action_display_download_badge), label = stringResource(MR.strings.action_display_download_badge),
pref = screenModel.libraryPreferences.downloadBadge(), pref = screenModel.libraryPreferences.downloadBadge,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.action_display_unread_badge), label = stringResource(MR.strings.action_display_unread_badge),
pref = screenModel.libraryPreferences.unreadBadge(), pref = screenModel.libraryPreferences.unreadBadge,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.action_display_local_badge), label = stringResource(MR.strings.action_display_local_badge),
pref = screenModel.libraryPreferences.localBadge(), pref = screenModel.libraryPreferences.localBadge,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.action_display_language_badge), label = stringResource(MR.strings.action_display_language_badge),
pref = screenModel.libraryPreferences.languageBadge(), pref = screenModel.libraryPreferences.languageBadge,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.action_display_show_continue_reading_button), label = stringResource(MR.strings.action_display_show_continue_reading_button),
pref = screenModel.libraryPreferences.showContinueReadingButton(), pref = screenModel.libraryPreferences.showContinueReadingButton,
) )
HeadingItem(MR.strings.tabs_header) HeadingItem(MR.strings.tabs_header)
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.action_display_show_tabs), label = stringResource(MR.strings.action_display_show_tabs),
pref = screenModel.libraryPreferences.categoryTabs(), pref = screenModel.libraryPreferences.categoryTabs,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.action_display_show_number_of_items), label = stringResource(MR.strings.action_display_show_number_of_items),
pref = screenModel.libraryPreferences.categoryNumberOfItems(), pref = screenModel.libraryPreferences.categoryNumberOfItems,
) )
} }
@@ -66,7 +66,7 @@ fun ChapterSettingsDialog(
) )
} }
val downloadedOnly = remember { Injekt.get<BasePreferences>().downloadedOnly().get() } val downloadedOnly = remember { Injekt.get<BasePreferences>().downloadedOnly.get() }
TabbedDialog( TabbedDialog(
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
@@ -618,7 +618,7 @@ private fun MangaSummary(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val preferences = remember { Injekt.get<UiPreferences>() } val preferences = remember { Injekt.get<UiPreferences>() }
val loadImages = remember { preferences.imagesInDescription().get() } val loadImages = remember { preferences.imagesInDescription.get() }
val animProgress by animateFloatAsState( val animProgress by animateFloatAsState(
targetValue = if (expanded) 1f else 0f, targetValue = if (expanded) 1f else 0f,
label = "summary", label = "summary",
@@ -125,7 +125,7 @@ internal class PermissionStep : OnboardingStep {
color = MaterialTheme.colorScheme.onPrimaryContainer, color = MaterialTheme.colorScheme.onPrimaryContainer,
) )
val crashlyticsPref = privacyPreferences.crashlytics() val crashlyticsPref = privacyPreferences.crashlytics
val crashlytics by crashlyticsPref.collectAsState() val crashlytics by crashlyticsPref.collectAsState()
PermissionSwitch( PermissionSwitch(
title = stringResource(MR.strings.onboarding_permission_crashlytics), title = stringResource(MR.strings.onboarding_permission_crashlytics),
@@ -134,7 +134,7 @@ internal class PermissionStep : OnboardingStep {
onToggleChange = crashlyticsPref::set, onToggleChange = crashlyticsPref::set,
) )
val analyticsPref = privacyPreferences.analytics() val analyticsPref = privacyPreferences.analytics
val analytics by analyticsPref.collectAsState() val analytics by analyticsPref.collectAsState()
PermissionSwitch( PermissionSwitch(
title = stringResource(MR.strings.onboarding_permission_analytics), title = stringResource(MR.strings.onboarding_permission_analytics),
@@ -30,7 +30,7 @@ import uy.kohesive.injekt.api.get
internal class StorageStep : OnboardingStep { internal class StorageStep : OnboardingStep {
private val storagePref = Injekt.get<StoragePreferences>().baseStorageDirectory() private val storagePref = Injekt.get<StoragePreferences>().baseStorageDirectory
private var _isComplete by mutableStateOf(false) private var _isComplete by mutableStateOf(false)
@@ -19,13 +19,13 @@ internal class ThemeStep : OnboardingStep {
@Composable @Composable
override fun Content() { override fun Content() {
val themeModePref = uiPreferences.themeMode() val themeModePref = uiPreferences.themeMode
val themeMode by themeModePref.collectAsState() val themeMode by themeModePref.collectAsState()
val appThemePref = uiPreferences.appTheme() val appThemePref = uiPreferences.appTheme
val appTheme by appThemePref.collectAsState() val appTheme by appThemePref.collectAsState()
val amoledPref = uiPreferences.themeDarkAmoled() val amoledPref = uiPreferences.themeDarkAmoled
val amoled by amoledPref.collectAsState() val amoled by amoledPref.collectAsState()
Column { Column {
@@ -99,7 +99,7 @@ object SettingsAdvancedScreen : SearchableSettings {
}, },
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = networkPreferences.verboseLogging(), preference = networkPreferences.verboseLogging,
title = stringResource(MR.strings.pref_verbose_logging), title = stringResource(MR.strings.pref_verbose_logging),
subtitle = stringResource(MR.strings.pref_verbose_logging_summary), subtitle = stringResource(MR.strings.pref_verbose_logging_summary),
onValueChanged = { onValueChanged = {
@@ -207,7 +207,7 @@ object SettingsAdvancedScreen : SearchableSettings {
val context = LocalContext.current val context = LocalContext.current
val networkHelper = remember { Injekt.get<NetworkHelper>() } val networkHelper = remember { Injekt.get<NetworkHelper>() }
val userAgentPref = networkPreferences.defaultUserAgent() val userAgentPref = networkPreferences.defaultUserAgent
val userAgent by userAgentPref.collectAsState() val userAgent by userAgentPref.collectAsState()
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
@@ -241,7 +241,7 @@ object SettingsAdvancedScreen : SearchableSettings {
}, },
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = networkPreferences.dohProvider(), preference = networkPreferences.dohProvider,
entries = persistentMapOf( entries = persistentMapOf(
-1 to stringResource(MR.strings.disabled), -1 to stringResource(MR.strings.disabled),
PREF_DOH_CLOUDFLARE to "Cloudflare", PREF_DOH_CLOUDFLARE to "Cloudflare",
@@ -322,12 +322,12 @@ object SettingsAdvancedScreen : SearchableSettings {
}, },
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = libraryPreferences.updateMangaTitles(), preference = libraryPreferences.updateMangaTitles,
title = stringResource(MR.strings.pref_update_library_manga_titles), title = stringResource(MR.strings.pref_update_library_manga_titles),
subtitle = stringResource(MR.strings.pref_update_library_manga_titles_summary), subtitle = stringResource(MR.strings.pref_update_library_manga_titles_summary),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = libraryPreferences.disallowNonAsciiFilenames(), preference = libraryPreferences.disallowNonAsciiFilenames,
title = stringResource(MR.strings.pref_disallow_non_ascii_filenames), title = stringResource(MR.strings.pref_disallow_non_ascii_filenames),
subtitle = stringResource(MR.strings.pref_disallow_non_ascii_filenames_details), subtitle = stringResource(MR.strings.pref_disallow_non_ascii_filenames_details),
), ),
@@ -346,14 +346,14 @@ object SettingsAdvancedScreen : SearchableSettings {
uri?.let { uri?.let {
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
context.contentResolver.takePersistableUriPermission(uri, flags) context.contentResolver.takePersistableUriPermission(uri, flags)
basePreferences.displayProfile().set(uri.toString()) basePreferences.displayProfile.set(uri.toString())
} }
} }
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_category_reader), title = stringResource(MR.strings.pref_category_reader),
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = basePreferences.hardwareBitmapThreshold(), preference = basePreferences.hardwareBitmapThreshold,
entries = GLUtil.CUSTOM_TEXTURE_LIMIT_OPTIONS entries = GLUtil.CUSTOM_TEXTURE_LIMIT_OPTIONS
.mapIndexed { index, option -> .mapIndexed { index, option ->
val display = if (index == 0) { val display = if (index == 0) {
@@ -373,13 +373,13 @@ object SettingsAdvancedScreen : SearchableSettings {
GLUtil.DEVICE_TEXTURE_LIMIT > GLUtil.SAFE_TEXTURE_LIMIT, GLUtil.DEVICE_TEXTURE_LIMIT > GLUtil.SAFE_TEXTURE_LIMIT,
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = basePreferences.alwaysDecodeLongStripWithSSIV(), preference = basePreferences.alwaysDecodeLongStripWithSSIV,
title = stringResource(MR.strings.pref_always_decode_long_strip_with_ssiv_2), title = stringResource(MR.strings.pref_always_decode_long_strip_with_ssiv_2),
subtitle = stringResource(MR.strings.pref_always_decode_long_strip_with_ssiv_summary), subtitle = stringResource(MR.strings.pref_always_decode_long_strip_with_ssiv_summary),
), ),
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.pref_display_profile), title = stringResource(MR.strings.pref_display_profile),
subtitle = basePreferences.displayProfile().get(), subtitle = basePreferences.displayProfile.get(),
onClick = { onClick = {
chooseColorProfile.launch(arrayOf("*/*")) chooseColorProfile.launch(arrayOf("*/*"))
}, },
@@ -394,7 +394,7 @@ object SettingsAdvancedScreen : SearchableSettings {
): Preference.PreferenceGroup { ): Preference.PreferenceGroup {
val context = LocalContext.current val context = LocalContext.current
val uriHandler = LocalUriHandler.current val uriHandler = LocalUriHandler.current
val extensionInstallerPref = basePreferences.extensionInstaller() val extensionInstallerPref = basePreferences.extensionInstaller
var shizukuMissing by rememberSaveable { mutableStateOf(false) } var shizukuMissing by rememberSaveable { mutableStateOf(false) }
val trustExtension = remember { Injekt.get<TrustExtension>() } val trustExtension = remember { Injekt.get<TrustExtension>() }
@@ -50,13 +50,13 @@ object SettingsAppearanceScreen : SearchableSettings {
): Preference.PreferenceGroup { ): Preference.PreferenceGroup {
val context = LocalContext.current val context = LocalContext.current
val themeModePref = uiPreferences.themeMode() val themeModePref = uiPreferences.themeMode
val themeMode by themeModePref.collectAsState() val themeMode by themeModePref.collectAsState()
val appThemePref = uiPreferences.appTheme() val appThemePref = uiPreferences.appTheme
val appTheme by appThemePref.collectAsState() val appTheme by appThemePref.collectAsState()
val amoledPref = uiPreferences.themeDarkAmoled() val amoledPref = uiPreferences.themeDarkAmoled
val amoled by amoledPref.collectAsState() val amoled by amoledPref.collectAsState()
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
@@ -103,7 +103,7 @@ object SettingsAppearanceScreen : SearchableSettings {
val now = remember { LocalDate.now() } val now = remember { LocalDate.now() }
val dateFormat by uiPreferences.dateFormat().collectAsState() val dateFormat by uiPreferences.dateFormat.collectAsState()
val formattedNow = remember(dateFormat) { val formattedNow = remember(dateFormat) {
UiPreferences.dateFormat(dateFormat).format(now) UiPreferences.dateFormat(dateFormat).format(now)
} }
@@ -116,7 +116,7 @@ object SettingsAppearanceScreen : SearchableSettings {
onClick = { navigator.push(AppLanguageScreen()) }, onClick = { navigator.push(AppLanguageScreen()) },
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = uiPreferences.tabletUiMode(), preference = uiPreferences.tabletUiMode,
entries = TabletUiMode.entries entries = TabletUiMode.entries
.associateWith { stringResource(it.titleRes) } .associateWith { stringResource(it.titleRes) }
.toImmutableMap(), .toImmutableMap(),
@@ -127,7 +127,7 @@ object SettingsAppearanceScreen : SearchableSettings {
}, },
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = uiPreferences.dateFormat(), preference = uiPreferences.dateFormat,
entries = DateFormats entries = DateFormats
.associateWith { .associateWith {
val formattedDate = UiPreferences.dateFormat(it).format(now) val formattedDate = UiPreferences.dateFormat(it).format(now)
@@ -137,7 +137,7 @@ object SettingsAppearanceScreen : SearchableSettings {
title = stringResource(MR.strings.pref_date_format), title = stringResource(MR.strings.pref_date_format),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = uiPreferences.relativeTime(), preference = uiPreferences.relativeTime,
title = stringResource(MR.strings.pref_relative_format), title = stringResource(MR.strings.pref_relative_format),
subtitle = stringResource( subtitle = stringResource(
MR.strings.pref_relative_format_summary, MR.strings.pref_relative_format_summary,
@@ -146,7 +146,7 @@ object SettingsAppearanceScreen : SearchableSettings {
), ),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = uiPreferences.imagesInDescription(), preference = uiPreferences.imagesInDescription,
title = stringResource(MR.strings.pref_display_images_description), title = stringResource(MR.strings.pref_display_images_description),
), ),
), ),
@@ -43,7 +43,7 @@ object SettingsBrowseScreen : SearchableSettings {
title = stringResource(MR.strings.label_sources), title = stringResource(MR.strings.label_sources),
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = sourcePreferences.hideInLibraryItems(), preference = sourcePreferences.hideInLibraryItems,
title = stringResource(MR.strings.pref_hide_in_library_items), title = stringResource(MR.strings.pref_hide_in_library_items),
), ),
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
@@ -59,7 +59,7 @@ object SettingsBrowseScreen : SearchableSettings {
title = stringResource(MR.strings.pref_category_nsfw_content), title = stringResource(MR.strings.pref_category_nsfw_content),
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = sourcePreferences.showNsfwSource(), preference = sourcePreferences.showNsfwSource,
title = stringResource(MR.strings.pref_show_nsfw_source), title = stringResource(MR.strings.pref_show_nsfw_source),
subtitle = stringResource(MR.strings.requires_app_restart), subtitle = stringResource(MR.strings.requires_app_restart),
onValueChanged = { onValueChanged = {
@@ -167,11 +167,11 @@ object SettingsDataScreen : SearchableSettings {
storagePreferences: StoragePreferences, storagePreferences: StoragePreferences,
): Preference.PreferenceItem.TextPreference { ): Preference.PreferenceItem.TextPreference {
val context = LocalContext.current val context = LocalContext.current
val pickStorageLocation = storageLocationPicker(storagePreferences.baseStorageDirectory()) val pickStorageLocation = storageLocationPicker(storagePreferences.baseStorageDirectory)
return Preference.PreferenceItem.TextPreference( return Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.pref_storage_location), title = stringResource(MR.strings.pref_storage_location),
subtitle = storageLocationText(storagePreferences.baseStorageDirectory()), subtitle = storageLocationText(storagePreferences.baseStorageDirectory),
onClick = { onClick = {
try { try {
pickStorageLocation.launch(null) pickStorageLocation.launch(null)
@@ -187,7 +187,7 @@ object SettingsDataScreen : SearchableSettings {
val context = LocalContext.current val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val lastAutoBackup by backupPreferences.lastAutoBackupTimestamp().collectAsState() val lastAutoBackup by backupPreferences.lastAutoBackupTimestamp.collectAsState()
val chooseBackup = rememberLauncherForActivityResult( val chooseBackup = rememberLauncherForActivityResult(
object : ActivityResultContracts.GetContent() { object : ActivityResultContracts.GetContent() {
@@ -254,7 +254,7 @@ object SettingsDataScreen : SearchableSettings {
// Automatic backups // Automatic backups
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = backupPreferences.backupInterval(), preference = backupPreferences.backupInterval,
entries = persistentMapOf( entries = persistentMapOf(
0 to stringResource(MR.strings.off), 0 to stringResource(MR.strings.off),
6 to stringResource(MR.strings.update_6hour), 6 to stringResource(MR.strings.update_6hour),
@@ -324,7 +324,7 @@ object SettingsDataScreen : SearchableSettings {
}, },
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = libraryPreferences.autoClearChapterCache(), preference = libraryPreferences.autoClearChapterCache,
title = stringResource(MR.strings.pref_auto_clear_chapter_cache), title = stringResource(MR.strings.pref_auto_clear_chapter_cache),
), ),
), ),
@@ -37,19 +37,19 @@ object SettingsDownloadScreen : SearchableSettings {
val allCategories by getCategories.subscribe().collectAsState(initial = emptyList()) val allCategories by getCategories.subscribe().collectAsState(initial = emptyList())
val downloadPreferences = remember { Injekt.get<DownloadPreferences>() } val downloadPreferences = remember { Injekt.get<DownloadPreferences>() }
val parallelSourceLimit by downloadPreferences.parallelSourceLimit().collectAsState() val parallelSourceLimit by downloadPreferences.parallelSourceLimit.collectAsState()
val parallelPageLimit by downloadPreferences.parallelPageLimit().collectAsState() val parallelPageLimit by downloadPreferences.parallelPageLimit.collectAsState()
return listOf( return listOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = downloadPreferences.downloadOnlyOverWifi(), preference = downloadPreferences.downloadOnlyOverWifi,
title = stringResource(MR.strings.connected_to_wifi), title = stringResource(MR.strings.connected_to_wifi),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = downloadPreferences.saveChaptersAsCBZ(), preference = downloadPreferences.saveChaptersAsCBZ,
title = stringResource(MR.strings.save_chapter_as_cbz), title = stringResource(MR.strings.save_chapter_as_cbz),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = downloadPreferences.splitTallImages(), preference = downloadPreferences.splitTallImages,
title = stringResource(MR.strings.split_tall_images), title = stringResource(MR.strings.split_tall_images),
subtitle = stringResource(MR.strings.split_tall_images_summary), subtitle = stringResource(MR.strings.split_tall_images_summary),
), ),
@@ -57,14 +57,14 @@ object SettingsDownloadScreen : SearchableSettings {
value = parallelSourceLimit, value = parallelSourceLimit,
valueRange = 1..10, valueRange = 1..10,
title = stringResource(MR.strings.pref_download_concurrent_sources), title = stringResource(MR.strings.pref_download_concurrent_sources),
onValueChanged = { downloadPreferences.parallelSourceLimit().set(it) }, onValueChanged = { downloadPreferences.parallelSourceLimit.set(it) },
), ),
Preference.PreferenceItem.SliderPreference( Preference.PreferenceItem.SliderPreference(
value = parallelPageLimit, value = parallelPageLimit,
valueRange = 1..15, valueRange = 1..15,
title = stringResource(MR.strings.pref_download_concurrent_pages), title = stringResource(MR.strings.pref_download_concurrent_pages),
subtitle = stringResource(MR.strings.pref_download_concurrent_pages_summary), subtitle = stringResource(MR.strings.pref_download_concurrent_pages_summary),
onValueChanged = { downloadPreferences.parallelPageLimit().set(it) }, onValueChanged = { downloadPreferences.parallelPageLimit.set(it) },
), ),
getDeleteChaptersGroup( getDeleteChaptersGroup(
downloadPreferences = downloadPreferences, downloadPreferences = downloadPreferences,
@@ -87,11 +87,11 @@ object SettingsDownloadScreen : SearchableSettings {
title = stringResource(MR.strings.pref_category_delete_chapters), title = stringResource(MR.strings.pref_category_delete_chapters),
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = downloadPreferences.removeAfterMarkedAsRead(), preference = downloadPreferences.removeAfterMarkedAsRead,
title = stringResource(MR.strings.pref_remove_after_marked_as_read), title = stringResource(MR.strings.pref_remove_after_marked_as_read),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = downloadPreferences.removeAfterReadSlots(), preference = downloadPreferences.removeAfterReadSlots,
entries = persistentMapOf( entries = persistentMapOf(
-1 to stringResource(MR.strings.disabled), -1 to stringResource(MR.strings.disabled),
0 to stringResource(MR.strings.last_read_chapter), 0 to stringResource(MR.strings.last_read_chapter),
@@ -103,7 +103,7 @@ object SettingsDownloadScreen : SearchableSettings {
title = stringResource(MR.strings.pref_remove_after_read), title = stringResource(MR.strings.pref_remove_after_read),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = downloadPreferences.removeBookmarkedChapters(), preference = downloadPreferences.removeBookmarkedChapters,
title = stringResource(MR.strings.pref_remove_bookmarked_chapters), title = stringResource(MR.strings.pref_remove_bookmarked_chapters),
), ),
getExcludedCategoriesPreference( getExcludedCategoriesPreference(
@@ -120,7 +120,7 @@ object SettingsDownloadScreen : SearchableSettings {
categories: () -> List<Category>, categories: () -> List<Category>,
): Preference.PreferenceItem.MultiSelectListPreference { ): Preference.PreferenceItem.MultiSelectListPreference {
return Preference.PreferenceItem.MultiSelectListPreference( return Preference.PreferenceItem.MultiSelectListPreference(
preference = downloadPreferences.removeExcludeCategories(), preference = downloadPreferences.removeExcludeCategories,
entries = categories() entries = categories()
.associate { it.id.toString() to it.visualName } .associate { it.id.toString() to it.visualName }
.toImmutableMap(), .toImmutableMap(),
@@ -133,10 +133,10 @@ object SettingsDownloadScreen : SearchableSettings {
downloadPreferences: DownloadPreferences, downloadPreferences: DownloadPreferences,
allCategories: List<Category>, allCategories: List<Category>,
): Preference.PreferenceGroup { ): Preference.PreferenceGroup {
val downloadNewChaptersPref = downloadPreferences.downloadNewChapters() val downloadNewChaptersPref = downloadPreferences.downloadNewChapters
val downloadNewUnreadChaptersOnlyPref = downloadPreferences.downloadNewUnreadChaptersOnly() val downloadNewUnreadChaptersOnlyPref = downloadPreferences.downloadNewUnreadChaptersOnly
val downloadNewChapterCategoriesPref = downloadPreferences.downloadNewChapterCategories() val downloadNewChapterCategoriesPref = downloadPreferences.downloadNewChapterCategories
val downloadNewChapterCategoriesExcludePref = downloadPreferences.downloadNewChapterCategoriesExclude() val downloadNewChapterCategoriesExcludePref = downloadPreferences.downloadNewChapterCategoriesExclude
val downloadNewChapters by downloadNewChaptersPref.collectAsState() val downloadNewChapters by downloadNewChaptersPref.collectAsState()
@@ -194,7 +194,7 @@ object SettingsDownloadScreen : SearchableSettings {
title = stringResource(MR.strings.download_ahead), title = stringResource(MR.strings.download_ahead),
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = downloadPreferences.autoDownloadWhileReading(), preference = downloadPreferences.autoDownloadWhileReading,
entries = listOf(0, 2, 3, 5, 10) entries = listOf(0, 2, 3, 5, 10)
.associateWith { .associateWith {
if (it == 0) { if (it == 0) {
@@ -73,7 +73,7 @@ object SettingsLibraryScreen : SearchableSettings {
val userCategoriesCount = allCategories.filterNot(Category::isSystemCategory).size val userCategoriesCount = allCategories.filterNot(Category::isSystemCategory).size
// For default category // For default category
val ids = listOf(libraryPreferences.defaultCategory().defaultValue()) + val ids = listOf(libraryPreferences.defaultCategory.defaultValue()) +
allCategories.fastMap { it.id.toInt() } allCategories.fastMap { it.id.toInt() }
val labels = listOf(stringResource(MR.strings.default_category_summary)) + val labels = listOf(stringResource(MR.strings.default_category_summary)) +
allCategories.fastMap { it.visualName } allCategories.fastMap { it.visualName }
@@ -91,12 +91,12 @@ object SettingsLibraryScreen : SearchableSettings {
onClick = { navigator.push(CategoryScreen()) }, onClick = { navigator.push(CategoryScreen()) },
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = libraryPreferences.defaultCategory(), preference = libraryPreferences.defaultCategory,
entries = ids.zip(labels).toMap().toImmutableMap(), entries = ids.zip(labels).toMap().toImmutableMap(),
title = stringResource(MR.strings.default_category), title = stringResource(MR.strings.default_category),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = libraryPreferences.categorizedDisplaySettings(), preference = libraryPreferences.categorizedDisplaySettings,
title = stringResource(MR.strings.categorized_display_settings), title = stringResource(MR.strings.categorized_display_settings),
onValueChanged = { onValueChanged = {
if (!it) { if (!it) {
@@ -118,9 +118,9 @@ object SettingsLibraryScreen : SearchableSettings {
): Preference.PreferenceGroup { ): Preference.PreferenceGroup {
val context = LocalContext.current val context = LocalContext.current
val autoUpdateIntervalPref = libraryPreferences.autoUpdateInterval() val autoUpdateIntervalPref = libraryPreferences.autoUpdateInterval
val autoUpdateCategoriesPref = libraryPreferences.updateCategories() val autoUpdateCategoriesPref = libraryPreferences.updateCategories
val autoUpdateCategoriesExcludePref = libraryPreferences.updateCategoriesExclude() val autoUpdateCategoriesExcludePref = libraryPreferences.updateCategoriesExclude
val autoUpdateInterval by autoUpdateIntervalPref.collectAsState() val autoUpdateInterval by autoUpdateIntervalPref.collectAsState()
@@ -164,7 +164,7 @@ object SettingsLibraryScreen : SearchableSettings {
}, },
), ),
Preference.PreferenceItem.MultiSelectListPreference( Preference.PreferenceItem.MultiSelectListPreference(
preference = libraryPreferences.autoUpdateDeviceRestrictions(), preference = libraryPreferences.autoUpdateDeviceRestrictions,
entries = persistentMapOf( entries = persistentMapOf(
DEVICE_ONLY_ON_WIFI to stringResource(MR.strings.connected_to_wifi), DEVICE_ONLY_ON_WIFI to stringResource(MR.strings.connected_to_wifi),
DEVICE_NETWORK_NOT_METERED to stringResource(MR.strings.network_not_metered), DEVICE_NETWORK_NOT_METERED to stringResource(MR.strings.network_not_metered),
@@ -189,12 +189,12 @@ object SettingsLibraryScreen : SearchableSettings {
onClick = { showCategoriesDialog = true }, onClick = { showCategoriesDialog = true },
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = libraryPreferences.autoUpdateMetadata(), preference = libraryPreferences.autoUpdateMetadata,
title = stringResource(MR.strings.pref_library_update_refresh_metadata), title = stringResource(MR.strings.pref_library_update_refresh_metadata),
subtitle = stringResource(MR.strings.pref_library_update_refresh_metadata_summary), subtitle = stringResource(MR.strings.pref_library_update_refresh_metadata_summary),
), ),
Preference.PreferenceItem.MultiSelectListPreference( Preference.PreferenceItem.MultiSelectListPreference(
preference = libraryPreferences.autoUpdateMangaRestrictions(), preference = libraryPreferences.autoUpdateMangaRestrictions,
entries = persistentMapOf( entries = persistentMapOf(
MANGA_HAS_UNREAD to stringResource(MR.strings.pref_update_only_completely_read), MANGA_HAS_UNREAD to stringResource(MR.strings.pref_update_only_completely_read),
MANGA_NON_READ to stringResource(MR.strings.pref_update_only_started), MANGA_NON_READ to stringResource(MR.strings.pref_update_only_started),
@@ -204,7 +204,7 @@ object SettingsLibraryScreen : SearchableSettings {
title = stringResource(MR.strings.pref_library_update_smart_update), title = stringResource(MR.strings.pref_library_update_smart_update),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = libraryPreferences.newShowUpdatesCount(), preference = libraryPreferences.newShowUpdatesCount,
title = stringResource(MR.strings.pref_library_update_show_tab_badge), title = stringResource(MR.strings.pref_library_update_show_tab_badge),
), ),
), ),
@@ -219,7 +219,7 @@ object SettingsLibraryScreen : SearchableSettings {
title = stringResource(MR.strings.pref_behavior), title = stringResource(MR.strings.pref_behavior),
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = libraryPreferences.swipeToStartAction(), preference = libraryPreferences.swipeToStartAction,
entries = persistentMapOf( entries = persistentMapOf(
LibraryPreferences.ChapterSwipeAction.Disabled to LibraryPreferences.ChapterSwipeAction.Disabled to
stringResource(MR.strings.disabled), stringResource(MR.strings.disabled),
@@ -233,7 +233,7 @@ object SettingsLibraryScreen : SearchableSettings {
title = stringResource(MR.strings.pref_chapter_swipe_start), title = stringResource(MR.strings.pref_chapter_swipe_start),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = libraryPreferences.swipeToEndAction(), preference = libraryPreferences.swipeToEndAction,
entries = persistentMapOf( entries = persistentMapOf(
LibraryPreferences.ChapterSwipeAction.Disabled to LibraryPreferences.ChapterSwipeAction.Disabled to
stringResource(MR.strings.disabled), stringResource(MR.strings.disabled),
@@ -247,7 +247,7 @@ object SettingsLibraryScreen : SearchableSettings {
title = stringResource(MR.strings.pref_chapter_swipe_end), title = stringResource(MR.strings.pref_chapter_swipe_end),
), ),
Preference.PreferenceItem.MultiSelectListPreference( Preference.PreferenceItem.MultiSelectListPreference(
preference = libraryPreferences.markDuplicateReadChapterAsRead(), preference = libraryPreferences.markDuplicateReadChapterAsRead,
entries = persistentMapOf( entries = persistentMapOf(
MARK_DUPLICATE_CHAPTER_READ_EXISTING to MARK_DUPLICATE_CHAPTER_READ_EXISTING to
stringResource(MR.strings.pref_mark_duplicate_read_chapter_read_existing), stringResource(MR.strings.pref_mark_duplicate_read_chapter_read_existing),
@@ -257,7 +257,7 @@ object SettingsLibraryScreen : SearchableSettings {
title = stringResource(MR.strings.pref_mark_duplicate_read_chapter_read), title = stringResource(MR.strings.pref_mark_duplicate_read_chapter_read),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = libraryPreferences.hideMissingChapters(), preference = libraryPreferences.hideMissingChapters,
title = stringResource(MR.strings.pref_hide_missing_chapter_indicators), title = stringResource(MR.strings.pref_hide_missing_chapter_indicators),
), ),
), ),
@@ -33,14 +33,14 @@ object SettingsReaderScreen : SearchableSettings {
return listOf( return listOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = readerPref.defaultReadingMode(), preference = readerPref.defaultReadingMode,
entries = ReadingMode.entries.drop(1) entries = ReadingMode.entries.drop(1)
.associate { it.flagValue to stringResource(it.stringRes) } .associate { it.flagValue to stringResource(it.stringRes) }
.toImmutableMap(), .toImmutableMap(),
title = stringResource(MR.strings.pref_viewer_type), title = stringResource(MR.strings.pref_viewer_type),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = readerPref.doubleTapAnimSpeed(), preference = readerPref.doubleTapAnimSpeed,
entries = persistentMapOf( entries = persistentMapOf(
1 to stringResource(MR.strings.double_tap_anim_speed_0), 1 to stringResource(MR.strings.double_tap_anim_speed_0),
500 to stringResource(MR.strings.double_tap_anim_speed_normal), 500 to stringResource(MR.strings.double_tap_anim_speed_normal),
@@ -49,17 +49,17 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_double_tap_anim_speed), title = stringResource(MR.strings.pref_double_tap_anim_speed),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPref.showReadingMode(), preference = readerPref.showReadingMode,
title = stringResource(MR.strings.pref_show_reading_mode), title = stringResource(MR.strings.pref_show_reading_mode),
subtitle = stringResource(MR.strings.pref_show_reading_mode_summary), subtitle = stringResource(MR.strings.pref_show_reading_mode_summary),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPref.showNavigationOverlayOnStart(), preference = readerPref.showNavigationOverlayOnStart,
title = stringResource(MR.strings.pref_show_navigation_mode), title = stringResource(MR.strings.pref_show_navigation_mode),
subtitle = stringResource(MR.strings.pref_show_navigation_mode_summary), subtitle = stringResource(MR.strings.pref_show_navigation_mode_summary),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPref.pageTransitions(), preference = readerPref.pageTransitions,
title = stringResource(MR.strings.pref_page_transitions), title = stringResource(MR.strings.pref_page_transitions),
), ),
getDisplayGroup(readerPreferences = readerPref), getDisplayGroup(readerPreferences = readerPref),
@@ -74,20 +74,20 @@ object SettingsReaderScreen : SearchableSettings {
@Composable @Composable
private fun getDisplayGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { private fun getDisplayGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
val fullscreenPref = readerPreferences.fullscreen() val fullscreenPref = readerPreferences.fullscreen
val fullscreen by fullscreenPref.collectAsState() val fullscreen by fullscreenPref.collectAsState()
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_category_display), title = stringResource(MR.strings.pref_category_display),
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = readerPreferences.defaultOrientationType(), preference = readerPreferences.defaultOrientationType,
entries = ReaderOrientation.entries.drop(1) entries = ReaderOrientation.entries.drop(1)
.associate { it.flagValue to stringResource(it.stringRes) } .associate { it.flagValue to stringResource(it.stringRes) }
.toImmutableMap(), .toImmutableMap(),
title = stringResource(MR.strings.pref_rotation_type), title = stringResource(MR.strings.pref_rotation_type),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = readerPreferences.readerTheme(), preference = readerPreferences.readerTheme,
entries = persistentMapOf( entries = persistentMapOf(
1 to stringResource(MR.strings.black_background), 1 to stringResource(MR.strings.black_background),
2 to stringResource(MR.strings.gray_background), 2 to stringResource(MR.strings.gray_background),
@@ -101,16 +101,16 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_fullscreen), title = stringResource(MR.strings.pref_fullscreen),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.drawUnderCutout(), preference = readerPreferences.drawUnderCutout,
title = stringResource(MR.strings.pref_cutout_short), title = stringResource(MR.strings.pref_cutout_short),
enabled = LocalView.current.hasDisplayCutout() && fullscreen, enabled = LocalView.current.hasDisplayCutout() && fullscreen,
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.keepScreenOn(), preference = readerPreferences.keepScreenOn,
title = stringResource(MR.strings.pref_keep_screen_on), title = stringResource(MR.strings.pref_keep_screen_on),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.showPageNumber(), preference = readerPreferences.showPageNumber,
title = stringResource(MR.strings.pref_show_page_number), title = stringResource(MR.strings.pref_show_page_number),
), ),
), ),
@@ -119,21 +119,21 @@ object SettingsReaderScreen : SearchableSettings {
@Composable @Composable
private fun getEInkGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { private fun getEInkGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
val flashPageState by readerPreferences.flashOnPageChange().collectAsState() val flashPageState by readerPreferences.flashOnPageChange.collectAsState()
val flashMillisPref = readerPreferences.flashDurationMillis() val flashMillisPref = readerPreferences.flashDurationMillis
val flashMillis by flashMillisPref.collectAsState() val flashMillis by flashMillisPref.collectAsState()
val flashIntervalPref = readerPreferences.flashPageInterval() val flashIntervalPref = readerPreferences.flashPageInterval
val flashInterval by flashIntervalPref.collectAsState() val flashInterval by flashIntervalPref.collectAsState()
val flashColorPref = readerPreferences.flashColor() val flashColorPref = readerPreferences.flashColor
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = "E-Ink", title = "E-Ink",
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.flashOnPageChange(), preference = readerPreferences.flashOnPageChange,
title = stringResource(MR.strings.pref_flash_page), title = stringResource(MR.strings.pref_flash_page),
subtitle = stringResource(MR.strings.pref_flash_page_summ), subtitle = stringResource(MR.strings.pref_flash_page_summ),
), ),
@@ -174,19 +174,19 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_category_reading), title = stringResource(MR.strings.pref_category_reading),
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.skipRead(), preference = readerPreferences.skipRead,
title = stringResource(MR.strings.pref_skip_read_chapters), title = stringResource(MR.strings.pref_skip_read_chapters),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.skipFiltered(), preference = readerPreferences.skipFiltered,
title = stringResource(MR.strings.pref_skip_filtered_chapters), title = stringResource(MR.strings.pref_skip_filtered_chapters),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.skipDupe(), preference = readerPreferences.skipDupe,
title = stringResource(MR.strings.pref_skip_dupe_chapters), title = stringResource(MR.strings.pref_skip_dupe_chapters),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.alwaysShowChapterTransition(), preference = readerPreferences.alwaysShowChapterTransition,
title = stringResource(MR.strings.pref_always_show_chapter_transition), title = stringResource(MR.strings.pref_always_show_chapter_transition),
), ),
), ),
@@ -195,10 +195,10 @@ object SettingsReaderScreen : SearchableSettings {
@Composable @Composable
private fun getPagedGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { private fun getPagedGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
val navModePref = readerPreferences.navigationModePager() val navModePref = readerPreferences.navigationModePager
val imageScaleTypePref = readerPreferences.imageScaleType() val imageScaleTypePref = readerPreferences.imageScaleType
val dualPageSplitPref = readerPreferences.dualPageSplitPaged() val dualPageSplitPref = readerPreferences.dualPageSplitPaged
val rotateToFitPref = readerPreferences.dualPageRotateToFit() val rotateToFitPref = readerPreferences.dualPageRotateToFit
val navMode by navModePref.collectAsState() val navMode by navModePref.collectAsState()
val imageScaleType by imageScaleTypePref.collectAsState() val imageScaleType by imageScaleTypePref.collectAsState()
@@ -217,7 +217,7 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_viewer_nav), title = stringResource(MR.strings.pref_viewer_nav),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = readerPreferences.pagerNavInverted(), preference = readerPreferences.pagerNavInverted,
entries = persistentListOf( entries = persistentListOf(
ReaderPreferences.TappingInvertMode.NONE, ReaderPreferences.TappingInvertMode.NONE,
ReaderPreferences.TappingInvertMode.HORIZONTAL, ReaderPreferences.TappingInvertMode.HORIZONTAL,
@@ -238,7 +238,7 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_image_scale_type), title = stringResource(MR.strings.pref_image_scale_type),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = readerPreferences.zoomStart(), preference = readerPreferences.zoomStart,
entries = ReaderPreferences.ZoomStart entries = ReaderPreferences.ZoomStart
.mapIndexed { index, it -> index + 1 to stringResource(it) } .mapIndexed { index, it -> index + 1 to stringResource(it) }
.toMap() .toMap()
@@ -246,16 +246,16 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_zoom_start), title = stringResource(MR.strings.pref_zoom_start),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.cropBorders(), preference = readerPreferences.cropBorders,
title = stringResource(MR.strings.pref_crop_borders), title = stringResource(MR.strings.pref_crop_borders),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.landscapeZoom(), preference = readerPreferences.landscapeZoom,
title = stringResource(MR.strings.pref_landscape_zoom), title = stringResource(MR.strings.pref_landscape_zoom),
enabled = imageScaleType == 1, enabled = imageScaleType == 1,
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.navigateToPan(), preference = readerPreferences.navigateToPan,
title = stringResource(MR.strings.pref_navigate_pan), title = stringResource(MR.strings.pref_navigate_pan),
enabled = navMode != 5, enabled = navMode != 5,
), ),
@@ -268,7 +268,7 @@ object SettingsReaderScreen : SearchableSettings {
}, },
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.dualPageInvertPaged(), preference = readerPreferences.dualPageInvertPaged,
title = stringResource(MR.strings.pref_dual_page_invert), title = stringResource(MR.strings.pref_dual_page_invert),
subtitle = stringResource(MR.strings.pref_dual_page_invert_summary), subtitle = stringResource(MR.strings.pref_dual_page_invert_summary),
enabled = dualPageSplit, enabled = dualPageSplit,
@@ -282,7 +282,7 @@ object SettingsReaderScreen : SearchableSettings {
}, },
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.dualPageRotateToFitInvert(), preference = readerPreferences.dualPageRotateToFitInvert,
title = stringResource(MR.strings.pref_page_rotate_invert), title = stringResource(MR.strings.pref_page_rotate_invert),
enabled = rotateToFit, enabled = rotateToFit,
), ),
@@ -294,10 +294,10 @@ object SettingsReaderScreen : SearchableSettings {
private fun getWebtoonGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { private fun getWebtoonGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
val numberFormat = remember { NumberFormat.getPercentInstance() } val numberFormat = remember { NumberFormat.getPercentInstance() }
val navModePref = readerPreferences.navigationModeWebtoon() val navModePref = readerPreferences.navigationModeWebtoon
val dualPageSplitPref = readerPreferences.dualPageSplitWebtoon() val dualPageSplitPref = readerPreferences.dualPageSplitWebtoon
val rotateToFitPref = readerPreferences.dualPageRotateToFitWebtoon() val rotateToFitPref = readerPreferences.dualPageRotateToFitWebtoon
val webtoonSidePaddingPref = readerPreferences.webtoonSidePadding() val webtoonSidePaddingPref = readerPreferences.webtoonSidePadding
val navMode by navModePref.collectAsState() val navMode by navModePref.collectAsState()
val dualPageSplit by dualPageSplitPref.collectAsState() val dualPageSplit by dualPageSplitPref.collectAsState()
@@ -316,7 +316,7 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_viewer_nav), title = stringResource(MR.strings.pref_viewer_nav),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = readerPreferences.webtoonNavInverted(), preference = readerPreferences.webtoonNavInverted,
entries = persistentListOf( entries = persistentListOf(
ReaderPreferences.TappingInvertMode.NONE, ReaderPreferences.TappingInvertMode.NONE,
ReaderPreferences.TappingInvertMode.HORIZONTAL, ReaderPreferences.TappingInvertMode.HORIZONTAL,
@@ -338,7 +338,7 @@ object SettingsReaderScreen : SearchableSettings {
onValueChanged = { webtoonSidePaddingPref.set(it) }, onValueChanged = { webtoonSidePaddingPref.set(it) },
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = readerPreferences.readerHideThreshold(), preference = readerPreferences.readerHideThreshold,
entries = persistentMapOf( entries = persistentMapOf(
ReaderPreferences.ReaderHideThreshold.HIGHEST to stringResource(MR.strings.pref_highest), ReaderPreferences.ReaderHideThreshold.HIGHEST to stringResource(MR.strings.pref_highest),
ReaderPreferences.ReaderHideThreshold.HIGH to stringResource(MR.strings.pref_high), ReaderPreferences.ReaderHideThreshold.HIGH to stringResource(MR.strings.pref_high),
@@ -348,7 +348,7 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_hide_threshold), title = stringResource(MR.strings.pref_hide_threshold),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.cropBordersWebtoon(), preference = readerPreferences.cropBordersWebtoon,
title = stringResource(MR.strings.pref_crop_borders), title = stringResource(MR.strings.pref_crop_borders),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
@@ -360,7 +360,7 @@ object SettingsReaderScreen : SearchableSettings {
}, },
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.dualPageInvertWebtoon(), preference = readerPreferences.dualPageInvertWebtoon,
title = stringResource(MR.strings.pref_dual_page_invert), title = stringResource(MR.strings.pref_dual_page_invert),
subtitle = stringResource(MR.strings.pref_dual_page_invert_summary), subtitle = stringResource(MR.strings.pref_dual_page_invert_summary),
enabled = dualPageSplit, enabled = dualPageSplit,
@@ -374,16 +374,16 @@ object SettingsReaderScreen : SearchableSettings {
}, },
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.dualPageRotateToFitInvertWebtoon(), preference = readerPreferences.dualPageRotateToFitInvertWebtoon,
title = stringResource(MR.strings.pref_page_rotate_invert), title = stringResource(MR.strings.pref_page_rotate_invert),
enabled = rotateToFit, enabled = rotateToFit,
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.webtoonDoubleTapZoomEnabled(), preference = readerPreferences.webtoonDoubleTapZoomEnabled,
title = stringResource(MR.strings.pref_double_tap_zoom), title = stringResource(MR.strings.pref_double_tap_zoom),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.webtoonDisableZoomOut(), preference = readerPreferences.webtoonDisableZoomOut,
title = stringResource(MR.strings.pref_webtoon_disable_zoom_out), title = stringResource(MR.strings.pref_webtoon_disable_zoom_out),
), ),
), ),
@@ -392,7 +392,7 @@ object SettingsReaderScreen : SearchableSettings {
@Composable @Composable
private fun getNavigationGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup { private fun getNavigationGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
val readWithVolumeKeysPref = readerPreferences.readWithVolumeKeys() val readWithVolumeKeysPref = readerPreferences.readWithVolumeKeys
val readWithVolumeKeys by readWithVolumeKeysPref.collectAsState() val readWithVolumeKeys by readWithVolumeKeysPref.collectAsState()
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_reader_navigation), title = stringResource(MR.strings.pref_reader_navigation),
@@ -402,7 +402,7 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_read_with_volume_keys), title = stringResource(MR.strings.pref_read_with_volume_keys),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.readWithVolumeKeysInverted(), preference = readerPreferences.readWithVolumeKeysInverted,
title = stringResource(MR.strings.pref_read_with_volume_keys_inverted), title = stringResource(MR.strings.pref_read_with_volume_keys_inverted),
enabled = readWithVolumeKeys, enabled = readWithVolumeKeys,
), ),
@@ -416,11 +416,11 @@ object SettingsReaderScreen : SearchableSettings {
title = stringResource(MR.strings.pref_reader_actions), title = stringResource(MR.strings.pref_reader_actions),
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.readWithLongTap(), preference = readerPreferences.readWithLongTap,
title = stringResource(MR.strings.pref_read_with_long_tap), title = stringResource(MR.strings.pref_read_with_long_tap),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = readerPreferences.folderPerManga(), preference = readerPreferences.folderPerManga,
title = stringResource(MR.strings.pref_create_folder_per_manga), title = stringResource(MR.strings.pref_create_folder_per_manga),
subtitle = stringResource(MR.strings.pref_create_folder_per_manga_summary), subtitle = stringResource(MR.strings.pref_create_folder_per_manga_summary),
), ),
@@ -45,7 +45,7 @@ object SettingsSecurityScreen : SearchableSettings {
): Preference.PreferenceGroup { ): Preference.PreferenceGroup {
val context = LocalContext.current val context = LocalContext.current
val authSupported = remember { context.isAuthenticationSupported() } val authSupported = remember { context.isAuthenticationSupported() }
val useAuthPref = securityPreferences.useAuthenticator() val useAuthPref = securityPreferences.useAuthenticator
val useAuth by useAuthPref.collectAsState() val useAuth by useAuthPref.collectAsState()
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
@@ -62,7 +62,7 @@ object SettingsSecurityScreen : SearchableSettings {
}, },
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = securityPreferences.lockAppAfter(), preference = securityPreferences.lockAppAfter,
entries = LockAfterValues entries = LockAfterValues
.associateWith { .associateWith {
when (it) { when (it) {
@@ -82,11 +82,11 @@ object SettingsSecurityScreen : SearchableSettings {
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = securityPreferences.hideNotificationContent(), preference = securityPreferences.hideNotificationContent,
title = stringResource(MR.strings.hide_notification_content), title = stringResource(MR.strings.hide_notification_content),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = securityPreferences.secureScreen(), preference = securityPreferences.secureScreen,
entries = SecurityPreferences.SecureScreenMode.entries entries = SecurityPreferences.SecureScreenMode.entries
.associateWith { stringResource(it.titleRes) } .associateWith { stringResource(it.titleRes) }
.toImmutableMap(), .toImmutableMap(),
@@ -105,12 +105,12 @@ object SettingsSecurityScreen : SearchableSettings {
title = stringResource(MR.strings.pref_firebase), title = stringResource(MR.strings.pref_firebase),
preferenceItems = persistentListOf( preferenceItems = persistentListOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = privacyPreferences.crashlytics(), preference = privacyPreferences.crashlytics,
title = stringResource(MR.strings.onboarding_permission_crashlytics), title = stringResource(MR.strings.onboarding_permission_crashlytics),
subtitle = stringResource(MR.strings.onboarding_permission_crashlytics_description), subtitle = stringResource(MR.strings.onboarding_permission_crashlytics_description),
), ),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = privacyPreferences.analytics(), preference = privacyPreferences.analytics,
title = stringResource(MR.strings.onboarding_permission_analytics), title = stringResource(MR.strings.onboarding_permission_analytics),
subtitle = stringResource(MR.strings.onboarding_permission_analytics_description), subtitle = stringResource(MR.strings.onboarding_permission_analytics_description),
), ),
@@ -90,7 +90,7 @@ object SettingsTrackingScreen : SearchableSettings {
val trackPreferences = remember { Injekt.get<TrackPreferences>() } val trackPreferences = remember { Injekt.get<TrackPreferences>() }
val trackerManager = remember { Injekt.get<TrackerManager>() } val trackerManager = remember { Injekt.get<TrackerManager>() }
val sourceManager = remember { Injekt.get<SourceManager>() } val sourceManager = remember { Injekt.get<SourceManager>() }
val autoTrackStatePref = trackPreferences.autoUpdateTrackOnMarkRead() val autoTrackStatePref = trackPreferences.autoUpdateTrackOnMarkRead
var dialog by remember { mutableStateOf<Any?>(null) } var dialog by remember { mutableStateOf<Any?>(null) }
dialog?.run { dialog?.run {
@@ -128,11 +128,11 @@ object SettingsTrackingScreen : SearchableSettings {
return listOf( return listOf(
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
preference = trackPreferences.autoUpdateTrack(), preference = trackPreferences.autoUpdateTrack,
title = stringResource(MR.strings.pref_auto_update_manga_sync), title = stringResource(MR.strings.pref_auto_update_manga_sync),
), ),
Preference.PreferenceItem.ListPreference( Preference.PreferenceItem.ListPreference(
preference = trackPreferences.autoUpdateTrackOnMarkRead(), preference = trackPreferences.autoUpdateTrackOnMarkRead,
entries = AutoTrackState.entries entries = AutoTrackState.entries
.associateWith { stringResource(it.titleRes) } .associateWith { stringResource(it.titleRes) }
.toPersistentMap(), .toPersistentMap(),
@@ -275,7 +275,7 @@ object AboutScreen : Screen() {
) )
.toDateTimestampString( .toDateTimestampString(
UiPreferences.dateFormat( UiPreferences.dateFormat(
Injekt.get<UiPreferences>().dateFormat().get(), Injekt.get<UiPreferences>().dateFormat.get(),
), ),
) )
} catch (e: Exception) { } catch (e: Exception) {
@@ -64,7 +64,7 @@ class DebugInfoScreen : Screen() {
val context = LocalContext.current val context = LocalContext.current
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val installationIdPref = remember { Injekt.get<BasePreferences>().installationId() } val installationIdPref = remember { Injekt.get<BasePreferences>().installationId }
val installationId by installationIdPref.collectAsState() val installationId by installationIdPref.collectAsState()
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
@@ -156,7 +156,7 @@ class WorkerInfoScreen : Screen() {
) )
.toDateTimestampString( .toDateTimestampString(
UiPreferences.dateFormat( UiPreferences.dateFormat(
Injekt.get<UiPreferences>().dateFormat().get(), Injekt.get<UiPreferences>().dateFormat.get(),
), ),
) )
appendLine("Next scheduled run: $timestamp") appendLine("Next scheduled run: $timestamp")
@@ -24,10 +24,10 @@ class DisplayRefreshHost {
internal var currentDisplayRefresh by mutableStateOf(false) internal var currentDisplayRefresh by mutableStateOf(false)
private val readerPreferences = Injekt.get<ReaderPreferences>() private val readerPreferences = Injekt.get<ReaderPreferences>()
internal val flashMillis = readerPreferences.flashDurationMillis() internal val flashMillis = readerPreferences.flashDurationMillis
internal val flashMode = readerPreferences.flashColor() internal val flashMode = readerPreferences.flashColor
internal val flashIntervalPref = readerPreferences.flashPageInterval() internal val flashIntervalPref = readerPreferences.flashPageInterval
// Internal State for Flash // Internal State for Flash
private var flashInterval = flashIntervalPref.get() private var flashInterval = flashIntervalPref.get()
@@ -22,10 +22,10 @@ import tachiyomi.presentation.core.util.collectAsState
@Composable @Composable
internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) { internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) {
val customBrightness by screenModel.preferences.customBrightness().collectAsState() val customBrightness by screenModel.preferences.customBrightness.collectAsState()
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_custom_brightness), label = stringResource(MR.strings.pref_custom_brightness),
pref = screenModel.preferences.customBrightness(), pref = screenModel.preferences.customBrightness,
) )
/* /*
@@ -35,31 +35,31 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
* 0 sets system brightness and hides the overlay. * 0 sets system brightness and hides the overlay.
*/ */
if (customBrightness) { if (customBrightness) {
val customBrightnessValue by screenModel.preferences.customBrightnessValue().collectAsState() val customBrightnessValue by screenModel.preferences.customBrightnessValue.collectAsState()
SliderItem( SliderItem(
value = customBrightnessValue, value = customBrightnessValue,
valueRange = -75..100, valueRange = -75..100,
steps = 0, steps = 0,
label = stringResource(MR.strings.pref_custom_brightness), label = stringResource(MR.strings.pref_custom_brightness),
onChange = { screenModel.preferences.customBrightnessValue().set(it) }, onChange = { screenModel.preferences.customBrightnessValue.set(it) },
pillColor = MaterialTheme.colorScheme.surfaceContainerHighest, pillColor = MaterialTheme.colorScheme.surfaceContainerHighest,
) )
} }
val colorFilter by screenModel.preferences.colorFilter().collectAsState() val colorFilter by screenModel.preferences.colorFilter.collectAsState()
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_custom_color_filter), label = stringResource(MR.strings.pref_custom_color_filter),
pref = screenModel.preferences.colorFilter(), pref = screenModel.preferences.colorFilter,
) )
if (colorFilter) { if (colorFilter) {
val colorFilterValue by screenModel.preferences.colorFilterValue().collectAsState() val colorFilterValue by screenModel.preferences.colorFilterValue.collectAsState()
SliderItem( SliderItem(
value = colorFilterValue.red, value = colorFilterValue.red,
valueRange = 0..255, valueRange = 0..255,
steps = 0, steps = 0,
label = stringResource(MR.strings.color_filter_r_value), label = stringResource(MR.strings.color_filter_r_value),
onChange = { newRValue -> onChange = { newRValue ->
screenModel.preferences.colorFilterValue().getAndSet { screenModel.preferences.colorFilterValue.getAndSet {
getColorValue(it, newRValue, RED_MASK, 16) getColorValue(it, newRValue, RED_MASK, 16)
} }
}, },
@@ -71,7 +71,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
steps = 0, steps = 0,
label = stringResource(MR.strings.color_filter_g_value), label = stringResource(MR.strings.color_filter_g_value),
onChange = { newGValue -> onChange = { newGValue ->
screenModel.preferences.colorFilterValue().getAndSet { screenModel.preferences.colorFilterValue.getAndSet {
getColorValue(it, newGValue, GREEN_MASK, 8) getColorValue(it, newGValue, GREEN_MASK, 8)
} }
}, },
@@ -83,7 +83,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
steps = 0, steps = 0,
label = stringResource(MR.strings.color_filter_b_value), label = stringResource(MR.strings.color_filter_b_value),
onChange = { newBValue -> onChange = { newBValue ->
screenModel.preferences.colorFilterValue().getAndSet { screenModel.preferences.colorFilterValue.getAndSet {
getColorValue(it, newBValue, BLUE_MASK, 0) getColorValue(it, newBValue, BLUE_MASK, 0)
} }
}, },
@@ -95,19 +95,19 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
steps = 0, steps = 0,
label = stringResource(MR.strings.color_filter_a_value), label = stringResource(MR.strings.color_filter_a_value),
onChange = { newAValue -> onChange = { newAValue ->
screenModel.preferences.colorFilterValue().getAndSet { screenModel.preferences.colorFilterValue.getAndSet {
getColorValue(it, newAValue, ALPHA_MASK, 24) getColorValue(it, newAValue, ALPHA_MASK, 24)
} }
}, },
pillColor = MaterialTheme.colorScheme.surfaceContainerHighest, pillColor = MaterialTheme.colorScheme.surfaceContainerHighest,
) )
val colorFilterMode by screenModel.preferences.colorFilterMode().collectAsState() val colorFilterMode by screenModel.preferences.colorFilterMode.collectAsState()
SettingsChipRow(MR.strings.pref_color_filter_mode) { SettingsChipRow(MR.strings.pref_color_filter_mode) {
ColorFilterMode.mapIndexed { index, it -> ColorFilterMode.mapIndexed { index, it ->
FilterChip( FilterChip(
selected = colorFilterMode == index, selected = colorFilterMode == index,
onClick = { screenModel.preferences.colorFilterMode().set(index) }, onClick = { screenModel.preferences.colorFilterMode.set(index) },
label = { Text(stringResource(it.first)) }, label = { Text(stringResource(it.first)) },
) )
} }
@@ -116,11 +116,11 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_grayscale), label = stringResource(MR.strings.pref_grayscale),
pref = screenModel.preferences.grayscale(), pref = screenModel.preferences.grayscale,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_inverted_colors), label = stringResource(MR.strings.pref_inverted_colors),
pref = screenModel.preferences.invertedColors(), pref = screenModel.preferences.invertedColors,
) )
} }
@@ -33,24 +33,24 @@ private val flashColors = listOf(
@Composable @Composable
internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) { internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
val readerTheme by screenModel.preferences.readerTheme().collectAsState() val readerTheme by screenModel.preferences.readerTheme.collectAsState()
val flashPageState by screenModel.preferences.flashOnPageChange().collectAsState() val flashPageState by screenModel.preferences.flashOnPageChange.collectAsState()
val flashMillisPref = screenModel.preferences.flashDurationMillis() val flashMillisPref = screenModel.preferences.flashDurationMillis
val flashMillis by flashMillisPref.collectAsState() val flashMillis by flashMillisPref.collectAsState()
val flashIntervalPref = screenModel.preferences.flashPageInterval() val flashIntervalPref = screenModel.preferences.flashPageInterval
val flashInterval by flashIntervalPref.collectAsState() val flashInterval by flashIntervalPref.collectAsState()
val flashColorPref = screenModel.preferences.flashColor() val flashColorPref = screenModel.preferences.flashColor
val flashColor by flashColorPref.collectAsState() val flashColor by flashColorPref.collectAsState()
SettingsChipRow(MR.strings.pref_reader_theme) { SettingsChipRow(MR.strings.pref_reader_theme) {
themes.map { (labelRes, value) -> themes.map { (labelRes, value) ->
FilterChip( FilterChip(
selected = readerTheme == value, selected = readerTheme == value,
onClick = { screenModel.preferences.readerTheme().set(value) }, onClick = { screenModel.preferences.readerTheme.set(value) },
label = { Text(stringResource(labelRes)) }, label = { Text(stringResource(labelRes)) },
) )
} }
@@ -58,45 +58,45 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_show_page_number), label = stringResource(MR.strings.pref_show_page_number),
pref = screenModel.preferences.showPageNumber(), pref = screenModel.preferences.showPageNumber,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_fullscreen), label = stringResource(MR.strings.pref_fullscreen),
pref = screenModel.preferences.fullscreen(), pref = screenModel.preferences.fullscreen,
) )
val isFullscreen by screenModel.preferences.fullscreen().collectAsState() val isFullscreen by screenModel.preferences.fullscreen.collectAsState()
if (LocalActivity.current?.hasDisplayCutout() == true && isFullscreen) { if (LocalActivity.current?.hasDisplayCutout() == true && isFullscreen) {
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_cutout_short), label = stringResource(MR.strings.pref_cutout_short),
pref = screenModel.preferences.drawUnderCutout(), pref = screenModel.preferences.drawUnderCutout,
) )
} }
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_keep_screen_on), label = stringResource(MR.strings.pref_keep_screen_on),
pref = screenModel.preferences.keepScreenOn(), pref = screenModel.preferences.keepScreenOn,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_read_with_long_tap), label = stringResource(MR.strings.pref_read_with_long_tap),
pref = screenModel.preferences.readWithLongTap(), pref = screenModel.preferences.readWithLongTap,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_always_show_chapter_transition), label = stringResource(MR.strings.pref_always_show_chapter_transition),
pref = screenModel.preferences.alwaysShowChapterTransition(), pref = screenModel.preferences.alwaysShowChapterTransition,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_page_transitions), label = stringResource(MR.strings.pref_page_transitions),
pref = screenModel.preferences.pageTransitions(), pref = screenModel.preferences.pageTransitions,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_flash_page), label = stringResource(MR.strings.pref_flash_page),
pref = screenModel.preferences.flashOnPageChange(), pref = screenModel.preferences.flashOnPageChange,
) )
if (flashPageState) { if (flashPageState) {
SliderItem( SliderItem(
@@ -63,32 +63,32 @@ internal fun ColumnScope.ReadingModePage(screenModel: ReaderSettingsScreenModel)
private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenModel) { private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenModel) {
HeadingItem(MR.strings.pager_viewer) HeadingItem(MR.strings.pager_viewer)
val navigationModePager by screenModel.preferences.navigationModePager().collectAsState() val navigationModePager by screenModel.preferences.navigationModePager.collectAsState()
val pagerNavInverted by screenModel.preferences.pagerNavInverted().collectAsState() val pagerNavInverted by screenModel.preferences.pagerNavInverted.collectAsState()
TapZonesItems( TapZonesItems(
selected = navigationModePager, selected = navigationModePager,
onSelect = screenModel.preferences.navigationModePager()::set, onSelect = screenModel.preferences.navigationModePager::set,
invertMode = pagerNavInverted, invertMode = pagerNavInverted,
onSelectInvertMode = screenModel.preferences.pagerNavInverted()::set, onSelectInvertMode = screenModel.preferences.pagerNavInverted::set,
) )
val imageScaleType by screenModel.preferences.imageScaleType().collectAsState() val imageScaleType by screenModel.preferences.imageScaleType.collectAsState()
SettingsChipRow(MR.strings.pref_image_scale_type) { SettingsChipRow(MR.strings.pref_image_scale_type) {
ReaderPreferences.ImageScaleType.mapIndexed { index, it -> ReaderPreferences.ImageScaleType.mapIndexed { index, it ->
FilterChip( FilterChip(
selected = imageScaleType == index + 1, selected = imageScaleType == index + 1,
onClick = { screenModel.preferences.imageScaleType().set(index + 1) }, onClick = { screenModel.preferences.imageScaleType.set(index + 1) },
label = { Text(stringResource(it)) }, label = { Text(stringResource(it)) },
) )
} }
} }
val zoomStart by screenModel.preferences.zoomStart().collectAsState() val zoomStart by screenModel.preferences.zoomStart.collectAsState()
SettingsChipRow(MR.strings.pref_zoom_start) { SettingsChipRow(MR.strings.pref_zoom_start) {
ReaderPreferences.ZoomStart.mapIndexed { index, it -> ReaderPreferences.ZoomStart.mapIndexed { index, it ->
FilterChip( FilterChip(
selected = zoomStart == index + 1, selected = zoomStart == index + 1,
onClick = { screenModel.preferences.zoomStart().set(index + 1) }, onClick = { screenModel.preferences.zoomStart.set(index + 1) },
label = { Text(stringResource(it)) }, label = { Text(stringResource(it)) },
) )
} }
@@ -96,42 +96,42 @@ private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenMod
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_crop_borders), label = stringResource(MR.strings.pref_crop_borders),
pref = screenModel.preferences.cropBorders(), pref = screenModel.preferences.cropBorders,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_landscape_zoom), label = stringResource(MR.strings.pref_landscape_zoom),
pref = screenModel.preferences.landscapeZoom(), pref = screenModel.preferences.landscapeZoom,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_navigate_pan), label = stringResource(MR.strings.pref_navigate_pan),
pref = screenModel.preferences.navigateToPan(), pref = screenModel.preferences.navigateToPan,
) )
val dualPageSplitPaged by screenModel.preferences.dualPageSplitPaged().collectAsState() val dualPageSplitPaged by screenModel.preferences.dualPageSplitPaged.collectAsState()
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_dual_page_split), label = stringResource(MR.strings.pref_dual_page_split),
pref = screenModel.preferences.dualPageSplitPaged(), pref = screenModel.preferences.dualPageSplitPaged,
) )
if (dualPageSplitPaged) { if (dualPageSplitPaged) {
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_dual_page_invert), label = stringResource(MR.strings.pref_dual_page_invert),
pref = screenModel.preferences.dualPageInvertPaged(), pref = screenModel.preferences.dualPageInvertPaged,
) )
} }
val dualPageRotateToFit by screenModel.preferences.dualPageRotateToFit().collectAsState() val dualPageRotateToFit by screenModel.preferences.dualPageRotateToFit.collectAsState()
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_page_rotate), label = stringResource(MR.strings.pref_page_rotate),
pref = screenModel.preferences.dualPageRotateToFit(), pref = screenModel.preferences.dualPageRotateToFit,
) )
if (dualPageRotateToFit) { if (dualPageRotateToFit) {
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_page_rotate_invert), label = stringResource(MR.strings.pref_page_rotate_invert),
pref = screenModel.preferences.dualPageRotateToFitInvert(), pref = screenModel.preferences.dualPageRotateToFitInvert,
) )
} }
} }
@@ -142,65 +142,65 @@ private fun ColumnScope.WebtoonViewerSettings(screenModel: ReaderSettingsScreenM
HeadingItem(MR.strings.webtoon_viewer) HeadingItem(MR.strings.webtoon_viewer)
val navigationModeWebtoon by screenModel.preferences.navigationModeWebtoon().collectAsState() val navigationModeWebtoon by screenModel.preferences.navigationModeWebtoon.collectAsState()
val webtoonNavInverted by screenModel.preferences.webtoonNavInverted().collectAsState() val webtoonNavInverted by screenModel.preferences.webtoonNavInverted.collectAsState()
TapZonesItems( TapZonesItems(
selected = navigationModeWebtoon, selected = navigationModeWebtoon,
onSelect = screenModel.preferences.navigationModeWebtoon()::set, onSelect = screenModel.preferences.navigationModeWebtoon::set,
invertMode = webtoonNavInverted, invertMode = webtoonNavInverted,
onSelectInvertMode = screenModel.preferences.webtoonNavInverted()::set, onSelectInvertMode = screenModel.preferences.webtoonNavInverted::set,
) )
val webtoonSidePadding by screenModel.preferences.webtoonSidePadding().collectAsState() val webtoonSidePadding by screenModel.preferences.webtoonSidePadding.collectAsState()
SliderItem( SliderItem(
value = webtoonSidePadding, value = webtoonSidePadding,
valueRange = ReaderPreferences.let { it.WEBTOON_PADDING_MIN..it.WEBTOON_PADDING_MAX }, valueRange = ReaderPreferences.let { it.WEBTOON_PADDING_MIN..it.WEBTOON_PADDING_MAX },
label = stringResource(MR.strings.pref_webtoon_side_padding), label = stringResource(MR.strings.pref_webtoon_side_padding),
valueString = numberFormat.format(webtoonSidePadding / 100f), valueString = numberFormat.format(webtoonSidePadding / 100f),
onChange = { onChange = {
screenModel.preferences.webtoonSidePadding().set(it) screenModel.preferences.webtoonSidePadding.set(it)
}, },
pillColor = MaterialTheme.colorScheme.surfaceContainerHighest, pillColor = MaterialTheme.colorScheme.surfaceContainerHighest,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_crop_borders), label = stringResource(MR.strings.pref_crop_borders),
pref = screenModel.preferences.cropBordersWebtoon(), pref = screenModel.preferences.cropBordersWebtoon,
) )
val dualPageSplitWebtoon by screenModel.preferences.dualPageSplitWebtoon().collectAsState() val dualPageSplitWebtoon by screenModel.preferences.dualPageSplitWebtoon.collectAsState()
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_dual_page_split), label = stringResource(MR.strings.pref_dual_page_split),
pref = screenModel.preferences.dualPageSplitWebtoon(), pref = screenModel.preferences.dualPageSplitWebtoon,
) )
if (dualPageSplitWebtoon) { if (dualPageSplitWebtoon) {
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_dual_page_invert), label = stringResource(MR.strings.pref_dual_page_invert),
pref = screenModel.preferences.dualPageInvertWebtoon(), pref = screenModel.preferences.dualPageInvertWebtoon,
) )
} }
val dualPageRotateToFitWebtoon by screenModel.preferences.dualPageRotateToFitWebtoon().collectAsState() val dualPageRotateToFitWebtoon by screenModel.preferences.dualPageRotateToFitWebtoon.collectAsState()
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_page_rotate), label = stringResource(MR.strings.pref_page_rotate),
pref = screenModel.preferences.dualPageRotateToFitWebtoon(), pref = screenModel.preferences.dualPageRotateToFitWebtoon,
) )
if (dualPageRotateToFitWebtoon) { if (dualPageRotateToFitWebtoon) {
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_page_rotate_invert), label = stringResource(MR.strings.pref_page_rotate_invert),
pref = screenModel.preferences.dualPageRotateToFitInvertWebtoon(), pref = screenModel.preferences.dualPageRotateToFitInvertWebtoon,
) )
} }
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_double_tap_zoom), label = stringResource(MR.strings.pref_double_tap_zoom),
pref = screenModel.preferences.webtoonDoubleTapZoomEnabled(), pref = screenModel.preferences.webtoonDoubleTapZoomEnabled,
) )
CheckboxItem( CheckboxItem(
label = stringResource(MR.strings.pref_webtoon_disable_zoom_out), label = stringResource(MR.strings.pref_webtoon_disable_zoom_out),
pref = screenModel.preferences.webtoonDisableZoomOut(), pref = screenModel.preferences.webtoonDisableZoomOut,
) )
} }
@@ -35,8 +35,8 @@ fun TachiyomiTheme(
) { ) {
val uiPreferences = Injekt.get<UiPreferences>() val uiPreferences = Injekt.get<UiPreferences>()
BaseTachiyomiTheme( BaseTachiyomiTheme(
appTheme = appTheme ?: uiPreferences.appTheme().get(), appTheme = appTheme ?: uiPreferences.appTheme.get(),
isAmoled = amoled ?: uiPreferences.themeDarkAmoled().get(), isAmoled = amoled ?: uiPreferences.themeDarkAmoled.get(),
content = content, content = content,
) )
} }
@@ -55,28 +55,28 @@ fun UpdatesFilterDialog(
private fun ColumnScope.FilterSheet( private fun ColumnScope.FilterSheet(
screenModel: UpdatesSettingsScreenModel, screenModel: UpdatesSettingsScreenModel,
) { ) {
val filterDownloaded by screenModel.updatesPreferences.filterDownloaded().collectAsState() val filterDownloaded by screenModel.updatesPreferences.filterDownloaded.collectAsState()
TriStateItem( TriStateItem(
label = stringResource(MR.strings.label_downloaded), label = stringResource(MR.strings.label_downloaded),
state = filterDownloaded, state = filterDownloaded,
onClick = { screenModel.toggleFilter(UpdatesPreferences::filterDownloaded) }, onClick = { screenModel.toggleFilter(UpdatesPreferences::filterDownloaded) },
) )
val filterUnread by screenModel.updatesPreferences.filterUnread().collectAsState() val filterUnread by screenModel.updatesPreferences.filterUnread.collectAsState()
TriStateItem( TriStateItem(
label = stringResource(MR.strings.action_filter_unread), label = stringResource(MR.strings.action_filter_unread),
state = filterUnread, state = filterUnread,
onClick = { screenModel.toggleFilter(UpdatesPreferences::filterUnread) }, onClick = { screenModel.toggleFilter(UpdatesPreferences::filterUnread) },
) )
val filterStarted by screenModel.updatesPreferences.filterStarted().collectAsState() val filterStarted by screenModel.updatesPreferences.filterStarted.collectAsState()
TriStateItem( TriStateItem(
label = stringResource(MR.strings.label_started), label = stringResource(MR.strings.label_started),
state = filterStarted, state = filterStarted,
onClick = { screenModel.toggleFilter(UpdatesPreferences::filterStarted) }, onClick = { screenModel.toggleFilter(UpdatesPreferences::filterStarted) },
) )
val filterBookmarked by screenModel.updatesPreferences.filterBookmarked().collectAsState() val filterBookmarked by screenModel.updatesPreferences.filterBookmarked.collectAsState()
TriStateItem( TriStateItem(
label = stringResource(MR.strings.action_filter_bookmarked), label = stringResource(MR.strings.action_filter_bookmarked),
state = filterBookmarked, state = filterBookmarked,
@@ -85,9 +85,9 @@ private fun ColumnScope.FilterSheet(
HorizontalDivider(modifier = Modifier.padding(MaterialTheme.padding.small)) HorizontalDivider(modifier = Modifier.padding(MaterialTheme.padding.small))
val filterExcludedScanlators by screenModel.updatesPreferences.filterExcludedScanlators().collectAsState() val filterExcludedScanlators by screenModel.updatesPreferences.filterExcludedScanlators.collectAsState()
fun toggleScanlatorFilter() = screenModel.updatesPreferences.filterExcludedScanlators().getAndSet { !it } fun toggleScanlatorFilter() = screenModel.updatesPreferences.filterExcludedScanlators.getAndSet { !it }
Row( Row(
modifier = Modifier modifier = Modifier
+9 -9
View File
@@ -107,7 +107,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
val scope = ProcessLifecycleOwner.get().lifecycleScope val scope = ProcessLifecycleOwner.get().lifecycleScope
// Show notification to disable Incognito Mode when it's enabled // Show notification to disable Incognito Mode when it's enabled
basePreferences.incognitoMode().changes() basePreferences.incognitoMode.changes()
.onEach { enabled -> .onEach { enabled ->
if (enabled) { if (enabled) {
disableIncognitoReceiver.register() disableIncognitoReceiver.register()
@@ -135,32 +135,32 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
} }
.launchIn(scope) .launchIn(scope)
privacyPreferences.analytics() privacyPreferences.analytics
.changes() .changes()
.onEach(TelemetryConfig::setAnalyticsEnabled) .onEach(TelemetryConfig::setAnalyticsEnabled)
.launchIn(scope) .launchIn(scope)
privacyPreferences.crashlytics() privacyPreferences.crashlytics
.changes() .changes()
.onEach(TelemetryConfig::setCrashlyticsEnabled) .onEach(TelemetryConfig::setCrashlyticsEnabled)
.launchIn(scope) .launchIn(scope)
basePreferences.hardwareBitmapThreshold().let { preference -> basePreferences.hardwareBitmapThreshold.let { preference ->
if (!preference.isSet()) preference.set(GLUtil.DEVICE_TEXTURE_LIMIT) if (!preference.isSet()) preference.set(GLUtil.DEVICE_TEXTURE_LIMIT)
} }
basePreferences.hardwareBitmapThreshold().changes() basePreferences.hardwareBitmapThreshold.changes()
.onEach { ImageUtil.hardwareBitmapThreshold = it } .onEach { ImageUtil.hardwareBitmapThreshold = it }
.launchIn(scope) .launchIn(scope)
setAppCompatDelegateThemeMode(Injekt.get<UiPreferences>().themeMode().get()) setAppCompatDelegateThemeMode(Injekt.get<UiPreferences>().themeMode.get())
// Updates widget update // Updates widget update
WidgetManager(Injekt.get(), Injekt.get()).apply { init(scope) } WidgetManager(Injekt.get(), Injekt.get()).apply { init(scope) }
if (!LogcatLogger.isInstalled) { if (!LogcatLogger.isInstalled) {
val minLogPriority = when { val minLogPriority = when {
networkPreferences.verboseLogging().get() -> LogPriority.VERBOSE networkPreferences.verboseLogging.get() -> LogPriority.VERBOSE
BuildConfig.DEBUG -> LogPriority.DEBUG BuildConfig.DEBUG -> LogPriority.DEBUG
else -> LogPriority.INFO else -> LogPriority.INFO
} }
@@ -211,7 +211,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
crossfade((300 * this@App.animatorDurationScale).toInt()) crossfade((300 * this@App.animatorDurationScale).toInt())
allowRgb565(DeviceUtil.isLowRamDevice(this@App)) allowRgb565(DeviceUtil.isLowRamDevice(this@App))
if (networkPreferences.verboseLogging().get()) logger(DebugLogger()) if (networkPreferences.verboseLogging.get()) logger(DebugLogger())
// Coil spawns a new thread for every image load by default // Coil spawns a new thread for every image load by default
fetcherCoroutineContext(Dispatchers.IO.limitedParallelism(8)) fetcherCoroutineContext(Dispatchers.IO.limitedParallelism(8))
@@ -256,7 +256,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
private var registered = false private var registered = false
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
basePreferences.incognitoMode().set(false) basePreferences.incognitoMode.set(false)
} }
fun register() { fun register() {
@@ -101,7 +101,7 @@ class BackupNotifier(private val context: Context) {
} }
setContentTitle(contentTitle) setContentTitle(contentTitle)
if (!preferences.hideNotificationContent().get()) { if (!preferences.hideNotificationContent.get()) {
setContentText(content) setContentText(content)
} }
@@ -89,7 +89,7 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete
fun setupTask(context: Context, prefInterval: Int? = null) { fun setupTask(context: Context, prefInterval: Int? = null) {
val backupPreferences = Injekt.get<BackupPreferences>() val backupPreferences = Injekt.get<BackupPreferences>()
val interval = prefInterval ?: backupPreferences.backupInterval().get() val interval = prefInterval ?: backupPreferences.backupInterval.get()
if (interval > 0) { if (interval > 0) {
val constraints = Constraints( val constraints = Constraints(
requiresBatteryNotLow = true, requiresBatteryNotLow = true,
@@ -108,7 +108,7 @@ class BackupCreator(
BackupFileValidator(context).validate(fileUri) BackupFileValidator(context).validate(fileUri)
if (isAutoBackup) { if (isAutoBackup) {
backupPreferences.lastAutoBackupTimestamp().set(Instant.now().toEpochMilli()) backupPreferences.lastAutoBackupTimestamp.set(Instant.now().toEpochMilli())
} }
return fileUri.toString() return fileUri.toString()
@@ -32,7 +32,7 @@ class CategoriesRestorer(
.let { id -> it.toCategory(id).copy(order = order) } .let { id -> it.toCategory(id).copy(order = order) }
} }
libraryPreferences.categorizedDisplaySettings().set( libraryPreferences.categorizedDisplaySettings.set(
(dbCategories + categories) (dbCategories + categories)
.distinctBy { it.flags } .distinctBy { it.flags }
.size > 1, .size > 1,
@@ -56,7 +56,7 @@ class DownloadJob(context: Context, workerParams: WorkerParameters) : CoroutineW
override suspend fun doWork(): Result { override suspend fun doWork(): Result {
var networkCheck = checkNetworkState( var networkCheck = checkNetworkState(
applicationContext.activeNetworkState(), applicationContext.activeNetworkState(),
downloadPreferences.downloadOnlyOverWifi().get(), downloadPreferences.downloadOnlyOverWifi.get(),
) )
var active = networkCheck && downloadManager.downloaderStart() var active = networkCheck && downloadManager.downloaderStart()
@@ -69,7 +69,7 @@ class DownloadJob(context: Context, workerParams: WorkerParameters) : CoroutineW
coroutineScope { coroutineScope {
combineTransform( combineTransform(
applicationContext.networkStateFlow(), applicationContext.networkStateFlow(),
downloadPreferences.downloadOnlyOverWifi().changes(), downloadPreferences.downloadOnlyOverWifi.changes(),
transform = { a, b -> emit(checkNetworkState(a, b)) }, transform = { a, b -> emit(checkNetworkState(a, b)) },
) )
.onEach { networkCheck = it } .onEach { networkCheck = it }
@@ -397,7 +397,7 @@ class DownloadManager(
private suspend fun getChaptersToDelete(chapters: List<Chapter>, manga: Manga): List<Chapter> { private suspend fun getChaptersToDelete(chapters: List<Chapter>, manga: Manga): List<Chapter> {
// Retrieve the categories that are set to exclude from being deleted on read // Retrieve the categories that are set to exclude from being deleted on read
val categoriesToExclude = downloadPreferences.removeExcludeCategories().get().map(String::toLong) val categoriesToExclude = downloadPreferences.removeExcludeCategories.get().map(String::toLong)
val categoriesForManga = getCategories.await(manga.id) val categoriesForManga = getCategories.await(manga.id)
.map { it.id } .map { it.id }
@@ -408,7 +408,7 @@ class DownloadManager(
chapters chapters
} }
return if (!downloadPreferences.removeBookmarkedChapters().get()) { return if (!downloadPreferences.removeBookmarkedChapters.get()) {
filteredCategoryManga.filterNot { it.bookmark } filteredCategoryManga.filterNot { it.bookmark }
} else { } else {
filteredCategoryManga filteredCategoryManga
@@ -96,7 +96,7 @@ internal class DownloadNotifier(private val context: Context) {
download.pages!!.size, download.pages!!.size,
) )
if (preferences.hideNotificationContent().get()) { if (preferences.hideNotificationContent.get()) {
setContentTitle(downloadingProgressText) setContentTitle(downloadingProgressText)
setContentText(null) setContentText(null)
} else { } else {
@@ -136,7 +136,7 @@ class DownloadProvider(
fun getSourceDirName(source: Source): String { fun getSourceDirName(source: Source): String {
return DiskUtil.buildValidFilename( return DiskUtil.buildValidFilename(
source.toString(), source.toString(),
disallowNonAscii = libraryPreferences.disallowNonAsciiFilenames().get(), disallowNonAscii = libraryPreferences.disallowNonAsciiFilenames.get(),
) )
} }
@@ -148,7 +148,7 @@ class DownloadProvider(
fun getMangaDirName(mangaTitle: String): String { fun getMangaDirName(mangaTitle: String): String {
return DiskUtil.buildValidFilename( return DiskUtil.buildValidFilename(
mangaTitle, mangaTitle,
disallowNonAscii = libraryPreferences.disallowNonAsciiFilenames().get(), disallowNonAscii = libraryPreferences.disallowNonAsciiFilenames.get(),
) )
} }
@@ -163,7 +163,7 @@ class DownloadProvider(
chapterName: String, chapterName: String,
chapterScanlator: String?, chapterScanlator: String?,
chapterUrl: String, chapterUrl: String,
disallowNonAsciiFilenames: Boolean = libraryPreferences.disallowNonAsciiFilenames().get(), disallowNonAsciiFilenames: Boolean = libraryPreferences.disallowNonAsciiFilenames.get(),
): String { ): String {
var dirName = sanitizeChapterName(chapterName) var dirName = sanitizeChapterName(chapterName)
if (!chapterScanlator.isNullOrBlank()) { if (!chapterScanlator.isNullOrBlank()) {
@@ -206,7 +206,7 @@ class DownloadProvider(
chapterName, chapterName,
chapterScanlator, chapterScanlator,
chapterUrl, chapterUrl,
!libraryPreferences.disallowNonAsciiFilenames().get(), !libraryPreferences.disallowNonAsciiFilenames.get(),
) )
return buildList(2) { return buildList(2) {
@@ -193,7 +193,7 @@ class Downloader(
downloaderJob = scope.launch { downloaderJob = scope.launch {
val activeDownloadsFlow = combine( val activeDownloadsFlow = combine(
queueState, queueState,
downloadPreferences.parallelSourceLimit().changes(), downloadPreferences.parallelSourceLimit.changes(),
) { a, b -> a to b }.transformLatest { (queue, parallelCount) -> ) { a, b -> a to b }.transformLatest { (queue, parallelCount) ->
while (true) { while (true) {
val activeDownloads = queue.asSequence() val activeDownloads = queue.asSequence()
@@ -369,7 +369,7 @@ class Downloader(
download.status = Download.State.DOWNLOADING download.status = Download.State.DOWNLOADING
// Start downloading images, consider we can have downloaded images already // Start downloading images, consider we can have downloaded images already
pageList.asFlow().flatMapMerge(concurrency = downloadPreferences.parallelPageLimit().get()) { page -> pageList.asFlow().flatMapMerge(concurrency = downloadPreferences.parallelPageLimit.get()) { page ->
flow { flow {
// Fetch image URL if necessary // Fetch image URL if necessary
if (page.imageUrl.isNullOrEmpty()) { if (page.imageUrl.isNullOrEmpty()) {
@@ -406,7 +406,7 @@ class Downloader(
) )
// Only rename the directory if it's downloaded // Only rename the directory if it's downloaded
if (downloadPreferences.saveChaptersAsCBZ().get()) { if (downloadPreferences.saveChaptersAsCBZ.get()) {
archiveChapter(mangaDir, chapterDirname, tmpDir) archiveChapter(mangaDir, chapterDirname, tmpDir)
} else { } else {
tmpDir.renameTo(chapterDirname) tmpDir.renameTo(chapterDirname)
@@ -545,7 +545,7 @@ class Downloader(
} }
private fun splitTallImageIfNeeded(page: Page, tmpDir: UniFile) { private fun splitTallImageIfNeeded(page: Page, tmpDir: UniFile) {
if (!downloadPreferences.splitTallImages().get()) return if (!downloadPreferences.splitTallImages.get()) return
try { try {
val filenamePrefix = "%03d".format(Locale.ENGLISH, page.number) val filenamePrefix = "%03d".format(Locale.ENGLISH, page.number)
@@ -99,7 +99,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
if (tags.contains(WORK_NAME_AUTO)) { if (tags.contains(WORK_NAME_AUTO)) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
val preferences = Injekt.get<LibraryPreferences>() val preferences = Injekt.get<LibraryPreferences>()
val restrictions = preferences.autoUpdateDeviceRestrictions().get() val restrictions = preferences.autoUpdateDeviceRestrictions.get()
if ((DEVICE_ONLY_ON_WIFI in restrictions) && !context.isConnectedToWifi()) { if ((DEVICE_ONLY_ON_WIFI in restrictions) && !context.isConnectedToWifi()) {
return Result.retry() return Result.retry()
} }
@@ -113,7 +113,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
setForegroundSafely() setForegroundSafely()
libraryPreferences.lastUpdatedTimestamp().set(Instant.now().toEpochMilli()) libraryPreferences.lastUpdatedTimestamp.set(Instant.now().toEpochMilli())
val categoryId = inputData.getLong(KEY_CATEGORY, -1L) val categoryId = inputData.getLong(KEY_CATEGORY, -1L)
addMangaToQueue(categoryId) addMangaToQueue(categoryId)
@@ -160,8 +160,8 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
val listToUpdate = if (categoryId != -1L) { val listToUpdate = if (categoryId != -1L) {
libraryManga.filter { categoryId in it.categories } libraryManga.filter { categoryId in it.categories }
} else { } else {
val includedCategories = libraryPreferences.updateCategories().get().map { it.toLong() } val includedCategories = libraryPreferences.updateCategories.get().map { it.toLong() }
val excludedCategories = libraryPreferences.updateCategoriesExclude().get().map { it.toLong() } val excludedCategories = libraryPreferences.updateCategoriesExclude.get().map { it.toLong() }
libraryManga.filter { libraryManga.filter {
val included = includedCategories.isEmpty() || it.categories.intersect(includedCategories).isNotEmpty() val included = includedCategories.isEmpty() || it.categories.intersect(includedCategories).isNotEmpty()
@@ -170,7 +170,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
} }
} }
val restrictions = libraryPreferences.autoUpdateMangaRestrictions().get() val restrictions = libraryPreferences.autoUpdateMangaRestrictions.get()
val skippedUpdates = mutableListOf<Pair<Manga, String?>>() val skippedUpdates = mutableListOf<Pair<Manga, String?>>()
val (_, fetchWindowUpperBound) = fetchInterval.getWindow(ZonedDateTime.now()) val (_, fetchWindowUpperBound) = fetchInterval.getWindow(ZonedDateTime.now())
@@ -272,7 +272,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
hasDownloads.store(true) hasDownloads.store(true)
} }
libraryPreferences.newUpdatesCount().getAndSet { it + newChapters.size } libraryPreferences.newUpdatesCount.getAndSet { it + newChapters.size }
// Convert to the manga that contains new chapters // Convert to the manga that contains new chapters
newUpdates.add(manga to newChapters.toTypedArray()) newUpdates.add(manga to newChapters.toTypedArray())
@@ -332,7 +332,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
val source = sourceManager.getOrStub(manga.source) val source = sourceManager.getOrStub(manga.source)
// Update manga metadata if needed // Update manga metadata if needed
if (libraryPreferences.autoUpdateMetadata().get()) { if (libraryPreferences.autoUpdateMetadata.get()) {
val networkManga = source.getMangaDetails(manga.toSManga()) val networkManga = source.getMangaDetails(manga.toSManga())
updateManga.awaitUpdateFromSource(manga, networkManga, manualFetch = false, coverCache) updateManga.awaitUpdateFromSource(manga, networkManga, manualFetch = false, coverCache)
} }
@@ -423,9 +423,9 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
prefInterval: Int? = null, prefInterval: Int? = null,
) { ) {
val preferences = Injekt.get<LibraryPreferences>() val preferences = Injekt.get<LibraryPreferences>()
val interval = prefInterval ?: preferences.autoUpdateInterval().get() val interval = prefInterval ?: preferences.autoUpdateInterval.get()
if (interval > 0) { if (interval > 0) {
val restrictions = preferences.autoUpdateDeviceRestrictions().get() val restrictions = preferences.autoUpdateDeviceRestrictions.get()
val networkType = if (DEVICE_NETWORK_NOT_METERED in restrictions) { val networkType = if (DEVICE_NETWORK_NOT_METERED in restrictions) {
NetworkType.UNMETERED NetworkType.UNMETERED
} else { } else {
@@ -98,7 +98,7 @@ class LibraryUpdateNotifier(
), ),
) )
if (!securityPreferences.hideNotificationContent().get()) { if (!securityPreferences.hideNotificationContent.get()) {
val updatingText = manga.joinToString("\n") { it.title.chop(40) } val updatingText = manga.joinToString("\n") { it.title.chop(40) }
progressNotificationBuilder.setStyle(NotificationCompat.BigTextStyle().bigText(updatingText)) progressNotificationBuilder.setStyle(NotificationCompat.BigTextStyle().bigText(updatingText))
} }
@@ -173,7 +173,7 @@ class LibraryUpdateNotifier(
Notifications.CHANNEL_NEW_CHAPTERS, Notifications.CHANNEL_NEW_CHAPTERS,
) { ) {
setContentTitle(context.stringResource(MR.strings.notification_new_chapters)) setContentTitle(context.stringResource(MR.strings.notification_new_chapters))
if (updates.size == 1 && !securityPreferences.hideNotificationContent().get()) { if (updates.size == 1 && !securityPreferences.hideNotificationContent.get()) {
setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN)) setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN))
} else { } else {
setContentText( setContentText(
@@ -184,7 +184,7 @@ class LibraryUpdateNotifier(
), ),
) )
if (!securityPreferences.hideNotificationContent().get()) { if (!securityPreferences.hideNotificationContent.get()) {
setStyle( setStyle(
NotificationCompat.BigTextStyle().bigText( NotificationCompat.BigTextStyle().bigText(
updates.joinToString("\n") { updates.joinToString("\n") {
@@ -208,7 +208,7 @@ class LibraryUpdateNotifier(
} }
// Per-manga notification // Per-manga notification
if (!securityPreferences.hideNotificationContent().get()) { if (!securityPreferences.hideNotificationContent.get()) {
launchUI { launchUI {
context.notify( context.notify(
updates.map { (manga, chapters) -> updates.map { (manga, chapters) ->
@@ -211,7 +211,7 @@ class NotificationReceiver : BroadcastReceiver() {
val toUpdate = chapterUrls.mapNotNull { getChapter.await(it, mangaId) } val toUpdate = chapterUrls.mapNotNull { getChapter.await(it, mangaId) }
.map { .map {
val chapter = it.copy(read = true) val chapter = it.copy(read = true)
if (downloadPreferences.removeAfterMarkedAsRead().get()) { if (downloadPreferences.removeAfterMarkedAsRead.get()) {
val manga = getManga.await(mangaId) val manga = getManga.await(mangaId)
if (manga != null) { if (manga != null) {
val source = sourceManager.get(manga.source) val source = sourceManager.get(manga.source)
@@ -43,7 +43,7 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
override val supportsPrivateTracking: Boolean = true override val supportsPrivateTracking: Boolean = true
private val scorePreference = trackPreferences.anilistScoreType() private val scorePreference = trackPreferences.anilistScoreType
init { init {
// If the preference is an int from APIv1, logout user to force using APIv2 // If the preference is an int from APIv1, logout user to force using APIv2
@@ -17,7 +17,7 @@ fun Track.toApiStatus() = when (status) {
private val preferences: TrackPreferences by injectLazy() private val preferences: TrackPreferences by injectLazy()
fun DomainTrack.toApiScore(): String = when (preferences.anilistScoreType().get()) { fun DomainTrack.toApiScore(): String = when (preferences.anilistScoreType.get()) {
// 10 point // 10 point
"POINT_10" -> (score.toInt() / 10).toString() "POINT_10" -> (score.toInt() / 10).toString()
// 100 point // 100 point
@@ -32,7 +32,7 @@ class PreferenceModule(val app: Application) : InjektModule {
addSingletonFactory { addSingletonFactory {
NetworkPreferences( NetworkPreferences(
preferenceStore = get(), preferenceStore = get(),
verboseLogging = isDebugBuildType, verboseLoggingDefault = isDebugBuildType,
) )
} }
addSingletonFactory { addSingletonFactory {
@@ -77,7 +77,7 @@ class ExtensionManager(
ExtensionInstallReceiver(InstallationListener()).register(context) ExtensionInstallReceiver(InstallationListener()).register(context)
} }
private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages().isSet() private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages.isSet()
fun getExtensionPackage(sourceId: Long): String? { fun getExtensionPackage(sourceId: Long): String? {
return installedExtensionsFlow.value.find { extension -> return installedExtensionsFlow.value.find { extension ->
@@ -174,12 +174,12 @@ class ExtensionManager(
.map(Extension.Available.Source::lang) .map(Extension.Available.Source::lang)
val deviceLanguage = Locale.getDefault().language val deviceLanguage = Locale.getDefault().language
val defaultLanguages = preferences.enabledLanguages().defaultValue() val defaultLanguages = preferences.enabledLanguages.defaultValue()
val languagesToEnable = availableLanguages.filter { val languagesToEnable = availableLanguages.filter {
it != deviceLanguage && it.startsWith(deviceLanguage) it != deviceLanguage && it.startsWith(deviceLanguage)
} }
preferences.enabledLanguages().set(defaultLanguages + languagesToEnable) preferences.enabledLanguages.set(defaultLanguages + languagesToEnable)
subLanguagesEnabledOnFirstRun = true subLanguagesEnabledOnFirstRun = true
} }
@@ -190,7 +190,7 @@ class ExtensionManager(
*/ */
private fun updatedInstalledExtensionsStatuses(availableExtensions: List<Extension.Available>) { private fun updatedInstalledExtensionsStatuses(availableExtensions: List<Extension.Available>) {
if (availableExtensions.isEmpty()) { if (availableExtensions.isEmpty()) {
preferences.extensionUpdatesCount().set(0) preferences.extensionUpdatesCount.set(0)
return return
} }
@@ -369,7 +369,7 @@ class ExtensionManager(
private fun updatePendingUpdatesCount() { private fun updatePendingUpdatesCount() {
val pendingUpdateCount = installedExtensionMapFlow.value.values.count { it.hasUpdate } val pendingUpdateCount = installedExtensionMapFlow.value.values.count { it.hasUpdate }
preferences.extensionUpdatesCount().set(pendingUpdateCount) preferences.extensionUpdatesCount.set(pendingUpdateCount)
if (pendingUpdateCount == 0) { if (pendingUpdateCount == 0) {
ExtensionUpdateNotifier(context).dismiss() ExtensionUpdateNotifier(context).dismiss()
} }
@@ -29,7 +29,7 @@ class ExtensionUpdateNotifier(
names.size, names.size,
), ),
) )
if (!securityPreferences.hideNotificationContent().get()) { if (!securityPreferences.hideNotificationContent.get()) {
val extNames = names.joinToString(", ") val extNames = names.joinToString(", ")
setContentText(extNames) setContentText(extNames)
setStyle(NotificationCompat.BigTextStyle().bigText(extNames)) setStyle(NotificationCompat.BigTextStyle().bigText(extNames))
@@ -39,7 +39,7 @@ internal class ExtensionInstaller(
private val scope = CoroutineScope(Dispatchers.IO) private val scope = CoroutineScope(Dispatchers.IO)
private val activeJobs = mutableMapOf<String, Job>() private val activeJobs = mutableMapOf<String, Job>()
private val activeSteps = mutableMapOf<Long, MutableStateFlow<InstallStep>>() private val activeSteps = mutableMapOf<Long, MutableStateFlow<InstallStep>>()
private val extensionInstaller = Injekt.get<BasePreferences>().extensionInstaller() private val extensionInstaller = Injekt.get<BasePreferences>().extensionInstaller
private val httpClient: OkHttpClient = Injekt.get<NetworkHelper>().client private val httpClient: OkHttpClient = Injekt.get<NetworkHelper>().client
@@ -44,7 +44,7 @@ internal object ExtensionLoader {
private val preferences: SourcePreferences by injectLazy() private val preferences: SourcePreferences by injectLazy()
private val trustExtension: TrustExtension by injectLazy() private val trustExtension: TrustExtension by injectLazy()
private val loadNsfwSource by lazy { private val loadNsfwSource by lazy {
preferences.showNsfwSource().get() preferences.showNsfwSource.get()
} }
private const val EXTENSION_FEATURE = "tachiyomi.extension" private const val EXTENSION_FEATURE = "tachiyomi.extension"
@@ -8,7 +8,7 @@ import uy.kohesive.injekt.api.get
fun Source.getNameForMangaInfo(): String { fun Source.getNameForMangaInfo(): String {
val preferences = Injekt.get<SourcePreferences>() val preferences = Injekt.get<SourcePreferences>()
val enabledLanguages = preferences.enabledLanguages().get() val enabledLanguages = preferences.enabledLanguages.get()
.filterNot { it in listOf("all", "other") } .filterNot { it in listOf("all", "other") }
val hasOneActiveLanguages = enabledLanguages.size == 1 val hasOneActiveLanguages = enabledLanguages.size == 1
val isInEnabledLanguages = lang in enabledLanguages val isInEnabledLanguages = lang in enabledLanguages
@@ -33,14 +33,14 @@ interface SecureActivityDelegate {
fun onApplicationStopped() { fun onApplicationStopped() {
val preferences = Injekt.get<SecurityPreferences>() val preferences = Injekt.get<SecurityPreferences>()
if (!preferences.useAuthenticator().get()) return if (!preferences.useAuthenticator.get()) return
if (!AuthenticatorUtil.isAuthenticating) { if (!AuthenticatorUtil.isAuthenticating) {
// Return if app is closed in locked state // Return if app is closed in locked state
if (requireUnlock) return if (requireUnlock) return
// Save app close time if lock is delayed // Save app close time if lock is delayed
if (preferences.lockAppAfter().get() > 0) { if (preferences.lockAppAfter.get() > 0) {
preferences.lastAppClosed().set(System.currentTimeMillis()) preferences.lastAppClosed.set(System.currentTimeMillis())
} }
} }
} }
@@ -50,13 +50,13 @@ interface SecureActivityDelegate {
*/ */
fun onApplicationStart() { fun onApplicationStart() {
val preferences = Injekt.get<SecurityPreferences>() val preferences = Injekt.get<SecurityPreferences>()
if (!preferences.useAuthenticator().get()) return if (!preferences.useAuthenticator.get()) return
val lastClosedPref = preferences.lastAppClosed() val lastClosedPref = preferences.lastAppClosed
// `requireUnlock` can be true on process start or if app was closed in locked state // `requireUnlock` can be true on process start or if app was closed in locked state
if (!AuthenticatorUtil.isAuthenticating && !requireUnlock) { if (!AuthenticatorUtil.isAuthenticating && !requireUnlock) {
requireUnlock = when (val lockDelay = preferences.lockAppAfter().get()) { requireUnlock = when (val lockDelay = preferences.lockAppAfter.get()) {
-1 -> false // Never -1 -> false // Never
0 -> true // Always 0 -> true // Always
else -> lastClosedPref.get() + lockDelay * 60_000 <= System.currentTimeMillis() else -> lastClosedPref.get() + lockDelay * 60_000 <= System.currentTimeMillis()
@@ -93,8 +93,8 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
} }
private fun setSecureScreen() { private fun setSecureScreen() {
val secureScreenFlow = securityPreferences.secureScreen().changes() val secureScreenFlow = securityPreferences.secureScreen.changes()
val incognitoModeFlow = preferences.incognitoMode().changes() val incognitoModeFlow = preferences.incognitoMode.changes()
combine(secureScreenFlow, incognitoModeFlow) { secureScreen, incognitoMode -> combine(secureScreenFlow, incognitoModeFlow) { secureScreen, incognitoMode ->
secureScreen == SecurityPreferences.SecureScreenMode.ALWAYS || secureScreen == SecurityPreferences.SecureScreenMode.ALWAYS ||
(secureScreen == SecurityPreferences.SecureScreenMode.INCOGNITO && incognitoMode) (secureScreen == SecurityPreferences.SecureScreenMode.INCOGNITO && incognitoMode)
@@ -104,7 +104,7 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
} }
private fun setAppLock() { private fun setAppLock() {
if (!securityPreferences.useAuthenticator().get()) return if (!securityPreferences.useAuthenticator.get()) return
if (activity.isAuthenticationSupported()) { if (activity.isAuthenticationSupported()) {
if (!SecureActivityDelegate.requireUnlock) return if (!SecureActivityDelegate.requireUnlock) return
activity.startActivity(Intent(activity, UnlockActivity::class.java)) activity.startActivity(Intent(activity, UnlockActivity::class.java))
@@ -115,7 +115,7 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
activity.overridePendingTransition(0, 0) activity.overridePendingTransition(0, 0)
} }
} else { } else {
securityPreferences.useAuthenticator().set(false) securityPreferences.useAuthenticator.set(false)
} }
} }
} }
@@ -23,7 +23,7 @@ interface ThemingDelegate {
class ThemingDelegateImpl : ThemingDelegate { class ThemingDelegateImpl : ThemingDelegate {
override fun applyAppTheme(activity: Activity) { override fun applyAppTheme(activity: Activity) {
val uiPreferences = Injekt.get<UiPreferences>() val uiPreferences = Injekt.get<UiPreferences>()
ThemingDelegate.getThemeResIds(uiPreferences.appTheme().get(), uiPreferences.themeDarkAmoled().get()) ThemingDelegate.getThemeResIds(uiPreferences.appTheme.get(), uiPreferences.themeDarkAmoled.get())
.forEach(activity::setTheme) .forEach(activity::setTheme)
} }
} }
@@ -37,7 +37,7 @@ class ExtensionFilterScreenModel(
screenModelScope.launch { screenModelScope.launch {
combine( combine(
getExtensionLanguages.subscribe(), getExtensionLanguages.subscribe(),
preferences.enabledLanguages().changes(), preferences.enabledLanguages.changes(),
) { a, b -> a to b } ) { a, b -> a to b }
.catch { throwable -> .catch { throwable ->
logcat(LogPriority.ERROR, throwable) logcat(LogPriority.ERROR, throwable)
@@ -98,11 +98,11 @@ class ExtensionsScreenModel(
screenModelScope.launchIO { findAvailableExtensions() } screenModelScope.launchIO { findAvailableExtensions() }
preferences.extensionUpdatesCount().changes() preferences.extensionUpdatesCount.changes()
.onEach { mutableState.update { state -> state.copy(updates = it) } } .onEach { mutableState.update { state -> state.copy(updates = it) } }
.launchIn(screenModelScope) .launchIn(screenModelScope)
basePreferences.extensionInstaller().changes() basePreferences.extensionInstaller.changes()
.onEach { mutableState.update { state -> state.copy(installer = it) } } .onEach { mutableState.update { state -> state.copy(installer = it) } }
.launchIn(screenModelScope) .launchIn(screenModelScope)
} }
@@ -86,7 +86,7 @@ class ExtensionDetailsScreenModel(
} }
} }
launch { launch {
preferences.incognitoExtensions() preferences.incognitoExtensions
.changes() .changes()
.map { pkgName in it } .map { pkgName in it }
.distinctUntilChanged() .distinctUntilChanged()
@@ -19,7 +19,7 @@ class MigrateSearchScreenModel(
private val sourcePreferences: SourcePreferences = Injekt.get(), private val sourcePreferences: SourcePreferences = Injekt.get(),
) : SearchScreenModel() { ) : SearchScreenModel() {
private val migrationSources by lazy { sourcePreferences.migrationSources().get() } private val migrationSources by lazy { sourcePreferences.migrationSources.get() }
override val sortComparator = { map: Map<CatalogueSource, SearchItemResult> -> override val sortComparator = { map: Map<CatalogueSource, SearchItemResult> ->
compareBy<CatalogueSource>( compareBy<CatalogueSource>(
@@ -49,11 +49,11 @@ class MigrateSourceScreenModel(
} }
} }
preferences.migrationSortingDirection().changes() preferences.migrationSortingDirection.changes()
.onEach { mutableState.update { state -> state.copy(sortingDirection = it) } } .onEach { mutableState.update { state -> state.copy(sortingDirection = it) } }
.launchIn(screenModelScope) .launchIn(screenModelScope)
preferences.migrationSortingMode().changes() preferences.migrationSortingMode.changes()
.onEach { mutableState.update { state -> state.copy(sortingMode = it) } } .onEach { mutableState.update { state -> state.copy(sortingMode = it) } }
.launchIn(screenModelScope) .launchIn(screenModelScope)
} }
@@ -28,8 +28,8 @@ class SourcesFilterScreenModel(
screenModelScope.launch { screenModelScope.launch {
combine( combine(
getLanguagesWithSources.subscribe(), getLanguagesWithSources.subscribe(),
preferences.enabledLanguages().changes(), preferences.enabledLanguages.changes(),
preferences.disabledSources().changes(), preferences.disabledSources.changes(),
) { a, b, c -> Triple(a, b, c) } ) { a, b, c -> Triple(a, b, c) }
.catch { throwable -> .catch { throwable ->
mutableState.update { mutableState.update {
@@ -71,7 +71,7 @@ class BrowseSourceScreenModel(
private val getIncognitoState: GetIncognitoState = Injekt.get(), private val getIncognitoState: GetIncognitoState = Injekt.get(),
) : StateScreenModel<BrowseSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) { ) : StateScreenModel<BrowseSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) {
var displayMode by sourcePreferences.sourceDisplayMode().asState(screenModelScope) var displayMode by sourcePreferences.sourceDisplayMode.asState(screenModelScope)
val source = sourceManager.getOrStub(sourceId) val source = sourceManager.getOrStub(sourceId)
@@ -95,14 +95,14 @@ class BrowseSourceScreenModel(
} }
if (!getIncognitoState.await(source.id)) { if (!getIncognitoState.await(source.id)) {
sourcePreferences.lastUsedSource().set(source.id) sourcePreferences.lastUsedSource.set(source.id)
} }
} }
/** /**
* Flow of Pager flow tied to [State.listing] * Flow of Pager flow tied to [State.listing]
*/ */
private val hideInLibraryItems = sourcePreferences.hideInLibraryItems().get() private val hideInLibraryItems = sourcePreferences.hideInLibraryItems.get()
val mangaPagerFlowFlow = state.map { it.listing } val mangaPagerFlowFlow = state.map { it.listing }
.distinctUntilChanged() .distinctUntilChanged()
.map { listing -> .map { listing ->
@@ -123,9 +123,9 @@ class BrowseSourceScreenModel(
fun getColumnsPreference(orientation: Int): GridCells { fun getColumnsPreference(orientation: Int): GridCells {
val isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE val isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE
val columns = if (isLandscape) { val columns = if (isLandscape) {
libraryPreferences.landscapeColumns() libraryPreferences.landscapeColumns
} else { } else {
libraryPreferences.portraitColumns() libraryPreferences.portraitColumns
}.get() }.get()
return if (columns == 0) GridCells.Adaptive(128.dp) else GridCells.Fixed(columns) return if (columns == 0) GridCells.Adaptive(128.dp) else GridCells.Fixed(columns)
} }
@@ -241,7 +241,7 @@ class BrowseSourceScreenModel(
fun addFavorite(manga: Manga) { fun addFavorite(manga: Manga) {
screenModelScope.launch { screenModelScope.launch {
val categories = getCategories() val categories = getCategories()
val defaultCategoryId = libraryPreferences.defaultCategory().get() val defaultCategoryId = libraryPreferences.defaultCategory.get()
val defaultCategory = categories.find { it.id == defaultCategoryId.toLong() } val defaultCategory = categories.find { it.id == defaultCategoryId.toLong() }
when { when {
@@ -47,9 +47,9 @@ abstract class SearchScreenModel(
private val coroutineDispatcher = Executors.newFixedThreadPool(5).asCoroutineDispatcher() private val coroutineDispatcher = Executors.newFixedThreadPool(5).asCoroutineDispatcher()
private var searchJob: Job? = null private var searchJob: Job? = null
private val enabledLanguages = sourcePreferences.enabledLanguages().get() private val enabledLanguages = sourcePreferences.enabledLanguages.get()
private val disabledSources = sourcePreferences.disabledSources().get() private val disabledSources = sourcePreferences.disabledSources.get()
protected val pinnedSources = sourcePreferences.pinnedSources().get() protected val pinnedSources = sourcePreferences.pinnedSources.get()
private var lastQuery: String? = null private var lastQuery: String? = null
private var lastSourceFilter: SourceFilter? = null private var lastSourceFilter: SourceFilter? = null
@@ -66,7 +66,7 @@ abstract class SearchScreenModel(
init { init {
screenModelScope.launch { screenModelScope.launch {
preferences.globalSearchFilterState().changes().collectLatest { state -> preferences.globalSearchFilterState.changes().collectLatest { state ->
mutableState.update { it.copy(onlyShowHasResults = state) } mutableState.update { it.copy(onlyShowHasResults = state) }
} }
} }
@@ -119,7 +119,7 @@ abstract class SearchScreenModel(
} }
fun toggleFilterResults() { fun toggleFilterResults() {
preferences.globalSearchFilterState().toggle() preferences.globalSearchFilterState.toggle()
} }
fun search() { fun search() {
@@ -189,7 +189,7 @@ class HistoryScreenModel(
screenModelScope.launchIO { screenModelScope.launchIO {
// Move to default category if applicable // Move to default category if applicable
val categories = getCategories() val categories = getCategories()
val defaultCategoryId = libraryPreferences.defaultCategory().get().toLong() val defaultCategoryId = libraryPreferences.defaultCategory.get().toLong()
val defaultCategory = categories.find { it.id == defaultCategoryId } val defaultCategory = categories.find { it.id == defaultCategoryId }
when { when {
@@ -242,8 +242,8 @@ object HomeScreen : Screen() {
val count by produceState(initialValue = 0) { val count by produceState(initialValue = 0) {
val pref = Injekt.get<LibraryPreferences>() val pref = Injekt.get<LibraryPreferences>()
combine( combine(
pref.newShowUpdatesCount().changes(), pref.newShowUpdatesCount.changes(),
pref.newUpdatesCount().changes(), pref.newUpdatesCount.changes(),
) { show, count -> if (show) count else 0 } ) { show, count -> if (show) count else 0 }
.collectLatest { value = it } .collectLatest { value = it }
} }
@@ -263,7 +263,7 @@ object HomeScreen : Screen() {
} }
BrowseTab::class.isInstance(tab) -> { BrowseTab::class.isInstance(tab) -> {
val count by produceState(initialValue = 0) { val count by produceState(initialValue = 0) {
Injekt.get<SourcePreferences>().extensionUpdatesCount().changes() Injekt.get<SourcePreferences>().extensionUpdatesCount.changes()
.collectLatest { value = it } .collectLatest { value = it }
} }
if (count > 0) { if (count > 0) {
@@ -89,7 +89,7 @@ class LibraryScreenModel(
init { init {
mutableState.update { state -> mutableState.update { state ->
state.copy(activeCategoryIndex = libraryPreferences.lastUsedCategory().get()) state.copy(activeCategoryIndex = libraryPreferences.lastUsedCategory.get())
} }
screenModelScope.launchIO { screenModelScope.launchIO {
combine( combine(
@@ -142,9 +142,9 @@ class LibraryScreenModel(
} }
combine( combine(
libraryPreferences.categoryTabs().changes(), libraryPreferences.categoryTabs.changes(),
libraryPreferences.categoryNumberOfItems().changes(), libraryPreferences.categoryNumberOfItems.changes(),
libraryPreferences.showContinueReadingButton().changes(), libraryPreferences.showContinueReadingButton.changes(),
) { a, b, c -> arrayOf(a, b, c) } ) { a, b, c -> arrayOf(a, b, c) }
.onEach { (showCategoryTabs, showMangaCount, showMangaContinueButton) -> .onEach { (showCategoryTabs, showMangaCount, showMangaContinueButton) ->
mutableState.update { state -> mutableState.update { state ->
@@ -337,7 +337,7 @@ class LibraryScreenModel(
return mapValues { (key, value) -> return mapValues { (key, value) ->
if (key.sort.type == LibrarySort.Type.Random) { if (key.sort.type == LibrarySort.Type.Random) {
return@mapValues value.shuffled(Random(libraryPreferences.randomSortSeed().get())) return@mapValues value.shuffled(Random(libraryPreferences.randomSortSeed.get()))
} }
val manga = value.mapNotNull { favoritesById[it] } val manga = value.mapNotNull { favoritesById[it] }
@@ -352,19 +352,19 @@ class LibraryScreenModel(
private fun getLibraryItemPreferencesFlow(): Flow<ItemPreferences> { private fun getLibraryItemPreferencesFlow(): Flow<ItemPreferences> {
return combine( return combine(
libraryPreferences.downloadBadge().changes(), libraryPreferences.downloadBadge.changes(),
libraryPreferences.unreadBadge().changes(), libraryPreferences.unreadBadge.changes(),
libraryPreferences.localBadge().changes(), libraryPreferences.localBadge.changes(),
libraryPreferences.languageBadge().changes(), libraryPreferences.languageBadge.changes(),
libraryPreferences.autoUpdateMangaRestrictions().changes(), libraryPreferences.autoUpdateMangaRestrictions.changes(),
preferences.downloadedOnly().changes(), preferences.downloadedOnly.changes(),
libraryPreferences.filterDownloaded().changes(), libraryPreferences.filterDownloaded.changes(),
libraryPreferences.filterUnread().changes(), libraryPreferences.filterUnread.changes(),
libraryPreferences.filterStarted().changes(), libraryPreferences.filterStarted.changes(),
libraryPreferences.filterBookmarked().changes(), libraryPreferences.filterBookmarked.changes(),
libraryPreferences.filterCompleted().changes(), libraryPreferences.filterCompleted.changes(),
libraryPreferences.filterIntervalCustom().changes(), libraryPreferences.filterIntervalCustom.changes(),
) { ) {
ItemPreferences( ItemPreferences(
downloadBadge = it[0] as Boolean, downloadBadge = it[0] as Boolean,
@@ -589,11 +589,11 @@ class LibraryScreenModel(
} }
fun getDisplayMode(): PreferenceMutableState<LibraryDisplayMode> { fun getDisplayMode(): PreferenceMutableState<LibraryDisplayMode> {
return libraryPreferences.displayMode().asState(screenModelScope) return libraryPreferences.displayMode.asState(screenModelScope)
} }
fun getColumnsForOrientation(isLandscape: Boolean): PreferenceMutableState<Int> { fun getColumnsForOrientation(isLandscape: Boolean): PreferenceMutableState<Int> {
return (if (isLandscape) libraryPreferences.landscapeColumns() else libraryPreferences.portraitColumns()) return (if (isLandscape) libraryPreferences.landscapeColumns else libraryPreferences.portraitColumns)
.asState(screenModelScope) .asState(screenModelScope)
} }
@@ -686,7 +686,7 @@ class LibraryScreenModel(
} }
.coercedActiveCategoryIndex .coercedActiveCategoryIndex
libraryPreferences.lastUsedCategory().set(newIndex) libraryPreferences.lastUsedCategory.set(newIndex)
} }
fun openChangeCategoryDialog() { fun openChangeCategoryDialog() {
@@ -146,7 +146,7 @@ class MainActivity : BaseActivity() {
val context = LocalContext.current val context = LocalContext.current
var incognito by remember { mutableStateOf(getIncognitoState.await(null)) } var incognito by remember { mutableStateOf(getIncognitoState.await(null)) }
val downloadOnly by preferences.downloadedOnly().collectAsState() val downloadOnly by preferences.downloadedOnly.collectAsState()
val indexing by downloadCache.isInitializing.collectAsState() val indexing by downloadCache.isInitializing.collectAsState()
val isSystemInDarkTheme = isSystemInDarkTheme() val isSystemInDarkTheme = isSystemInDarkTheme()
@@ -178,7 +178,7 @@ class MainActivity : BaseActivity() {
handleIntentAction(intent, navigator) handleIntentAction(intent, navigator)
// Reset Incognito Mode on relaunch // Reset Incognito Mode on relaunch
preferences.incognitoMode().set(false) preferences.incognitoMode.set(false)
} }
} }
LaunchedEffect(navigator.lastItem) { LaunchedEffect(navigator.lastItem) {
@@ -225,7 +225,7 @@ class MainActivity : BaseActivity() {
// Pop source-related screens when incognito mode is turned off // Pop source-related screens when incognito mode is turned off
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
preferences.incognitoMode().changes() preferences.incognitoMode.changes()
.drop(1) .drop(1)
.filter { !it } .filter { !it }
.onEach { .onEach {
@@ -271,7 +271,7 @@ class MainActivity : BaseActivity() {
} }
setSplashScreenExitAnimation(splashScreen) setSplashScreenExitAnimation(splashScreen)
if (isLaunch && libraryPreferences.autoClearChapterCache().get()) { if (isLaunch && libraryPreferences.autoClearChapterCache.get()) {
lifecycleScope.launchIO { lifecycleScope.launchIO {
chapterCache.clear() chapterCache.clear()
} }
@@ -340,7 +340,7 @@ class MainActivity : BaseActivity() {
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
if (!preferences.shownOnboardingFlow().get() && navigator.lastItem !is OnboardingScreen) { if (!preferences.shownOnboardingFlow.get() && navigator.lastItem !is OnboardingScreen) {
navigator.push(OnboardingScreen()) navigator.push(OnboardingScreen())
} }
} }
@@ -141,14 +141,14 @@ class MangaScreenModel(
private val filteredChapters: List<ChapterList.Item>? private val filteredChapters: List<ChapterList.Item>?
get() = successState?.processedChapters get() = successState?.processedChapters
val chapterSwipeStartAction = libraryPreferences.swipeToEndAction().get() val chapterSwipeStartAction = libraryPreferences.swipeToEndAction.get()
val chapterSwipeEndAction = libraryPreferences.swipeToStartAction().get() val chapterSwipeEndAction = libraryPreferences.swipeToStartAction.get()
var autoTrackState = trackPreferences.autoUpdateTrackOnMarkRead().get() var autoTrackState = trackPreferences.autoUpdateTrackOnMarkRead.get()
private val skipFiltered by readerPreferences.skipFiltered().asState(screenModelScope) private val skipFiltered by readerPreferences.skipFiltered.asState(screenModelScope)
val isUpdateIntervalEnabled = val isUpdateIntervalEnabled =
LibraryPreferences.MANGA_OUTSIDE_RELEASE_PERIOD in libraryPreferences.autoUpdateMangaRestrictions().get() LibraryPreferences.MANGA_OUTSIDE_RELEASE_PERIOD in libraryPreferences.autoUpdateMangaRestrictions.get()
private val selectedPositions: Array<Int> = arrayOf(-1, -1) // first and last selected index in list private val selectedPositions: Array<Int> = arrayOf(-1, -1) // first and last selected index in list
private val selectedChapterIds: HashSet<Long> = HashSet() private val selectedChapterIds: HashSet<Long> = HashSet()
@@ -230,7 +230,7 @@ class MangaScreenModel(
excludedScanlators = getExcludedScanlators.await(mangaId), excludedScanlators = getExcludedScanlators.await(mangaId),
isRefreshingData = needRefreshInfo || needRefreshChapter, isRefreshingData = needRefreshInfo || needRefreshChapter,
dialog = null, dialog = null,
hideMissingChapters = libraryPreferences.hideMissingChapters().get(), hideMissingChapters = libraryPreferences.hideMissingChapters.get(),
) )
} }
@@ -338,7 +338,7 @@ class MangaScreenModel(
// Now check if user previously set categories, when available // Now check if user previously set categories, when available
val categories = getCategories() val categories = getCategories()
val defaultCategoryId = libraryPreferences.defaultCategory().get().toLong() val defaultCategoryId = libraryPreferences.defaultCategory.get().toLong()
val defaultCategory = categories.find { it.id == defaultCategoryId } val defaultCategory = categories.find { it.id == defaultCategoryId }
when { when {
// Default category set // Default category set
@@ -99,7 +99,7 @@ data class TrackInfoDialogHomeScreen(
val context = LocalContext.current val context = LocalContext.current
val screenModel = rememberScreenModel { Model(mangaId, sourceId) } val screenModel = rememberScreenModel { Model(mangaId, sourceId) }
val dateFormat = remember { UiPreferences.dateFormat(Injekt.get<UiPreferences>().dateFormat().get()) } val dateFormat = remember { UiPreferences.dateFormat(Injekt.get<UiPreferences>().dateFormat.get()) }
val state by screenModel.state.collectAsState() val state by screenModel.state.collectAsState()
TrackInfoDialogHome( TrackInfoDialogHome(
@@ -82,8 +82,8 @@ private class MoreScreenModel(
preferences: BasePreferences = Injekt.get(), preferences: BasePreferences = Injekt.get(),
) : ScreenModel { ) : ScreenModel {
var downloadedOnly by preferences.downloadedOnly().asState(screenModelScope) var downloadedOnly by preferences.downloadedOnly.asState(screenModelScope)
var incognitoMode by preferences.incognitoMode().asState(screenModelScope) var incognitoMode by preferences.incognitoMode.asState(screenModelScope)
private var _downloadQueueState: MutableStateFlow<DownloadQueueState> = MutableStateFlow(DownloadQueueState.Stopped) private var _downloadQueueState: MutableStateFlow<DownloadQueueState> = MutableStateFlow(DownloadQueueState.Stopped)
val downloadQueueState: StateFlow<DownloadQueueState> = _downloadQueueState.asStateFlow() val downloadQueueState: StateFlow<DownloadQueueState> = _downloadQueueState.asStateFlow()
@@ -24,10 +24,10 @@ class OnboardingScreen : Screen() {
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val basePreferences = remember { Injekt.get<BasePreferences>() } val basePreferences = remember { Injekt.get<BasePreferences>() }
val shownOnboardingFlow by basePreferences.shownOnboardingFlow().collectAsState() val shownOnboardingFlow by basePreferences.shownOnboardingFlow.collectAsState()
val finishOnboarding: () -> Unit = { val finishOnboarding: () -> Unit = {
basePreferences.shownOnboardingFlow().set(true) basePreferences.shownOnboardingFlow.set(true)
navigator.pop() navigator.pop()
} }
@@ -192,7 +192,7 @@ class ReaderActivity : BaseActivity() {
setMenuVisibility(viewModel.state.value.menuVisible) setMenuVisibility(viewModel.state.value.menuVisible)
// Finish when incognito mode is disabled // Finish when incognito mode is disabled
preferences.incognitoMode().changes() preferences.incognitoMode.changes()
.drop(1) .drop(1)
.onEach { if (!it) finish() } .onEach { if (!it) finish() }
.launchIn(lifecycleScope) .launchIn(lifecycleScope)
@@ -248,7 +248,7 @@ class ReaderActivity : BaseActivity() {
private fun ReaderActivityBinding.setComposeOverlay(): Unit = composeOverlay.setComposeContent { private fun ReaderActivityBinding.setComposeOverlay(): Unit = composeOverlay.setComposeContent {
val state by viewModel.state.collectAsState() val state by viewModel.state.collectAsState()
val showPageNumber by readerPreferences.showPageNumber().collectAsState() val showPageNumber by readerPreferences.showPageNumber.collectAsState()
val settingsScreenModel = remember { val settingsScreenModel = remember {
ReaderSettingsScreenModel( ReaderSettingsScreenModel(
readerState = viewModel.state, readerState = viewModel.state,
@@ -304,7 +304,7 @@ class ReaderActivity : BaseActivity() {
screenModel = settingsScreenModel, screenModel = settingsScreenModel,
onChange = { stringRes -> onChange = { stringRes ->
menuToggleToast?.cancel() menuToggleToast?.cancel()
if (!readerPreferences.showReadingMode().get()) { if (!readerPreferences.showReadingMode.get()) {
menuToggleToast = toast(stringRes) menuToggleToast = toast(stringRes)
} }
}, },
@@ -425,11 +425,11 @@ class ReaderActivity : BaseActivity() {
@Composable @Composable
private fun ContentOverlay(state: ReaderViewModel.State) { private fun ContentOverlay(state: ReaderViewModel.State) {
val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState() val flashOnPageChange by readerPreferences.flashOnPageChange.collectAsState()
val colorOverlayEnabled by readerPreferences.colorFilter().collectAsState() val colorOverlayEnabled by readerPreferences.colorFilter.collectAsState()
val colorOverlay by readerPreferences.colorFilterValue().collectAsState() val colorOverlay by readerPreferences.colorFilterValue.collectAsState()
val colorOverlayMode by readerPreferences.colorFilterMode().collectAsState() val colorOverlayMode by readerPreferences.colorFilterMode.collectAsState()
val colorOverlayBlendMode = remember(colorOverlayMode) { val colorOverlayBlendMode = remember(colorOverlayMode) {
ReaderPreferences.ColorFilterMode.getOrNull(colorOverlayMode)?.second ReaderPreferences.ColorFilterMode.getOrNull(colorOverlayMode)?.second
} }
@@ -453,8 +453,8 @@ class ReaderActivity : BaseActivity() {
val isHttpSource = viewModel.getSource() is HttpSource val isHttpSource = viewModel.getSource() is HttpSource
val cropBorderPaged by readerPreferences.cropBorders().collectAsState() val cropBorderPaged by readerPreferences.cropBorders.collectAsState()
val cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState() val cropBorderWebtoon by readerPreferences.cropBordersWebtoon.collectAsState()
val isPagerType = ReadingMode.isPagerType(viewModel.getMangaReadingMode()) val isPagerType = ReadingMode.isPagerType(viewModel.getMangaReadingMode())
val cropEnabled = if (isPagerType) cropBorderPaged else cropBorderWebtoon val cropEnabled = if (isPagerType) cropBorderPaged else cropBorderWebtoon
@@ -508,7 +508,7 @@ class ReaderActivity : BaseActivity() {
viewModel.showMenus(visible) viewModel.showMenus(visible)
if (visible) { if (visible) {
windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
} else if (readerPreferences.fullscreen().get()) { } else if (readerPreferences.fullscreen.get()) {
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
} }
} }
@@ -535,10 +535,10 @@ class ReaderActivity : BaseActivity() {
binding.viewerContainer.removeAllViews() binding.viewerContainer.removeAllViews()
} }
viewModel.onViewerLoaded(newViewer) viewModel.onViewerLoaded(newViewer)
updateViewerInset(readerPreferences.fullscreen().get(), readerPreferences.drawUnderCutout().get()) updateViewerInset(readerPreferences.fullscreen.get(), readerPreferences.drawUnderCutout.get())
binding.viewerContainer.addView(newViewer.getView()) binding.viewerContainer.addView(newViewer.getView())
if (readerPreferences.showReadingMode().get()) { if (readerPreferences.showReadingMode.get()) {
showReadingModeToast(viewModel.getMangaReadingMode()) showReadingModeToast(viewModel.getMangaReadingMode())
} }
@@ -839,7 +839,7 @@ class ReaderActivity : BaseActivity() {
* Initializes the reader subscriptions. * Initializes the reader subscriptions.
*/ */
init { init {
readerPreferences.readerTheme().changes() readerPreferences.readerTheme.changes()
.onEach { theme -> .onEach { theme ->
binding.readerContainer.setBackgroundColor( binding.readerContainer.setBackgroundColor(
when (theme) { when (theme) {
@@ -852,21 +852,21 @@ class ReaderActivity : BaseActivity() {
} }
.launchIn(lifecycleScope) .launchIn(lifecycleScope)
preferences.displayProfile().changes() preferences.displayProfile.changes()
.onEach { setDisplayProfile(it) } .onEach { setDisplayProfile(it) }
.launchIn(lifecycleScope) .launchIn(lifecycleScope)
readerPreferences.keepScreenOn().changes() readerPreferences.keepScreenOn.changes()
.onEach(::setKeepScreenOn) .onEach(::setKeepScreenOn)
.launchIn(lifecycleScope) .launchIn(lifecycleScope)
readerPreferences.customBrightness().changes() readerPreferences.customBrightness.changes()
.onEach(::setCustomBrightness) .onEach(::setCustomBrightness)
.launchIn(lifecycleScope) .launchIn(lifecycleScope)
combine( combine(
readerPreferences.grayscale().changes(), readerPreferences.grayscale.changes(),
readerPreferences.invertedColors().changes(), readerPreferences.invertedColors.changes(),
) { grayscale, invertedColors -> grayscale to invertedColors } ) { grayscale, invertedColors -> grayscale to invertedColors }
.onEach { (grayscale, invertedColors) -> .onEach { (grayscale, invertedColors) ->
setLayerPaint(grayscale, invertedColors) setLayerPaint(grayscale, invertedColors)
@@ -874,8 +874,8 @@ class ReaderActivity : BaseActivity() {
.launchIn(lifecycleScope) .launchIn(lifecycleScope)
combine( combine(
readerPreferences.fullscreen().changes(), readerPreferences.fullscreen.changes(),
readerPreferences.drawUnderCutout().changes(), readerPreferences.drawUnderCutout.changes(),
) { fullscreen, drawUnderCutout -> fullscreen to drawUnderCutout } ) { fullscreen, drawUnderCutout -> fullscreen to drawUnderCutout }
.onEach { (fullscreen, drawUnderCutout) -> .onEach { (fullscreen, drawUnderCutout) ->
updateViewerInset(fullscreen, drawUnderCutout) updateViewerInset(fullscreen, drawUnderCutout)
@@ -929,7 +929,7 @@ class ReaderActivity : BaseActivity() {
*/ */
private fun setCustomBrightness(enabled: Boolean) { private fun setCustomBrightness(enabled: Boolean) {
if (enabled) { if (enabled) {
readerPreferences.customBrightnessValue().changes() readerPreferences.customBrightnessValue.changes()
.sample(100) .sample(100)
.onEach(::setCustomBrightnessValue) .onEach(::setCustomBrightnessValue)
.launchIn(lifecycleScope) .launchIn(lifecycleScope)
@@ -169,11 +169,11 @@ class ReaderViewModel @JvmOverloads constructor(
?: error("Requested chapter of id $chapterId not found in chapter list") ?: error("Requested chapter of id $chapterId not found in chapter list")
val chaptersForReader = when { val chaptersForReader = when {
(readerPreferences.skipRead().get() || readerPreferences.skipFiltered().get()) -> { (readerPreferences.skipRead.get() || readerPreferences.skipFiltered.get()) -> {
val filteredChapters = chapters.filterNot { val filteredChapters = chapters.filterNot {
when { when {
readerPreferences.skipRead().get() && it.read -> true readerPreferences.skipRead.get() && it.read -> true
readerPreferences.skipFiltered().get() -> { readerPreferences.skipFiltered.get() -> {
(manga.unreadFilterRaw == Manga.CHAPTER_SHOW_READ && !it.read) || (manga.unreadFilterRaw == Manga.CHAPTER_SHOW_READ && !it.read) ||
(manga.unreadFilterRaw == Manga.CHAPTER_SHOW_UNREAD && it.read) || (manga.unreadFilterRaw == Manga.CHAPTER_SHOW_UNREAD && it.read) ||
( (
@@ -215,14 +215,14 @@ class ReaderViewModel @JvmOverloads constructor(
val result = chaptersForReader val result = chaptersForReader
.sortedWith(getChapterSort(manga, sortDescending = false)) .sortedWith(getChapterSort(manga, sortDescending = false))
.run { .run {
if (readerPreferences.skipDupe().get()) { if (readerPreferences.skipDupe.get()) {
removeDuplicates(selectedChapter) removeDuplicates(selectedChapter)
} else { } else {
this this
} }
} }
.run { .run {
if (basePreferences.downloadedOnly().get()) { if (basePreferences.downloadedOnly.get()) {
filterDownloaded(manga) filterDownloaded(manga)
} else { } else {
this this
@@ -235,7 +235,7 @@ class ReaderViewModel @JvmOverloads constructor(
} }
private val incognitoMode: Boolean by lazy { getIncognitoState.await(manga?.source) } private val incognitoMode: Boolean by lazy { getIncognitoState.await(manga?.source) }
private val downloadAheadAmount = downloadPreferences.autoDownloadWhileReading().get() private val downloadAheadAmount = downloadPreferences.autoDownloadWhileReading.get()
init { init {
// To save state // To save state
@@ -492,7 +492,7 @@ class ReaderViewModel @JvmOverloads constructor(
if (!isNextChapterDownloaded) return@launchIO if (!isNextChapterDownloaded) return@launchIO
val chaptersToDownload = getNextChapters.await(manga.id, nextChapter.id!!).run { val chaptersToDownload = getNextChapters.await(manga.id, nextChapter.id!!).run {
if (readerPreferences.skipDupe().get()) { if (readerPreferences.skipDupe.get()) {
removeDuplicates(nextChapter.toDomainChapter()!!) removeDuplicates(nextChapter.toDomainChapter()!!)
} else { } else {
this this
@@ -522,7 +522,7 @@ class ReaderViewModel @JvmOverloads constructor(
* @param currentChapter current chapter, which is going to be marked as read. * @param currentChapter current chapter, which is going to be marked as read.
*/ */
private suspend fun deleteChapterIfNeeded(currentChapter: ReaderChapter) { private suspend fun deleteChapterIfNeeded(currentChapter: ReaderChapter) {
val removeAfterReadSlots = downloadPreferences.removeAfterReadSlots().get() val removeAfterReadSlots = downloadPreferences.removeAfterReadSlots.get()
if (removeAfterReadSlots == -1) return if (removeAfterReadSlots == -1) return
// Determine which chapter should be deleted and enqueue // Determine which chapter should be deleted and enqueue
@@ -573,7 +573,7 @@ class ReaderViewModel @JvmOverloads constructor(
updateTrackChapterRead(readerChapter) updateTrackChapterRead(readerChapter)
deleteChapterIfNeeded(readerChapter) deleteChapterIfNeeded(readerChapter)
val markDuplicateAsRead = libraryPreferences.markDuplicateReadChapterAsRead().get() val markDuplicateAsRead = libraryPreferences.markDuplicateReadChapterAsRead.get()
.contains(LibraryPreferences.MARK_DUPLICATE_CHAPTER_READ_EXISTING) .contains(LibraryPreferences.MARK_DUPLICATE_CHAPTER_READ_EXISTING)
if (!markDuplicateAsRead) return if (!markDuplicateAsRead) return
@@ -677,7 +677,7 @@ class ReaderViewModel @JvmOverloads constructor(
* Returns the viewer position used by this manga or the default one. * Returns the viewer position used by this manga or the default one.
*/ */
fun getMangaReadingMode(resolveDefault: Boolean = true): Int { fun getMangaReadingMode(resolveDefault: Boolean = true): Int {
val default = readerPreferences.defaultReadingMode().get() val default = readerPreferences.defaultReadingMode.get()
val readingMode = ReadingMode.fromPreference(manga?.readingMode?.toInt()) val readingMode = ReadingMode.fromPreference(manga?.readingMode?.toInt())
return when { return when {
resolveDefault && readingMode == ReadingMode.DEFAULT -> default resolveDefault && readingMode == ReadingMode.DEFAULT -> default
@@ -713,7 +713,7 @@ class ReaderViewModel @JvmOverloads constructor(
* Returns the orientation type used by this manga or the default one. * Returns the orientation type used by this manga or the default one.
*/ */
fun getMangaOrientation(resolveDefault: Boolean = true): Int { fun getMangaOrientation(resolveDefault: Boolean = true): Int {
val default = readerPreferences.defaultOrientationType().get() val default = readerPreferences.defaultOrientationType.get()
val orientation = ReaderOrientation.fromPreference(manga?.readerOrientation?.toInt()) val orientation = ReaderOrientation.fromPreference(manga?.readerOrientation?.toInt())
return when { return when {
resolveDefault && orientation == ReaderOrientation.DEFAULT -> default resolveDefault && orientation == ReaderOrientation.DEFAULT -> default
@@ -749,9 +749,9 @@ class ReaderViewModel @JvmOverloads constructor(
fun toggleCropBorders(): Boolean { fun toggleCropBorders(): Boolean {
val isPagerType = ReadingMode.isPagerType(getMangaReadingMode()) val isPagerType = ReadingMode.isPagerType(getMangaReadingMode())
return if (isPagerType) { return if (isPagerType) {
readerPreferences.cropBorders().toggle() readerPreferences.cropBorders.toggle()
} else { } else {
readerPreferences.cropBordersWebtoon().toggle() readerPreferences.cropBordersWebtoon.toggle()
} }
} }
@@ -818,7 +818,7 @@ class ReaderViewModel @JvmOverloads constructor(
val filename = generateFilename(manga, page) val filename = generateFilename(manga, page)
// Pictures directory. // Pictures directory.
val relativePath = if (readerPreferences.folderPerManga().get()) { val relativePath = if (readerPreferences.folderPerManga.get()) {
DiskUtil.buildValidFilename( DiskUtil.buildValidFilename(
manga.title, manga.title,
) )
@@ -922,7 +922,7 @@ class ReaderViewModel @JvmOverloads constructor(
*/ */
private fun updateTrackChapterRead(readerChapter: ReaderChapter) { private fun updateTrackChapterRead(readerChapter: ReaderChapter) {
if (incognitoMode) return if (incognitoMode) return
if (!trackPreferences.autoUpdateTrack().get()) return if (!trackPreferences.autoUpdateTrack.get()) return
val manga = manga ?: return val manga = manga ?: return
val context = Injekt.get<Application>() val context = Injekt.get<Application>()
@@ -3,139 +3,173 @@ package eu.kanade.tachiyomi.ui.reader.setting
import android.os.Build import android.os.Build
import androidx.compose.ui.graphics.BlendMode import androidx.compose.ui.graphics.BlendMode
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import tachiyomi.core.common.preference.Preference
import tachiyomi.core.common.preference.PreferenceStore import tachiyomi.core.common.preference.PreferenceStore
import tachiyomi.core.common.preference.getEnum import tachiyomi.core.common.preference.getEnum
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
class ReaderPreferences( class ReaderPreferences(
private val preferenceStore: PreferenceStore, preferenceStore: PreferenceStore,
) { ) {
// region General // region General
fun pageTransitions() = preferenceStore.getBoolean("pref_enable_transitions_key", true) val pageTransitions: Preference<Boolean> = preferenceStore.getBoolean("pref_enable_transitions_key", true)
fun flashOnPageChange() = preferenceStore.getBoolean("pref_reader_flash", false) val flashOnPageChange: Preference<Boolean> = preferenceStore.getBoolean("pref_reader_flash", false)
fun flashDurationMillis() = preferenceStore.getInt("pref_reader_flash_duration", MILLI_CONVERSION) val flashDurationMillis: Preference<Int> = preferenceStore.getInt("pref_reader_flash_duration", MILLI_CONVERSION)
fun flashPageInterval() = preferenceStore.getInt("pref_reader_flash_interval", 1) val flashPageInterval: Preference<Int> = preferenceStore.getInt("pref_reader_flash_interval", 1)
fun flashColor() = preferenceStore.getEnum("pref_reader_flash_mode", FlashColor.BLACK) val flashColor: Preference<FlashColor> = preferenceStore.getEnum("pref_reader_flash_mode", FlashColor.BLACK)
fun doubleTapAnimSpeed() = preferenceStore.getInt("pref_double_tap_anim_speed", 500) val doubleTapAnimSpeed: Preference<Int> = preferenceStore.getInt("pref_double_tap_anim_speed", 500)
fun showPageNumber() = preferenceStore.getBoolean("pref_show_page_number_key", true) val showPageNumber: Preference<Boolean> = preferenceStore.getBoolean("pref_show_page_number_key", true)
fun showReadingMode() = preferenceStore.getBoolean("pref_show_reading_mode", true) val showReadingMode: Preference<Boolean> = preferenceStore.getBoolean("pref_show_reading_mode", true)
fun fullscreen() = preferenceStore.getBoolean("fullscreen", true) val fullscreen: Preference<Boolean> = preferenceStore.getBoolean("fullscreen", true)
fun drawUnderCutout() = preferenceStore.getBoolean("cutout_short", true) val drawUnderCutout: Preference<Boolean> = preferenceStore.getBoolean("cutout_short", true)
fun keepScreenOn() = preferenceStore.getBoolean("pref_keep_screen_on_key", false) val keepScreenOn: Preference<Boolean> = preferenceStore.getBoolean("pref_keep_screen_on_key", false)
fun defaultReadingMode() = preferenceStore.getInt( val defaultReadingMode: Preference<Int> = preferenceStore.getInt(
"pref_default_reading_mode_key", "pref_default_reading_mode_key",
ReadingMode.RIGHT_TO_LEFT.flagValue, ReadingMode.RIGHT_TO_LEFT.flagValue,
) )
fun defaultOrientationType() = preferenceStore.getInt( val defaultOrientationType: Preference<Int> = preferenceStore.getInt(
"pref_default_orientation_type_key", "pref_default_orientation_type_key",
ReaderOrientation.FREE.flagValue, ReaderOrientation.FREE.flagValue,
) )
fun webtoonDoubleTapZoomEnabled() = preferenceStore.getBoolean("pref_enable_double_tap_zoom_webtoon", true) val webtoonDoubleTapZoomEnabled: Preference<Boolean> = preferenceStore.getBoolean(
"pref_enable_double_tap_zoom_webtoon",
true,
)
fun imageScaleType() = preferenceStore.getInt("pref_image_scale_type_key", 1) val imageScaleType: Preference<Int> = preferenceStore.getInt("pref_image_scale_type_key", 1)
fun zoomStart() = preferenceStore.getInt("pref_zoom_start_key", 1) val zoomStart: Preference<Int> = preferenceStore.getInt("pref_zoom_start_key", 1)
fun readerTheme() = preferenceStore.getInt("pref_reader_theme_key", 1) val readerTheme: Preference<Int> = preferenceStore.getInt("pref_reader_theme_key", 1)
fun alwaysShowChapterTransition() = preferenceStore.getBoolean("always_show_chapter_transition", true) val alwaysShowChapterTransition: Preference<Boolean> = preferenceStore.getBoolean(
"always_show_chapter_transition",
true,
)
fun cropBorders() = preferenceStore.getBoolean("crop_borders", false) val cropBorders: Preference<Boolean> = preferenceStore.getBoolean("crop_borders", false)
fun navigateToPan() = preferenceStore.getBoolean("navigate_pan", true) val navigateToPan: Preference<Boolean> = preferenceStore.getBoolean("navigate_pan", true)
fun landscapeZoom() = preferenceStore.getBoolean("landscape_zoom", true) val landscapeZoom: Preference<Boolean> = preferenceStore.getBoolean("landscape_zoom", true)
fun cropBordersWebtoon() = preferenceStore.getBoolean("crop_borders_webtoon", false) val cropBordersWebtoon: Preference<Boolean> = preferenceStore.getBoolean("crop_borders_webtoon", false)
fun webtoonSidePadding() = preferenceStore.getInt("webtoon_side_padding", WEBTOON_PADDING_MIN) val webtoonSidePadding: Preference<Int> = preferenceStore.getInt("webtoon_side_padding", WEBTOON_PADDING_MIN)
fun readerHideThreshold() = preferenceStore.getEnum("reader_hide_threshold", ReaderHideThreshold.LOW) val readerHideThreshold: Preference<ReaderHideThreshold> = preferenceStore.getEnum(
"reader_hide_threshold",
ReaderHideThreshold.LOW,
)
fun folderPerManga() = preferenceStore.getBoolean("create_folder_per_manga", false) val folderPerManga: Preference<Boolean> = preferenceStore.getBoolean("create_folder_per_manga", false)
fun skipRead() = preferenceStore.getBoolean("skip_read", false) val skipRead: Preference<Boolean> = preferenceStore.getBoolean("skip_read", false)
fun skipFiltered() = preferenceStore.getBoolean("skip_filtered", true) val skipFiltered: Preference<Boolean> = preferenceStore.getBoolean("skip_filtered", true)
fun skipDupe() = preferenceStore.getBoolean("skip_dupe", false) val skipDupe: Preference<Boolean> = preferenceStore.getBoolean("skip_dupe", false)
fun webtoonDisableZoomOut() = preferenceStore.getBoolean("webtoon_disable_zoom_out", false) val webtoonDisableZoomOut: Preference<Boolean> = preferenceStore.getBoolean("webtoon_disable_zoom_out", false)
// endregion // endregion
// region Split two page spread // region Split two-page spread
fun dualPageSplitPaged() = preferenceStore.getBoolean("pref_dual_page_split", false) val dualPageSplitPaged: Preference<Boolean> = preferenceStore.getBoolean("pref_dual_page_split", false)
fun dualPageInvertPaged() = preferenceStore.getBoolean("pref_dual_page_invert", false) val dualPageInvertPaged: Preference<Boolean> = preferenceStore.getBoolean("pref_dual_page_invert", false)
fun dualPageSplitWebtoon() = preferenceStore.getBoolean("pref_dual_page_split_webtoon", false) val dualPageSplitWebtoon: Preference<Boolean> = preferenceStore.getBoolean("pref_dual_page_split_webtoon", false)
fun dualPageInvertWebtoon() = preferenceStore.getBoolean("pref_dual_page_invert_webtoon", false) val dualPageInvertWebtoon: Preference<Boolean> = preferenceStore.getBoolean("pref_dual_page_invert_webtoon", false)
fun dualPageRotateToFit() = preferenceStore.getBoolean("pref_dual_page_rotate", false) val dualPageRotateToFit: Preference<Boolean> = preferenceStore.getBoolean("pref_dual_page_rotate", false)
fun dualPageRotateToFitInvert() = preferenceStore.getBoolean("pref_dual_page_rotate_invert", false) val dualPageRotateToFitInvert: Preference<Boolean> = preferenceStore.getBoolean(
"pref_dual_page_rotate_invert",
false,
)
fun dualPageRotateToFitWebtoon() = preferenceStore.getBoolean("pref_dual_page_rotate_webtoon", false) val dualPageRotateToFitWebtoon: Preference<Boolean> = preferenceStore.getBoolean(
"pref_dual_page_rotate_webtoon",
false,
)
fun dualPageRotateToFitInvertWebtoon() = preferenceStore.getBoolean("pref_dual_page_rotate_invert_webtoon", false) val dualPageRotateToFitInvertWebtoon: Preference<Boolean> = preferenceStore.getBoolean(
"pref_dual_page_rotate_invert_webtoon",
false,
)
// endregion // endregion
// region Color filter // region Color filter
fun customBrightness() = preferenceStore.getBoolean("pref_custom_brightness_key", false) val customBrightness: Preference<Boolean> = preferenceStore.getBoolean("pref_custom_brightness_key", false)
fun customBrightnessValue() = preferenceStore.getInt("custom_brightness_value", 0) val customBrightnessValue: Preference<Int> = preferenceStore.getInt("custom_brightness_value", 0)
fun colorFilter() = preferenceStore.getBoolean("pref_color_filter_key", false) val colorFilter: Preference<Boolean> = preferenceStore.getBoolean("pref_color_filter_key", false)
fun colorFilterValue() = preferenceStore.getInt("color_filter_value", 0) val colorFilterValue: Preference<Int> = preferenceStore.getInt("color_filter_value", 0)
fun colorFilterMode() = preferenceStore.getInt("color_filter_mode", 0) val colorFilterMode: Preference<Int> = preferenceStore.getInt("color_filter_mode", 0)
fun grayscale() = preferenceStore.getBoolean("pref_grayscale", false) val grayscale: Preference<Boolean> = preferenceStore.getBoolean("pref_grayscale", false)
fun invertedColors() = preferenceStore.getBoolean("pref_inverted_colors", false) val invertedColors: Preference<Boolean> = preferenceStore.getBoolean("pref_inverted_colors", false)
// endregion // endregion
// region Controls // region Controls
fun readWithLongTap() = preferenceStore.getBoolean("reader_long_tap", true) val readWithLongTap: Preference<Boolean> = preferenceStore.getBoolean("reader_long_tap", true)
fun readWithVolumeKeys() = preferenceStore.getBoolean("reader_volume_keys", false) val readWithVolumeKeys: Preference<Boolean> = preferenceStore.getBoolean("reader_volume_keys", false)
fun readWithVolumeKeysInverted() = preferenceStore.getBoolean("reader_volume_keys_inverted", false) val readWithVolumeKeysInverted: Preference<Boolean> = preferenceStore.getBoolean(
"reader_volume_keys_inverted",
false,
)
fun navigationModePager() = preferenceStore.getInt("reader_navigation_mode_pager", 0) val navigationModePager: Preference<Int> = preferenceStore.getInt("reader_navigation_mode_pager", 0)
fun navigationModeWebtoon() = preferenceStore.getInt("reader_navigation_mode_webtoon", 0) val navigationModeWebtoon: Preference<Int> = preferenceStore.getInt("reader_navigation_mode_webtoon", 0)
fun pagerNavInverted() = preferenceStore.getEnum("reader_tapping_inverted", TappingInvertMode.NONE) val pagerNavInverted: Preference<TappingInvertMode> = preferenceStore.getEnum(
"reader_tapping_inverted",
TappingInvertMode.NONE,
)
fun webtoonNavInverted() = preferenceStore.getEnum("reader_tapping_inverted_webtoon", TappingInvertMode.NONE) val webtoonNavInverted: Preference<TappingInvertMode> = preferenceStore.getEnum(
"reader_tapping_inverted_webtoon",
TappingInvertMode.NONE,
)
fun showNavigationOverlayNewUser() = preferenceStore.getBoolean("reader_navigation_overlay_new_user", true) val showNavigationOverlayNewUser: Preference<Boolean> = preferenceStore.getBoolean(
"reader_navigation_overlay_new_user",
true,
)
fun showNavigationOverlayOnStart() = preferenceStore.getBoolean("reader_navigation_overlay_on_start", false) val showNavigationOverlayOnStart: Preference<Boolean> = preferenceStore.getBoolean(
"reader_navigation_overlay_on_start",
false,
)
// endregion // endregion
@@ -61,7 +61,7 @@ open class ReaderPageImageView @JvmOverloads constructor(
) : FrameLayout(context, attrs, defStyleAttrs, defStyleRes) { ) : FrameLayout(context, attrs, defStyleAttrs, defStyleRes) {
private val alwaysDecodeLongStripWithSSIV by lazy { private val alwaysDecodeLongStripWithSSIV by lazy {
Injekt.get<BasePreferences>().alwaysDecodeLongStripWithSSIV().get() Injekt.get<BasePreferences>().alwaysDecodeLongStripWithSSIV.get()
} }
private var pageView: View? = null private var pageView: View? = null
@@ -46,30 +46,30 @@ abstract class ViewerConfig(readerPreferences: ReaderPreferences, private val sc
protected set protected set
init { init {
readerPreferences.readWithLongTap() readerPreferences.readWithLongTap
.register({ longTapEnabled = it }) .register({ longTapEnabled = it })
readerPreferences.pageTransitions() readerPreferences.pageTransitions
.register({ usePageTransitions = it }) .register({ usePageTransitions = it })
readerPreferences.doubleTapAnimSpeed() readerPreferences.doubleTapAnimSpeed
.register({ doubleTapAnimDuration = it }) .register({ doubleTapAnimDuration = it })
readerPreferences.readWithVolumeKeys() readerPreferences.readWithVolumeKeys
.register({ volumeKeysEnabled = it }) .register({ volumeKeysEnabled = it })
readerPreferences.readWithVolumeKeysInverted() readerPreferences.readWithVolumeKeysInverted
.register({ volumeKeysInverted = it }) .register({ volumeKeysInverted = it })
readerPreferences.alwaysShowChapterTransition() readerPreferences.alwaysShowChapterTransition
.register({ alwaysShowChapterTransition = it }) .register({ alwaysShowChapterTransition = it })
forceNavigationOverlay = readerPreferences.showNavigationOverlayNewUser().get() forceNavigationOverlay = readerPreferences.showNavigationOverlayNewUser.get()
if (forceNavigationOverlay) { if (forceNavigationOverlay) {
readerPreferences.showNavigationOverlayNewUser().set(false) readerPreferences.showNavigationOverlayNewUser.set(false)
} }
readerPreferences.showNavigationOverlayOnStart() readerPreferences.showNavigationOverlayOnStart
.register({ navigationOverlayOnStart = it }) .register({ navigationOverlayOnStart = it })
} }
@@ -25,7 +25,7 @@ class PagerConfig(
readerPreferences: ReaderPreferences = Injekt.get(), readerPreferences: ReaderPreferences = Injekt.get(),
) : ViewerConfig(readerPreferences, scope) { ) : ViewerConfig(readerPreferences, scope) {
var theme = readerPreferences.readerTheme().get() var theme = readerPreferences.readerTheme.get()
private set private set
var automaticBackground = false var automaticBackground = false
@@ -49,7 +49,7 @@ class PagerConfig(
private set private set
init { init {
readerPreferences.readerTheme() readerPreferences.readerTheme
.register( .register(
{ {
theme = it theme = it
@@ -58,32 +58,32 @@ class PagerConfig(
{ imagePropertyChangedListener?.invoke() }, { imagePropertyChangedListener?.invoke() },
) )
readerPreferences.imageScaleType() readerPreferences.imageScaleType
.register({ imageScaleType = it }, { imagePropertyChangedListener?.invoke() }) .register({ imageScaleType = it }, { imagePropertyChangedListener?.invoke() })
readerPreferences.zoomStart() readerPreferences.zoomStart
.register({ zoomTypeFromPreference(it) }, { imagePropertyChangedListener?.invoke() }) .register({ zoomTypeFromPreference(it) }, { imagePropertyChangedListener?.invoke() })
readerPreferences.cropBorders() readerPreferences.cropBorders
.register({ imageCropBorders = it }, { imagePropertyChangedListener?.invoke() }) .register({ imageCropBorders = it }, { imagePropertyChangedListener?.invoke() })
readerPreferences.navigateToPan() readerPreferences.navigateToPan
.register({ navigateToPan = it }) .register({ navigateToPan = it })
readerPreferences.landscapeZoom() readerPreferences.landscapeZoom
.register({ landscapeZoom = it }, { imagePropertyChangedListener?.invoke() }) .register({ landscapeZoom = it }, { imagePropertyChangedListener?.invoke() })
readerPreferences.navigationModePager() readerPreferences.navigationModePager
.register({ navigationMode = it }, { updateNavigation(navigationMode) }) .register({ navigationMode = it }, { updateNavigation(navigationMode) })
readerPreferences.pagerNavInverted() readerPreferences.pagerNavInverted
.register({ tappingInverted = it }, { navigator.invertMode = it }) .register({ tappingInverted = it }, { navigator.invertMode = it })
readerPreferences.pagerNavInverted().changes() readerPreferences.pagerNavInverted.changes()
.drop(1) .drop(1)
.onEach { navigationModeChangedListener?.invoke() } .onEach { navigationModeChangedListener?.invoke() }
.launchIn(scope) .launchIn(scope)
readerPreferences.dualPageSplitPaged() readerPreferences.dualPageSplitPaged
.register( .register(
{ dualPageSplit = it }, { dualPageSplit = it },
{ {
@@ -92,16 +92,16 @@ class PagerConfig(
}, },
) )
readerPreferences.dualPageInvertPaged() readerPreferences.dualPageInvertPaged
.register({ dualPageInvert = it }, { imagePropertyChangedListener?.invoke() }) .register({ dualPageInvert = it }, { imagePropertyChangedListener?.invoke() })
readerPreferences.dualPageRotateToFit() readerPreferences.dualPageRotateToFit
.register( .register(
{ dualPageRotateToFit = it }, { dualPageRotateToFit = it },
{ imagePropertyChangedListener?.invoke() }, { imagePropertyChangedListener?.invoke() },
) )
readerPreferences.dualPageRotateToFitInvert() readerPreferences.dualPageRotateToFitInvert
.register( .register(
{ dualPageRotateToFitInvert = it }, { dualPageRotateToFitInvert = it },
{ imagePropertyChangedListener?.invoke() }, { imagePropertyChangedListener?.invoke() },
@@ -42,56 +42,56 @@ class WebtoonConfig(
var doubleTapZoomChangedListener: ((Boolean) -> Unit)? = null var doubleTapZoomChangedListener: ((Boolean) -> Unit)? = null
val theme = readerPreferences.readerTheme().get() val theme = readerPreferences.readerTheme.get()
init { init {
readerPreferences.cropBordersWebtoon() readerPreferences.cropBordersWebtoon
.register({ imageCropBorders = it }, { imagePropertyChangedListener?.invoke() }) .register({ imageCropBorders = it }, { imagePropertyChangedListener?.invoke() })
readerPreferences.webtoonSidePadding() readerPreferences.webtoonSidePadding
.register({ sidePadding = it }, { imagePropertyChangedListener?.invoke() }) .register({ sidePadding = it }, { imagePropertyChangedListener?.invoke() })
readerPreferences.navigationModeWebtoon() readerPreferences.navigationModeWebtoon
.register({ navigationMode = it }, { updateNavigation(it) }) .register({ navigationMode = it }, { updateNavigation(it) })
readerPreferences.webtoonNavInverted() readerPreferences.webtoonNavInverted
.register({ tappingInverted = it }, { navigator.invertMode = it }) .register({ tappingInverted = it }, { navigator.invertMode = it })
readerPreferences.webtoonNavInverted().changes() readerPreferences.webtoonNavInverted.changes()
.drop(1) .drop(1)
.onEach { navigationModeChangedListener?.invoke() } .onEach { navigationModeChangedListener?.invoke() }
.launchIn(scope) .launchIn(scope)
readerPreferences.dualPageSplitWebtoon() readerPreferences.dualPageSplitWebtoon
.register({ dualPageSplit = it }, { imagePropertyChangedListener?.invoke() }) .register({ dualPageSplit = it }, { imagePropertyChangedListener?.invoke() })
readerPreferences.dualPageInvertWebtoon() readerPreferences.dualPageInvertWebtoon
.register({ dualPageInvert = it }, { imagePropertyChangedListener?.invoke() }) .register({ dualPageInvert = it }, { imagePropertyChangedListener?.invoke() })
readerPreferences.dualPageRotateToFitWebtoon() readerPreferences.dualPageRotateToFitWebtoon
.register( .register(
{ dualPageRotateToFit = it }, { dualPageRotateToFit = it },
{ imagePropertyChangedListener?.invoke() }, { imagePropertyChangedListener?.invoke() },
) )
readerPreferences.dualPageRotateToFitInvertWebtoon() readerPreferences.dualPageRotateToFitInvertWebtoon
.register( .register(
{ dualPageRotateToFitInvert = it }, { dualPageRotateToFitInvert = it },
{ imagePropertyChangedListener?.invoke() }, { imagePropertyChangedListener?.invoke() },
) )
readerPreferences.webtoonDisableZoomOut() readerPreferences.webtoonDisableZoomOut
.register( .register(
{ zoomOutDisabled = it }, { zoomOutDisabled = it },
{ zoomPropertyChangedListener?.invoke(it) }, { zoomPropertyChangedListener?.invoke(it) },
) )
readerPreferences.webtoonDoubleTapZoomEnabled() readerPreferences.webtoonDoubleTapZoomEnabled
.register( .register(
{ doubleTapZoom = it }, { doubleTapZoom = it },
{ doubleTapZoomChangedListener?.invoke(it) }, { doubleTapZoomChangedListener?.invoke(it) },
) )
readerPreferences.readerTheme().changes() readerPreferences.readerTheme.changes()
.drop(1) .drop(1)
.distinctUntilChanged() .distinctUntilChanged()
.onEach { themeChangedListener?.invoke() } .onEach { themeChangedListener?.invoke() }
@@ -74,7 +74,7 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
private val threshold: Int = private val threshold: Int =
Injekt.get<ReaderPreferences>() Injekt.get<ReaderPreferences>()
.readerHideThreshold() .readerHideThreshold
.get() .get()
.threshold .threshold
@@ -85,9 +85,9 @@ class StatsScreenModel(
} }
private fun getGlobalUpdateItemCount(libraryManga: List<LibraryManga>): Int { private fun getGlobalUpdateItemCount(libraryManga: List<LibraryManga>): Int {
val includedCategories = preferences.updateCategories().get().map { it.toLong() } val includedCategories = preferences.updateCategories.get().map { it.toLong() }
val excludedCategories = preferences.updateCategoriesExclude().get().map { it.toLong() } val excludedCategories = preferences.updateCategoriesExclude.get().map { it.toLong() }
val updateRestrictions = preferences.autoUpdateMangaRestrictions().get() val updateRestrictions = preferences.autoUpdateMangaRestrictions.get()
return libraryManga.filter { return libraryManga.filter {
val included = includedCategories.isEmpty() || it.categories.intersect(includedCategories).isNotEmpty() val included = includedCategories.isEmpty() || it.categories.intersect(includedCategories).isNotEmpty()
@@ -72,7 +72,7 @@ class UpdatesScreenModel(
private val _events: Channel<Event> = Channel(Int.MAX_VALUE) private val _events: Channel<Event> = Channel(Int.MAX_VALUE)
val events: Flow<Event> = _events.receiveAsFlow() val events: Flow<Event> = _events.receiveAsFlow()
val lastUpdated by libraryPreferences.lastUpdatedTimestamp().asState(screenModelScope) val lastUpdated by libraryPreferences.lastUpdatedTimestamp.asState(screenModelScope)
// First and last selected index in list // First and last selected index in list
private val selectedPositions: Array<Int> = arrayOf(-1, -1) private val selectedPositions: Array<Int> = arrayOf(-1, -1)
@@ -415,16 +415,16 @@ class UpdatesScreenModel(
} }
fun resetNewUpdatesCount() { fun resetNewUpdatesCount() {
libraryPreferences.newUpdatesCount().set(0) libraryPreferences.newUpdatesCount.set(0)
} }
private fun getUpdatesItemPreferenceFlow(): Flow<ItemPreferences> { private fun getUpdatesItemPreferenceFlow(): Flow<ItemPreferences> {
return combine( return combine(
updatesPreferences.filterDownloaded().changes(), updatesPreferences.filterDownloaded.changes(),
updatesPreferences.filterUnread().changes(), updatesPreferences.filterUnread.changes(),
updatesPreferences.filterStarted().changes(), updatesPreferences.filterStarted.changes(),
updatesPreferences.filterBookmarked().changes(), updatesPreferences.filterBookmarked.changes(),
updatesPreferences.filterExcludedScanlators().changes(), updatesPreferences.filterExcludedScanlators.changes(),
) { downloaded, unread, started, bookmarked, excludedScanlators -> ) { downloaded, unread, started, bookmarked, excludedScanlators ->
ItemPreferences( ItemPreferences(
filterDownloaded = downloaded, filterDownloaded = downloaded,
@@ -44,7 +44,7 @@ class CrashLogUtil(
return """ return """
App ID: ${BuildConfig.APPLICATION_ID} App ID: ${BuildConfig.APPLICATION_ID}
App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.COMMIT_SHA}, ${BuildConfig.VERSION_CODE}, ${BuildConfig.BUILD_TIME}) App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.COMMIT_SHA}, ${BuildConfig.VERSION_CODE}, ${BuildConfig.BUILD_TIME})
Installation ID: ${preferences.installationId().get()} Installation ID: ${preferences.installationId.get()}
Android version: ${Build.VERSION.RELEASE} (SDK ${Build.VERSION.SDK_INT}; build ${Build.DISPLAY}) Android version: ${Build.VERSION.RELEASE} (SDK ${Build.VERSION.SDK_INT}; build ${Build.DISPLAY})
Device brand: ${Build.BRAND} Device brand: ${Build.BRAND}
Device manufacturer: ${Build.MANUFACTURER} Device manufacturer: ${Build.MANUFACTURER}
@@ -107,8 +107,8 @@ fun Context.createFileInCacheDir(name: String): File {
fun Context.createReaderThemeContext(): Context { fun Context.createReaderThemeContext(): Context {
val preferences = Injekt.get<UiPreferences>() val preferences = Injekt.get<UiPreferences>()
val readerPreferences = Injekt.get<ReaderPreferences>() val readerPreferences = Injekt.get<ReaderPreferences>()
val themeMode = preferences.themeMode().get() val themeMode = preferences.themeMode.get()
val isDarkBackground = when (readerPreferences.readerTheme().get()) { val isDarkBackground = when (readerPreferences.readerTheme.get()) {
1, 2 -> true // Black, Gray 1, 2 -> true // Black, Gray
3 -> when (themeMode) { // Automatic bg uses activity background by default 3 -> when (themeMode) { // Automatic bg uses activity background by default
ThemeMode.SYSTEM -> applicationContext.isNightMode() ThemeMode.SYSTEM -> applicationContext.isNightMode()
@@ -124,7 +124,7 @@ fun Context.createReaderThemeContext(): Context {
val wrappedContext = ContextThemeWrapper(this, R.style.Theme_Tachiyomi) val wrappedContext = ContextThemeWrapper(this, R.style.Theme_Tachiyomi)
wrappedContext.applyOverrideConfiguration(overrideConf) wrappedContext.applyOverrideConfiguration(overrideConf)
ThemingDelegate.getThemeResIds(preferences.appTheme().get(), preferences.themeDarkAmoled().get()) ThemingDelegate.getThemeResIds(preferences.appTheme.get(), preferences.themeDarkAmoled.get())
.forEach { wrappedContext.theme.applyStyle(it, true) } .forEach { wrappedContext.theme.applyStyle(it, true) }
return wrappedContext return wrappedContext
} }
@@ -25,7 +25,7 @@ fun Configuration.isTabletUi(): Boolean {
// TODO: move the logic to `isTabletUi()` when main activity is rewritten in Compose // TODO: move the logic to `isTabletUi()` when main activity is rewritten in Compose
fun Context.prepareTabletUiContext(): Context { fun Context.prepareTabletUiContext(): Context {
val configuration = resources.configuration val configuration = resources.configuration
val expected = when (Injekt.get<UiPreferences>().tabletUiMode().get()) { val expected = when (Injekt.get<UiPreferences>().tabletUiMode.get()) {
TabletUiMode.AUTOMATIC -> TabletUiMode.AUTOMATIC ->
configuration.smallestScreenWidthDp >= when (configuration.orientation) { configuration.smallestScreenWidthDp >= when (configuration.orientation) {
Configuration.ORIENTATION_PORTRAIT -> TABLET_UI_MIN_SCREEN_WIDTH_PORTRAIT_DP Configuration.ORIENTATION_PORTRAIT -> TABLET_UI_MIN_SCREEN_WIDTH_PORTRAIT_DP
@@ -49,7 +49,7 @@ class TachiyomiTextInputEditText @JvmOverloads constructor(
* if [BasePreferences.incognitoMode] is true. Some IMEs may not respect this flag. * if [BasePreferences.incognitoMode] is true. Some IMEs may not respect this flag.
*/ */
fun EditText.setIncognito(viewScope: CoroutineScope) { fun EditText.setIncognito(viewScope: CoroutineScope) {
Injekt.get<BasePreferences>().incognitoMode().changes() Injekt.get<BasePreferences>().incognitoMode.changes()
.onEach { .onEach {
imeOptions = if (it) { imeOptions = if (it) {
imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING
@@ -17,17 +17,17 @@ class CategoryPreferencesCleanupMigration : Migration {
val getCategories = migrationContext.get<GetCategories>() ?: return@withIOContext false val getCategories = migrationContext.get<GetCategories>() ?: return@withIOContext false
val allCategories = getCategories.await().map { it.id.toString() }.toSet() val allCategories = getCategories.await().map { it.id.toString() }.toSet()
val defaultCategory = libraryPreferences.defaultCategory().get() val defaultCategory = libraryPreferences.defaultCategory.get()
if (defaultCategory.toString() !in allCategories) { if (defaultCategory.toString() !in allCategories) {
libraryPreferences.defaultCategory().delete() libraryPreferences.defaultCategory.delete()
} }
val categoryPreferences = listOf( val categoryPreferences = listOf(
libraryPreferences.updateCategories(), libraryPreferences.updateCategories,
libraryPreferences.updateCategoriesExclude(), libraryPreferences.updateCategoriesExclude,
downloadPreferences.removeExcludeCategories(), downloadPreferences.removeExcludeCategories,
downloadPreferences.downloadNewChapterCategories(), downloadPreferences.downloadNewChapterCategories,
downloadPreferences.downloadNewChapterCategoriesExclude(), downloadPreferences.downloadNewChapterCategoriesExclude,
) )
categoryPreferences.forEach { preference -> categoryPreferences.forEach { preference ->
val ids = preference.get() val ids = preference.get()

Some files were not shown because too many files have changed in this diff Show More