mirror of
https://github.com/mihonapp/mihon.git
synced 2026-10-17 14:12:25 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b58d2a5d4b | ||
|
|
d3dcb7fe4b | ||
|
|
56b70ef529 | ||
|
|
5cf305b620 | ||
|
|
87665736a9 | ||
|
|
2f9edb551f | ||
|
|
d4b88b13b8 | ||
|
|
99edfbe4a8 | ||
|
|
fa7155896c | ||
|
|
51fb9c0b76 | ||
|
|
c495753315 | ||
|
|
11ced33fdb | ||
|
|
8c480c6355 | ||
|
|
e9ca71d837 | ||
|
|
e4091c0160 | ||
|
|
a2d22a7d55 | ||
|
|
db22517339 | ||
|
|
33faa5a356 | ||
|
|
8c5ae44f51 | ||
|
|
575d7e8b89 | ||
|
|
8c00b44eda | ||
|
|
77a86d486f | ||
|
|
4b379576f4 | ||
|
|
be88ce199c | ||
|
|
32b8ef6240 | ||
|
|
f82b8300b0 | ||
|
|
ce5820b496 | ||
|
|
f6b2684323 | ||
|
|
0d768af3d0 | ||
|
|
08f0bcc0d8 | ||
|
|
a3c45a05b8 | ||
|
|
6926914385 | ||
|
|
f3d5491a7d | ||
|
|
81871a3469 | ||
|
|
0024278f4b |
@@ -0,0 +1 @@
|
||||
21
|
||||
@@ -30,7 +30,7 @@ body:
|
||||
required: true
|
||||
- label: I have written a short but informative title.
|
||||
required: true
|
||||
- label: I have updated the app to version **[0.19.4](https://github.com/mihonapp/mihon/releases/latest)**.
|
||||
- label: I have updated the app to version **[0.19.5](https://github.com/mihonapp/mihon/releases/latest)**.
|
||||
required: true
|
||||
- label: I will fill out all of the requested information in this form.
|
||||
required: true
|
||||
|
||||
@@ -52,7 +52,7 @@ body:
|
||||
label: Mihon version
|
||||
description: You can find your Mihon version in **More → About**.
|
||||
placeholder: |
|
||||
Example: "0.19.4"
|
||||
Example: "0.19.5"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -95,7 +95,7 @@ body:
|
||||
required: true
|
||||
- label: I have gone through the [FAQ](https://mihon.app/docs/faq/general) and [troubleshooting guide](https://mihon.app/docs/guides/troubleshooting/).
|
||||
required: true
|
||||
- label: I have updated the app to version **[0.19.4](https://github.com/mihonapp/mihon/releases/latest)**.
|
||||
- label: I have updated the app to version **[0.19.5](https://github.com/mihonapp/mihon/releases/latest)**.
|
||||
required: true
|
||||
- label: I have filled out all of the requested information in this form, including specific version numbers.
|
||||
required: true
|
||||
|
||||
@@ -30,12 +30,12 @@ jobs:
|
||||
|
||||
- name: Dependency Review
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/dependency-review-action@05fe4576374b728f0c523d6a13d64c25081e0803 # v4.8.3
|
||||
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
java-version: 17
|
||||
java-version-file: .github/.java-version
|
||||
distribution: temurin
|
||||
|
||||
- name: Set up Gradle
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
java-version: 17
|
||||
java-version-file: .github/.java-version
|
||||
distribution: temurin
|
||||
|
||||
- name: Set up Gradle
|
||||
@@ -88,7 +88,7 @@ jobs:
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
java-version: 17
|
||||
java-version-file: .github/.java-version
|
||||
distribution: temurin
|
||||
|
||||
- name: Set up Gradle
|
||||
@@ -143,7 +143,7 @@ jobs:
|
||||
mihon-foss
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
|
||||
with:
|
||||
tag_name: ${{ needs.get_tag.outputs.tag }}
|
||||
name: Mihon ${{ needs.get_tag.outputs.tag }}
|
||||
|
||||
+15
-3
@@ -12,6 +12,17 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.19.5] - 2026-03-20
|
||||
### Changed
|
||||
- Retry in reader now redownloads image ([@AntsyLich](https://github.com/AntsyLich)) ([#3089](https://github.com/mihonapp/mihon/pull/3089))
|
||||
|
||||
### Fixed
|
||||
- Fix performance regression introduced in v0.19.4 ([@AntsyLich](https://github.com/AntsyLich)) ([#3082](https://github.com/mihonapp/mihon/pull/3082))
|
||||
- Fix duplicate key crash in duplicate detection ([@leodyversemilla07](https://github.com/leodyversemilla07)) ([#3040](https://github.com/mihonapp/mihon/pull/3040))
|
||||
- Fix MangaUpdates HTTP 4XX errors ([@leodyversemilla07](https://github.com/leodyversemilla07)) ([#3021](https://github.com/mihonapp/mihon/pull/3021))
|
||||
- Fix WebView JavaScript dialogs popup after screen is closed ([@leodyversemilla07](https://github.com/leodyversemilla07)) ([#3041](https://github.com/mihonapp/mihon/pull/3041))
|
||||
- Fix extension actions disappearing after installing and uninstalling in same session ([@leodyversemilla07](https://github.com/leodyversemilla07)) ([#3049](https://github.com/mihonapp/mihon/pull/3049))
|
||||
|
||||
## [v0.19.4] - 2026-02-25
|
||||
### Added
|
||||
- Automatically remove downloads on Suwayomi after reading, configurable via extension settings ([@cpiber](https://github.com/cpiber)) ([#2673](https://github.com/mihonapp/mihon/pull/2673))
|
||||
@@ -26,7 +37,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
|
||||
- Optimize MAL search queries ([@MajorTanya](https://github.com/MajorTanya)) ([#2832](https://github.com/mihonapp/mihon/pull/2832))
|
||||
- Reword download reindexing message to avoid confusion ([@MajorTanya](https://github.com/MajorTanya)) ([#2874](https://github.com/mihonapp/mihon/pull/2874))
|
||||
- Optimize tracked library filter ([@NarwhalHorns](https://github.com/NarwhalHorns)) ([#2977](https://github.com/mihonapp/mihon/pull/2977))
|
||||
- Utilize tracker for library duplicate detection ([@NarwhalHorns](https://github.com/NarwhalHorns)) ([#2977](https://github.com/mihonapp/mihon/pull/2978))
|
||||
- Utilize tracker for library duplicate detection ([@NarwhalHorns](https://github.com/NarwhalHorns)) ([#2978](https://github.com/mihonapp/mihon/pull/2978))
|
||||
|
||||
### Changed
|
||||
- Update tracker icons ([@AntsyLich](https://github.com/AntsyLich)) ([#2773](https://github.com/mihonapp/mihon/pull/2773))
|
||||
@@ -46,7 +57,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
|
||||
- Fix migration's selected sources order not preserved ([@AntsyLich](https://github.com/AntsyLich)) ([#2993](https://github.com/mihonapp/mihon/pull/2993))
|
||||
- Fix migration dialog not showing for consecutive prompts from the same screen ([@AntsyLich](https://github.com/AntsyLich)) ([#2994](https://github.com/mihonapp/mihon/pull/2994))
|
||||
- Fix extension install/update stuck at pending ([@AntsyLich](https://github.com/AntsyLich)) ([#3000](https://github.com/mihonapp/mihon/pull/3000))
|
||||
- Fix crash when downloading multiple chapters with Arabic locale ([@MajorTanya](https://github.com/MajorTanya)) ([#2676](https://github.com/mihonapp/mihon/pull/2676))
|
||||
- Fix crash when downloading multiple chapters with Arabic locale ([@MajorTanya](https://github.com/MajorTanya)) ([#2676](https://github.com/mihonapp/mihon/pull/2676))
|
||||
|
||||
### Other
|
||||
- Enable logcat logging on stable and debug builds without enabling verbose logging ([@NGB-Was-Taken](https://github.com/NGB-Was-Taken)) ([#2836](https://github.com/mihonapp/mihon/pull/2836))
|
||||
@@ -484,7 +495,8 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
|
||||
- Branding to Mihon ([@AntsyLich](https://github.com/AntsyLich))
|
||||
- Minimum supported Android version to 8 ([@AntsyLich](https://github.com/AntsyLich)) ([`dfb3091`](https://github.com/mihonapp/mihon/commit/dfb3091e380dda3e9bfb64bf5c9a685cf3a03d0e))
|
||||
|
||||
[unreleased]: https://github.com/mihonapp/mihon/compare/v0.19.4...main
|
||||
[unreleased]: https://github.com/mihonapp/mihon/compare/v0.19.5...main
|
||||
[v0.19.4]: https://github.com/mihonapp/mihon/compare/v0.19.4...v0.19.5
|
||||
[v0.19.4]: https://github.com/mihonapp/mihon/compare/v0.19.3...v0.19.4
|
||||
[v0.19.3]: https://github.com/mihonapp/mihon/compare/v0.19.2...v0.19.3
|
||||
[v0.19.2]: https://github.com/mihonapp/mihon/compare/v0.19.1...v0.19.2
|
||||
|
||||
@@ -26,8 +26,8 @@ android {
|
||||
defaultConfig {
|
||||
applicationId = "app.mihon"
|
||||
|
||||
versionCode = 17
|
||||
versionName = "0.19.4"
|
||||
versionCode = 19
|
||||
versionName = "0.19.5"
|
||||
|
||||
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
||||
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")
|
||||
@@ -200,7 +200,7 @@ dependencies {
|
||||
implementation(androidx.paging.runtime)
|
||||
implementation(androidx.paging.compose)
|
||||
|
||||
implementation(libs.bundles.sqlite)
|
||||
implementation(androidx.sqlite.bundled)
|
||||
|
||||
implementation(kotlinx.reflect)
|
||||
implementation(kotlinx.immutables)
|
||||
|
||||
@@ -9,19 +9,22 @@ import tachiyomi.i18n.MR
|
||||
|
||||
class BasePreferences(
|
||||
val context: Context,
|
||||
private val preferenceStore: PreferenceStore,
|
||||
preferenceStore: PreferenceStore,
|
||||
) {
|
||||
|
||||
fun downloadedOnly() = preferenceStore.getBoolean(
|
||||
val downloadedOnly: Preference<Boolean> = preferenceStore.getBoolean(
|
||||
Preference.appStateKey("pref_downloaded_only"),
|
||||
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) {
|
||||
LEGACY(MR.strings.ext_installer_legacy, true),
|
||||
@@ -30,9 +33,17 @@ class BasePreferences(
|
||||
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,
|
||||
)
|
||||
|
||||
val installationId: Preference<String> = preferenceStore.getString(Preference.appStateKey("installation_id"), "")
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class SetReadStatus(
|
||||
return@withNonCancellableContext Result.InternalError(e)
|
||||
}
|
||||
|
||||
if (read && downloadPreferences.removeAfterMarkedAsRead().get()) {
|
||||
if (read && downloadPreferences.removeAfterMarkedAsRead.get()) {
|
||||
chaptersToUpdate
|
||||
.groupBy { it.mangaId }
|
||||
.forEach { (mangaId, chapters) ->
|
||||
|
||||
@@ -171,7 +171,7 @@ class SyncChaptersWithSource(
|
||||
val deletedChapterNumberDateFetchMap = removedChapters.sortedByDescending { 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)
|
||||
|
||||
// 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>> {
|
||||
return combine(
|
||||
preferences.enabledLanguages().changes(),
|
||||
preferences.enabledLanguages.changes(),
|
||||
extensionManager.availableExtensionsFlow,
|
||||
) { enabledLanguage, availableExtensions ->
|
||||
availableExtensions
|
||||
|
||||
@@ -15,7 +15,7 @@ class GetExtensionSources(
|
||||
val isMultiLangSingleSource =
|
||||
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
|
||||
|
||||
extension.sources
|
||||
|
||||
@@ -13,10 +13,10 @@ class GetExtensionsByType(
|
||||
) {
|
||||
|
||||
fun subscribe(): Flow<Extensions> {
|
||||
val showNsfwSources = preferences.showNsfwSource().get()
|
||||
val showNsfwSources = preferences.showNsfwSource.get()
|
||||
|
||||
return combine(
|
||||
preferences.enabledLanguages().changes(),
|
||||
preferences.enabledLanguages.changes(),
|
||||
extensionManager.installedExtensionsFlow,
|
||||
extensionManager.untrustedExtensionsFlow,
|
||||
extensionManager.availableExtensionsFlow,
|
||||
|
||||
@@ -14,11 +14,11 @@ class TrustExtension(
|
||||
suspend fun isTrusted(pkgInfo: PackageInfo, fingerprints: List<String>): Boolean {
|
||||
val trustedFingerprints = extensionRepoRepository.getAll().map { it.signingKeyFingerprint }.toHashSet()
|
||||
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) {
|
||||
preferences.trustedExtensions().getAndSet { exts ->
|
||||
preferences.trustedExtensions.getAndSet { exts ->
|
||||
// Remove previously trusted versions
|
||||
val removed = exts.filterNot { it.startsWith("$pkgName:") }.toMutableSet()
|
||||
|
||||
@@ -27,6 +27,6 @@ class TrustExtension(
|
||||
}
|
||||
|
||||
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
|
||||
val title =
|
||||
if (remoteTitle.isNotEmpty() && (!localManga.favorite || libraryPreferences.updateMangaTitles().get())) {
|
||||
if (remoteTitle.isNotEmpty() && (!localManga.favorite || libraryPreferences.updateMangaTitles.get())) {
|
||||
remoteTitle
|
||||
} else {
|
||||
null
|
||||
|
||||
@@ -22,7 +22,7 @@ val Manga.readerOrientation: Long
|
||||
|
||||
val Manga.downloadedFilter: TriState
|
||||
get() {
|
||||
if (Injekt.get<BasePreferences>().downloadedOnly().get()) return TriState.ENABLED_IS
|
||||
if (Injekt.get<BasePreferences>().downloadedOnly.get()) return TriState.ENABLED_IS
|
||||
return when (downloadedFilterRaw) {
|
||||
Manga.CHAPTER_SHOW_DOWNLOADED -> TriState.ENABLED_IS
|
||||
Manga.CHAPTER_SHOW_NOT_DOWNLOADED -> TriState.ENABLED_NOT
|
||||
|
||||
@@ -17,10 +17,10 @@ class GetEnabledSources(
|
||||
|
||||
fun subscribe(): Flow<List<Source>> {
|
||||
return combine(
|
||||
preferences.pinnedSources().changes(),
|
||||
preferences.enabledLanguages().changes(),
|
||||
preferences.disabledSources().changes(),
|
||||
preferences.lastUsedSource().changes(),
|
||||
preferences.pinnedSources.changes(),
|
||||
preferences.enabledLanguages.changes(),
|
||||
preferences.disabledSources.changes(),
|
||||
preferences.lastUsedSource.changes(),
|
||||
repository.getSources(),
|
||||
) { pinnedSourceIds, enabledLanguages, disabledSources, lastUsedSource, sources ->
|
||||
sources
|
||||
|
||||
@@ -13,19 +13,19 @@ class GetIncognitoState(
|
||||
private val extensionManager: ExtensionManager,
|
||||
) {
|
||||
fun await(sourceId: Long?): Boolean {
|
||||
if (basePreferences.incognitoMode().get()) return true
|
||||
if (basePreferences.incognitoMode.get()) return true
|
||||
if (sourceId == null) 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> {
|
||||
if (sourceId == null) return basePreferences.incognitoMode().changes()
|
||||
if (sourceId == null) return basePreferences.incognitoMode.changes()
|
||||
|
||||
return combine(
|
||||
basePreferences.incognitoMode().changes(),
|
||||
sourcePreferences.incognitoExtensions().changes(),
|
||||
basePreferences.incognitoMode.changes(),
|
||||
sourcePreferences.incognitoExtensions.changes(),
|
||||
extensionManager.getExtensionPackageAsFlow(sourceId),
|
||||
) { incognito, incognitoExtensions, extensionPackage ->
|
||||
incognito || (extensionPackage in incognitoExtensions)
|
||||
|
||||
@@ -15,8 +15,8 @@ class GetLanguagesWithSources(
|
||||
|
||||
fun subscribe(): Flow<SortedMap<String, List<Source>>> {
|
||||
return combine(
|
||||
preferences.enabledLanguages().changes(),
|
||||
preferences.disabledSources().changes(),
|
||||
preferences.enabledLanguages.changes(),
|
||||
preferences.disabledSources.changes(),
|
||||
repository.getOnlineSources(),
|
||||
) { enabledLanguage, disabledSource, onlineSources ->
|
||||
val sortedSources = onlineSources.sortedWith(
|
||||
|
||||
@@ -16,8 +16,8 @@ class GetSourcesWithFavoriteCount(
|
||||
|
||||
fun subscribe(): Flow<List<Pair<Source, Long>>> {
|
||||
return combine(
|
||||
preferences.migrationSortingDirection().changes(),
|
||||
preferences.migrationSortingMode().changes(),
|
||||
preferences.migrationSortingDirection.changes(),
|
||||
preferences.migrationSortingMode.changes(),
|
||||
repository.getSourcesWithFavoriteCount(),
|
||||
) { direction, mode, list ->
|
||||
list
|
||||
|
||||
@@ -7,8 +7,8 @@ class SetMigrateSorting(
|
||||
) {
|
||||
|
||||
fun await(mode: Mode, direction: Direction) {
|
||||
preferences.migrationSortingMode().set(mode)
|
||||
preferences.migrationSortingDirection().set(direction)
|
||||
preferences.migrationSortingMode.set(mode)
|
||||
preferences.migrationSortingDirection.set(direction)
|
||||
}
|
||||
|
||||
enum class Mode {
|
||||
|
||||
@@ -7,7 +7,7 @@ class ToggleIncognito(
|
||||
private val preferences: SourcePreferences,
|
||||
) {
|
||||
fun await(extensions: String, enable: Boolean) {
|
||||
preferences.incognitoExtensions().getAndSet {
|
||||
preferences.incognitoExtensions.getAndSet {
|
||||
if (enable) it.plus(extensions) else it.minus(extensions)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ class ToggleLanguage(
|
||||
) {
|
||||
|
||||
fun await(language: String) {
|
||||
val isEnabled = language in preferences.enabledLanguages().get()
|
||||
preferences.enabledLanguages().getAndSet { enabled ->
|
||||
val isEnabled = language in preferences.enabledLanguages.get()
|
||||
preferences.enabledLanguages.getAndSet { enabled ->
|
||||
if (isEnabled) enabled.minus(language) else enabled.plus(language)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,19 +13,19 @@ class ToggleSource(
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
fun await(sourceIds: List<Long>, enable: Boolean) {
|
||||
val transformedSourceIds = sourceIds.map { it.toString() }
|
||||
preferences.disabledSources().getAndSet { disabled ->
|
||||
preferences.disabledSources.getAndSet { disabled ->
|
||||
if (enable) disabled.minus(transformedSourceIds) else disabled.plus(transformedSourceIds)
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
val isPinned = source.id.toString() in preferences.pinnedSources().get()
|
||||
preferences.pinnedSources().getAndSet { pinned ->
|
||||
val isPinned = source.id.toString() in preferences.pinnedSources.get()
|
||||
preferences.pinnedSources.getAndSet { pinned ->
|
||||
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
|
||||
|
||||
class SourcePreferences(
|
||||
private val preferenceStore: PreferenceStore,
|
||||
preferenceStore: PreferenceStore,
|
||||
) {
|
||||
|
||||
fun sourceDisplayMode() = preferenceStore.getObjectFromString(
|
||||
val sourceDisplayMode: Preference<LibraryDisplayMode> = preferenceStore.getObjectFromString(
|
||||
"pref_display_mode_catalogue",
|
||||
LibraryDisplayMode.default,
|
||||
LibraryDisplayMode.Serializer::serialize,
|
||||
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"),
|
||||
-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",
|
||||
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"),
|
||||
emptySet(),
|
||||
)
|
||||
|
||||
fun globalSearchFilterState() = preferenceStore.getBoolean(
|
||||
val globalSearchFilterState: Preference<Boolean> = preferenceStore.getBoolean(
|
||||
Preference.appStateKey("has_filters_toggle_state"),
|
||||
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",
|
||||
defaultValue = MigrationFlag.entries.toSet(),
|
||||
serializer = { MigrationFlag.toBit(it) },
|
||||
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 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",
|
||||
AutoTrackState.ALWAYS,
|
||||
)
|
||||
|
||||
@@ -5,6 +5,7 @@ import eu.kanade.domain.ui.model.TabletUiMode
|
||||
import eu.kanade.domain.ui.model.ThemeMode
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable
|
||||
import tachiyomi.core.common.preference.Preference
|
||||
import tachiyomi.core.common.preference.PreferenceStore
|
||||
import tachiyomi.core.common.preference.getEnum
|
||||
import java.time.format.DateTimeFormatter
|
||||
@@ -12,12 +13,12 @@ import java.time.format.FormatStyle
|
||||
import java.util.Locale
|
||||
|
||||
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",
|
||||
if (DeviceUtil.isDynamicColorAvailable) {
|
||||
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 {
|
||||
fun dateFormat(format: String): DateTimeFormatter = when (format) {
|
||||
|
||||
@@ -33,8 +33,8 @@ fun relativeDateText(
|
||||
val context = LocalContext.current
|
||||
|
||||
val preferences = remember { Injekt.get<UiPreferences>() }
|
||||
val relativeTime = remember { preferences.relativeTime().get() }
|
||||
val dateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat().get()) }
|
||||
val relativeTime = remember { preferences.relativeTime.get() }
|
||||
val dateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat.get()) }
|
||||
|
||||
return localDate?.toRelativeString(
|
||||
context = context,
|
||||
|
||||
@@ -78,9 +78,9 @@ fun LibrarySettingsDialog(
|
||||
private fun ColumnScope.FilterPage(
|
||||
screenModel: LibrarySettingsScreenModel,
|
||||
) {
|
||||
val filterDownloaded by screenModel.libraryPreferences.filterDownloaded().collectAsState()
|
||||
val downloadedOnly by screenModel.preferences.downloadedOnly().collectAsState()
|
||||
val autoUpdateMangaRestrictions by screenModel.libraryPreferences.autoUpdateMangaRestrictions().collectAsState()
|
||||
val filterDownloaded by screenModel.libraryPreferences.filterDownloaded.collectAsState()
|
||||
val downloadedOnly by screenModel.preferences.downloadedOnly.collectAsState()
|
||||
val autoUpdateMangaRestrictions by screenModel.libraryPreferences.autoUpdateMangaRestrictions.collectAsState()
|
||||
|
||||
TriStateItem(
|
||||
label = stringResource(MR.strings.label_downloaded),
|
||||
@@ -92,25 +92,25 @@ private fun ColumnScope.FilterPage(
|
||||
enabled = !downloadedOnly,
|
||||
onClick = { screenModel.toggleFilter(LibraryPreferences::filterDownloaded) },
|
||||
)
|
||||
val filterUnread by screenModel.libraryPreferences.filterUnread().collectAsState()
|
||||
val filterUnread by screenModel.libraryPreferences.filterUnread.collectAsState()
|
||||
TriStateItem(
|
||||
label = stringResource(MR.strings.action_filter_unread),
|
||||
state = filterUnread,
|
||||
onClick = { screenModel.toggleFilter(LibraryPreferences::filterUnread) },
|
||||
)
|
||||
val filterStarted by screenModel.libraryPreferences.filterStarted().collectAsState()
|
||||
val filterStarted by screenModel.libraryPreferences.filterStarted.collectAsState()
|
||||
TriStateItem(
|
||||
label = stringResource(MR.strings.label_started),
|
||||
state = filterStarted,
|
||||
onClick = { screenModel.toggleFilter(LibraryPreferences::filterStarted) },
|
||||
)
|
||||
val filterBookmarked by screenModel.libraryPreferences.filterBookmarked().collectAsState()
|
||||
val filterBookmarked by screenModel.libraryPreferences.filterBookmarked.collectAsState()
|
||||
TriStateItem(
|
||||
label = stringResource(MR.strings.action_filter_bookmarked),
|
||||
state = filterBookmarked,
|
||||
onClick = { screenModel.toggleFilter(LibraryPreferences::filterBookmarked) },
|
||||
)
|
||||
val filterCompleted by screenModel.libraryPreferences.filterCompleted().collectAsState()
|
||||
val filterCompleted by screenModel.libraryPreferences.filterCompleted.collectAsState()
|
||||
TriStateItem(
|
||||
label = stringResource(MR.strings.completed),
|
||||
state = filterCompleted,
|
||||
@@ -118,7 +118,7 @@ private fun ColumnScope.FilterPage(
|
||||
)
|
||||
// TODO: re-enable when custom intervals are ready for stable
|
||||
if ((!isReleaseBuildType) && LibraryPreferences.MANGA_OUTSIDE_RELEASE_PERIOD in autoUpdateMangaRestrictions) {
|
||||
val filterIntervalCustom by screenModel.libraryPreferences.filterIntervalCustom().collectAsState()
|
||||
val filterIntervalCustom by screenModel.libraryPreferences.filterIntervalCustom.collectAsState()
|
||||
TriStateItem(
|
||||
label = stringResource(MR.strings.action_filter_interval_custom),
|
||||
state = filterIntervalCustom,
|
||||
@@ -229,7 +229,7 @@ private val displayModes = listOf(
|
||||
private fun ColumnScope.DisplayPage(
|
||||
screenModel: LibrarySettingsScreenModel,
|
||||
) {
|
||||
val displayMode by screenModel.libraryPreferences.displayMode().collectAsState()
|
||||
val displayMode by screenModel.libraryPreferences.displayMode.collectAsState()
|
||||
SettingsChipRow(MR.strings.action_display_mode) {
|
||||
displayModes.map { (titleRes, mode) ->
|
||||
FilterChip(
|
||||
@@ -244,9 +244,9 @@ private fun ColumnScope.DisplayPage(
|
||||
val configuration = LocalConfiguration.current
|
||||
val columnPreference = remember {
|
||||
if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
screenModel.libraryPreferences.landscapeColumns()
|
||||
screenModel.libraryPreferences.landscapeColumns
|
||||
} else {
|
||||
screenModel.libraryPreferences.portraitColumns()
|
||||
screenModel.libraryPreferences.portraitColumns
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,32 +268,32 @@ private fun ColumnScope.DisplayPage(
|
||||
HeadingItem(MR.strings.overlay_header)
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.action_display_download_badge),
|
||||
pref = screenModel.libraryPreferences.downloadBadge(),
|
||||
pref = screenModel.libraryPreferences.downloadBadge,
|
||||
)
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.action_display_unread_badge),
|
||||
pref = screenModel.libraryPreferences.unreadBadge(),
|
||||
pref = screenModel.libraryPreferences.unreadBadge,
|
||||
)
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.action_display_local_badge),
|
||||
pref = screenModel.libraryPreferences.localBadge(),
|
||||
pref = screenModel.libraryPreferences.localBadge,
|
||||
)
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.action_display_language_badge),
|
||||
pref = screenModel.libraryPreferences.languageBadge(),
|
||||
pref = screenModel.libraryPreferences.languageBadge,
|
||||
)
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.action_display_show_continue_reading_button),
|
||||
pref = screenModel.libraryPreferences.showContinueReadingButton(),
|
||||
pref = screenModel.libraryPreferences.showContinueReadingButton,
|
||||
)
|
||||
|
||||
HeadingItem(MR.strings.tabs_header)
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.action_display_show_tabs),
|
||||
pref = screenModel.libraryPreferences.categoryTabs(),
|
||||
pref = screenModel.libraryPreferences.categoryTabs,
|
||||
)
|
||||
CheckboxItem(
|
||||
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(
|
||||
onDismissRequest = onDismissRequest,
|
||||
|
||||
@@ -618,7 +618,7 @@ private fun MangaSummary(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val preferences = remember { Injekt.get<UiPreferences>() }
|
||||
val loadImages = remember { preferences.imagesInDescription().get() }
|
||||
val loadImages = remember { preferences.imagesInDescription.get() }
|
||||
val animProgress by animateFloatAsState(
|
||||
targetValue = if (expanded) 1f else 0f,
|
||||
label = "summary",
|
||||
|
||||
@@ -125,7 +125,7 @@ internal class PermissionStep : OnboardingStep {
|
||||
color = MaterialTheme.colorScheme.onPrimaryContainer,
|
||||
)
|
||||
|
||||
val crashlyticsPref = privacyPreferences.crashlytics()
|
||||
val crashlyticsPref = privacyPreferences.crashlytics
|
||||
val crashlytics by crashlyticsPref.collectAsState()
|
||||
PermissionSwitch(
|
||||
title = stringResource(MR.strings.onboarding_permission_crashlytics),
|
||||
@@ -134,7 +134,7 @@ internal class PermissionStep : OnboardingStep {
|
||||
onToggleChange = crashlyticsPref::set,
|
||||
)
|
||||
|
||||
val analyticsPref = privacyPreferences.analytics()
|
||||
val analyticsPref = privacyPreferences.analytics
|
||||
val analytics by analyticsPref.collectAsState()
|
||||
PermissionSwitch(
|
||||
title = stringResource(MR.strings.onboarding_permission_analytics),
|
||||
|
||||
@@ -30,7 +30,7 @@ import uy.kohesive.injekt.api.get
|
||||
|
||||
internal class StorageStep : OnboardingStep {
|
||||
|
||||
private val storagePref = Injekt.get<StoragePreferences>().baseStorageDirectory()
|
||||
private val storagePref = Injekt.get<StoragePreferences>().baseStorageDirectory
|
||||
|
||||
private var _isComplete by mutableStateOf(false)
|
||||
|
||||
|
||||
@@ -19,13 +19,13 @@ internal class ThemeStep : OnboardingStep {
|
||||
|
||||
@Composable
|
||||
override fun Content() {
|
||||
val themeModePref = uiPreferences.themeMode()
|
||||
val themeModePref = uiPreferences.themeMode
|
||||
val themeMode by themeModePref.collectAsState()
|
||||
|
||||
val appThemePref = uiPreferences.appTheme()
|
||||
val appThemePref = uiPreferences.appTheme
|
||||
val appTheme by appThemePref.collectAsState()
|
||||
|
||||
val amoledPref = uiPreferences.themeDarkAmoled()
|
||||
val amoledPref = uiPreferences.themeDarkAmoled
|
||||
val amoled by amoledPref.collectAsState()
|
||||
|
||||
Column {
|
||||
|
||||
@@ -27,6 +27,7 @@ sealed class Preference {
|
||||
override val title: String,
|
||||
override val subtitle: String? = null,
|
||||
override val enabled: Boolean = true,
|
||||
val widget: @Composable (() -> Unit)? = null,
|
||||
val onClick: (() -> Unit)? = null,
|
||||
) : PreferenceItem<String, Unit>() {
|
||||
override val icon: ImageVector? = null
|
||||
|
||||
@@ -147,6 +147,7 @@ internal fun PreferenceItem(
|
||||
title = item.title,
|
||||
subtitle = item.subtitle,
|
||||
icon = item.icon,
|
||||
widget = item.widget,
|
||||
onPreferenceClick = item.onClick,
|
||||
)
|
||||
}
|
||||
|
||||
+10
-10
@@ -99,7 +99,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = networkPreferences.verboseLogging(),
|
||||
preference = networkPreferences.verboseLogging,
|
||||
title = stringResource(MR.strings.pref_verbose_logging),
|
||||
subtitle = stringResource(MR.strings.pref_verbose_logging_summary),
|
||||
onValueChanged = {
|
||||
@@ -204,7 +204,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
val context = LocalContext.current
|
||||
val networkHelper = remember { Injekt.get<NetworkHelper>() }
|
||||
|
||||
val userAgentPref = networkPreferences.defaultUserAgent()
|
||||
val userAgentPref = networkPreferences.defaultUserAgent
|
||||
val userAgent by userAgentPref.collectAsState()
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
@@ -238,7 +238,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = networkPreferences.dohProvider(),
|
||||
preference = networkPreferences.dohProvider,
|
||||
entries = persistentMapOf(
|
||||
-1 to stringResource(MR.strings.disabled),
|
||||
PREF_DOH_CLOUDFLARE to "Cloudflare",
|
||||
@@ -319,12 +319,12 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = libraryPreferences.updateMangaTitles(),
|
||||
preference = libraryPreferences.updateMangaTitles,
|
||||
title = stringResource(MR.strings.pref_update_library_manga_titles),
|
||||
subtitle = stringResource(MR.strings.pref_update_library_manga_titles_summary),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = libraryPreferences.disallowNonAsciiFilenames(),
|
||||
preference = libraryPreferences.disallowNonAsciiFilenames,
|
||||
title = stringResource(MR.strings.pref_disallow_non_ascii_filenames),
|
||||
subtitle = stringResource(MR.strings.pref_disallow_non_ascii_filenames_details),
|
||||
),
|
||||
@@ -343,14 +343,14 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
uri?.let {
|
||||
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
context.contentResolver.takePersistableUriPermission(uri, flags)
|
||||
basePreferences.displayProfile().set(uri.toString())
|
||||
basePreferences.displayProfile.set(uri.toString())
|
||||
}
|
||||
}
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(MR.strings.pref_category_reader),
|
||||
preferenceItems = persistentListOf(
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = basePreferences.hardwareBitmapThreshold(),
|
||||
preference = basePreferences.hardwareBitmapThreshold,
|
||||
entries = GLUtil.CUSTOM_TEXTURE_LIMIT_OPTIONS
|
||||
.mapIndexed { index, option ->
|
||||
val display = if (index == 0) {
|
||||
@@ -370,13 +370,13 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
GLUtil.DEVICE_TEXTURE_LIMIT > GLUtil.SAFE_TEXTURE_LIMIT,
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = basePreferences.alwaysDecodeLongStripWithSSIV(),
|
||||
preference = basePreferences.alwaysDecodeLongStripWithSSIV,
|
||||
title = stringResource(MR.strings.pref_always_decode_long_strip_with_ssiv_2),
|
||||
subtitle = stringResource(MR.strings.pref_always_decode_long_strip_with_ssiv_summary),
|
||||
),
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(MR.strings.pref_display_profile),
|
||||
subtitle = basePreferences.displayProfile().get(),
|
||||
subtitle = basePreferences.displayProfile.get(),
|
||||
onClick = {
|
||||
chooseColorProfile.launch(arrayOf("*/*"))
|
||||
},
|
||||
@@ -391,7 +391,7 @@ object SettingsAdvancedScreen : SearchableSettings {
|
||||
): Preference.PreferenceGroup {
|
||||
val context = LocalContext.current
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val extensionInstallerPref = basePreferences.extensionInstaller()
|
||||
val extensionInstallerPref = basePreferences.extensionInstaller
|
||||
var shizukuMissing by rememberSaveable { mutableStateOf(false) }
|
||||
val trustExtension = remember { Injekt.get<TrustExtension>() }
|
||||
|
||||
|
||||
+8
-8
@@ -50,13 +50,13 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
): Preference.PreferenceGroup {
|
||||
val context = LocalContext.current
|
||||
|
||||
val themeModePref = uiPreferences.themeMode()
|
||||
val themeModePref = uiPreferences.themeMode
|
||||
val themeMode by themeModePref.collectAsState()
|
||||
|
||||
val appThemePref = uiPreferences.appTheme()
|
||||
val appThemePref = uiPreferences.appTheme
|
||||
val appTheme by appThemePref.collectAsState()
|
||||
|
||||
val amoledPref = uiPreferences.themeDarkAmoled()
|
||||
val amoledPref = uiPreferences.themeDarkAmoled
|
||||
val amoled by amoledPref.collectAsState()
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
@@ -103,7 +103,7 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
|
||||
val now = remember { LocalDate.now() }
|
||||
|
||||
val dateFormat by uiPreferences.dateFormat().collectAsState()
|
||||
val dateFormat by uiPreferences.dateFormat.collectAsState()
|
||||
val formattedNow = remember(dateFormat) {
|
||||
UiPreferences.dateFormat(dateFormat).format(now)
|
||||
}
|
||||
@@ -116,7 +116,7 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
onClick = { navigator.push(AppLanguageScreen()) },
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = uiPreferences.tabletUiMode(),
|
||||
preference = uiPreferences.tabletUiMode,
|
||||
entries = TabletUiMode.entries
|
||||
.associateWith { stringResource(it.titleRes) }
|
||||
.toImmutableMap(),
|
||||
@@ -127,7 +127,7 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = uiPreferences.dateFormat(),
|
||||
preference = uiPreferences.dateFormat,
|
||||
entries = DateFormats
|
||||
.associateWith {
|
||||
val formattedDate = UiPreferences.dateFormat(it).format(now)
|
||||
@@ -137,7 +137,7 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_date_format),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = uiPreferences.relativeTime(),
|
||||
preference = uiPreferences.relativeTime,
|
||||
title = stringResource(MR.strings.pref_relative_format),
|
||||
subtitle = stringResource(
|
||||
MR.strings.pref_relative_format_summary,
|
||||
@@ -146,7 +146,7 @@ object SettingsAppearanceScreen : SearchableSettings {
|
||||
),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = uiPreferences.imagesInDescription(),
|
||||
preference = uiPreferences.imagesInDescription,
|
||||
title = stringResource(MR.strings.pref_display_images_description),
|
||||
),
|
||||
),
|
||||
|
||||
+2
-2
@@ -43,7 +43,7 @@ object SettingsBrowseScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.label_sources),
|
||||
preferenceItems = persistentListOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = sourcePreferences.hideInLibraryItems(),
|
||||
preference = sourcePreferences.hideInLibraryItems,
|
||||
title = stringResource(MR.strings.pref_hide_in_library_items),
|
||||
),
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
@@ -59,7 +59,7 @@ object SettingsBrowseScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_category_nsfw_content),
|
||||
preferenceItems = persistentListOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = sourcePreferences.showNsfwSource(),
|
||||
preference = sourcePreferences.showNsfwSource,
|
||||
title = stringResource(MR.strings.pref_show_nsfw_source),
|
||||
subtitle = stringResource(MR.strings.requires_app_restart),
|
||||
onValueChanged = {
|
||||
|
||||
@@ -167,11 +167,11 @@ object SettingsDataScreen : SearchableSettings {
|
||||
storagePreferences: StoragePreferences,
|
||||
): Preference.PreferenceItem.TextPreference {
|
||||
val context = LocalContext.current
|
||||
val pickStorageLocation = storageLocationPicker(storagePreferences.baseStorageDirectory())
|
||||
val pickStorageLocation = storageLocationPicker(storagePreferences.baseStorageDirectory)
|
||||
|
||||
return Preference.PreferenceItem.TextPreference(
|
||||
title = stringResource(MR.strings.pref_storage_location),
|
||||
subtitle = storageLocationText(storagePreferences.baseStorageDirectory()),
|
||||
subtitle = storageLocationText(storagePreferences.baseStorageDirectory),
|
||||
onClick = {
|
||||
try {
|
||||
pickStorageLocation.launch(null)
|
||||
@@ -187,7 +187,7 @@ object SettingsDataScreen : SearchableSettings {
|
||||
val context = LocalContext.current
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
val lastAutoBackup by backupPreferences.lastAutoBackupTimestamp().collectAsState()
|
||||
val lastAutoBackup by backupPreferences.lastAutoBackupTimestamp.collectAsState()
|
||||
|
||||
val chooseBackup = rememberLauncherForActivityResult(
|
||||
object : ActivityResultContracts.GetContent() {
|
||||
@@ -254,7 +254,7 @@ object SettingsDataScreen : SearchableSettings {
|
||||
|
||||
// Automatic backups
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = backupPreferences.backupInterval(),
|
||||
preference = backupPreferences.backupInterval,
|
||||
entries = persistentMapOf(
|
||||
0 to stringResource(MR.strings.off),
|
||||
6 to stringResource(MR.strings.update_6hour),
|
||||
@@ -321,7 +321,7 @@ object SettingsDataScreen : SearchableSettings {
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = libraryPreferences.autoClearChapterCache(),
|
||||
preference = libraryPreferences.autoClearChapterCache,
|
||||
title = stringResource(MR.strings.pref_auto_clear_chapter_cache),
|
||||
),
|
||||
),
|
||||
|
||||
+16
-16
@@ -37,19 +37,19 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
val allCategories by getCategories.subscribe().collectAsState(initial = emptyList())
|
||||
|
||||
val downloadPreferences = remember { Injekt.get<DownloadPreferences>() }
|
||||
val parallelSourceLimit by downloadPreferences.parallelSourceLimit().collectAsState()
|
||||
val parallelPageLimit by downloadPreferences.parallelPageLimit().collectAsState()
|
||||
val parallelSourceLimit by downloadPreferences.parallelSourceLimit.collectAsState()
|
||||
val parallelPageLimit by downloadPreferences.parallelPageLimit.collectAsState()
|
||||
return listOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = downloadPreferences.downloadOnlyOverWifi(),
|
||||
preference = downloadPreferences.downloadOnlyOverWifi,
|
||||
title = stringResource(MR.strings.connected_to_wifi),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = downloadPreferences.saveChaptersAsCBZ(),
|
||||
preference = downloadPreferences.saveChaptersAsCBZ,
|
||||
title = stringResource(MR.strings.save_chapter_as_cbz),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = downloadPreferences.splitTallImages(),
|
||||
preference = downloadPreferences.splitTallImages,
|
||||
title = stringResource(MR.strings.split_tall_images),
|
||||
subtitle = stringResource(MR.strings.split_tall_images_summary),
|
||||
),
|
||||
@@ -57,14 +57,14 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
value = parallelSourceLimit,
|
||||
valueRange = 1..10,
|
||||
title = stringResource(MR.strings.pref_download_concurrent_sources),
|
||||
onValueChanged = { downloadPreferences.parallelSourceLimit().set(it) },
|
||||
onValueChanged = { downloadPreferences.parallelSourceLimit.set(it) },
|
||||
),
|
||||
Preference.PreferenceItem.SliderPreference(
|
||||
value = parallelPageLimit,
|
||||
valueRange = 1..15,
|
||||
title = stringResource(MR.strings.pref_download_concurrent_pages),
|
||||
subtitle = stringResource(MR.strings.pref_download_concurrent_pages_summary),
|
||||
onValueChanged = { downloadPreferences.parallelPageLimit().set(it) },
|
||||
onValueChanged = { downloadPreferences.parallelPageLimit.set(it) },
|
||||
),
|
||||
getDeleteChaptersGroup(
|
||||
downloadPreferences = downloadPreferences,
|
||||
@@ -87,11 +87,11 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_category_delete_chapters),
|
||||
preferenceItems = persistentListOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = downloadPreferences.removeAfterMarkedAsRead(),
|
||||
preference = downloadPreferences.removeAfterMarkedAsRead,
|
||||
title = stringResource(MR.strings.pref_remove_after_marked_as_read),
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = downloadPreferences.removeAfterReadSlots(),
|
||||
preference = downloadPreferences.removeAfterReadSlots,
|
||||
entries = persistentMapOf(
|
||||
-1 to stringResource(MR.strings.disabled),
|
||||
0 to stringResource(MR.strings.last_read_chapter),
|
||||
@@ -103,7 +103,7 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_remove_after_read),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = downloadPreferences.removeBookmarkedChapters(),
|
||||
preference = downloadPreferences.removeBookmarkedChapters,
|
||||
title = stringResource(MR.strings.pref_remove_bookmarked_chapters),
|
||||
),
|
||||
getExcludedCategoriesPreference(
|
||||
@@ -120,7 +120,7 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
categories: () -> List<Category>,
|
||||
): Preference.PreferenceItem.MultiSelectListPreference {
|
||||
return Preference.PreferenceItem.MultiSelectListPreference(
|
||||
preference = downloadPreferences.removeExcludeCategories(),
|
||||
preference = downloadPreferences.removeExcludeCategories,
|
||||
entries = categories()
|
||||
.associate { it.id.toString() to it.visualName }
|
||||
.toImmutableMap(),
|
||||
@@ -133,10 +133,10 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
downloadPreferences: DownloadPreferences,
|
||||
allCategories: List<Category>,
|
||||
): Preference.PreferenceGroup {
|
||||
val downloadNewChaptersPref = downloadPreferences.downloadNewChapters()
|
||||
val downloadNewUnreadChaptersOnlyPref = downloadPreferences.downloadNewUnreadChaptersOnly()
|
||||
val downloadNewChapterCategoriesPref = downloadPreferences.downloadNewChapterCategories()
|
||||
val downloadNewChapterCategoriesExcludePref = downloadPreferences.downloadNewChapterCategoriesExclude()
|
||||
val downloadNewChaptersPref = downloadPreferences.downloadNewChapters
|
||||
val downloadNewUnreadChaptersOnlyPref = downloadPreferences.downloadNewUnreadChaptersOnly
|
||||
val downloadNewChapterCategoriesPref = downloadPreferences.downloadNewChapterCategories
|
||||
val downloadNewChapterCategoriesExcludePref = downloadPreferences.downloadNewChapterCategoriesExclude
|
||||
|
||||
val downloadNewChapters by downloadNewChaptersPref.collectAsState()
|
||||
|
||||
@@ -194,7 +194,7 @@ object SettingsDownloadScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.download_ahead),
|
||||
preferenceItems = persistentListOf(
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = downloadPreferences.autoDownloadWhileReading(),
|
||||
preference = downloadPreferences.autoDownloadWhileReading,
|
||||
entries = listOf(0, 2, 3, 5, 10)
|
||||
.associateWith {
|
||||
if (it == 0) {
|
||||
|
||||
+14
-14
@@ -73,7 +73,7 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
val userCategoriesCount = allCategories.filterNot(Category::isSystemCategory).size
|
||||
|
||||
// For default category
|
||||
val ids = listOf(libraryPreferences.defaultCategory().defaultValue()) +
|
||||
val ids = listOf(libraryPreferences.defaultCategory.defaultValue()) +
|
||||
allCategories.fastMap { it.id.toInt() }
|
||||
val labels = listOf(stringResource(MR.strings.default_category_summary)) +
|
||||
allCategories.fastMap { it.visualName }
|
||||
@@ -91,12 +91,12 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
onClick = { navigator.push(CategoryScreen()) },
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = libraryPreferences.defaultCategory(),
|
||||
preference = libraryPreferences.defaultCategory,
|
||||
entries = ids.zip(labels).toMap().toImmutableMap(),
|
||||
title = stringResource(MR.strings.default_category),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = libraryPreferences.categorizedDisplaySettings(),
|
||||
preference = libraryPreferences.categorizedDisplaySettings,
|
||||
title = stringResource(MR.strings.categorized_display_settings),
|
||||
onValueChanged = {
|
||||
if (!it) {
|
||||
@@ -118,9 +118,9 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
): Preference.PreferenceGroup {
|
||||
val context = LocalContext.current
|
||||
|
||||
val autoUpdateIntervalPref = libraryPreferences.autoUpdateInterval()
|
||||
val autoUpdateCategoriesPref = libraryPreferences.updateCategories()
|
||||
val autoUpdateCategoriesExcludePref = libraryPreferences.updateCategoriesExclude()
|
||||
val autoUpdateIntervalPref = libraryPreferences.autoUpdateInterval
|
||||
val autoUpdateCategoriesPref = libraryPreferences.updateCategories
|
||||
val autoUpdateCategoriesExcludePref = libraryPreferences.updateCategoriesExclude
|
||||
|
||||
val autoUpdateInterval by autoUpdateIntervalPref.collectAsState()
|
||||
|
||||
@@ -164,7 +164,7 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.MultiSelectListPreference(
|
||||
preference = libraryPreferences.autoUpdateDeviceRestrictions(),
|
||||
preference = libraryPreferences.autoUpdateDeviceRestrictions,
|
||||
entries = persistentMapOf(
|
||||
DEVICE_ONLY_ON_WIFI to stringResource(MR.strings.connected_to_wifi),
|
||||
DEVICE_NETWORK_NOT_METERED to stringResource(MR.strings.network_not_metered),
|
||||
@@ -189,12 +189,12 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
onClick = { showCategoriesDialog = true },
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = libraryPreferences.autoUpdateMetadata(),
|
||||
preference = libraryPreferences.autoUpdateMetadata,
|
||||
title = stringResource(MR.strings.pref_library_update_refresh_metadata),
|
||||
subtitle = stringResource(MR.strings.pref_library_update_refresh_metadata_summary),
|
||||
),
|
||||
Preference.PreferenceItem.MultiSelectListPreference(
|
||||
preference = libraryPreferences.autoUpdateMangaRestrictions(),
|
||||
preference = libraryPreferences.autoUpdateMangaRestrictions,
|
||||
entries = persistentMapOf(
|
||||
MANGA_HAS_UNREAD to stringResource(MR.strings.pref_update_only_completely_read),
|
||||
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),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = libraryPreferences.newShowUpdatesCount(),
|
||||
preference = libraryPreferences.newShowUpdatesCount,
|
||||
title = stringResource(MR.strings.pref_library_update_show_tab_badge),
|
||||
),
|
||||
),
|
||||
@@ -219,7 +219,7 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_behavior),
|
||||
preferenceItems = persistentListOf(
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = libraryPreferences.swipeToStartAction(),
|
||||
preference = libraryPreferences.swipeToStartAction,
|
||||
entries = persistentMapOf(
|
||||
LibraryPreferences.ChapterSwipeAction.Disabled to
|
||||
stringResource(MR.strings.disabled),
|
||||
@@ -233,7 +233,7 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_chapter_swipe_start),
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = libraryPreferences.swipeToEndAction(),
|
||||
preference = libraryPreferences.swipeToEndAction,
|
||||
entries = persistentMapOf(
|
||||
LibraryPreferences.ChapterSwipeAction.Disabled to
|
||||
stringResource(MR.strings.disabled),
|
||||
@@ -247,7 +247,7 @@ object SettingsLibraryScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_chapter_swipe_end),
|
||||
),
|
||||
Preference.PreferenceItem.MultiSelectListPreference(
|
||||
preference = libraryPreferences.markDuplicateReadChapterAsRead(),
|
||||
preference = libraryPreferences.markDuplicateReadChapterAsRead,
|
||||
entries = persistentMapOf(
|
||||
MARK_DUPLICATE_CHAPTER_READ_EXISTING to
|
||||
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),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = libraryPreferences.hideMissingChapters(),
|
||||
preference = libraryPreferences.hideMissingChapters,
|
||||
title = stringResource(MR.strings.pref_hide_missing_chapter_indicators),
|
||||
),
|
||||
),
|
||||
|
||||
+46
-46
@@ -33,14 +33,14 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
|
||||
return listOf(
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = readerPref.defaultReadingMode(),
|
||||
preference = readerPref.defaultReadingMode,
|
||||
entries = ReadingMode.entries.drop(1)
|
||||
.associate { it.flagValue to stringResource(it.stringRes) }
|
||||
.toImmutableMap(),
|
||||
title = stringResource(MR.strings.pref_viewer_type),
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = readerPref.doubleTapAnimSpeed(),
|
||||
preference = readerPref.doubleTapAnimSpeed,
|
||||
entries = persistentMapOf(
|
||||
1 to stringResource(MR.strings.double_tap_anim_speed_0),
|
||||
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),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPref.showReadingMode(),
|
||||
preference = readerPref.showReadingMode,
|
||||
title = stringResource(MR.strings.pref_show_reading_mode),
|
||||
subtitle = stringResource(MR.strings.pref_show_reading_mode_summary),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPref.showNavigationOverlayOnStart(),
|
||||
preference = readerPref.showNavigationOverlayOnStart,
|
||||
title = stringResource(MR.strings.pref_show_navigation_mode),
|
||||
subtitle = stringResource(MR.strings.pref_show_navigation_mode_summary),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPref.pageTransitions(),
|
||||
preference = readerPref.pageTransitions,
|
||||
title = stringResource(MR.strings.pref_page_transitions),
|
||||
),
|
||||
getDisplayGroup(readerPreferences = readerPref),
|
||||
@@ -74,20 +74,20 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
|
||||
@Composable
|
||||
private fun getDisplayGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
|
||||
val fullscreenPref = readerPreferences.fullscreen()
|
||||
val fullscreenPref = readerPreferences.fullscreen
|
||||
val fullscreen by fullscreenPref.collectAsState()
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(MR.strings.pref_category_display),
|
||||
preferenceItems = persistentListOf(
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = readerPreferences.defaultOrientationType(),
|
||||
preference = readerPreferences.defaultOrientationType,
|
||||
entries = ReaderOrientation.entries.drop(1)
|
||||
.associate { it.flagValue to stringResource(it.stringRes) }
|
||||
.toImmutableMap(),
|
||||
title = stringResource(MR.strings.pref_rotation_type),
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = readerPreferences.readerTheme(),
|
||||
preference = readerPreferences.readerTheme,
|
||||
entries = persistentMapOf(
|
||||
1 to stringResource(MR.strings.black_background),
|
||||
2 to stringResource(MR.strings.gray_background),
|
||||
@@ -101,16 +101,16 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_fullscreen),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.drawUnderCutout(),
|
||||
preference = readerPreferences.drawUnderCutout,
|
||||
title = stringResource(MR.strings.pref_cutout_short),
|
||||
enabled = LocalView.current.hasDisplayCutout() && fullscreen,
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.keepScreenOn(),
|
||||
preference = readerPreferences.keepScreenOn,
|
||||
title = stringResource(MR.strings.pref_keep_screen_on),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.showPageNumber(),
|
||||
preference = readerPreferences.showPageNumber,
|
||||
title = stringResource(MR.strings.pref_show_page_number),
|
||||
),
|
||||
),
|
||||
@@ -119,21 +119,21 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
|
||||
@Composable
|
||||
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 flashIntervalPref = readerPreferences.flashPageInterval()
|
||||
val flashIntervalPref = readerPreferences.flashPageInterval
|
||||
val flashInterval by flashIntervalPref.collectAsState()
|
||||
|
||||
val flashColorPref = readerPreferences.flashColor()
|
||||
val flashColorPref = readerPreferences.flashColor
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
title = "E-Ink",
|
||||
preferenceItems = persistentListOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.flashOnPageChange(),
|
||||
preference = readerPreferences.flashOnPageChange,
|
||||
title = stringResource(MR.strings.pref_flash_page),
|
||||
subtitle = stringResource(MR.strings.pref_flash_page_summ),
|
||||
),
|
||||
@@ -174,19 +174,19 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_category_reading),
|
||||
preferenceItems = persistentListOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.skipRead(),
|
||||
preference = readerPreferences.skipRead,
|
||||
title = stringResource(MR.strings.pref_skip_read_chapters),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.skipFiltered(),
|
||||
preference = readerPreferences.skipFiltered,
|
||||
title = stringResource(MR.strings.pref_skip_filtered_chapters),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.skipDupe(),
|
||||
preference = readerPreferences.skipDupe,
|
||||
title = stringResource(MR.strings.pref_skip_dupe_chapters),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.alwaysShowChapterTransition(),
|
||||
preference = readerPreferences.alwaysShowChapterTransition,
|
||||
title = stringResource(MR.strings.pref_always_show_chapter_transition),
|
||||
),
|
||||
),
|
||||
@@ -195,10 +195,10 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
|
||||
@Composable
|
||||
private fun getPagedGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
|
||||
val navModePref = readerPreferences.navigationModePager()
|
||||
val imageScaleTypePref = readerPreferences.imageScaleType()
|
||||
val dualPageSplitPref = readerPreferences.dualPageSplitPaged()
|
||||
val rotateToFitPref = readerPreferences.dualPageRotateToFit()
|
||||
val navModePref = readerPreferences.navigationModePager
|
||||
val imageScaleTypePref = readerPreferences.imageScaleType
|
||||
val dualPageSplitPref = readerPreferences.dualPageSplitPaged
|
||||
val rotateToFitPref = readerPreferences.dualPageRotateToFit
|
||||
|
||||
val navMode by navModePref.collectAsState()
|
||||
val imageScaleType by imageScaleTypePref.collectAsState()
|
||||
@@ -217,7 +217,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_viewer_nav),
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = readerPreferences.pagerNavInverted(),
|
||||
preference = readerPreferences.pagerNavInverted,
|
||||
entries = persistentListOf(
|
||||
ReaderPreferences.TappingInvertMode.NONE,
|
||||
ReaderPreferences.TappingInvertMode.HORIZONTAL,
|
||||
@@ -238,7 +238,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_image_scale_type),
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = readerPreferences.zoomStart(),
|
||||
preference = readerPreferences.zoomStart,
|
||||
entries = ReaderPreferences.ZoomStart
|
||||
.mapIndexed { index, it -> index + 1 to stringResource(it) }
|
||||
.toMap()
|
||||
@@ -246,16 +246,16 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_zoom_start),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.cropBorders(),
|
||||
preference = readerPreferences.cropBorders,
|
||||
title = stringResource(MR.strings.pref_crop_borders),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.landscapeZoom(),
|
||||
preference = readerPreferences.landscapeZoom,
|
||||
title = stringResource(MR.strings.pref_landscape_zoom),
|
||||
enabled = imageScaleType == 1,
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.navigateToPan(),
|
||||
preference = readerPreferences.navigateToPan,
|
||||
title = stringResource(MR.strings.pref_navigate_pan),
|
||||
enabled = navMode != 5,
|
||||
),
|
||||
@@ -268,7 +268,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.dualPageInvertPaged(),
|
||||
preference = readerPreferences.dualPageInvertPaged,
|
||||
title = stringResource(MR.strings.pref_dual_page_invert),
|
||||
subtitle = stringResource(MR.strings.pref_dual_page_invert_summary),
|
||||
enabled = dualPageSplit,
|
||||
@@ -282,7 +282,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.dualPageRotateToFitInvert(),
|
||||
preference = readerPreferences.dualPageRotateToFitInvert,
|
||||
title = stringResource(MR.strings.pref_page_rotate_invert),
|
||||
enabled = rotateToFit,
|
||||
),
|
||||
@@ -294,10 +294,10 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
private fun getWebtoonGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
|
||||
val numberFormat = remember { NumberFormat.getPercentInstance() }
|
||||
|
||||
val navModePref = readerPreferences.navigationModeWebtoon()
|
||||
val dualPageSplitPref = readerPreferences.dualPageSplitWebtoon()
|
||||
val rotateToFitPref = readerPreferences.dualPageRotateToFitWebtoon()
|
||||
val webtoonSidePaddingPref = readerPreferences.webtoonSidePadding()
|
||||
val navModePref = readerPreferences.navigationModeWebtoon
|
||||
val dualPageSplitPref = readerPreferences.dualPageSplitWebtoon
|
||||
val rotateToFitPref = readerPreferences.dualPageRotateToFitWebtoon
|
||||
val webtoonSidePaddingPref = readerPreferences.webtoonSidePadding
|
||||
|
||||
val navMode by navModePref.collectAsState()
|
||||
val dualPageSplit by dualPageSplitPref.collectAsState()
|
||||
@@ -316,7 +316,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_viewer_nav),
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = readerPreferences.webtoonNavInverted(),
|
||||
preference = readerPreferences.webtoonNavInverted,
|
||||
entries = persistentListOf(
|
||||
ReaderPreferences.TappingInvertMode.NONE,
|
||||
ReaderPreferences.TappingInvertMode.HORIZONTAL,
|
||||
@@ -338,7 +338,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
onValueChanged = { webtoonSidePaddingPref.set(it) },
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = readerPreferences.readerHideThreshold(),
|
||||
preference = readerPreferences.readerHideThreshold,
|
||||
entries = persistentMapOf(
|
||||
ReaderPreferences.ReaderHideThreshold.HIGHEST to stringResource(MR.strings.pref_highest),
|
||||
ReaderPreferences.ReaderHideThreshold.HIGH to stringResource(MR.strings.pref_high),
|
||||
@@ -348,7 +348,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_hide_threshold),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.cropBordersWebtoon(),
|
||||
preference = readerPreferences.cropBordersWebtoon,
|
||||
title = stringResource(MR.strings.pref_crop_borders),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
@@ -360,7 +360,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.dualPageInvertWebtoon(),
|
||||
preference = readerPreferences.dualPageInvertWebtoon,
|
||||
title = stringResource(MR.strings.pref_dual_page_invert),
|
||||
subtitle = stringResource(MR.strings.pref_dual_page_invert_summary),
|
||||
enabled = dualPageSplit,
|
||||
@@ -374,16 +374,16 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.dualPageRotateToFitInvertWebtoon(),
|
||||
preference = readerPreferences.dualPageRotateToFitInvertWebtoon,
|
||||
title = stringResource(MR.strings.pref_page_rotate_invert),
|
||||
enabled = rotateToFit,
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.webtoonDoubleTapZoomEnabled(),
|
||||
preference = readerPreferences.webtoonDoubleTapZoomEnabled,
|
||||
title = stringResource(MR.strings.pref_double_tap_zoom),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.webtoonDisableZoomOut(),
|
||||
preference = readerPreferences.webtoonDisableZoomOut,
|
||||
title = stringResource(MR.strings.pref_webtoon_disable_zoom_out),
|
||||
),
|
||||
),
|
||||
@@ -392,7 +392,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
|
||||
@Composable
|
||||
private fun getNavigationGroup(readerPreferences: ReaderPreferences): Preference.PreferenceGroup {
|
||||
val readWithVolumeKeysPref = readerPreferences.readWithVolumeKeys()
|
||||
val readWithVolumeKeysPref = readerPreferences.readWithVolumeKeys
|
||||
val readWithVolumeKeys by readWithVolumeKeysPref.collectAsState()
|
||||
return Preference.PreferenceGroup(
|
||||
title = stringResource(MR.strings.pref_reader_navigation),
|
||||
@@ -402,7 +402,7 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_read_with_volume_keys),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.readWithVolumeKeysInverted(),
|
||||
preference = readerPreferences.readWithVolumeKeysInverted,
|
||||
title = stringResource(MR.strings.pref_read_with_volume_keys_inverted),
|
||||
enabled = readWithVolumeKeys,
|
||||
),
|
||||
@@ -416,11 +416,11 @@ object SettingsReaderScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_reader_actions),
|
||||
preferenceItems = persistentListOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.readWithLongTap(),
|
||||
preference = readerPreferences.readWithLongTap,
|
||||
title = stringResource(MR.strings.pref_read_with_long_tap),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = readerPreferences.folderPerManga(),
|
||||
preference = readerPreferences.folderPerManga,
|
||||
title = stringResource(MR.strings.pref_create_folder_per_manga),
|
||||
subtitle = stringResource(MR.strings.pref_create_folder_per_manga_summary),
|
||||
),
|
||||
|
||||
+6
-6
@@ -45,7 +45,7 @@ object SettingsSecurityScreen : SearchableSettings {
|
||||
): Preference.PreferenceGroup {
|
||||
val context = LocalContext.current
|
||||
val authSupported = remember { context.isAuthenticationSupported() }
|
||||
val useAuthPref = securityPreferences.useAuthenticator()
|
||||
val useAuthPref = securityPreferences.useAuthenticator
|
||||
val useAuth by useAuthPref.collectAsState()
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
@@ -62,7 +62,7 @@ object SettingsSecurityScreen : SearchableSettings {
|
||||
},
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = securityPreferences.lockAppAfter(),
|
||||
preference = securityPreferences.lockAppAfter,
|
||||
entries = LockAfterValues
|
||||
.associateWith {
|
||||
when (it) {
|
||||
@@ -82,11 +82,11 @@ object SettingsSecurityScreen : SearchableSettings {
|
||||
),
|
||||
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = securityPreferences.hideNotificationContent(),
|
||||
preference = securityPreferences.hideNotificationContent,
|
||||
title = stringResource(MR.strings.hide_notification_content),
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = securityPreferences.secureScreen(),
|
||||
preference = securityPreferences.secureScreen,
|
||||
entries = SecurityPreferences.SecureScreenMode.entries
|
||||
.associateWith { stringResource(it.titleRes) }
|
||||
.toImmutableMap(),
|
||||
@@ -105,12 +105,12 @@ object SettingsSecurityScreen : SearchableSettings {
|
||||
title = stringResource(MR.strings.pref_firebase),
|
||||
preferenceItems = persistentListOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = privacyPreferences.crashlytics(),
|
||||
preference = privacyPreferences.crashlytics,
|
||||
title = stringResource(MR.strings.onboarding_permission_crashlytics),
|
||||
subtitle = stringResource(MR.strings.onboarding_permission_crashlytics_description),
|
||||
),
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = privacyPreferences.analytics(),
|
||||
preference = privacyPreferences.analytics,
|
||||
title = stringResource(MR.strings.onboarding_permission_analytics),
|
||||
subtitle = stringResource(MR.strings.onboarding_permission_analytics_description),
|
||||
),
|
||||
|
||||
+3
-3
@@ -90,7 +90,7 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
val trackPreferences = remember { Injekt.get<TrackPreferences>() }
|
||||
val trackerManager = remember { Injekt.get<TrackerManager>() }
|
||||
val sourceManager = remember { Injekt.get<SourceManager>() }
|
||||
val autoTrackStatePref = trackPreferences.autoUpdateTrackOnMarkRead()
|
||||
val autoTrackStatePref = trackPreferences.autoUpdateTrackOnMarkRead
|
||||
|
||||
var dialog by remember { mutableStateOf<Any?>(null) }
|
||||
dialog?.run {
|
||||
@@ -128,11 +128,11 @@ object SettingsTrackingScreen : SearchableSettings {
|
||||
|
||||
return listOf(
|
||||
Preference.PreferenceItem.SwitchPreference(
|
||||
preference = trackPreferences.autoUpdateTrack(),
|
||||
preference = trackPreferences.autoUpdateTrack,
|
||||
title = stringResource(MR.strings.pref_auto_update_manga_sync),
|
||||
),
|
||||
Preference.PreferenceItem.ListPreference(
|
||||
preference = trackPreferences.autoUpdateTrackOnMarkRead(),
|
||||
preference = trackPreferences.autoUpdateTrackOnMarkRead,
|
||||
entries = AutoTrackState.entries
|
||||
.associateWith { stringResource(it.titleRes) }
|
||||
.toPersistentMap(),
|
||||
|
||||
@@ -275,7 +275,7 @@ object AboutScreen : Screen() {
|
||||
)
|
||||
.toDateTimestampString(
|
||||
UiPreferences.dateFormat(
|
||||
Injekt.get<UiPreferences>().dateFormat().get(),
|
||||
Injekt.get<UiPreferences>().dateFormat.get(),
|
||||
),
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
|
||||
+42
@@ -1,24 +1,38 @@
|
||||
package eu.kanade.presentation.more.settings.screen.debug
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Autorenew
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.produceState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.profileinstaller.ProfileVerifier
|
||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.presentation.more.settings.Preference
|
||||
import eu.kanade.presentation.more.settings.PreferenceScaffold
|
||||
import eu.kanade.presentation.more.settings.screen.about.AboutScreen
|
||||
import eu.kanade.presentation.util.Screen
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.WebViewUtil
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
import kotlinx.collections.immutable.mutate
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.guava.await
|
||||
import kotlinx.coroutines.launch
|
||||
import mihon.core.common.FeatureFlags
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.util.collectAsState
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class DebugInfoScreen : Screen() {
|
||||
|
||||
@@ -47,6 +61,12 @@ class DebugInfoScreen : Screen() {
|
||||
|
||||
@Composable
|
||||
private fun getAppInfoGroup(): Preference.PreferenceGroup {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
val installationIdPref = remember { Injekt.get<BasePreferences>().installationId }
|
||||
val installationId by installationIdPref.collectAsState()
|
||||
|
||||
return Preference.PreferenceGroup(
|
||||
title = "App info",
|
||||
preferenceItems = persistentListOf(
|
||||
@@ -58,6 +78,28 @@ class DebugInfoScreen : Screen() {
|
||||
title = "Build time",
|
||||
subtitle = AboutScreen.getFormattedBuildTime(),
|
||||
),
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = "Installation ID",
|
||||
subtitle = installationId,
|
||||
widget = {
|
||||
IconButton(
|
||||
onClick = {
|
||||
scope.launch {
|
||||
installationIdPref.set(FeatureFlags.newInstallationId())
|
||||
}
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Autorenew,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
},
|
||||
onClick = {
|
||||
context.copyToClipboard(installationId, installationId)
|
||||
},
|
||||
),
|
||||
getProfileVerifierPreference(),
|
||||
Preference.PreferenceItem.TextPreference(
|
||||
title = "WebView version",
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ class WorkerInfoScreen : Screen() {
|
||||
)
|
||||
.toDateTimestampString(
|
||||
UiPreferences.dateFormat(
|
||||
Injekt.get<UiPreferences>().dateFormat().get(),
|
||||
Injekt.get<UiPreferences>().dateFormat.get(),
|
||||
),
|
||||
)
|
||||
appendLine("Next scheduled run: $timestamp")
|
||||
|
||||
@@ -24,10 +24,10 @@ class DisplayRefreshHost {
|
||||
internal var currentDisplayRefresh by mutableStateOf(false)
|
||||
private val readerPreferences = Injekt.get<ReaderPreferences>()
|
||||
|
||||
internal val flashMillis = readerPreferences.flashDurationMillis()
|
||||
internal val flashMode = readerPreferences.flashColor()
|
||||
internal val flashMillis = readerPreferences.flashDurationMillis
|
||||
internal val flashMode = readerPreferences.flashColor
|
||||
|
||||
internal val flashIntervalPref = readerPreferences.flashPageInterval()
|
||||
internal val flashIntervalPref = readerPreferences.flashPageInterval
|
||||
|
||||
// Internal State for Flash
|
||||
private var flashInterval = flashIntervalPref.get()
|
||||
|
||||
@@ -22,10 +22,10 @@ import tachiyomi.presentation.core.util.collectAsState
|
||||
|
||||
@Composable
|
||||
internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel) {
|
||||
val customBrightness by screenModel.preferences.customBrightness().collectAsState()
|
||||
val customBrightness by screenModel.preferences.customBrightness.collectAsState()
|
||||
CheckboxItem(
|
||||
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.
|
||||
*/
|
||||
if (customBrightness) {
|
||||
val customBrightnessValue by screenModel.preferences.customBrightnessValue().collectAsState()
|
||||
val customBrightnessValue by screenModel.preferences.customBrightnessValue.collectAsState()
|
||||
SliderItem(
|
||||
value = customBrightnessValue,
|
||||
valueRange = -75..100,
|
||||
steps = 0,
|
||||
label = stringResource(MR.strings.pref_custom_brightness),
|
||||
onChange = { screenModel.preferences.customBrightnessValue().set(it) },
|
||||
onChange = { screenModel.preferences.customBrightnessValue.set(it) },
|
||||
pillColor = MaterialTheme.colorScheme.surfaceContainerHighest,
|
||||
)
|
||||
}
|
||||
|
||||
val colorFilter by screenModel.preferences.colorFilter().collectAsState()
|
||||
val colorFilter by screenModel.preferences.colorFilter.collectAsState()
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_custom_color_filter),
|
||||
pref = screenModel.preferences.colorFilter(),
|
||||
pref = screenModel.preferences.colorFilter,
|
||||
)
|
||||
if (colorFilter) {
|
||||
val colorFilterValue by screenModel.preferences.colorFilterValue().collectAsState()
|
||||
val colorFilterValue by screenModel.preferences.colorFilterValue.collectAsState()
|
||||
SliderItem(
|
||||
value = colorFilterValue.red,
|
||||
valueRange = 0..255,
|
||||
steps = 0,
|
||||
label = stringResource(MR.strings.color_filter_r_value),
|
||||
onChange = { newRValue ->
|
||||
screenModel.preferences.colorFilterValue().getAndSet {
|
||||
screenModel.preferences.colorFilterValue.getAndSet {
|
||||
getColorValue(it, newRValue, RED_MASK, 16)
|
||||
}
|
||||
},
|
||||
@@ -71,7 +71,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
steps = 0,
|
||||
label = stringResource(MR.strings.color_filter_g_value),
|
||||
onChange = { newGValue ->
|
||||
screenModel.preferences.colorFilterValue().getAndSet {
|
||||
screenModel.preferences.colorFilterValue.getAndSet {
|
||||
getColorValue(it, newGValue, GREEN_MASK, 8)
|
||||
}
|
||||
},
|
||||
@@ -83,7 +83,7 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
steps = 0,
|
||||
label = stringResource(MR.strings.color_filter_b_value),
|
||||
onChange = { newBValue ->
|
||||
screenModel.preferences.colorFilterValue().getAndSet {
|
||||
screenModel.preferences.colorFilterValue.getAndSet {
|
||||
getColorValue(it, newBValue, BLUE_MASK, 0)
|
||||
}
|
||||
},
|
||||
@@ -95,19 +95,19 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
steps = 0,
|
||||
label = stringResource(MR.strings.color_filter_a_value),
|
||||
onChange = { newAValue ->
|
||||
screenModel.preferences.colorFilterValue().getAndSet {
|
||||
screenModel.preferences.colorFilterValue.getAndSet {
|
||||
getColorValue(it, newAValue, ALPHA_MASK, 24)
|
||||
}
|
||||
},
|
||||
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) {
|
||||
ColorFilterMode.mapIndexed { index, it ->
|
||||
FilterChip(
|
||||
selected = colorFilterMode == index,
|
||||
onClick = { screenModel.preferences.colorFilterMode().set(index) },
|
||||
onClick = { screenModel.preferences.colorFilterMode.set(index) },
|
||||
label = { Text(stringResource(it.first)) },
|
||||
)
|
||||
}
|
||||
@@ -116,11 +116,11 @@ internal fun ColumnScope.ColorFilterPage(screenModel: ReaderSettingsScreenModel)
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_grayscale),
|
||||
pref = screenModel.preferences.grayscale(),
|
||||
pref = screenModel.preferences.grayscale,
|
||||
)
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_inverted_colors),
|
||||
pref = screenModel.preferences.invertedColors(),
|
||||
pref = screenModel.preferences.invertedColors,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -33,24 +33,24 @@ private val flashColors = listOf(
|
||||
|
||||
@Composable
|
||||
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 flashIntervalPref = screenModel.preferences.flashPageInterval()
|
||||
val flashIntervalPref = screenModel.preferences.flashPageInterval
|
||||
val flashInterval by flashIntervalPref.collectAsState()
|
||||
|
||||
val flashColorPref = screenModel.preferences.flashColor()
|
||||
val flashColorPref = screenModel.preferences.flashColor
|
||||
val flashColor by flashColorPref.collectAsState()
|
||||
|
||||
SettingsChipRow(MR.strings.pref_reader_theme) {
|
||||
themes.map { (labelRes, value) ->
|
||||
FilterChip(
|
||||
selected = readerTheme == value,
|
||||
onClick = { screenModel.preferences.readerTheme().set(value) },
|
||||
onClick = { screenModel.preferences.readerTheme.set(value) },
|
||||
label = { Text(stringResource(labelRes)) },
|
||||
)
|
||||
}
|
||||
@@ -58,45 +58,45 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) {
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_show_page_number),
|
||||
pref = screenModel.preferences.showPageNumber(),
|
||||
pref = screenModel.preferences.showPageNumber,
|
||||
)
|
||||
|
||||
CheckboxItem(
|
||||
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) {
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_cutout_short),
|
||||
pref = screenModel.preferences.drawUnderCutout(),
|
||||
pref = screenModel.preferences.drawUnderCutout,
|
||||
)
|
||||
}
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_keep_screen_on),
|
||||
pref = screenModel.preferences.keepScreenOn(),
|
||||
pref = screenModel.preferences.keepScreenOn,
|
||||
)
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_read_with_long_tap),
|
||||
pref = screenModel.preferences.readWithLongTap(),
|
||||
pref = screenModel.preferences.readWithLongTap,
|
||||
)
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_always_show_chapter_transition),
|
||||
pref = screenModel.preferences.alwaysShowChapterTransition(),
|
||||
pref = screenModel.preferences.alwaysShowChapterTransition,
|
||||
)
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_page_transitions),
|
||||
pref = screenModel.preferences.pageTransitions(),
|
||||
pref = screenModel.preferences.pageTransitions,
|
||||
)
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_flash_page),
|
||||
pref = screenModel.preferences.flashOnPageChange(),
|
||||
pref = screenModel.preferences.flashOnPageChange,
|
||||
)
|
||||
if (flashPageState) {
|
||||
SliderItem(
|
||||
|
||||
@@ -63,32 +63,32 @@ internal fun ColumnScope.ReadingModePage(screenModel: ReaderSettingsScreenModel)
|
||||
private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenModel) {
|
||||
HeadingItem(MR.strings.pager_viewer)
|
||||
|
||||
val navigationModePager by screenModel.preferences.navigationModePager().collectAsState()
|
||||
val pagerNavInverted by screenModel.preferences.pagerNavInverted().collectAsState()
|
||||
val navigationModePager by screenModel.preferences.navigationModePager.collectAsState()
|
||||
val pagerNavInverted by screenModel.preferences.pagerNavInverted.collectAsState()
|
||||
TapZonesItems(
|
||||
selected = navigationModePager,
|
||||
onSelect = screenModel.preferences.navigationModePager()::set,
|
||||
onSelect = screenModel.preferences.navigationModePager::set,
|
||||
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) {
|
||||
ReaderPreferences.ImageScaleType.mapIndexed { index, it ->
|
||||
FilterChip(
|
||||
selected = imageScaleType == index + 1,
|
||||
onClick = { screenModel.preferences.imageScaleType().set(index + 1) },
|
||||
onClick = { screenModel.preferences.imageScaleType.set(index + 1) },
|
||||
label = { Text(stringResource(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val zoomStart by screenModel.preferences.zoomStart().collectAsState()
|
||||
val zoomStart by screenModel.preferences.zoomStart.collectAsState()
|
||||
SettingsChipRow(MR.strings.pref_zoom_start) {
|
||||
ReaderPreferences.ZoomStart.mapIndexed { index, it ->
|
||||
FilterChip(
|
||||
selected = zoomStart == index + 1,
|
||||
onClick = { screenModel.preferences.zoomStart().set(index + 1) },
|
||||
onClick = { screenModel.preferences.zoomStart.set(index + 1) },
|
||||
label = { Text(stringResource(it)) },
|
||||
)
|
||||
}
|
||||
@@ -96,42 +96,42 @@ private fun ColumnScope.PagerViewerSettings(screenModel: ReaderSettingsScreenMod
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_crop_borders),
|
||||
pref = screenModel.preferences.cropBorders(),
|
||||
pref = screenModel.preferences.cropBorders,
|
||||
)
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_landscape_zoom),
|
||||
pref = screenModel.preferences.landscapeZoom(),
|
||||
pref = screenModel.preferences.landscapeZoom,
|
||||
)
|
||||
|
||||
CheckboxItem(
|
||||
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(
|
||||
label = stringResource(MR.strings.pref_dual_page_split),
|
||||
pref = screenModel.preferences.dualPageSplitPaged(),
|
||||
pref = screenModel.preferences.dualPageSplitPaged,
|
||||
)
|
||||
|
||||
if (dualPageSplitPaged) {
|
||||
CheckboxItem(
|
||||
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(
|
||||
label = stringResource(MR.strings.pref_page_rotate),
|
||||
pref = screenModel.preferences.dualPageRotateToFit(),
|
||||
pref = screenModel.preferences.dualPageRotateToFit,
|
||||
)
|
||||
|
||||
if (dualPageRotateToFit) {
|
||||
CheckboxItem(
|
||||
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)
|
||||
|
||||
val navigationModeWebtoon by screenModel.preferences.navigationModeWebtoon().collectAsState()
|
||||
val webtoonNavInverted by screenModel.preferences.webtoonNavInverted().collectAsState()
|
||||
val navigationModeWebtoon by screenModel.preferences.navigationModeWebtoon.collectAsState()
|
||||
val webtoonNavInverted by screenModel.preferences.webtoonNavInverted.collectAsState()
|
||||
TapZonesItems(
|
||||
selected = navigationModeWebtoon,
|
||||
onSelect = screenModel.preferences.navigationModeWebtoon()::set,
|
||||
onSelect = screenModel.preferences.navigationModeWebtoon::set,
|
||||
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(
|
||||
value = webtoonSidePadding,
|
||||
valueRange = ReaderPreferences.let { it.WEBTOON_PADDING_MIN..it.WEBTOON_PADDING_MAX },
|
||||
label = stringResource(MR.strings.pref_webtoon_side_padding),
|
||||
valueString = numberFormat.format(webtoonSidePadding / 100f),
|
||||
onChange = {
|
||||
screenModel.preferences.webtoonSidePadding().set(it)
|
||||
screenModel.preferences.webtoonSidePadding.set(it)
|
||||
},
|
||||
pillColor = MaterialTheme.colorScheme.surfaceContainerHighest,
|
||||
)
|
||||
|
||||
CheckboxItem(
|
||||
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(
|
||||
label = stringResource(MR.strings.pref_dual_page_split),
|
||||
pref = screenModel.preferences.dualPageSplitWebtoon(),
|
||||
pref = screenModel.preferences.dualPageSplitWebtoon,
|
||||
)
|
||||
|
||||
if (dualPageSplitWebtoon) {
|
||||
CheckboxItem(
|
||||
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(
|
||||
label = stringResource(MR.strings.pref_page_rotate),
|
||||
pref = screenModel.preferences.dualPageRotateToFitWebtoon(),
|
||||
pref = screenModel.preferences.dualPageRotateToFitWebtoon,
|
||||
)
|
||||
|
||||
if (dualPageRotateToFitWebtoon) {
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_page_rotate_invert),
|
||||
pref = screenModel.preferences.dualPageRotateToFitInvertWebtoon(),
|
||||
pref = screenModel.preferences.dualPageRotateToFitInvertWebtoon,
|
||||
)
|
||||
}
|
||||
|
||||
CheckboxItem(
|
||||
label = stringResource(MR.strings.pref_double_tap_zoom),
|
||||
pref = screenModel.preferences.webtoonDoubleTapZoomEnabled(),
|
||||
pref = screenModel.preferences.webtoonDoubleTapZoomEnabled,
|
||||
)
|
||||
CheckboxItem(
|
||||
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>()
|
||||
BaseTachiyomiTheme(
|
||||
appTheme = appTheme ?: uiPreferences.appTheme().get(),
|
||||
isAmoled = amoled ?: uiPreferences.themeDarkAmoled().get(),
|
||||
appTheme = appTheme ?: uiPreferences.appTheme.get(),
|
||||
isAmoled = amoled ?: uiPreferences.themeDarkAmoled.get(),
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -55,28 +55,28 @@ fun UpdatesFilterDialog(
|
||||
private fun ColumnScope.FilterSheet(
|
||||
screenModel: UpdatesSettingsScreenModel,
|
||||
) {
|
||||
val filterDownloaded by screenModel.updatesPreferences.filterDownloaded().collectAsState()
|
||||
val filterDownloaded by screenModel.updatesPreferences.filterDownloaded.collectAsState()
|
||||
TriStateItem(
|
||||
label = stringResource(MR.strings.label_downloaded),
|
||||
state = filterDownloaded,
|
||||
onClick = { screenModel.toggleFilter(UpdatesPreferences::filterDownloaded) },
|
||||
)
|
||||
|
||||
val filterUnread by screenModel.updatesPreferences.filterUnread().collectAsState()
|
||||
val filterUnread by screenModel.updatesPreferences.filterUnread.collectAsState()
|
||||
TriStateItem(
|
||||
label = stringResource(MR.strings.action_filter_unread),
|
||||
state = filterUnread,
|
||||
onClick = { screenModel.toggleFilter(UpdatesPreferences::filterUnread) },
|
||||
)
|
||||
|
||||
val filterStarted by screenModel.updatesPreferences.filterStarted().collectAsState()
|
||||
val filterStarted by screenModel.updatesPreferences.filterStarted.collectAsState()
|
||||
TriStateItem(
|
||||
label = stringResource(MR.strings.label_started),
|
||||
state = filterStarted,
|
||||
onClick = { screenModel.toggleFilter(UpdatesPreferences::filterStarted) },
|
||||
)
|
||||
|
||||
val filterBookmarked by screenModel.updatesPreferences.filterBookmarked().collectAsState()
|
||||
val filterBookmarked by screenModel.updatesPreferences.filterBookmarked.collectAsState()
|
||||
TriStateItem(
|
||||
label = stringResource(MR.strings.action_filter_bookmarked),
|
||||
state = filterBookmarked,
|
||||
@@ -85,9 +85,9 @@ private fun ColumnScope.FilterSheet(
|
||||
|
||||
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(
|
||||
modifier = Modifier
|
||||
|
||||
@@ -3,6 +3,8 @@ package eu.kanade.presentation.webview
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Message
|
||||
import android.webkit.JsPromptResult
|
||||
import android.webkit.JsResult
|
||||
import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebView
|
||||
import androidx.activity.compose.BackHandler
|
||||
@@ -20,6 +22,7 @@ import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -95,6 +98,11 @@ fun WebViewScreenContent(
|
||||
|
||||
var currentUrl by remember { mutableStateOf(url) }
|
||||
var showCloudflareHelp by remember { mutableStateOf(false) }
|
||||
var isActive by remember { mutableStateOf(true) }
|
||||
|
||||
DisposableEffect(Unit) {
|
||||
onDispose { isActive = false }
|
||||
}
|
||||
|
||||
val webClient = remember {
|
||||
object : AccompanistWebViewClient() {
|
||||
@@ -163,6 +171,36 @@ fun WebViewScreenContent(
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onJsAlert(view: WebView, url: String?, message: String?, result: JsResult): Boolean {
|
||||
if (!isActive) {
|
||||
result.confirm()
|
||||
return true
|
||||
}
|
||||
return super.onJsAlert(view, url, message, result)
|
||||
}
|
||||
|
||||
override fun onJsConfirm(view: WebView, url: String?, message: String?, result: JsResult): Boolean {
|
||||
if (!isActive) {
|
||||
result.cancel()
|
||||
return true
|
||||
}
|
||||
return super.onJsConfirm(view, url, message, result)
|
||||
}
|
||||
|
||||
override fun onJsPrompt(
|
||||
view: WebView,
|
||||
url: String?,
|
||||
message: String?,
|
||||
defaultValue: String?,
|
||||
result: JsPromptResult,
|
||||
): Boolean {
|
||||
if (!isActive) {
|
||||
result.cancel()
|
||||
return true
|
||||
}
|
||||
return super.onJsPrompt(view, url, message, defaultValue, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||
val scope = ProcessLifecycleOwner.get().lifecycleScope
|
||||
|
||||
// Show notification to disable Incognito Mode when it's enabled
|
||||
basePreferences.incognitoMode().changes()
|
||||
basePreferences.incognitoMode.changes()
|
||||
.onEach { enabled ->
|
||||
if (enabled) {
|
||||
disableIncognitoReceiver.register()
|
||||
@@ -135,32 +135,32 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
privacyPreferences.analytics()
|
||||
privacyPreferences.analytics
|
||||
.changes()
|
||||
.onEach(TelemetryConfig::setAnalyticsEnabled)
|
||||
.launchIn(scope)
|
||||
|
||||
privacyPreferences.crashlytics()
|
||||
privacyPreferences.crashlytics
|
||||
.changes()
|
||||
.onEach(TelemetryConfig::setCrashlyticsEnabled)
|
||||
.launchIn(scope)
|
||||
|
||||
basePreferences.hardwareBitmapThreshold().let { preference ->
|
||||
basePreferences.hardwareBitmapThreshold.let { preference ->
|
||||
if (!preference.isSet()) preference.set(GLUtil.DEVICE_TEXTURE_LIMIT)
|
||||
}
|
||||
|
||||
basePreferences.hardwareBitmapThreshold().changes()
|
||||
basePreferences.hardwareBitmapThreshold.changes()
|
||||
.onEach { ImageUtil.hardwareBitmapThreshold = it }
|
||||
.launchIn(scope)
|
||||
|
||||
setAppCompatDelegateThemeMode(Injekt.get<UiPreferences>().themeMode().get())
|
||||
setAppCompatDelegateThemeMode(Injekt.get<UiPreferences>().themeMode.get())
|
||||
|
||||
// Updates widget update
|
||||
WidgetManager(Injekt.get(), Injekt.get()).apply { init(scope) }
|
||||
|
||||
if (!LogcatLogger.isInstalled) {
|
||||
val minLogPriority = when {
|
||||
networkPreferences.verboseLogging().get() -> LogPriority.VERBOSE
|
||||
networkPreferences.verboseLogging.get() -> LogPriority.VERBOSE
|
||||
BuildConfig.DEBUG -> LogPriority.DEBUG
|
||||
else -> LogPriority.INFO
|
||||
}
|
||||
@@ -211,7 +211,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||
|
||||
crossfade((300 * this@App.animatorDurationScale).toInt())
|
||||
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
|
||||
fetcherCoroutineContext(Dispatchers.IO.limitedParallelism(8))
|
||||
@@ -256,7 +256,7 @@ class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.Factor
|
||||
private var registered = false
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
basePreferences.incognitoMode().set(false)
|
||||
basePreferences.incognitoMode.set(false)
|
||||
}
|
||||
|
||||
fun register() {
|
||||
|
||||
@@ -101,7 +101,7 @@ class BackupNotifier(private val context: Context) {
|
||||
}
|
||||
setContentTitle(contentTitle)
|
||||
|
||||
if (!preferences.hideNotificationContent().get()) {
|
||||
if (!preferences.hideNotificationContent.get()) {
|
||||
setContentText(content)
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete
|
||||
|
||||
fun setupTask(context: Context, prefInterval: Int? = null) {
|
||||
val backupPreferences = Injekt.get<BackupPreferences>()
|
||||
val interval = prefInterval ?: backupPreferences.backupInterval().get()
|
||||
val interval = prefInterval ?: backupPreferences.backupInterval.get()
|
||||
if (interval > 0) {
|
||||
val constraints = Constraints(
|
||||
requiresBatteryNotLow = true,
|
||||
|
||||
@@ -108,7 +108,7 @@ class BackupCreator(
|
||||
BackupFileValidator(context).validate(fileUri)
|
||||
|
||||
if (isAutoBackup) {
|
||||
backupPreferences.lastAutoBackupTimestamp().set(Instant.now().toEpochMilli())
|
||||
backupPreferences.lastAutoBackupTimestamp.set(Instant.now().toEpochMilli())
|
||||
}
|
||||
|
||||
return fileUri.toString()
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ class CategoriesRestorer(
|
||||
.let { id -> it.toCategory(id).copy(order = order) }
|
||||
}
|
||||
|
||||
libraryPreferences.categorizedDisplaySettings().set(
|
||||
libraryPreferences.categorizedDisplaySettings.set(
|
||||
(dbCategories + categories)
|
||||
.distinctBy { it.flags }
|
||||
.size > 1,
|
||||
|
||||
@@ -56,7 +56,7 @@ class DownloadJob(context: Context, workerParams: WorkerParameters) : CoroutineW
|
||||
override suspend fun doWork(): Result {
|
||||
var networkCheck = checkNetworkState(
|
||||
applicationContext.activeNetworkState(),
|
||||
downloadPreferences.downloadOnlyOverWifi().get(),
|
||||
downloadPreferences.downloadOnlyOverWifi.get(),
|
||||
)
|
||||
var active = networkCheck && downloadManager.downloaderStart()
|
||||
|
||||
@@ -69,7 +69,7 @@ class DownloadJob(context: Context, workerParams: WorkerParameters) : CoroutineW
|
||||
coroutineScope {
|
||||
combineTransform(
|
||||
applicationContext.networkStateFlow(),
|
||||
downloadPreferences.downloadOnlyOverWifi().changes(),
|
||||
downloadPreferences.downloadOnlyOverWifi.changes(),
|
||||
transform = { a, b -> emit(checkNetworkState(a, b)) },
|
||||
)
|
||||
.onEach { networkCheck = it }
|
||||
|
||||
@@ -397,7 +397,7 @@ class DownloadManager(
|
||||
|
||||
private suspend fun getChaptersToDelete(chapters: List<Chapter>, manga: Manga): List<Chapter> {
|
||||
// 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)
|
||||
.map { it.id }
|
||||
@@ -408,7 +408,7 @@ class DownloadManager(
|
||||
chapters
|
||||
}
|
||||
|
||||
return if (!downloadPreferences.removeBookmarkedChapters().get()) {
|
||||
return if (!downloadPreferences.removeBookmarkedChapters.get()) {
|
||||
filteredCategoryManga.filterNot { it.bookmark }
|
||||
} else {
|
||||
filteredCategoryManga
|
||||
|
||||
@@ -96,7 +96,7 @@ internal class DownloadNotifier(private val context: Context) {
|
||||
download.pages!!.size,
|
||||
)
|
||||
|
||||
if (preferences.hideNotificationContent().get()) {
|
||||
if (preferences.hideNotificationContent.get()) {
|
||||
setContentTitle(downloadingProgressText)
|
||||
setContentText(null)
|
||||
} else {
|
||||
|
||||
@@ -136,7 +136,7 @@ class DownloadProvider(
|
||||
fun getSourceDirName(source: Source): String {
|
||||
return DiskUtil.buildValidFilename(
|
||||
source.toString(),
|
||||
disallowNonAscii = libraryPreferences.disallowNonAsciiFilenames().get(),
|
||||
disallowNonAscii = libraryPreferences.disallowNonAsciiFilenames.get(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ class DownloadProvider(
|
||||
fun getMangaDirName(mangaTitle: String): String {
|
||||
return DiskUtil.buildValidFilename(
|
||||
mangaTitle,
|
||||
disallowNonAscii = libraryPreferences.disallowNonAsciiFilenames().get(),
|
||||
disallowNonAscii = libraryPreferences.disallowNonAsciiFilenames.get(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ class DownloadProvider(
|
||||
chapterName: String,
|
||||
chapterScanlator: String?,
|
||||
chapterUrl: String,
|
||||
disallowNonAsciiFilenames: Boolean = libraryPreferences.disallowNonAsciiFilenames().get(),
|
||||
disallowNonAsciiFilenames: Boolean = libraryPreferences.disallowNonAsciiFilenames.get(),
|
||||
): String {
|
||||
var dirName = sanitizeChapterName(chapterName)
|
||||
if (!chapterScanlator.isNullOrBlank()) {
|
||||
@@ -206,7 +206,7 @@ class DownloadProvider(
|
||||
chapterName,
|
||||
chapterScanlator,
|
||||
chapterUrl,
|
||||
!libraryPreferences.disallowNonAsciiFilenames().get(),
|
||||
!libraryPreferences.disallowNonAsciiFilenames.get(),
|
||||
)
|
||||
|
||||
return buildList(2) {
|
||||
|
||||
@@ -193,7 +193,7 @@ class Downloader(
|
||||
downloaderJob = scope.launch {
|
||||
val activeDownloadsFlow = combine(
|
||||
queueState,
|
||||
downloadPreferences.parallelSourceLimit().changes(),
|
||||
downloadPreferences.parallelSourceLimit.changes(),
|
||||
) { a, b -> a to b }.transformLatest { (queue, parallelCount) ->
|
||||
while (true) {
|
||||
val activeDownloads = queue.asSequence()
|
||||
@@ -369,7 +369,7 @@ class Downloader(
|
||||
download.status = Download.State.DOWNLOADING
|
||||
|
||||
// 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 {
|
||||
// Fetch image URL if necessary
|
||||
if (page.imageUrl.isNullOrEmpty()) {
|
||||
@@ -406,7 +406,7 @@ class Downloader(
|
||||
)
|
||||
|
||||
// Only rename the directory if it's downloaded
|
||||
if (downloadPreferences.saveChaptersAsCBZ().get()) {
|
||||
if (downloadPreferences.saveChaptersAsCBZ.get()) {
|
||||
archiveChapter(mangaDir, chapterDirname, tmpDir)
|
||||
} else {
|
||||
tmpDir.renameTo(chapterDirname)
|
||||
@@ -545,7 +545,7 @@ class Downloader(
|
||||
}
|
||||
|
||||
private fun splitTallImageIfNeeded(page: Page, tmpDir: UniFile) {
|
||||
if (!downloadPreferences.splitTallImages().get()) return
|
||||
if (!downloadPreferences.splitTallImages.get()) return
|
||||
|
||||
try {
|
||||
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 (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
|
||||
val preferences = Injekt.get<LibraryPreferences>()
|
||||
val restrictions = preferences.autoUpdateDeviceRestrictions().get()
|
||||
val restrictions = preferences.autoUpdateDeviceRestrictions.get()
|
||||
if ((DEVICE_ONLY_ON_WIFI in restrictions) && !context.isConnectedToWifi()) {
|
||||
return Result.retry()
|
||||
}
|
||||
@@ -113,7 +113,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
|
||||
setForegroundSafely()
|
||||
|
||||
libraryPreferences.lastUpdatedTimestamp().set(Instant.now().toEpochMilli())
|
||||
libraryPreferences.lastUpdatedTimestamp.set(Instant.now().toEpochMilli())
|
||||
|
||||
val categoryId = inputData.getLong(KEY_CATEGORY, -1L)
|
||||
addMangaToQueue(categoryId)
|
||||
@@ -160,8 +160,8 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
val listToUpdate = if (categoryId != -1L) {
|
||||
libraryManga.filter { categoryId in it.categories }
|
||||
} else {
|
||||
val includedCategories = libraryPreferences.updateCategories().get().map { it.toLong() }
|
||||
val excludedCategories = libraryPreferences.updateCategoriesExclude().get().map { it.toLong() }
|
||||
val includedCategories = libraryPreferences.updateCategories.get().map { it.toLong() }
|
||||
val excludedCategories = libraryPreferences.updateCategoriesExclude.get().map { it.toLong() }
|
||||
|
||||
libraryManga.filter {
|
||||
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 (_, fetchWindowUpperBound) = fetchInterval.getWindow(ZonedDateTime.now())
|
||||
|
||||
@@ -272,7 +272,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
hasDownloads.store(true)
|
||||
}
|
||||
|
||||
libraryPreferences.newUpdatesCount().getAndSet { it + newChapters.size }
|
||||
libraryPreferences.newUpdatesCount.getAndSet { it + newChapters.size }
|
||||
|
||||
// Convert to the manga that contains new chapters
|
||||
newUpdates.add(manga to newChapters.toTypedArray())
|
||||
@@ -332,7 +332,7 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
val source = sourceManager.getOrStub(manga.source)
|
||||
|
||||
// Update manga metadata if needed
|
||||
if (libraryPreferences.autoUpdateMetadata().get()) {
|
||||
if (libraryPreferences.autoUpdateMetadata.get()) {
|
||||
val networkManga = source.getMangaDetails(manga.toSManga())
|
||||
updateManga.awaitUpdateFromSource(manga, networkManga, manualFetch = false, coverCache)
|
||||
}
|
||||
@@ -423,9 +423,9 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
|
||||
prefInterval: Int? = null,
|
||||
) {
|
||||
val preferences = Injekt.get<LibraryPreferences>()
|
||||
val interval = prefInterval ?: preferences.autoUpdateInterval().get()
|
||||
val interval = prefInterval ?: preferences.autoUpdateInterval.get()
|
||||
if (interval > 0) {
|
||||
val restrictions = preferences.autoUpdateDeviceRestrictions().get()
|
||||
val restrictions = preferences.autoUpdateDeviceRestrictions.get()
|
||||
val networkType = if (DEVICE_NETWORK_NOT_METERED in restrictions) {
|
||||
NetworkType.UNMETERED
|
||||
} else {
|
||||
|
||||
@@ -98,7 +98,7 @@ class LibraryUpdateNotifier(
|
||||
),
|
||||
)
|
||||
|
||||
if (!securityPreferences.hideNotificationContent().get()) {
|
||||
if (!securityPreferences.hideNotificationContent.get()) {
|
||||
val updatingText = manga.joinToString("\n") { it.title.chop(40) }
|
||||
progressNotificationBuilder.setStyle(NotificationCompat.BigTextStyle().bigText(updatingText))
|
||||
}
|
||||
@@ -173,7 +173,7 @@ class LibraryUpdateNotifier(
|
||||
Notifications.CHANNEL_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))
|
||||
} else {
|
||||
setContentText(
|
||||
@@ -184,7 +184,7 @@ class LibraryUpdateNotifier(
|
||||
),
|
||||
)
|
||||
|
||||
if (!securityPreferences.hideNotificationContent().get()) {
|
||||
if (!securityPreferences.hideNotificationContent.get()) {
|
||||
setStyle(
|
||||
NotificationCompat.BigTextStyle().bigText(
|
||||
updates.joinToString("\n") {
|
||||
@@ -208,7 +208,7 @@ class LibraryUpdateNotifier(
|
||||
}
|
||||
|
||||
// Per-manga notification
|
||||
if (!securityPreferences.hideNotificationContent().get()) {
|
||||
if (!securityPreferences.hideNotificationContent.get()) {
|
||||
launchUI {
|
||||
context.notify(
|
||||
updates.map { (manga, chapters) ->
|
||||
|
||||
@@ -201,7 +201,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
val toUpdate = chapterUrls.mapNotNull { getChapter.await(it, mangaId) }
|
||||
.map {
|
||||
val chapter = it.copy(read = true)
|
||||
if (downloadPreferences.removeAfterMarkedAsRead().get()) {
|
||||
if (downloadPreferences.removeAfterMarkedAsRead.get()) {
|
||||
val manga = getManga.await(mangaId)
|
||||
if (manga != null) {
|
||||
val source = sourceManager.get(manga.source)
|
||||
|
||||
@@ -43,7 +43,7 @@ class Anilist(id: Long) : BaseTracker(id, "AniList"), DeletableTracker {
|
||||
|
||||
override val supportsPrivateTracking: Boolean = true
|
||||
|
||||
private val scorePreference = trackPreferences.anilistScoreType()
|
||||
private val scorePreference = trackPreferences.anilistScoreType
|
||||
|
||||
init {
|
||||
// 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()
|
||||
|
||||
fun DomainTrack.toApiScore(): String = when (preferences.anilistScoreType().get()) {
|
||||
fun DomainTrack.toApiScore(): String = when (preferences.anilistScoreType.get()) {
|
||||
// 10 point
|
||||
"POINT_10" -> (score.toInt() / 10).toString()
|
||||
// 100 point
|
||||
|
||||
@@ -193,6 +193,6 @@ class MangaUpdatesApi(
|
||||
companion object {
|
||||
private const val BASE_URL = "https://api.mangaupdates.com"
|
||||
|
||||
private val CONTENT_TYPE = "application/vnd.api+json".toMediaType()
|
||||
private val CONTENT_TYPE = "application/json".toMediaType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package eu.kanade.tachiyomi.di
|
||||
|
||||
import android.app.Application
|
||||
import android.os.Build
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
|
||||
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
|
||||
import app.cash.sqldelight.db.SqlDriver
|
||||
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
|
||||
import com.eygraber.sqldelight.androidx.driver.AndroidxSqliteConfiguration
|
||||
import com.eygraber.sqldelight.androidx.driver.AndroidxSqliteDatabaseType
|
||||
import com.eygraber.sqldelight.androidx.driver.AndroidxSqliteDriver
|
||||
import com.eygraber.sqldelight.androidx.driver.File
|
||||
import com.eygraber.sqldelight.androidx.driver.FileProvider
|
||||
import eu.kanade.domain.track.store.DelayedTrackingStore
|
||||
import eu.kanade.tachiyomi.BuildConfig
|
||||
import eu.kanade.tachiyomi.data.cache.ChapterCache
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
import eu.kanade.tachiyomi.data.download.DownloadCache
|
||||
@@ -20,7 +21,6 @@ import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||
import eu.kanade.tachiyomi.network.JavaScriptEngine
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.source.AndroidSourceManager
|
||||
import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.protobuf.ProtoBuf
|
||||
import nl.adaptivity.xmlutil.XmlDeclMode
|
||||
@@ -51,29 +51,13 @@ class AppModule(val app: Application) : InjektModule {
|
||||
addSingleton(app)
|
||||
|
||||
addSingletonFactory<SqlDriver> {
|
||||
AndroidSqliteDriver(
|
||||
AndroidxSqliteDriver(
|
||||
driver = BundledSQLiteDriver(),
|
||||
databaseType = AndroidxSqliteDatabaseType.FileProvider(app, "tachiyomi.db"),
|
||||
schema = Database.Schema,
|
||||
context = app,
|
||||
name = "tachiyomi.db",
|
||||
factory = if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
// Support database inspector in Android Studio
|
||||
FrameworkSQLiteOpenHelperFactory()
|
||||
} else {
|
||||
RequerySQLiteOpenHelperFactory()
|
||||
},
|
||||
callback = object : AndroidSqliteDriver.Callback(Database.Schema) {
|
||||
override fun onOpen(db: SupportSQLiteDatabase) {
|
||||
super.onOpen(db)
|
||||
setPragma(db, "foreign_keys = ON")
|
||||
setPragma(db, "journal_mode = WAL")
|
||||
setPragma(db, "synchronous = NORMAL")
|
||||
}
|
||||
private fun setPragma(db: SupportSQLiteDatabase, pragma: String) {
|
||||
val cursor = db.query("PRAGMA $pragma")
|
||||
cursor.moveToFirst()
|
||||
cursor.close()
|
||||
}
|
||||
},
|
||||
configuration = AndroidxSqliteConfiguration(
|
||||
isForeignKeyConstraintsEnabled = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
addSingletonFactory {
|
||||
|
||||
@@ -32,7 +32,7 @@ class PreferenceModule(val app: Application) : InjektModule {
|
||||
addSingletonFactory {
|
||||
NetworkPreferences(
|
||||
preferenceStore = get(),
|
||||
verboseLogging = isDebugBuildType,
|
||||
verboseLoggingDefault = isDebugBuildType,
|
||||
)
|
||||
}
|
||||
addSingletonFactory {
|
||||
|
||||
@@ -76,7 +76,7 @@ class ExtensionManager(
|
||||
ExtensionInstallReceiver(InstallationListener()).register(context)
|
||||
}
|
||||
|
||||
private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages().isSet()
|
||||
private var subLanguagesEnabledOnFirstRun = preferences.enabledLanguages.isSet()
|
||||
|
||||
fun getExtensionPackage(sourceId: Long): String? {
|
||||
return installedExtensionsFlow.value.find { extension ->
|
||||
@@ -171,12 +171,12 @@ class ExtensionManager(
|
||||
.map(Extension.Available.Source::lang)
|
||||
|
||||
val deviceLanguage = Locale.getDefault().language
|
||||
val defaultLanguages = preferences.enabledLanguages().defaultValue()
|
||||
val defaultLanguages = preferences.enabledLanguages.defaultValue()
|
||||
val languagesToEnable = availableLanguages.filter {
|
||||
it != deviceLanguage && it.startsWith(deviceLanguage)
|
||||
}
|
||||
|
||||
preferences.enabledLanguages().set(defaultLanguages + languagesToEnable)
|
||||
preferences.enabledLanguages.set(defaultLanguages + languagesToEnable)
|
||||
subLanguagesEnabledOnFirstRun = true
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ class ExtensionManager(
|
||||
*/
|
||||
private fun updatedInstalledExtensionsStatuses(availableExtensions: List<Extension.Available>) {
|
||||
if (availableExtensions.isEmpty()) {
|
||||
preferences.extensionUpdatesCount().set(0)
|
||||
preferences.extensionUpdatesCount.set(0)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -366,7 +366,7 @@ class ExtensionManager(
|
||||
|
||||
private fun updatePendingUpdatesCount() {
|
||||
val pendingUpdateCount = installedExtensionMapFlow.value.values.count { it.hasUpdate }
|
||||
preferences.extensionUpdatesCount().set(pendingUpdateCount)
|
||||
preferences.extensionUpdatesCount.set(pendingUpdateCount)
|
||||
if (pendingUpdateCount == 0) {
|
||||
ExtensionUpdateNotifier(context).dismiss()
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class ExtensionUpdateNotifier(
|
||||
names.size,
|
||||
),
|
||||
)
|
||||
if (!securityPreferences.hideNotificationContent().get()) {
|
||||
if (!securityPreferences.hideNotificationContent.get()) {
|
||||
val extNames = names.joinToString(", ")
|
||||
setContentText(extNames)
|
||||
setStyle(NotificationCompat.BigTextStyle().bigText(extNames))
|
||||
|
||||
@@ -39,7 +39,7 @@ internal class ExtensionInstaller(
|
||||
private val scope = CoroutineScope(Dispatchers.IO)
|
||||
private val activeJobs = mutableMapOf<String, Job>()
|
||||
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
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ internal object ExtensionLoader {
|
||||
private val preferences: SourcePreferences by injectLazy()
|
||||
private val trustExtension: TrustExtension by injectLazy()
|
||||
private val loadNsfwSource by lazy {
|
||||
preferences.showNsfwSource().get()
|
||||
preferences.showNsfwSource.get()
|
||||
}
|
||||
|
||||
private const val EXTENSION_FEATURE = "tachiyomi.extension"
|
||||
|
||||
@@ -8,7 +8,7 @@ import uy.kohesive.injekt.api.get
|
||||
|
||||
fun Source.getNameForMangaInfo(): String {
|
||||
val preferences = Injekt.get<SourcePreferences>()
|
||||
val enabledLanguages = preferences.enabledLanguages().get()
|
||||
val enabledLanguages = preferences.enabledLanguages.get()
|
||||
.filterNot { it in listOf("all", "other") }
|
||||
val hasOneActiveLanguages = enabledLanguages.size == 1
|
||||
val isInEnabledLanguages = lang in enabledLanguages
|
||||
|
||||
@@ -33,14 +33,14 @@ interface SecureActivityDelegate {
|
||||
|
||||
fun onApplicationStopped() {
|
||||
val preferences = Injekt.get<SecurityPreferences>()
|
||||
if (!preferences.useAuthenticator().get()) return
|
||||
if (!preferences.useAuthenticator.get()) return
|
||||
|
||||
if (!AuthenticatorUtil.isAuthenticating) {
|
||||
// Return if app is closed in locked state
|
||||
if (requireUnlock) return
|
||||
// Save app close time if lock is delayed
|
||||
if (preferences.lockAppAfter().get() > 0) {
|
||||
preferences.lastAppClosed().set(System.currentTimeMillis())
|
||||
if (preferences.lockAppAfter.get() > 0) {
|
||||
preferences.lastAppClosed.set(System.currentTimeMillis())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,13 +50,13 @@ interface SecureActivityDelegate {
|
||||
*/
|
||||
fun onApplicationStart() {
|
||||
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
|
||||
if (!AuthenticatorUtil.isAuthenticating && !requireUnlock) {
|
||||
requireUnlock = when (val lockDelay = preferences.lockAppAfter().get()) {
|
||||
requireUnlock = when (val lockDelay = preferences.lockAppAfter.get()) {
|
||||
-1 -> false // Never
|
||||
0 -> true // Always
|
||||
else -> lastClosedPref.get() + lockDelay * 60_000 <= System.currentTimeMillis()
|
||||
@@ -93,8 +93,8 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
|
||||
}
|
||||
|
||||
private fun setSecureScreen() {
|
||||
val secureScreenFlow = securityPreferences.secureScreen().changes()
|
||||
val incognitoModeFlow = preferences.incognitoMode().changes()
|
||||
val secureScreenFlow = securityPreferences.secureScreen.changes()
|
||||
val incognitoModeFlow = preferences.incognitoMode.changes()
|
||||
combine(secureScreenFlow, incognitoModeFlow) { secureScreen, incognitoMode ->
|
||||
secureScreen == SecurityPreferences.SecureScreenMode.ALWAYS ||
|
||||
(secureScreen == SecurityPreferences.SecureScreenMode.INCOGNITO && incognitoMode)
|
||||
@@ -104,7 +104,7 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
|
||||
}
|
||||
|
||||
private fun setAppLock() {
|
||||
if (!securityPreferences.useAuthenticator().get()) return
|
||||
if (!securityPreferences.useAuthenticator.get()) return
|
||||
if (activity.isAuthenticationSupported()) {
|
||||
if (!SecureActivityDelegate.requireUnlock) return
|
||||
activity.startActivity(Intent(activity, UnlockActivity::class.java))
|
||||
@@ -115,7 +115,7 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
|
||||
activity.overridePendingTransition(0, 0)
|
||||
}
|
||||
} else {
|
||||
securityPreferences.useAuthenticator().set(false)
|
||||
securityPreferences.useAuthenticator.set(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ interface ThemingDelegate {
|
||||
class ThemingDelegateImpl : ThemingDelegate {
|
||||
override fun applyAppTheme(activity: Activity) {
|
||||
val uiPreferences = Injekt.get<UiPreferences>()
|
||||
ThemingDelegate.getThemeResIds(uiPreferences.appTheme().get(), uiPreferences.themeDarkAmoled().get())
|
||||
ThemingDelegate.getThemeResIds(uiPreferences.appTheme.get(), uiPreferences.themeDarkAmoled.get())
|
||||
.forEach(activity::setTheme)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ class ExtensionFilterScreenModel(
|
||||
screenModelScope.launch {
|
||||
combine(
|
||||
getExtensionLanguages.subscribe(),
|
||||
preferences.enabledLanguages().changes(),
|
||||
preferences.enabledLanguages.changes(),
|
||||
) { a, b -> a to b }
|
||||
.catch { throwable ->
|
||||
logcat(LogPriority.ERROR, throwable)
|
||||
|
||||
@@ -26,6 +26,7 @@ import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onCompletion
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.takeWhile
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
@@ -97,11 +98,11 @@ class ExtensionsScreenModel(
|
||||
|
||||
screenModelScope.launchIO { findAvailableExtensions() }
|
||||
|
||||
preferences.extensionUpdatesCount().changes()
|
||||
preferences.extensionUpdatesCount.changes()
|
||||
.onEach { mutableState.update { state -> state.copy(updates = it) } }
|
||||
.launchIn(screenModelScope)
|
||||
|
||||
basePreferences.extensionInstaller().changes()
|
||||
basePreferences.extensionInstaller.changes()
|
||||
.onEach { mutableState.update { state -> state.copy(installer = it) } }
|
||||
.launchIn(screenModelScope)
|
||||
}
|
||||
@@ -180,6 +181,7 @@ class ExtensionsScreenModel(
|
||||
private suspend fun Flow<InstallStep>.collectToInstallUpdate(extension: Extension) =
|
||||
this
|
||||
.onEach { installStep -> addDownloadState(extension, installStep) }
|
||||
.takeWhile { installStep -> installStep != InstallStep.Installed }
|
||||
.onCompletion { removeDownloadState(extension) }
|
||||
.collect()
|
||||
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ class ExtensionDetailsScreenModel(
|
||||
}
|
||||
}
|
||||
launch {
|
||||
preferences.incognitoExtensions()
|
||||
preferences.incognitoExtensions
|
||||
.changes()
|
||||
.map { pkgName in it }
|
||||
.distinctUntilChanged()
|
||||
|
||||
+3
-2
@@ -16,7 +16,6 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentContainerView
|
||||
import androidx.fragment.app.FragmentManager
|
||||
@@ -167,7 +166,9 @@ class SourcePreferencesFragment : PreferenceFragmentCompat() {
|
||||
|
||||
fun getInstance(sourceId: Long): SourcePreferencesFragment {
|
||||
return SourcePreferencesFragment().apply {
|
||||
arguments = bundleOf(SOURCE_ID to sourceId)
|
||||
arguments = Bundle().apply {
|
||||
putLong(SOURCE_ID, sourceId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ class MigrateSearchScreenModel(
|
||||
private val sourcePreferences: SourcePreferences = Injekt.get(),
|
||||
) : SearchScreenModel() {
|
||||
|
||||
private val migrationSources by lazy { sourcePreferences.migrationSources().get() }
|
||||
private val migrationSources by lazy { sourcePreferences.migrationSources.get() }
|
||||
|
||||
override val sortComparator = { map: Map<CatalogueSource, SearchItemResult> ->
|
||||
compareBy<CatalogueSource>(
|
||||
|
||||
+2
-2
@@ -49,11 +49,11 @@ class MigrateSourceScreenModel(
|
||||
}
|
||||
}
|
||||
|
||||
preferences.migrationSortingDirection().changes()
|
||||
preferences.migrationSortingDirection.changes()
|
||||
.onEach { mutableState.update { state -> state.copy(sortingDirection = it) } }
|
||||
.launchIn(screenModelScope)
|
||||
|
||||
preferences.migrationSortingMode().changes()
|
||||
preferences.migrationSortingMode.changes()
|
||||
.onEach { mutableState.update { state -> state.copy(sortingMode = it) } }
|
||||
.launchIn(screenModelScope)
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ class SourcesFilterScreenModel(
|
||||
screenModelScope.launch {
|
||||
combine(
|
||||
getLanguagesWithSources.subscribe(),
|
||||
preferences.enabledLanguages().changes(),
|
||||
preferences.disabledSources().changes(),
|
||||
preferences.enabledLanguages.changes(),
|
||||
preferences.disabledSources.changes(),
|
||||
) { a, b, c -> Triple(a, b, c) }
|
||||
.catch { throwable ->
|
||||
mutableState.update {
|
||||
|
||||
+6
-6
@@ -71,7 +71,7 @@ class BrowseSourceScreenModel(
|
||||
private val getIncognitoState: GetIncognitoState = Injekt.get(),
|
||||
) : 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)
|
||||
|
||||
@@ -95,14 +95,14 @@ class BrowseSourceScreenModel(
|
||||
}
|
||||
|
||||
if (!getIncognitoState.await(source.id)) {
|
||||
sourcePreferences.lastUsedSource().set(source.id)
|
||||
sourcePreferences.lastUsedSource.set(source.id)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 }
|
||||
.distinctUntilChanged()
|
||||
.map { listing ->
|
||||
@@ -123,9 +123,9 @@ class BrowseSourceScreenModel(
|
||||
fun getColumnsPreference(orientation: Int): GridCells {
|
||||
val isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
val columns = if (isLandscape) {
|
||||
libraryPreferences.landscapeColumns()
|
||||
libraryPreferences.landscapeColumns
|
||||
} else {
|
||||
libraryPreferences.portraitColumns()
|
||||
libraryPreferences.portraitColumns
|
||||
}.get()
|
||||
return if (columns == 0) GridCells.Adaptive(128.dp) else GridCells.Fixed(columns)
|
||||
}
|
||||
@@ -241,7 +241,7 @@ class BrowseSourceScreenModel(
|
||||
fun addFavorite(manga: Manga) {
|
||||
screenModelScope.launch {
|
||||
val categories = getCategories()
|
||||
val defaultCategoryId = libraryPreferences.defaultCategory().get()
|
||||
val defaultCategoryId = libraryPreferences.defaultCategory.get()
|
||||
val defaultCategory = categories.find { it.id == defaultCategoryId.toLong() }
|
||||
|
||||
when {
|
||||
|
||||
+5
-5
@@ -47,9 +47,9 @@ abstract class SearchScreenModel(
|
||||
private val coroutineDispatcher = Executors.newFixedThreadPool(5).asCoroutineDispatcher()
|
||||
private var searchJob: Job? = null
|
||||
|
||||
private val enabledLanguages = sourcePreferences.enabledLanguages().get()
|
||||
private val disabledSources = sourcePreferences.disabledSources().get()
|
||||
protected val pinnedSources = sourcePreferences.pinnedSources().get()
|
||||
private val enabledLanguages = sourcePreferences.enabledLanguages.get()
|
||||
private val disabledSources = sourcePreferences.disabledSources.get()
|
||||
protected val pinnedSources = sourcePreferences.pinnedSources.get()
|
||||
|
||||
private var lastQuery: String? = null
|
||||
private var lastSourceFilter: SourceFilter? = null
|
||||
@@ -66,7 +66,7 @@ abstract class SearchScreenModel(
|
||||
|
||||
init {
|
||||
screenModelScope.launch {
|
||||
preferences.globalSearchFilterState().changes().collectLatest { state ->
|
||||
preferences.globalSearchFilterState.changes().collectLatest { state ->
|
||||
mutableState.update { it.copy(onlyShowHasResults = state) }
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ abstract class SearchScreenModel(
|
||||
}
|
||||
|
||||
fun toggleFilterResults() {
|
||||
preferences.globalSearchFilterState().toggle()
|
||||
preferences.globalSearchFilterState.toggle()
|
||||
}
|
||||
|
||||
fun search() {
|
||||
|
||||
@@ -189,7 +189,7 @@ class HistoryScreenModel(
|
||||
screenModelScope.launchIO {
|
||||
// Move to default category if applicable
|
||||
val categories = getCategories()
|
||||
val defaultCategoryId = libraryPreferences.defaultCategory().get().toLong()
|
||||
val defaultCategoryId = libraryPreferences.defaultCategory.get().toLong()
|
||||
val defaultCategory = categories.find { it.id == defaultCategoryId }
|
||||
|
||||
when {
|
||||
|
||||
@@ -242,8 +242,8 @@ object HomeScreen : Screen() {
|
||||
val count by produceState(initialValue = 0) {
|
||||
val pref = Injekt.get<LibraryPreferences>()
|
||||
combine(
|
||||
pref.newShowUpdatesCount().changes(),
|
||||
pref.newUpdatesCount().changes(),
|
||||
pref.newShowUpdatesCount.changes(),
|
||||
pref.newUpdatesCount.changes(),
|
||||
) { show, count -> if (show) count else 0 }
|
||||
.collectLatest { value = it }
|
||||
}
|
||||
@@ -263,7 +263,7 @@ object HomeScreen : Screen() {
|
||||
}
|
||||
BrowseTab::class.isInstance(tab) -> {
|
||||
val count by produceState(initialValue = 0) {
|
||||
Injekt.get<SourcePreferences>().extensionUpdatesCount().changes()
|
||||
Injekt.get<SourcePreferences>().extensionUpdatesCount.changes()
|
||||
.collectLatest { value = it }
|
||||
}
|
||||
if (count > 0) {
|
||||
|
||||
@@ -89,7 +89,7 @@ class LibraryScreenModel(
|
||||
|
||||
init {
|
||||
mutableState.update { state ->
|
||||
state.copy(activeCategoryIndex = libraryPreferences.lastUsedCategory().get())
|
||||
state.copy(activeCategoryIndex = libraryPreferences.lastUsedCategory.get())
|
||||
}
|
||||
screenModelScope.launchIO {
|
||||
combine(
|
||||
@@ -142,9 +142,9 @@ class LibraryScreenModel(
|
||||
}
|
||||
|
||||
combine(
|
||||
libraryPreferences.categoryTabs().changes(),
|
||||
libraryPreferences.categoryNumberOfItems().changes(),
|
||||
libraryPreferences.showContinueReadingButton().changes(),
|
||||
libraryPreferences.categoryTabs.changes(),
|
||||
libraryPreferences.categoryNumberOfItems.changes(),
|
||||
libraryPreferences.showContinueReadingButton.changes(),
|
||||
) { a, b, c -> arrayOf(a, b, c) }
|
||||
.onEach { (showCategoryTabs, showMangaCount, showMangaContinueButton) ->
|
||||
mutableState.update { state ->
|
||||
@@ -337,7 +337,7 @@ class LibraryScreenModel(
|
||||
|
||||
return mapValues { (key, value) ->
|
||||
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] }
|
||||
@@ -352,19 +352,19 @@ class LibraryScreenModel(
|
||||
|
||||
private fun getLibraryItemPreferencesFlow(): Flow<ItemPreferences> {
|
||||
return combine(
|
||||
libraryPreferences.downloadBadge().changes(),
|
||||
libraryPreferences.unreadBadge().changes(),
|
||||
libraryPreferences.localBadge().changes(),
|
||||
libraryPreferences.languageBadge().changes(),
|
||||
libraryPreferences.autoUpdateMangaRestrictions().changes(),
|
||||
libraryPreferences.downloadBadge.changes(),
|
||||
libraryPreferences.unreadBadge.changes(),
|
||||
libraryPreferences.localBadge.changes(),
|
||||
libraryPreferences.languageBadge.changes(),
|
||||
libraryPreferences.autoUpdateMangaRestrictions.changes(),
|
||||
|
||||
preferences.downloadedOnly().changes(),
|
||||
libraryPreferences.filterDownloaded().changes(),
|
||||
libraryPreferences.filterUnread().changes(),
|
||||
libraryPreferences.filterStarted().changes(),
|
||||
libraryPreferences.filterBookmarked().changes(),
|
||||
libraryPreferences.filterCompleted().changes(),
|
||||
libraryPreferences.filterIntervalCustom().changes(),
|
||||
preferences.downloadedOnly.changes(),
|
||||
libraryPreferences.filterDownloaded.changes(),
|
||||
libraryPreferences.filterUnread.changes(),
|
||||
libraryPreferences.filterStarted.changes(),
|
||||
libraryPreferences.filterBookmarked.changes(),
|
||||
libraryPreferences.filterCompleted.changes(),
|
||||
libraryPreferences.filterIntervalCustom.changes(),
|
||||
) {
|
||||
ItemPreferences(
|
||||
downloadBadge = it[0] as Boolean,
|
||||
@@ -589,11 +589,11 @@ class LibraryScreenModel(
|
||||
}
|
||||
|
||||
fun getDisplayMode(): PreferenceMutableState<LibraryDisplayMode> {
|
||||
return libraryPreferences.displayMode().asState(screenModelScope)
|
||||
return libraryPreferences.displayMode.asState(screenModelScope)
|
||||
}
|
||||
|
||||
fun getColumnsForOrientation(isLandscape: Boolean): PreferenceMutableState<Int> {
|
||||
return (if (isLandscape) libraryPreferences.landscapeColumns() else libraryPreferences.portraitColumns())
|
||||
return (if (isLandscape) libraryPreferences.landscapeColumns else libraryPreferences.portraitColumns)
|
||||
.asState(screenModelScope)
|
||||
}
|
||||
|
||||
@@ -686,7 +686,7 @@ class LibraryScreenModel(
|
||||
}
|
||||
.coercedActiveCategoryIndex
|
||||
|
||||
libraryPreferences.lastUsedCategory().set(newIndex)
|
||||
libraryPreferences.lastUsedCategory.set(newIndex)
|
||||
}
|
||||
|
||||
fun openChangeCategoryDialog() {
|
||||
|
||||
@@ -143,7 +143,7 @@ class MainActivity : BaseActivity() {
|
||||
val context = LocalContext.current
|
||||
|
||||
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 isSystemInDarkTheme = isSystemInDarkTheme()
|
||||
@@ -175,7 +175,7 @@ class MainActivity : BaseActivity() {
|
||||
handleIntentAction(intent, navigator)
|
||||
|
||||
// Reset Incognito Mode on relaunch
|
||||
preferences.incognitoMode().set(false)
|
||||
preferences.incognitoMode.set(false)
|
||||
}
|
||||
}
|
||||
LaunchedEffect(navigator.lastItem) {
|
||||
@@ -222,7 +222,7 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
// Pop source-related screens when incognito mode is turned off
|
||||
LaunchedEffect(Unit) {
|
||||
preferences.incognitoMode().changes()
|
||||
preferences.incognitoMode.changes()
|
||||
.drop(1)
|
||||
.filter { !it }
|
||||
.onEach {
|
||||
@@ -268,7 +268,7 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
setSplashScreenExitAnimation(splashScreen)
|
||||
|
||||
if (isLaunch && libraryPreferences.autoClearChapterCache().get()) {
|
||||
if (isLaunch && libraryPreferences.autoClearChapterCache.get()) {
|
||||
lifecycleScope.launchIO {
|
||||
chapterCache.clear()
|
||||
}
|
||||
@@ -337,7 +337,7 @@ class MainActivity : BaseActivity() {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
if (!preferences.shownOnboardingFlow().get() && navigator.lastItem !is OnboardingScreen) {
|
||||
if (!preferences.shownOnboardingFlow.get() && navigator.lastItem !is OnboardingScreen) {
|
||||
navigator.push(OnboardingScreen())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,14 +141,14 @@ class MangaScreenModel(
|
||||
private val filteredChapters: List<ChapterList.Item>?
|
||||
get() = successState?.processedChapters
|
||||
|
||||
val chapterSwipeStartAction = libraryPreferences.swipeToEndAction().get()
|
||||
val chapterSwipeEndAction = libraryPreferences.swipeToStartAction().get()
|
||||
var autoTrackState = trackPreferences.autoUpdateTrackOnMarkRead().get()
|
||||
val chapterSwipeStartAction = libraryPreferences.swipeToEndAction.get()
|
||||
val chapterSwipeEndAction = libraryPreferences.swipeToStartAction.get()
|
||||
var autoTrackState = trackPreferences.autoUpdateTrackOnMarkRead.get()
|
||||
|
||||
private val skipFiltered by readerPreferences.skipFiltered().asState(screenModelScope)
|
||||
private val skipFiltered by readerPreferences.skipFiltered.asState(screenModelScope)
|
||||
|
||||
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 selectedChapterIds: HashSet<Long> = HashSet()
|
||||
@@ -230,7 +230,7 @@ class MangaScreenModel(
|
||||
excludedScanlators = getExcludedScanlators.await(mangaId),
|
||||
isRefreshingData = needRefreshInfo || needRefreshChapter,
|
||||
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
|
||||
val categories = getCategories()
|
||||
val defaultCategoryId = libraryPreferences.defaultCategory().get().toLong()
|
||||
val defaultCategoryId = libraryPreferences.defaultCategory.get().toLong()
|
||||
val defaultCategory = categories.find { it.id == defaultCategoryId }
|
||||
when {
|
||||
// Default category set
|
||||
|
||||
@@ -99,7 +99,7 @@ data class TrackInfoDialogHomeScreen(
|
||||
val context = LocalContext.current
|
||||
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()
|
||||
|
||||
TrackInfoDialogHome(
|
||||
|
||||
@@ -82,8 +82,8 @@ private class MoreScreenModel(
|
||||
preferences: BasePreferences = Injekt.get(),
|
||||
) : ScreenModel {
|
||||
|
||||
var downloadedOnly by preferences.downloadedOnly().asState(screenModelScope)
|
||||
var incognitoMode by preferences.incognitoMode().asState(screenModelScope)
|
||||
var downloadedOnly by preferences.downloadedOnly.asState(screenModelScope)
|
||||
var incognitoMode by preferences.incognitoMode.asState(screenModelScope)
|
||||
|
||||
private var _downloadQueueState: MutableStateFlow<DownloadQueueState> = MutableStateFlow(DownloadQueueState.Stopped)
|
||||
val downloadQueueState: StateFlow<DownloadQueueState> = _downloadQueueState.asStateFlow()
|
||||
|
||||
@@ -24,10 +24,10 @@ class OnboardingScreen : Screen() {
|
||||
val navigator = LocalNavigator.currentOrThrow
|
||||
|
||||
val basePreferences = remember { Injekt.get<BasePreferences>() }
|
||||
val shownOnboardingFlow by basePreferences.shownOnboardingFlow().collectAsState()
|
||||
val shownOnboardingFlow by basePreferences.shownOnboardingFlow.collectAsState()
|
||||
|
||||
val finishOnboarding: () -> Unit = {
|
||||
basePreferences.shownOnboardingFlow().set(true)
|
||||
basePreferences.shownOnboardingFlow.set(true)
|
||||
navigator.pop()
|
||||
}
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ class ReaderActivity : BaseActivity() {
|
||||
setMenuVisibility(viewModel.state.value.menuVisible)
|
||||
|
||||
// Finish when incognito mode is disabled
|
||||
preferences.incognitoMode().changes()
|
||||
preferences.incognitoMode.changes()
|
||||
.drop(1)
|
||||
.onEach { if (!it) finish() }
|
||||
.launchIn(lifecycleScope)
|
||||
@@ -248,7 +248,7 @@ class ReaderActivity : BaseActivity() {
|
||||
|
||||
private fun ReaderActivityBinding.setComposeOverlay(): Unit = composeOverlay.setComposeContent {
|
||||
val state by viewModel.state.collectAsState()
|
||||
val showPageNumber by readerPreferences.showPageNumber().collectAsState()
|
||||
val showPageNumber by readerPreferences.showPageNumber.collectAsState()
|
||||
val settingsScreenModel = remember {
|
||||
ReaderSettingsScreenModel(
|
||||
readerState = viewModel.state,
|
||||
@@ -304,7 +304,7 @@ class ReaderActivity : BaseActivity() {
|
||||
screenModel = settingsScreenModel,
|
||||
onChange = { stringRes ->
|
||||
menuToggleToast?.cancel()
|
||||
if (!readerPreferences.showReadingMode().get()) {
|
||||
if (!readerPreferences.showReadingMode.get()) {
|
||||
menuToggleToast = toast(stringRes)
|
||||
}
|
||||
},
|
||||
@@ -425,11 +425,11 @@ class ReaderActivity : BaseActivity() {
|
||||
|
||||
@Composable
|
||||
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 colorOverlay by readerPreferences.colorFilterValue().collectAsState()
|
||||
val colorOverlayMode by readerPreferences.colorFilterMode().collectAsState()
|
||||
val colorOverlayEnabled by readerPreferences.colorFilter.collectAsState()
|
||||
val colorOverlay by readerPreferences.colorFilterValue.collectAsState()
|
||||
val colorOverlayMode by readerPreferences.colorFilterMode.collectAsState()
|
||||
val colorOverlayBlendMode = remember(colorOverlayMode) {
|
||||
ReaderPreferences.ColorFilterMode.getOrNull(colorOverlayMode)?.second
|
||||
}
|
||||
@@ -453,8 +453,8 @@ class ReaderActivity : BaseActivity() {
|
||||
|
||||
val isHttpSource = viewModel.getSource() is HttpSource
|
||||
|
||||
val cropBorderPaged by readerPreferences.cropBorders().collectAsState()
|
||||
val cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState()
|
||||
val cropBorderPaged by readerPreferences.cropBorders.collectAsState()
|
||||
val cropBorderWebtoon by readerPreferences.cropBordersWebtoon.collectAsState()
|
||||
val isPagerType = ReadingMode.isPagerType(viewModel.getMangaReadingMode())
|
||||
val cropEnabled = if (isPagerType) cropBorderPaged else cropBorderWebtoon
|
||||
|
||||
@@ -508,7 +508,7 @@ class ReaderActivity : BaseActivity() {
|
||||
viewModel.showMenus(visible)
|
||||
if (visible) {
|
||||
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||
} else if (readerPreferences.fullscreen().get()) {
|
||||
} else if (readerPreferences.fullscreen.get()) {
|
||||
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||
}
|
||||
}
|
||||
@@ -535,10 +535,10 @@ class ReaderActivity : BaseActivity() {
|
||||
binding.viewerContainer.removeAllViews()
|
||||
}
|
||||
viewModel.onViewerLoaded(newViewer)
|
||||
updateViewerInset(readerPreferences.fullscreen().get(), readerPreferences.drawUnderCutout().get())
|
||||
updateViewerInset(readerPreferences.fullscreen.get(), readerPreferences.drawUnderCutout.get())
|
||||
binding.viewerContainer.addView(newViewer.getView())
|
||||
|
||||
if (readerPreferences.showReadingMode().get()) {
|
||||
if (readerPreferences.showReadingMode.get()) {
|
||||
showReadingModeToast(viewModel.getMangaReadingMode())
|
||||
}
|
||||
|
||||
@@ -839,7 +839,7 @@ class ReaderActivity : BaseActivity() {
|
||||
* Initializes the reader subscriptions.
|
||||
*/
|
||||
init {
|
||||
readerPreferences.readerTheme().changes()
|
||||
readerPreferences.readerTheme.changes()
|
||||
.onEach { theme ->
|
||||
binding.readerContainer.setBackgroundColor(
|
||||
when (theme) {
|
||||
@@ -852,21 +852,21 @@ class ReaderActivity : BaseActivity() {
|
||||
}
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
preferences.displayProfile().changes()
|
||||
preferences.displayProfile.changes()
|
||||
.onEach { setDisplayProfile(it) }
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
readerPreferences.keepScreenOn().changes()
|
||||
readerPreferences.keepScreenOn.changes()
|
||||
.onEach(::setKeepScreenOn)
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
readerPreferences.customBrightness().changes()
|
||||
readerPreferences.customBrightness.changes()
|
||||
.onEach(::setCustomBrightness)
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
combine(
|
||||
readerPreferences.grayscale().changes(),
|
||||
readerPreferences.invertedColors().changes(),
|
||||
readerPreferences.grayscale.changes(),
|
||||
readerPreferences.invertedColors.changes(),
|
||||
) { grayscale, invertedColors -> grayscale to invertedColors }
|
||||
.onEach { (grayscale, invertedColors) ->
|
||||
setLayerPaint(grayscale, invertedColors)
|
||||
@@ -874,8 +874,8 @@ class ReaderActivity : BaseActivity() {
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
combine(
|
||||
readerPreferences.fullscreen().changes(),
|
||||
readerPreferences.drawUnderCutout().changes(),
|
||||
readerPreferences.fullscreen.changes(),
|
||||
readerPreferences.drawUnderCutout.changes(),
|
||||
) { fullscreen, drawUnderCutout -> fullscreen to drawUnderCutout }
|
||||
.onEach { (fullscreen, drawUnderCutout) ->
|
||||
updateViewerInset(fullscreen, drawUnderCutout)
|
||||
@@ -929,7 +929,7 @@ class ReaderActivity : BaseActivity() {
|
||||
*/
|
||||
private fun setCustomBrightness(enabled: Boolean) {
|
||||
if (enabled) {
|
||||
readerPreferences.customBrightnessValue().changes()
|
||||
readerPreferences.customBrightnessValue.changes()
|
||||
.sample(100)
|
||||
.onEach(::setCustomBrightnessValue)
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
@@ -162,11 +162,11 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
?: error("Requested chapter of id $chapterId not found in chapter list")
|
||||
|
||||
val chaptersForReader = when {
|
||||
(readerPreferences.skipRead().get() || readerPreferences.skipFiltered().get()) -> {
|
||||
(readerPreferences.skipRead.get() || readerPreferences.skipFiltered.get()) -> {
|
||||
val filteredChapters = chapters.filterNot {
|
||||
when {
|
||||
readerPreferences.skipRead().get() && it.read -> true
|
||||
readerPreferences.skipFiltered().get() -> {
|
||||
readerPreferences.skipRead.get() && it.read -> true
|
||||
readerPreferences.skipFiltered.get() -> {
|
||||
(manga.unreadFilterRaw == Manga.CHAPTER_SHOW_READ && !it.read) ||
|
||||
(manga.unreadFilterRaw == Manga.CHAPTER_SHOW_UNREAD && it.read) ||
|
||||
(
|
||||
@@ -208,14 +208,14 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
chaptersForReader
|
||||
.sortedWith(getChapterSort(manga, sortDescending = false))
|
||||
.run {
|
||||
if (readerPreferences.skipDupe().get()) {
|
||||
if (readerPreferences.skipDupe.get()) {
|
||||
removeDuplicates(selectedChapter)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
.run {
|
||||
if (basePreferences.downloadedOnly().get()) {
|
||||
if (basePreferences.downloadedOnly.get()) {
|
||||
filterDownloaded(manga)
|
||||
} else {
|
||||
this
|
||||
@@ -226,7 +226,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
private val incognitoMode: Boolean by lazy { getIncognitoState.await(manga?.source) }
|
||||
private val downloadAheadAmount = downloadPreferences.autoDownloadWhileReading().get()
|
||||
private val downloadAheadAmount = downloadPreferences.autoDownloadWhileReading.get()
|
||||
|
||||
init {
|
||||
// To save state
|
||||
@@ -482,7 +482,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
if (!isNextChapterDownloaded) return@launchIO
|
||||
|
||||
val chaptersToDownload = getNextChapters.await(manga.id, nextChapter.id!!).run {
|
||||
if (readerPreferences.skipDupe().get()) {
|
||||
if (readerPreferences.skipDupe.get()) {
|
||||
removeDuplicates(nextChapter.toDomainChapter()!!)
|
||||
} else {
|
||||
this
|
||||
@@ -512,7 +512,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
* @param currentChapter current chapter, which is going to be marked as read.
|
||||
*/
|
||||
private fun deleteChapterIfNeeded(currentChapter: ReaderChapter) {
|
||||
val removeAfterReadSlots = downloadPreferences.removeAfterReadSlots().get()
|
||||
val removeAfterReadSlots = downloadPreferences.removeAfterReadSlots.get()
|
||||
if (removeAfterReadSlots == -1) return
|
||||
|
||||
// Determine which chapter should be deleted and enqueue
|
||||
@@ -562,7 +562,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
updateTrackChapterRead(readerChapter)
|
||||
deleteChapterIfNeeded(readerChapter)
|
||||
|
||||
val markDuplicateAsRead = libraryPreferences.markDuplicateReadChapterAsRead().get()
|
||||
val markDuplicateAsRead = libraryPreferences.markDuplicateReadChapterAsRead.get()
|
||||
.contains(LibraryPreferences.MARK_DUPLICATE_CHAPTER_READ_EXISTING)
|
||||
if (!markDuplicateAsRead) return
|
||||
|
||||
@@ -666,7 +666,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
* Returns the viewer position used by this manga or the default one.
|
||||
*/
|
||||
fun getMangaReadingMode(resolveDefault: Boolean = true): Int {
|
||||
val default = readerPreferences.defaultReadingMode().get()
|
||||
val default = readerPreferences.defaultReadingMode.get()
|
||||
val readingMode = ReadingMode.fromPreference(manga?.readingMode?.toInt())
|
||||
return when {
|
||||
resolveDefault && readingMode == ReadingMode.DEFAULT -> default
|
||||
@@ -702,7 +702,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
* Returns the orientation type used by this manga or the default one.
|
||||
*/
|
||||
fun getMangaOrientation(resolveDefault: Boolean = true): Int {
|
||||
val default = readerPreferences.defaultOrientationType().get()
|
||||
val default = readerPreferences.defaultOrientationType.get()
|
||||
val orientation = ReaderOrientation.fromPreference(manga?.readerOrientation?.toInt())
|
||||
return when {
|
||||
resolveDefault && orientation == ReaderOrientation.DEFAULT -> default
|
||||
@@ -738,9 +738,9 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
fun toggleCropBorders(): Boolean {
|
||||
val isPagerType = ReadingMode.isPagerType(getMangaReadingMode())
|
||||
return if (isPagerType) {
|
||||
readerPreferences.cropBorders().toggle()
|
||||
readerPreferences.cropBorders.toggle()
|
||||
} else {
|
||||
readerPreferences.cropBordersWebtoon().toggle()
|
||||
readerPreferences.cropBordersWebtoon.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -807,7 +807,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
val filename = generateFilename(manga, page)
|
||||
|
||||
// Pictures directory.
|
||||
val relativePath = if (readerPreferences.folderPerManga().get()) {
|
||||
val relativePath = if (readerPreferences.folderPerManga.get()) {
|
||||
DiskUtil.buildValidFilename(
|
||||
manga.title,
|
||||
)
|
||||
@@ -911,7 +911,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||
*/
|
||||
private fun updateTrackChapterRead(readerChapter: ReaderChapter) {
|
||||
if (incognitoMode) return
|
||||
if (!trackPreferences.autoUpdateTrack().get()) return
|
||||
if (!trackPreferences.autoUpdateTrack.get()) return
|
||||
|
||||
val manga = manga ?: return
|
||||
val context = Injekt.get<Application>()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user