diff --git a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt index c075ce7a0..ba3869210 100644 --- a/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/history/HistoryScreen.kt @@ -5,12 +5,12 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.DeleteSweep -import androidx.compose.material.icons.outlined.Panorama +import androidx.compose.material.icons.outlined.FilterList +import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.tooling.preview.PreviewParameter @@ -23,19 +23,16 @@ import eu.kanade.presentation.history.components.HistoryItem import eu.kanade.presentation.theme.TachiyomiPreviewTheme import eu.kanade.presentation.util.animateItemFastScroll import eu.kanade.tachiyomi.ui.history.HistoryScreenModel -import eu.kanade.tachiyomi.ui.updates.UpdatesSettingsScreenModel import kotlinx.collections.immutable.persistentListOf import tachiyomi.domain.history.model.HistoryWithRelations -import tachiyomi.domain.updates.service.UpdatesPreferences import tachiyomi.i18n.MR -import tachiyomi.i18n.kmk.KMR import tachiyomi.presentation.core.components.FastScrollLazyColumn import tachiyomi.presentation.core.components.ListGroupHeader import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.screens.EmptyScreen import tachiyomi.presentation.core.screens.LoadingScreen -import tachiyomi.presentation.core.util.collectAsState +import tachiyomi.presentation.core.theme.active import java.time.LocalDate @Composable @@ -48,13 +45,11 @@ fun HistoryScreen( onClickFavorite: (mangaId: Long) -> Unit, onDialogChange: (HistoryScreenModel.Dialog?) -> Unit, // KMK --> - settingsScreenModel: UpdatesSettingsScreenModel, + onFilterClicked: () -> Unit, + hasActiveFilters: Boolean, + usePanoramaCover: Boolean, // KMK <-- ) { - // KMK --> - val usePanoramaCover by settingsScreenModel.updatesPreferences.usePanoramaCover().collectAsState() - // KMK <-- - Scaffold( topBar = { scrollBehavior -> SearchToolbar( @@ -63,33 +58,23 @@ fun HistoryScreen( onChangeSearchQuery = onSearchQueryChange, actions = { AppBarActions( - // KMK --> - persistentListOf().builder() - .apply { - if (!state.list.isNullOrEmpty()) { - add( - AppBar.Action( - title = stringResource(KMR.strings.action_panorama_cover), - icon = Icons.Outlined.Panorama, - iconTint = MaterialTheme.colorScheme.primary.takeIf { usePanoramaCover }, - onClick = { settingsScreenModel.toggleSwitch(UpdatesPreferences::usePanoramaCover) }, - ), - ) - } - add( - // KMK <-- - AppBar.Action( - title = stringResource(MR.strings.pref_clear_history), - icon = Icons.Outlined.DeleteSweep, - onClick = { - onDialogChange(HistoryScreenModel.Dialog.DeleteAll) - }, - ), - // KMK --> - ) - } - .build(), - // KMK <-- + persistentListOf( + // KMK --> + AppBar.Action( + title = stringResource(MR.strings.action_filter), + icon = Icons.Outlined.FilterList, + iconTint = if (hasActiveFilters) MaterialTheme.colorScheme.active else LocalContentColor.current, + onClick = onFilterClicked, + ), + // KMK <-- + AppBar.Action( + title = stringResource(MR.strings.pref_clear_history), + icon = Icons.Outlined.DeleteSweep, + onClick = { + onDialogChange(HistoryScreenModel.Dialog.DeleteAll) + }, + ), + ), ) }, scrollBehavior = scrollBehavior, @@ -198,7 +183,6 @@ internal fun HistoryScreenPreviews( @PreviewParameter(HistoryScreenModelStateProvider::class) historyState: HistoryScreenModel.State, ) { - val settingsScreenModel = UpdatesSettingsScreenModel() TachiyomiPreviewTheme { HistoryScreen( state = historyState, @@ -208,7 +192,11 @@ internal fun HistoryScreenPreviews( onClickResume = { _, _ -> run {} }, onDialogChange = {}, onClickFavorite = {}, - settingsScreenModel = settingsScreenModel, + // KMK --> + onFilterClicked = {}, + hasActiveFilters = true, + usePanoramaCover = true, + // KMK <-- ) } } diff --git a/app/src/main/java/eu/kanade/presentation/history/HistoryScreenModelStateProvider.kt b/app/src/main/java/eu/kanade/presentation/history/HistoryScreenModelStateProvider.kt index 6b6404a60..76c1d4883 100644 --- a/app/src/main/java/eu/kanade/presentation/history/HistoryScreenModelStateProvider.kt +++ b/app/src/main/java/eu/kanade/presentation/history/HistoryScreenModelStateProvider.kt @@ -101,8 +101,8 @@ class HistoryScreenModelStateProvider : PreviewParameterProvider read = Random.nextBoolean(), lastPageRead = Random.nextLong(1, 10), - totalChapters = Random.nextLong(1, 100), - readCount = 1, + totalCountCalculated = Random.nextLong(1, 100), + readCountCalculated = 1, // KMK <-- readAt = Date.from(Instant.now()), readDuration = Random.nextLong(), diff --git a/app/src/main/java/eu/kanade/presentation/history/components/HistoryFilterDialog.kt b/app/src/main/java/eu/kanade/presentation/history/components/HistoryFilterDialog.kt new file mode 100644 index 000000000..5d0a9ad39 --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/history/components/HistoryFilterDialog.kt @@ -0,0 +1,102 @@ +package eu.kanade.presentation.history.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import eu.kanade.presentation.components.TabbedDialog +import eu.kanade.presentation.components.TabbedDialogPaddings +import eu.kanade.tachiyomi.ui.history.HistorySettingsScreenModel +import kotlinx.collections.immutable.persistentListOf +import tachiyomi.domain.history.service.HistoryPreferences +import tachiyomi.i18n.MR +import tachiyomi.i18n.kmk.KMR +import tachiyomi.presentation.core.components.SettingsItemsPaddings +import tachiyomi.presentation.core.components.TriStateItem +import tachiyomi.presentation.core.components.material.padding +import tachiyomi.presentation.core.i18n.stringResource +import tachiyomi.presentation.core.util.collectAsState + +@Composable +fun HistoryFilterDialog( + onDismissRequest: () -> Unit, + screenModel: HistorySettingsScreenModel, +) { + TabbedDialog( + onDismissRequest = onDismissRequest, + tabTitles = persistentListOf( + stringResource(MR.strings.action_filter), + ), + ) { + Column( + modifier = Modifier + .padding(vertical = TabbedDialogPaddings.Vertical) + .verticalScroll(rememberScrollState()), + ) { + FilterSheet(screenModel = screenModel) + } + } +} + +@Composable +private fun ColumnScope.FilterSheet( + screenModel: HistorySettingsScreenModel, +) { + val filterUnfinishedManga by screenModel.historyPreferences.filterUnfinishedManga().collectAsState() + TriStateItem( + label = stringResource(KMR.strings.action_filter_unfinished_manga), + state = filterUnfinishedManga, + onClick = { screenModel.toggleFilter(HistoryPreferences::filterUnfinishedManga) }, + ) + + val filterUnfinishedChapter by screenModel.historyPreferences.filterUnfinishedChapter().collectAsState() + TriStateItem( + label = stringResource(KMR.strings.action_filter_unfinished_chapter), + state = filterUnfinishedChapter, + onClick = { screenModel.toggleFilter(HistoryPreferences::filterUnfinishedChapter) }, + ) + + val filterNonLibraryManga by screenModel.historyPreferences.filterNonLibraryManga().collectAsState() + TriStateItem( + label = stringResource(KMR.strings.action_filter_non_library_entries), + state = filterNonLibraryManga, + onClick = { screenModel.toggleFilter(HistoryPreferences::filterNonLibraryManga) }, + ) + + HorizontalDivider(modifier = Modifier.padding(MaterialTheme.padding.small)) + + val panoramaCover by screenModel.historyPreferences.usePanoramaCover().collectAsState() + + Row( + modifier = Modifier + .clickable { screenModel.toggleSwitch(HistoryPreferences::usePanoramaCover) } + .fillMaxWidth() + .padding(horizontal = SettingsItemsPaddings.Horizontal), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Text( + text = stringResource(KMR.strings.action_panorama_cover), + color = MaterialTheme.colorScheme.onSurface, + style = MaterialTheme.typography.bodyMedium, + ) + + Switch( + checked = panoramaCover, + onCheckedChange = { screenModel.toggleSwitch(HistoryPreferences::usePanoramaCover) }, + ) + } +} diff --git a/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt b/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt index c5e76e1e6..e6b33c401 100644 --- a/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt +++ b/app/src/main/java/eu/kanade/presentation/history/components/HistoryItem.kt @@ -38,6 +38,7 @@ import eu.kanade.tachiyomi.util.lang.toTimestampString import exh.debug.DebugToggles import tachiyomi.domain.history.model.HistoryWithRelations import tachiyomi.i18n.MR +import tachiyomi.i18n.kmk.KMR import tachiyomi.presentation.core.components.material.DISABLED_ALPHA import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.i18n.stringResource @@ -139,7 +140,7 @@ fun HistoryItem( if (hasUnread) { Icon( imageVector = Icons.Filled.Circle, - contentDescription = stringResource(MR.strings.unread), + contentDescription = stringResource(KMR.strings.action_filter_unfinished_manga), modifier = Modifier .height(8.dp) .padding(end = 4.dp), diff --git a/app/src/main/java/eu/kanade/presentation/history/components/HistoryWithRelationsProvider.kt b/app/src/main/java/eu/kanade/presentation/history/components/HistoryWithRelationsProvider.kt index 958ea37c6..8cd1d6cb1 100644 --- a/app/src/main/java/eu/kanade/presentation/history/components/HistoryWithRelationsProvider.kt +++ b/app/src/main/java/eu/kanade/presentation/history/components/HistoryWithRelationsProvider.kt @@ -17,8 +17,8 @@ internal class HistoryWithRelationsProvider : PreviewParameterProvider read = true, lastPageRead = 5, - totalChapters = 5L, - readCount = 3L, + totalCountCalculated = 5L, + readCountCalculated = 3L, // KMK <-- readAt = Date(1697247357L), readDuration = 123L, @@ -42,8 +42,8 @@ internal class HistoryWithRelationsProvider : PreviewParameterProvider read = false, lastPageRead = 5, - totalChapters = 5L, - readCount = 3L, + totalCountCalculated = 5L, + readCountCalculated = 3L, // KMK <-- readAt = null, readDuration = 123L, @@ -67,8 +67,8 @@ internal class HistoryWithRelationsProvider : PreviewParameterProvider read = true, lastPageRead = 5, - totalChapters = 5L, - readCount = 3L, + totalCountCalculated = 5L, + readCountCalculated = 3L, // KMK <-- readAt = Date(1697247357L), readDuration = 123L, diff --git a/app/src/main/java/eu/kanade/tachiyomi/di/PreferenceModule.kt b/app/src/main/java/eu/kanade/tachiyomi/di/PreferenceModule.kt index 6e6608f74..875e121c2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/di/PreferenceModule.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/di/PreferenceModule.kt @@ -17,6 +17,7 @@ import tachiyomi.core.common.preference.PreferenceStore import tachiyomi.core.common.storage.AndroidStorageFolderProvider import tachiyomi.domain.backup.service.BackupPreferences import tachiyomi.domain.download.service.DownloadPreferences +import tachiyomi.domain.history.service.HistoryPreferences import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.storage.service.StoragePreferences import tachiyomi.domain.updates.service.UpdatesPreferences @@ -52,6 +53,11 @@ class PreferenceModule(val app: Application) : InjektModule { addSingletonFactory { UpdatesPreferences(get()) } + // KMK --> + addSingletonFactory { + HistoryPreferences(get()) + } + // KMK <-- addSingletonFactory { ReaderPreferences(get()) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt index 7db4fdec3..3aec5caf6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryScreenModel.kt @@ -15,15 +15,19 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import logcat.LogPriority import tachiyomi.core.common.preference.CheckboxState +import tachiyomi.core.common.preference.TriState import tachiyomi.core.common.preference.mapAsCheckboxState import tachiyomi.core.common.util.lang.launchIO import tachiyomi.core.common.util.lang.withIOContext @@ -36,6 +40,7 @@ import tachiyomi.domain.history.interactor.GetHistory import tachiyomi.domain.history.interactor.GetNextChapters import tachiyomi.domain.history.interactor.RemoveHistory import tachiyomi.domain.history.model.HistoryWithRelations +import tachiyomi.domain.history.service.HistoryPreferences import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.manga.interactor.GetDuplicateLibraryManga import tachiyomi.domain.manga.interactor.GetManga @@ -58,6 +63,9 @@ class HistoryScreenModel( private val updateManga: UpdateManga = Injekt.get(), val snackbarHostState: SnackbarHostState = SnackbarHostState(), private val sourceManager: SourceManager = Injekt.get(), + // KMK --> + private val historyPreferences: HistoryPreferences = Injekt.get(), + // KMK <-- ) : StateScreenModel(State()) { private val _events: Channel = Channel(Channel.UNLIMITED) @@ -65,10 +73,25 @@ class HistoryScreenModel( init { screenModelScope.launch { - state.map { it.searchQuery } - .distinctUntilChanged() - .flatMapLatest { query -> - getHistory.subscribe(query ?: "") + // KMK --> + combine( + // KMK <-- + state.map { it.searchQuery } + .distinctUntilChanged(), + // KMK --> + getHistoryItemPreferenceFlow() + .distinctUntilChanged(), + ) { query, itemPreferences -> query to itemPreferences } + .flatMapLatest { (query, pref) -> + // KMK <-- + getHistory.subscribe( + query ?: "", + // KMK --> + unfinishedManga = pref.filterUnfinishedManga.toBooleanOrNull(), + unfinishedChapter = pref.filterUnfinishedChapter.toBooleanOrNull(), + nonLibraryEntries = pref.filterNonLibraryManga.toBooleanOrNull(), + // KMK <-- + ) .distinctUntilChanged() .catch { error -> logcat(LogPriority.ERROR, error) @@ -79,6 +102,25 @@ class HistoryScreenModel( } .collect { newList -> mutableState.update { it.copy(list = newList) } } } + + // KMK --> + getHistoryItemPreferenceFlow() + .map { prefs -> + listOf( + prefs.filterUnfinishedManga, + prefs.filterUnfinishedChapter, + prefs.filterNonLibraryManga, + ) + .any { it != TriState.DISABLED } + } + .distinctUntilChanged() + .onEach { + mutableState.update { state -> + state.copy(hasActiveFilters = it) + } + } + .launchIn(screenModelScope) + // KMK <-- } private fun List.toHistoryUiModels(): List { @@ -237,11 +279,41 @@ class HistoryScreenModel( } } + // KMK --> + private fun getHistoryItemPreferenceFlow(): Flow { + return combine( + historyPreferences.filterUnfinishedManga().changes(), + historyPreferences.filterUnfinishedChapter().changes(), + historyPreferences.filterNonLibraryManga().changes(), + ) { unfinishedManga, unfinishedChapter, nonLibraryManga -> + ItemPreferences( + filterUnfinishedManga = unfinishedManga, + filterUnfinishedChapter = unfinishedChapter, + filterNonLibraryManga = nonLibraryManga, + ) + } + } + + fun showFilterDialog() { + mutableState.update { it.copy(dialog = Dialog.FilterSheet) } + } + + @Immutable + private data class ItemPreferences( + val filterUnfinishedManga: TriState, + val filterUnfinishedChapter: TriState, + val filterNonLibraryManga: TriState, + ) + // KMK <-- + @Immutable data class State( val searchQuery: String? = null, val list: List? = null, val dialog: Dialog? = null, + // KMk --> + val hasActiveFilters: Boolean = false, + // KMK <-- ) sealed interface Dialog { @@ -253,8 +325,21 @@ class HistoryScreenModel( val initialSelection: ImmutableList>, ) : Dialog data class Migrate(val target: Manga, val current: Manga) : Dialog + // KMK --> + data object FilterSheet : Dialog + // KMK <-- } + // KMK --> + private fun TriState.toBooleanOrNull(): Boolean? { + return when (this) { + TriState.DISABLED -> null + TriState.ENABLED_IS -> true + TriState.ENABLED_NOT -> false + } + } + // KMK <-- + sealed interface Event { data class OpenChapter(val chapter: Chapter?) : Event data object InternalError : Event diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistorySettingsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistorySettingsScreenModel.kt new file mode 100644 index 000000000..3f099e902 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistorySettingsScreenModel.kt @@ -0,0 +1,24 @@ +package eu.kanade.tachiyomi.ui.history + +import cafe.adriel.voyager.core.model.ScreenModel +import tachiyomi.core.common.preference.Preference +import tachiyomi.core.common.preference.TriState +import tachiyomi.core.common.preference.getAndSet +import tachiyomi.domain.history.service.HistoryPreferences +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get + +class HistorySettingsScreenModel( + val historyPreferences: HistoryPreferences = Injekt.get(), +) : ScreenModel { + + fun toggleFilter(preference: (HistoryPreferences) -> Preference) { + preference(historyPreferences).getAndSet { + it.next() + } + } + + fun toggleSwitch(preference: (HistoryPreferences) -> Preference) { + preference(historyPreferences).getAndSet { !it } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt index 545f7c75f..42e5b4073 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/history/HistoryTab.kt @@ -24,6 +24,7 @@ import eu.kanade.presentation.category.components.ChangeCategoryDialog import eu.kanade.presentation.history.HistoryScreen import eu.kanade.presentation.history.components.HistoryDeleteAllDialog import eu.kanade.presentation.history.components.HistoryDeleteDialog +import eu.kanade.presentation.history.components.HistoryFilterDialog import eu.kanade.presentation.manga.DuplicateMangaDialog import eu.kanade.presentation.util.Tab import eu.kanade.tachiyomi.R @@ -33,7 +34,6 @@ import eu.kanade.tachiyomi.ui.category.CategoryScreen import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.manga.MangaScreen import eu.kanade.tachiyomi.ui.reader.ReaderActivity -import eu.kanade.tachiyomi.ui.updates.UpdatesSettingsScreenModel import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.receiveAsFlow @@ -43,6 +43,7 @@ import tachiyomi.core.common.util.lang.launchIO import tachiyomi.domain.chapter.model.Chapter import tachiyomi.i18n.MR import tachiyomi.presentation.core.i18n.stringResource +import tachiyomi.presentation.core.util.collectAsState import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -87,7 +88,8 @@ data object HistoryTab : Tab { val screenModel = rememberScreenModel { HistoryScreenModel() } val state by screenModel.state.collectAsState() // KMK --> - val settingsScreenModel = rememberScreenModel { UpdatesSettingsScreenModel() } + val settingsScreenModel = rememberScreenModel { HistorySettingsScreenModel() } + val usePanoramaCover by settingsScreenModel.historyPreferences.usePanoramaCover().collectAsState() // KMK <-- HistoryScreen( @@ -99,7 +101,9 @@ data object HistoryTab : Tab { onDialogChange = screenModel::setDialog, onClickFavorite = screenModel::addFavorite, // KMK --> - settingsScreenModel = settingsScreenModel, + onFilterClicked = screenModel::showFilterDialog, + hasActiveFilters = state.hasActiveFilters, + usePanoramaCover = usePanoramaCover, // KMK <-- ) @@ -154,6 +158,14 @@ data object HistoryTab : Tab { onDismissRequest = onDismissRequest, ) } + // KMK --> + is HistoryScreenModel.Dialog.FilterSheet -> { + HistoryFilterDialog( + onDismissRequest = onDismissRequest, + screenModel = settingsScreenModel, + ) + } + // KMK <-- null -> {} } diff --git a/data/src/main/java/tachiyomi/data/history/HistoryMapper.kt b/data/src/main/java/tachiyomi/data/history/HistoryMapper.kt index 7cf405526..3dde93430 100644 --- a/data/src/main/java/tachiyomi/data/history/HistoryMapper.kt +++ b/data/src/main/java/tachiyomi/data/history/HistoryMapper.kt @@ -47,8 +47,8 @@ object HistoryMapper { // KMK --> read = read, lastPageRead = lastPageRead, - totalChapters = totalCount.toLong(), - readCount = readCount.toLong(), + totalCountCalculated = totalCount.toLong(), + readCountCalculated = readCount.toLong(), // KMK <-- readAt = readAt, readDuration = readDuration, diff --git a/data/src/main/java/tachiyomi/data/history/HistoryRepositoryImpl.kt b/data/src/main/java/tachiyomi/data/history/HistoryRepositoryImpl.kt index cdff58939..9829b1c2e 100644 --- a/data/src/main/java/tachiyomi/data/history/HistoryRepositoryImpl.kt +++ b/data/src/main/java/tachiyomi/data/history/HistoryRepositoryImpl.kt @@ -2,6 +2,7 @@ package tachiyomi.data.history import kotlinx.coroutines.flow.Flow import logcat.LogPriority +import tachiyomi.core.common.util.lang.toLong import tachiyomi.core.common.util.system.logcat import tachiyomi.data.DatabaseHandler import tachiyomi.domain.history.model.History @@ -14,11 +15,23 @@ class HistoryRepositoryImpl( private val handler: DatabaseHandler, ) : HistoryRepository { - override fun getHistory(query: String): Flow> { + override fun getHistory( + query: String, + // KMK --> + unfinishedManga: Boolean?, + unfinishedChapter: Boolean?, + nonLibraryEntries: Boolean?, + // KMK <-- + ): Flow> { return handler.subscribeToList { historyViewQueries.history( + // KMK --> Manga.CHAPTER_SHOW_NOT_BOOKMARKED, Manga.CHAPTER_SHOW_BOOKMARKED, + unfinishedManga?.toLong(), + unfinishedChapter, + nonLibraryEntries, + // KMK <-- query, HistoryMapper::mapHistoryWithRelations, ) diff --git a/data/src/main/sqldelight/tachiyomi/view/historyView.sq b/data/src/main/sqldelight/tachiyomi/view/historyView.sq index a4257ea0a..709fe70a0 100644 --- a/data/src/main/sqldelight/tachiyomi/view/historyView.sq +++ b/data/src/main/sqldelight/tachiyomi/view/historyView.sq @@ -71,17 +71,26 @@ CASE WHEN (chapterFlags & :bookmarkUnmask) != 0 THEN totalCount - bookmarkCount WHEN (chapterFlags & :bookmarkMask) != 0 THEN bookmarkCount ELSE totalCount -END AS totalCount, +END AS totalCountCalculated, CASE WHEN (chapterFlags & :bookmarkUnmask) != 0 THEN readCount - bookmarkReadCount WHEN (chapterFlags & :bookmarkMask) != 0 THEN bookmarkReadCount ELSE readCount -END AS readCount, +END AS readCountCalculated, -- KMK <-- readAt, readDuration FROM historyView WHERE historyView.readAt > 0 +-- KMK --> +AND ( + :unfinishedManga IS NULL + OR (:unfinishedManga = 1 AND totalCountCalculated > readCountCalculated) + OR (:unfinishedManga = 0 AND totalCountCalculated <= readCountCalculated) +) +AND (:unfinishedChapter IS NULL OR read != :unfinishedChapter) +AND (:nonLibraryEntries IS NULL OR favorite != :nonLibraryEntries) +-- KMK <-- AND maxReadAtChapterId = historyView.chapterId AND lower(historyView.title) LIKE ('%' || :query || '%') ORDER BY readAt DESC; diff --git a/domain/src/main/java/tachiyomi/domain/history/interactor/GetHistory.kt b/domain/src/main/java/tachiyomi/domain/history/interactor/GetHistory.kt index 8a40096f8..1a8f18d2a 100644 --- a/domain/src/main/java/tachiyomi/domain/history/interactor/GetHistory.kt +++ b/domain/src/main/java/tachiyomi/domain/history/interactor/GetHistory.kt @@ -13,7 +13,21 @@ class GetHistory( return repository.getHistoryByMangaId(mangaId) } - fun subscribe(query: String): Flow> { - return repository.getHistory(query) + fun subscribe( + query: String, + // KMK --> + unfinishedManga: Boolean?, + unfinishedChapter: Boolean?, + nonLibraryEntries: Boolean?, + // KMK <-- + ): Flow> { + return repository.getHistory( + query, + // KMK --> + unfinishedManga, + unfinishedChapter, + nonLibraryEntries, + // KMK <-- + ) } } diff --git a/domain/src/main/java/tachiyomi/domain/history/model/HistoryWithRelations.kt b/domain/src/main/java/tachiyomi/domain/history/model/HistoryWithRelations.kt index 85a5e19fd..d57601320 100644 --- a/domain/src/main/java/tachiyomi/domain/history/model/HistoryWithRelations.kt +++ b/domain/src/main/java/tachiyomi/domain/history/model/HistoryWithRelations.kt @@ -16,8 +16,8 @@ data class HistoryWithRelations( // KMK --> val read: Boolean, val lastPageRead: Long, - val totalChapters: Long, - val readCount: Long, + val totalCountCalculated: Long, + val readCountCalculated: Long, // KMK <-- val readAt: Date?, val readDuration: Long, @@ -33,6 +33,6 @@ data class HistoryWithRelations( // KMK --> val unreadCount - get() = totalChapters - readCount + get() = totalCountCalculated - readCountCalculated // KMK <-- } diff --git a/domain/src/main/java/tachiyomi/domain/history/repository/HistoryRepository.kt b/domain/src/main/java/tachiyomi/domain/history/repository/HistoryRepository.kt index 0c5a7366f..43c5c8cd2 100644 --- a/domain/src/main/java/tachiyomi/domain/history/repository/HistoryRepository.kt +++ b/domain/src/main/java/tachiyomi/domain/history/repository/HistoryRepository.kt @@ -7,7 +7,14 @@ import tachiyomi.domain.history.model.HistoryWithRelations interface HistoryRepository { - fun getHistory(query: String): Flow> + fun getHistory( + query: String, + // KMK --> + unfinishedManga: Boolean?, + unfinishedChapter: Boolean?, + nonLibraryEntries: Boolean?, + // KMK <-- + ): Flow> suspend fun getLastHistory(): HistoryWithRelations? diff --git a/domain/src/main/java/tachiyomi/domain/history/service/HistoryPreferences.kt b/domain/src/main/java/tachiyomi/domain/history/service/HistoryPreferences.kt new file mode 100644 index 000000000..4f4152f52 --- /dev/null +++ b/domain/src/main/java/tachiyomi/domain/history/service/HistoryPreferences.kt @@ -0,0 +1,31 @@ +package tachiyomi.domain.history.service + +import tachiyomi.core.common.preference.PreferenceStore +import tachiyomi.core.common.preference.TriState +import tachiyomi.core.common.preference.getEnum +import tachiyomi.domain.updates.service.USE_PANORAMA_COVER_PREF + +class HistoryPreferences( + private val preferenceStore: PreferenceStore, +) { + + fun filterUnfinishedManga() = preferenceStore.getEnum( + "pref_filter_history_unfinished_manga", + TriState.DISABLED, + ) + + fun filterUnfinishedChapter() = preferenceStore.getEnum( + "pref_filter_history_unfinished_chapter", + TriState.DISABLED, + ) + + fun filterNonLibraryManga() = preferenceStore.getEnum( + "pref_filter_history_non_library_manga", + TriState.DISABLED, + ) + + fun usePanoramaCover() = preferenceStore.getBoolean( + USE_PANORAMA_COVER_PREF, + false, + ) +} diff --git a/domain/src/main/java/tachiyomi/domain/updates/service/UpdatesPreferences.kt b/domain/src/main/java/tachiyomi/domain/updates/service/UpdatesPreferences.kt index 7b932c421..ed61a1adf 100644 --- a/domain/src/main/java/tachiyomi/domain/updates/service/UpdatesPreferences.kt +++ b/domain/src/main/java/tachiyomi/domain/updates/service/UpdatesPreferences.kt @@ -35,8 +35,12 @@ class UpdatesPreferences( // KMK --> fun usePanoramaCover() = preferenceStore.getBoolean( - "pref_updates_screen_use_panorama_cover", + USE_PANORAMA_COVER_PREF, false, ) // KMK <-- } + +// KMK --> +const val USE_PANORAMA_COVER_PREF = "pref_updates_history_screen_use_panorama_cover" +// KMK <-- diff --git a/i18n-kmk/src/commonMain/moko-resources/base/strings.xml b/i18n-kmk/src/commonMain/moko-resources/base/strings.xml index bad93256e..d909414a1 100644 --- a/i18n-kmk/src/commonMain/moko-resources/base/strings.xml +++ b/i18n-kmk/src/commonMain/moko-resources/base/strings.xml @@ -17,6 +17,10 @@ Open folder Clear manga Update + + Unfinished manga + Unfinished chapter + Non-library entries Copy first page to clipboard