Add "Play" button on manga in library (#8218)

* resume manga button in libarary

* work on resume button

* Backup

* work on opening the last read chapter

* backup

* renaming

* fab instead of image

* done with logic

* cleanup

* cleanup

* import cleanup

* cleanup...

* refactoring

* fixing logic

* fixing scopes

* Reworking design

* adding ability to turn on/off the feature

* cleanup

* refactoring, fixing logic, adding filter logic (partial)

* backup

* backup

* logic done

* backup before merge fix

* merge conflict....

* merge conflict...

* reworking ui logic

* removing unnecessary file

* refactoring

* refactoring

* review changes + minor parameter position movement

* commiting suggestion

Co-authored-by: arkon <arkon@users.noreply.github.com>

* fixing minor mistake

* moving ChapterFilter.kt

Co-authored-by: arkon <arkon@users.noreply.github.com>
(cherry picked from commit ba00d9e5d2c00b9cf415932bb2821bf9914fe248)

# Conflicts:
#	app/src/main/java/eu/kanade/presentation/components/CommonMangaItem.kt
#	app/src/main/java/eu/kanade/presentation/library/LibraryScreen.kt
#	app/src/main/java/eu/kanade/presentation/library/components/LibraryComfortableGrid.kt
#	app/src/main/java/eu/kanade/presentation/library/components/LibraryCompactGrid.kt
#	app/src/main/java/eu/kanade/presentation/library/components/LibraryContent.kt
#	app/src/main/java/eu/kanade/presentation/library/components/LibraryPager.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
This commit is contained in:
d-najd 2022-11-08 04:32:23 +01:00 committed by Jobobby04
parent 206aab6755
commit 1903453ce7
15 changed files with 305 additions and 219 deletions

View File

@ -0,0 +1,93 @@
package eu.kanade.domain.chapter.model
import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.TriStateFilter
import eu.kanade.domain.manga.model.isLocal
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.ui.manga.ChapterItem
import eu.kanade.tachiyomi.util.chapter.getChapterSort
import exh.md.utils.MdUtil
/**
* Applies the view filters to the list of chapters obtained from the database.
* @return an observable of the list of chapters filtered and sorted.
*/
fun List<Chapter>.applyFilters(manga: Manga, downloadManager: DownloadManager): List<Chapter> {
val isLocalManga = manga.isLocal()
val unreadFilter = manga.unreadFilter
val downloadedFilter = manga.downloadedFilter
val bookmarkedFilter = manga.bookmarkedFilter
return filter { chapter ->
when (unreadFilter) {
TriStateFilter.DISABLED -> true
TriStateFilter.ENABLED_IS -> !chapter.read
TriStateFilter.ENABLED_NOT -> chapter.read
}
}
.filter { chapter ->
when (bookmarkedFilter) {
TriStateFilter.DISABLED -> true
TriStateFilter.ENABLED_IS -> chapter.bookmark
TriStateFilter.ENABLED_NOT -> !chapter.bookmark
}
}
.filter { chapter ->
val downloaded = downloadManager.isChapterDownloaded(chapter.name, chapter.scanlator, manga.title, manga.source)
val downloadState = when {
downloaded -> Download.State.DOWNLOADED
else -> Download.State.NOT_DOWNLOADED
}
when (downloadedFilter) {
TriStateFilter.DISABLED -> true
TriStateFilter.ENABLED_IS -> downloadState == Download.State.DOWNLOADED || isLocalManga
TriStateFilter.ENABLED_NOT -> downloadState != Download.State.DOWNLOADED && !isLocalManga
}
}
// SY -->
.filter { chapter ->
manga.filteredScanlators.isNullOrEmpty() || MdUtil.getScanlators(chapter.scanlator).any { group -> manga.filteredScanlators.contains(group) }
}
// SY <--
.sortedWith(getChapterSort(manga))
}
/**
* Applies the view filters to the list of chapters obtained from the database.
* @return an observable of the list of chapters filtered and sorted.
*/
fun List<ChapterItem>.applyFilters(manga: Manga): Sequence<ChapterItem> {
val isLocalManga = manga.isLocal()
val unreadFilter = manga.unreadFilter
val downloadedFilter = manga.downloadedFilter
val bookmarkedFilter = manga.bookmarkedFilter
return asSequence()
.filter { (chapter) ->
when (unreadFilter) {
TriStateFilter.DISABLED -> true
TriStateFilter.ENABLED_IS -> !chapter.read
TriStateFilter.ENABLED_NOT -> chapter.read
}
}
.filter { (chapter) ->
when (bookmarkedFilter) {
TriStateFilter.DISABLED -> true
TriStateFilter.ENABLED_IS -> chapter.bookmark
TriStateFilter.ENABLED_NOT -> !chapter.bookmark
}
}
.filter {
when (downloadedFilter) {
TriStateFilter.DISABLED -> true
TriStateFilter.ENABLED_IS -> it.isDownloaded || isLocalManga
TriStateFilter.ENABLED_NOT -> !it.isDownloaded && !isLocalManga
}
}
// SY -->
.filter { chapter ->
manga.filteredScanlators.isNullOrEmpty() || MdUtil.getScanlators(chapter.chapter.scanlator).any { group -> manga.filteredScanlators.contains(group) }
}
// SY <--
.sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) }
}

View File

@ -35,6 +35,8 @@ class LibraryPreferences(
fun autoUpdateTrackers() = preferenceStore.getBoolean("auto_update_trackers", false) fun autoUpdateTrackers() = preferenceStore.getBoolean("auto_update_trackers", false)
fun showContinueReadingButton() = preferenceStore.getBoolean("display_continue_reading_button", false)
// region Filter // region Filter
fun filterDownloaded() = preferenceStore.getInt("pref_filter_library_downloaded", ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) fun filterDownloaded() = preferenceStore.getInt("pref_filter_library_downloaded", ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value)
@ -122,8 +124,6 @@ class LibraryPreferences(
fun groupLibraryUpdateType() = preferenceStore.getEnum("group_library_update_type", GroupLibraryMode.GLOBAL) fun groupLibraryUpdateType() = preferenceStore.getEnum("group_library_update_type", GroupLibraryMode.GLOBAL)
fun startReadingButton() = preferenceStore.getBoolean("start_reading_button", true)
fun groupLibraryBy() = preferenceStore.getInt("group_library_by", LibraryGroup.BY_DEFAULT) fun groupLibraryBy() = preferenceStore.getInt("group_library_by", LibraryGroup.BY_DEFAULT)
// SY <-- // SY <--

View File

@ -12,10 +12,17 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.LocalContentColor import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -41,6 +48,7 @@ object CommonMangaItemDefaults {
const val BrowseFavoriteCoverAlpha = 0.34f const val BrowseFavoriteCoverAlpha = 0.34f
} }
private val ContinueReadingButtonSize = 38.dp
private const val GridSelectedCoverAlpha = 0.76f private const val GridSelectedCoverAlpha = 0.76f
/** /**
@ -55,12 +63,10 @@ fun MangaCompactGridItem(
coverAlpha: Float = 1f, coverAlpha: Float = 1f,
coverBadgeStart: (@Composable RowScope.() -> Unit)? = null, coverBadgeStart: (@Composable RowScope.() -> Unit)? = null,
coverBadgeEnd: (@Composable RowScope.() -> Unit)? = null, coverBadgeEnd: (@Composable RowScope.() -> Unit)? = null,
// SY --> showContinueReadingButton: Boolean = false,
buttonTop: (@Composable () -> Unit)? = null,
buttonBottom: (@Composable () -> Unit)? = null,
// SY <--
onLongClick: () -> Unit, onLongClick: () -> Unit,
onClick: () -> Unit, onClick: () -> Unit,
onClickContinueReading: (() -> Unit)? = null,
) { ) {
GridItemSelectable( GridItemSelectable(
isSelected = isSelected, isSelected = isSelected,
@ -78,13 +84,14 @@ fun MangaCompactGridItem(
}, },
badgesStart = coverBadgeStart, badgesStart = coverBadgeStart,
badgesEnd = coverBadgeEnd, badgesEnd = coverBadgeEnd,
// SY -->
buttonTop = buttonTop,
buttonBottom = buttonBottom,
// SY <--
content = { content = {
if (title != null) { if (title != null) {
CoverTextOverlay(title = title) CoverTextOverlay(title = title, showContinueReadingButton)
}
},
continueReadingButton = {
if (showContinueReadingButton && onClickContinueReading != null) {
ContinueReadingButton(onClickContinueReading)
} }
}, },
) )
@ -95,7 +102,10 @@ fun MangaCompactGridItem(
* Title overlay for [MangaCompactGridItem] * Title overlay for [MangaCompactGridItem]
*/ */
@Composable @Composable
private fun BoxScope.CoverTextOverlay(title: String) { private fun BoxScope.CoverTextOverlay(
title: String,
showContinueReadingButton: Boolean = false,
) {
Box( Box(
modifier = Modifier modifier = Modifier
.clip(RoundedCornerShape(bottomStart = 4.dp, bottomEnd = 4.dp)) .clip(RoundedCornerShape(bottomStart = 4.dp, bottomEnd = 4.dp))
@ -109,9 +119,10 @@ private fun BoxScope.CoverTextOverlay(title: String) {
.fillMaxWidth() .fillMaxWidth()
.align(Alignment.BottomCenter), .align(Alignment.BottomCenter),
) )
val endPadding = if (showContinueReadingButton) ContinueReadingButtonSize else 8.dp
GridItemTitle( GridItemTitle(
modifier = Modifier modifier = Modifier
.padding(8.dp) .padding(start = 8.dp, top = 8.dp, end = endPadding, bottom = 8.dp)
.align(Alignment.BottomStart), .align(Alignment.BottomStart),
title = title, title = title,
style = MaterialTheme.typography.titleSmall.copy( style = MaterialTheme.typography.titleSmall.copy(
@ -135,12 +146,10 @@ fun MangaComfortableGridItem(
coverAlpha: Float = 1f, coverAlpha: Float = 1f,
coverBadgeStart: (@Composable RowScope.() -> Unit)? = null, coverBadgeStart: (@Composable RowScope.() -> Unit)? = null,
coverBadgeEnd: (@Composable RowScope.() -> Unit)? = null, coverBadgeEnd: (@Composable RowScope.() -> Unit)? = null,
// SY --> showContinueReadingButton: Boolean = false,
buttonTop: (@Composable () -> Unit)? = null,
buttonBottom: (@Composable () -> Unit)? = null,
// SY <--
onLongClick: () -> Unit, onLongClick: () -> Unit,
onClick: () -> Unit, onClick: () -> Unit,
onClickContinueReading: (() -> Unit)? = null,
) { ) {
GridItemSelectable( GridItemSelectable(
isSelected = isSelected, isSelected = isSelected,
@ -159,10 +168,11 @@ fun MangaComfortableGridItem(
}, },
badgesStart = coverBadgeStart, badgesStart = coverBadgeStart,
badgesEnd = coverBadgeEnd, badgesEnd = coverBadgeEnd,
// SY --> continueReadingButton = {
buttonTop = buttonTop, if (showContinueReadingButton && onClickContinueReading != null) {
buttonBottom = buttonBottom, ContinueReadingButton(onClickContinueReading)
// SY <-- }
},
) )
GridItemTitle( GridItemTitle(
modifier = Modifier.padding(4.dp), modifier = Modifier.padding(4.dp),
@ -182,10 +192,7 @@ private fun MangaGridCover(
cover: @Composable BoxScope.() -> Unit = {}, cover: @Composable BoxScope.() -> Unit = {},
badgesStart: (@Composable RowScope.() -> Unit)? = null, badgesStart: (@Composable RowScope.() -> Unit)? = null,
badgesEnd: (@Composable RowScope.() -> Unit)? = null, badgesEnd: (@Composable RowScope.() -> Unit)? = null,
// SY --> continueReadingButton: (@Composable BoxScope.() -> Unit)? = null,
buttonTop: (@Composable () -> Unit)? = null,
buttonBottom: (@Composable () -> Unit)? = null,
// SY <--
content: @Composable (BoxScope.() -> Unit)? = null, content: @Composable (BoxScope.() -> Unit)? = null,
) { ) {
Box( Box(
@ -204,26 +211,15 @@ private fun MangaGridCover(
) )
} }
// SY --> if (badgesEnd != null) {
Column(Modifier.align(Alignment.TopEnd), horizontalAlignment = Alignment.End) { BadgeGroup(
// SY <-- modifier = Modifier
if (badgesEnd != null) { .padding(4.dp)
BadgeGroup( .align(Alignment.TopEnd),
modifier = Modifier content = badgesEnd,
.padding(4.dp), )
// SY --> .align(Alignment.TopEnd), SY <--
content = badgesEnd,
)
}
// SY -->
buttonTop?.invoke()
} }
if (buttonBottom != null) { continueReadingButton?.invoke(this)
Box(Modifier.align(Alignment.BottomEnd)) {
buttonBottom()
}
}
// SY <--
} }
} }
@ -315,8 +311,10 @@ fun MangaListItem(
coverData: eu.kanade.domain.manga.model.MangaCover, coverData: eu.kanade.domain.manga.model.MangaCover,
coverAlpha: Float = 1f, coverAlpha: Float = 1f,
badge: @Composable RowScope.() -> Unit, badge: @Composable RowScope.() -> Unit,
showContinueReadingButton: Boolean = false,
onLongClick: () -> Unit, onLongClick: () -> Unit,
onClick: () -> Unit, onClick: () -> Unit,
onClickContinueReading: (() -> Unit)? = null,
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@ -345,5 +343,37 @@ fun MangaListItem(
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
) )
BadgeGroup(content = badge) BadgeGroup(content = badge)
if (showContinueReadingButton && onClickContinueReading != null) {
Box {
ContinueReadingButton(onClickContinueReading)
}
}
}
}
@Composable
private fun BoxScope.ContinueReadingButton(
onClickContinueReading: () -> Unit,
) {
FilledIconButton(
onClick = {
onClickContinueReading()
},
modifier = Modifier
.size(ContinueReadingButtonSize)
.padding(3.dp)
.align(Alignment.BottomEnd),
shape = MaterialTheme.shapes.small,
colors = IconButtonDefaults.filledIconButtonColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
contentColor = contentColorFor(MaterialTheme.colorScheme.primaryContainer),
),
) {
Icon(
imageVector = Icons.Filled.PlayArrow,
contentDescription = "",
modifier = Modifier
.size(15.dp),
)
} }
} }

View File

@ -29,6 +29,7 @@ import eu.kanade.tachiyomi.widget.TachiyomiBottomNavigationView
fun LibraryScreen( fun LibraryScreen(
presenter: LibraryPresenter, presenter: LibraryPresenter,
onMangaClicked: (Long) -> Unit, onMangaClicked: (Long) -> Unit,
onContinueReadingClicked: (LibraryManga) -> Unit,
onGlobalSearchClicked: () -> Unit, onGlobalSearchClicked: () -> Unit,
onChangeCategoryClicked: () -> Unit, onChangeCategoryClicked: () -> Unit,
onMarkAsReadClicked: () -> Unit, onMarkAsReadClicked: () -> Unit,
@ -46,7 +47,6 @@ fun LibraryScreen(
onClickMigrate: () -> Unit, onClickMigrate: () -> Unit,
onClickAddToMangaDex: () -> Unit, onClickAddToMangaDex: () -> Unit,
onClickSyncExh: () -> Unit, onClickSyncExh: () -> Unit,
onOpenReader: (LibraryManga) -> Unit,
// SY <-- // SY <--
) { ) {
val haptic = LocalHapticFeedback.current val haptic = LocalHapticFeedback.current
@ -119,6 +119,7 @@ fun LibraryScreen(
showMangaCount = presenter.mangaCountVisibility, showMangaCount = presenter.mangaCountVisibility,
onChangeCurrentPage = { presenter.activeCategory = it }, onChangeCurrentPage = { presenter.activeCategory = it },
onMangaClicked = onMangaClicked, onMangaClicked = onMangaClicked,
onContinueReadingClicked = onContinueReadingClicked,
onToggleSelection = { presenter.toggleSelection(it) }, onToggleSelection = { presenter.toggleSelection(it) },
onToggleRangeSelection = { onToggleRangeSelection = {
presenter.toggleRangeSelection(it) presenter.toggleRangeSelection(it)
@ -136,13 +137,10 @@ fun LibraryScreen(
showUnreadBadges = presenter.showUnreadBadges, showUnreadBadges = presenter.showUnreadBadges,
showLocalBadges = presenter.showLocalBadges, showLocalBadges = presenter.showLocalBadges,
showLanguageBadges = presenter.showLanguageBadges, showLanguageBadges = presenter.showLanguageBadges,
// SY --> showContinueReadingButton = presenter.showContinueReadingButton,
showStartReadingButton = presenter.showStartReadingButton,
// SY <--
isIncognitoMode = presenter.isIncognitoMode, isIncognitoMode = presenter.isIncognitoMode,
isDownloadOnly = presenter.isDownloadOnly, isDownloadOnly = presenter.isDownloadOnly,
// SY --> // SY -->
onOpenReader = onOpenReader,
getCategoryName = presenter::getCategoryName, getCategoryName = presenter::getCategoryName,
// SY <-- // SY <--
) )

View File

@ -18,19 +18,15 @@ fun LibraryComfortableGrid(
showUnreadBadges: Boolean, showUnreadBadges: Boolean,
showLocalBadges: Boolean, showLocalBadges: Boolean,
showLanguageBadges: Boolean, showLanguageBadges: Boolean,
// SY --> showContinueReadingButton: Boolean,
showStartReadingButton: Boolean,
// SY <--
columns: Int, columns: Int,
contentPadding: PaddingValues, contentPadding: PaddingValues,
selection: List<LibraryManga>, selection: List<LibraryManga>,
onClick: (LibraryManga) -> Unit, onClick: (LibraryManga) -> Unit,
onLongClick: (LibraryManga) -> Unit, onLongClick: (LibraryManga) -> Unit,
onClickContinueReading: (LibraryManga) -> Unit,
searchQuery: String?, searchQuery: String?,
onGlobalSearchClicked: () -> Unit, onGlobalSearchClicked: () -> Unit,
// SY -->
onOpenReader: (LibraryManga) -> Unit,
// SY <--
) { ) {
LazyLibraryGrid( LazyLibraryGrid(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
@ -71,15 +67,10 @@ fun LibraryComfortableGrid(
item = libraryItem, item = libraryItem,
) )
}, },
// SY --> showContinueReadingButton = showContinueReadingButton,
buttonBottom = if (showStartReadingButton && libraryItem.unreadCount > 0) {
{ StartReadingButton(onOpenReader = { onOpenReader(libraryItem.libraryManga) }) }
} else {
null
},
// SY <--
onLongClick = { onLongClick(libraryItem.libraryManga) }, onLongClick = { onLongClick(libraryItem.libraryManga) },
onClick = { onClick(libraryItem.libraryManga) }, onClick = { onClick(libraryItem.libraryManga) },
onClickContinueReading = { onClickContinueReading(libraryItem.libraryManga) },
) )
} }
} }

View File

@ -19,19 +19,15 @@ fun LibraryCompactGrid(
showUnreadBadges: Boolean, showUnreadBadges: Boolean,
showLocalBadges: Boolean, showLocalBadges: Boolean,
showLanguageBadges: Boolean, showLanguageBadges: Boolean,
// SY --> showContinueReadingButton: Boolean,
showStartReadingButton: Boolean,
// SY <--
columns: Int, columns: Int,
contentPadding: PaddingValues, contentPadding: PaddingValues,
selection: List<LibraryManga>, selection: List<LibraryManga>,
onClick: (LibraryManga) -> Unit, onClick: (LibraryManga) -> Unit,
onLongClick: (LibraryManga) -> Unit, onLongClick: (LibraryManga) -> Unit,
onClickContinueReading: (LibraryManga) -> Unit,
searchQuery: String?, searchQuery: String?,
onGlobalSearchClicked: () -> Unit, onGlobalSearchClicked: () -> Unit,
// SY -->
onOpenReader: (LibraryManga) -> Unit,
// SY <--
) { ) {
LazyLibraryGrid( LazyLibraryGrid(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
@ -72,20 +68,10 @@ fun LibraryCompactGrid(
item = libraryItem, item = libraryItem,
) )
}, },
// SY --> showContinueReadingButton = showContinueReadingButton,
buttonTop = if (showStartReadingButton && showTitle && libraryItem.unreadCount > 0) {
{ StartReadingButton(onOpenReader = { onOpenReader(libraryItem.libraryManga) }) }
} else {
null
},
buttonBottom = if (showStartReadingButton && !showTitle && libraryItem.unreadCount > 0) {
{ StartReadingButton(onOpenReader = { onOpenReader(libraryItem.libraryManga) }) }
} else {
null
},
// SY <--
onLongClick = { onLongClick(libraryItem.libraryManga) }, onLongClick = { onLongClick(libraryItem.libraryManga) },
onClick = { onClick(libraryItem.libraryManga) }, onClick = { onClick(libraryItem.libraryManga) },
onClickContinueReading = { onClickContinueReading(libraryItem.libraryManga) },
) )
} }
} }

View File

@ -39,6 +39,7 @@ fun LibraryContent(
showMangaCount: Boolean, showMangaCount: Boolean,
onChangeCurrentPage: (Int) -> Unit, onChangeCurrentPage: (Int) -> Unit,
onMangaClicked: (Long) -> Unit, onMangaClicked: (Long) -> Unit,
onContinueReadingClicked: (LibraryManga) -> Unit,
onToggleSelection: (LibraryManga) -> Unit, onToggleSelection: (LibraryManga) -> Unit,
onToggleRangeSelection: (LibraryManga) -> Unit, onToggleRangeSelection: (LibraryManga) -> Unit,
onRefresh: (Category?) -> Boolean, onRefresh: (Category?) -> Boolean,
@ -51,13 +52,10 @@ fun LibraryContent(
showUnreadBadges: Boolean, showUnreadBadges: Boolean,
showLocalBadges: Boolean, showLocalBadges: Boolean,
showLanguageBadges: Boolean, showLanguageBadges: Boolean,
// SY --> showContinueReadingButton: Boolean,
showStartReadingButton: Boolean,
// SY <--
isDownloadOnly: Boolean, isDownloadOnly: Boolean,
isIncognitoMode: Boolean, isIncognitoMode: Boolean,
// SY --> // SY -->
onOpenReader: (LibraryManga) -> Unit,
getCategoryName: (Context, Category, Int, String) -> String, getCategoryName: (Context, Category, Int, String) -> String,
// SY <-- // SY <--
) { ) {
@ -105,6 +103,9 @@ fun LibraryContent(
val onLongClickManga = { manga: LibraryManga -> val onLongClickManga = { manga: LibraryManga ->
onToggleRangeSelection(manga) onToggleRangeSelection(manga)
} }
val onClickContinueReading = { manga: LibraryManga ->
onContinueReadingClicked(manga)
}
SwipeRefresh( SwipeRefresh(
refreshing = isRefreshing, refreshing = isRefreshing,
@ -132,16 +133,12 @@ fun LibraryContent(
showUnreadBadges = showUnreadBadges, showUnreadBadges = showUnreadBadges,
showLocalBadges = showLocalBadges, showLocalBadges = showLocalBadges,
showLanguageBadges = showLanguageBadges, showLanguageBadges = showLanguageBadges,
// SY --> showContinueReadingButton = showContinueReadingButton,
showStartReadingButton = showStartReadingButton,
// SY <--
onClickManga = onClickManga, onClickManga = onClickManga,
onLongClickManga = onLongClickManga, onLongClickManga = onLongClickManga,
onClickContinueReading = onClickContinueReading,
onGlobalSearchClicked = onGlobalSearchClicked, onGlobalSearchClicked = onGlobalSearchClicked,
searchQuery = state.searchQuery, searchQuery = state.searchQuery,
// SY -->
onOpenReader = onOpenReader,
// SY <--
) )
} }

View File

@ -27,10 +27,12 @@ fun LibraryList(
showUnreadBadges: Boolean, showUnreadBadges: Boolean,
showLocalBadges: Boolean, showLocalBadges: Boolean,
showLanguageBadges: Boolean, showLanguageBadges: Boolean,
showContinueReadingButton: Boolean,
contentPadding: PaddingValues, contentPadding: PaddingValues,
selection: List<LibraryManga>, selection: List<LibraryManga>,
onClick: (LibraryManga) -> Unit, onClick: (LibraryManga) -> Unit,
onLongClick: (LibraryManga) -> Unit, onLongClick: (LibraryManga) -> Unit,
onClickContinueReading: (LibraryManga) -> Unit,
searchQuery: String?, searchQuery: String?,
onGlobalSearchClicked: () -> Unit, onGlobalSearchClicked: () -> Unit,
) { ) {
@ -72,8 +74,10 @@ fun LibraryList(
UnreadBadge(enabled = showUnreadBadges, item = libraryItem) UnreadBadge(enabled = showUnreadBadges, item = libraryItem)
LanguageBadge(showLanguage = showLanguageBadges, showLocal = showLocalBadges, item = libraryItem) LanguageBadge(showLanguage = showLanguageBadges, showLocal = showLocalBadges, item = libraryItem)
}, },
showContinueReadingButton = showContinueReadingButton,
onLongClick = { onLongClick(libraryItem.libraryManga) }, onLongClick = { onLongClick(libraryItem.libraryManga) },
onClick = { onClick(libraryItem.libraryManga) }, onClick = { onClick(libraryItem.libraryManga) },
onClickContinueReading = { onClickContinueReading(libraryItem.libraryManga) },
) )
} }
} }

View File

@ -32,14 +32,10 @@ fun LibraryPager(
showUnreadBadges: Boolean, showUnreadBadges: Boolean,
showLocalBadges: Boolean, showLocalBadges: Boolean,
showLanguageBadges: Boolean, showLanguageBadges: Boolean,
// SY --> showContinueReadingButton: Boolean,
showStartReadingButton: Boolean,
// SY <--
onClickManga: (LibraryManga) -> Unit, onClickManga: (LibraryManga) -> Unit,
onLongClickManga: (LibraryManga) -> Unit, onLongClickManga: (LibraryManga) -> Unit,
// SY --> onClickContinueReading: (LibraryManga) -> Unit,
onOpenReader: (LibraryManga) -> Unit,
// SY <--
) { ) {
HorizontalPager( HorizontalPager(
count = pageCount, count = pageCount,
@ -70,10 +66,12 @@ fun LibraryPager(
showUnreadBadges = showUnreadBadges, showUnreadBadges = showUnreadBadges,
showLocalBadges = showLocalBadges, showLocalBadges = showLocalBadges,
showLanguageBadges = showLanguageBadges, showLanguageBadges = showLanguageBadges,
showContinueReadingButton = showContinueReadingButton,
contentPadding = contentPadding, contentPadding = contentPadding,
selection = selectedManga, selection = selectedManga,
onClick = onClickManga, onClick = onClickManga,
onLongClick = onLongClickManga, onLongClick = onLongClickManga,
onClickContinueReading = onClickContinueReading,
searchQuery = searchQuery, searchQuery = searchQuery,
onGlobalSearchClicked = onGlobalSearchClicked, onGlobalSearchClicked = onGlobalSearchClicked,
) )
@ -86,19 +84,15 @@ fun LibraryPager(
showUnreadBadges = showUnreadBadges, showUnreadBadges = showUnreadBadges,
showLocalBadges = showLocalBadges, showLocalBadges = showLocalBadges,
showLanguageBadges = showLanguageBadges, showLanguageBadges = showLanguageBadges,
// SY --> showContinueReadingButton = showContinueReadingButton,
showStartReadingButton = showStartReadingButton,
// SY <--
columns = columns, columns = columns,
contentPadding = contentPadding, contentPadding = contentPadding,
selection = selectedManga, selection = selectedManga,
onClick = onClickManga, onClick = onClickManga,
onLongClick = onLongClickManga, onLongClick = onLongClickManga,
onClickContinueReading = onClickContinueReading,
searchQuery = searchQuery, searchQuery = searchQuery,
onGlobalSearchClicked = onGlobalSearchClicked, onGlobalSearchClicked = onGlobalSearchClicked,
// SY -->
onOpenReader = onOpenReader,
// SY <--
) )
} }
LibraryDisplayMode.ComfortableGrid -> { LibraryDisplayMode.ComfortableGrid -> {
@ -108,19 +102,15 @@ fun LibraryPager(
showUnreadBadges = showUnreadBadges, showUnreadBadges = showUnreadBadges,
showLocalBadges = showLocalBadges, showLocalBadges = showLocalBadges,
showLanguageBadges = showLanguageBadges, showLanguageBadges = showLanguageBadges,
// SY --> showContinueReadingButton = showContinueReadingButton,
showStartReadingButton = showStartReadingButton,
// SY <--
columns = columns, columns = columns,
contentPadding = contentPadding, contentPadding = contentPadding,
selection = selectedManga, selection = selectedManga,
onClick = onClickManga, onClick = onClickManga,
onClickContinueReading = onClickContinueReading,
onLongClick = onLongClickManga, onLongClick = onLongClickManga,
searchQuery = searchQuery, searchQuery = searchQuery,
onGlobalSearchClicked = onGlobalSearchClicked, onGlobalSearchClicked = onGlobalSearchClicked,
// SY -->
onOpenReader = onOpenReader,
// SY <--
) )
} }
} }

View File

@ -13,7 +13,9 @@ import com.bluelinelabs.conductor.ControllerChangeType
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import eu.kanade.core.prefs.CheckboxState import eu.kanade.core.prefs.CheckboxState
import eu.kanade.domain.UnsortedPreferences import eu.kanade.domain.UnsortedPreferences
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.library.model.LibraryGroup import eu.kanade.domain.library.model.LibraryGroup
import eu.kanade.domain.library.model.LibraryManga
import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.isLocal import eu.kanade.domain.manga.model.isLocal
import eu.kanade.domain.manga.model.toDbManga import eu.kanade.domain.manga.model.toDbManga
@ -35,7 +37,6 @@ import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import exh.favorites.FavoritesIntroDialog import exh.favorites.FavoritesIntroDialog
import exh.favorites.FavoritesSyncStatus import exh.favorites.FavoritesSyncStatus
@ -84,6 +85,7 @@ class LibraryController(
LibraryScreen( LibraryScreen(
presenter = presenter, presenter = presenter,
onMangaClicked = ::openManga, onMangaClicked = ::openManga,
onContinueReadingClicked = ::continueReading,
onGlobalSearchClicked = { onGlobalSearchClicked = {
router.pushController(GlobalSearchController(presenter.searchQuery)) router.pushController(GlobalSearchController(presenter.searchQuery))
}, },
@ -140,9 +142,6 @@ class LibraryController(
} }
}, },
onClickAddToMangaDex = ::pushToMdList, onClickAddToMangaDex = ::pushToMdList,
onOpenReader = {
startReading(it.manga)
},
onClickSyncExh = { onClickSyncExh = {
// TODO // TODO
if (Injekt.get<UnsortedPreferences>().exhShowSyncIntro().get()) { if (Injekt.get<UnsortedPreferences>().exhShowSyncIntro().get()) {
@ -280,6 +279,19 @@ class LibraryController(
router.pushController(MangaController(mangaId)) router.pushController(MangaController(mangaId))
} }
private fun continueReading(libraryManga: LibraryManga) {
viewScope.launchIO {
val chapter = presenter.getNextUnreadChapter(libraryManga.manga)
if (chapter != null) openChapter(chapter)
}
}
private fun openChapter(chapter: Chapter) {
activity?.run {
startActivity(ReaderActivity.newIntent(this, chapter.mangaId, chapter.id))
}
}
/** /**
* Clear all of the manga currently selected, and * Clear all of the manga currently selected, and
* invalidate the action mode to revert the top toolbar * invalidate the action mode to revert the top toolbar
@ -496,17 +508,5 @@ class LibraryController(
favSyncDialog?.setMessage(status.delayedMessage) favSyncDialog?.setMessage(status.delayedMessage)
} }
} }
private fun startReading(manga: Manga) {
val activity = activity ?: return
viewScope.launchIO {
val chapter = presenter.getFirstUnread(manga) ?: return@launchIO
val intent = ReaderActivity.newIntent(activity, manga.id, chapter.id)
presenter.clearSelection()
withUIContext {
startActivity(intent)
}
}
}
// <-- EXH // <-- EXH
} }

View File

@ -20,6 +20,7 @@ import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.category.interactor.GetCategories
import eu.kanade.domain.category.interactor.SetMangaCategories import eu.kanade.domain.category.interactor.SetMangaCategories
import eu.kanade.domain.category.model.Category import eu.kanade.domain.category.model.Category
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId import eu.kanade.domain.chapter.interactor.GetMergedChapterByMangaId
import eu.kanade.domain.chapter.interactor.SetReadStatus import eu.kanade.domain.chapter.interactor.SetReadStatus
import eu.kanade.domain.chapter.model.Chapter import eu.kanade.domain.chapter.model.Chapter
@ -64,6 +65,7 @@ import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.all.MergedSource import eu.kanade.tachiyomi.source.online.all.MergedSource
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.chapter.getNextUnread
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchNonCancellable import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.lang.withIOContext
@ -118,9 +120,10 @@ typealias LibraryMap = Map<Long, List<LibraryItem>>
class LibraryPresenter( class LibraryPresenter(
private val state: LibraryStateImpl = LibraryState() as LibraryStateImpl, private val state: LibraryStateImpl = LibraryState() as LibraryStateImpl,
private val getLibraryManga: GetLibraryManga = Injekt.get(), private val getLibraryManga: GetLibraryManga = Injekt.get(),
private val getTracksPerManga: GetTracksPerManga = Injekt.get(),
private val getCategories: GetCategories = Injekt.get(), private val getCategories: GetCategories = Injekt.get(),
private val getTracksPerManga: GetTracksPerManga = Injekt.get(),
private val getNextChapters: GetNextChapters = Injekt.get(), private val getNextChapters: GetNextChapters = Injekt.get(),
private val getChaptersByMangaId: GetChapterByMangaId = Injekt.get(),
private val setReadStatus: SetReadStatus = Injekt.get(), private val setReadStatus: SetReadStatus = Injekt.get(),
private val updateManga: UpdateManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(),
private val setMangaCategories: SetMangaCategories = Injekt.get(), private val setMangaCategories: SetMangaCategories = Injekt.get(),
@ -157,12 +160,10 @@ class LibraryPresenter(
val showLocalBadges by libraryPreferences.localBadge().asState() val showLocalBadges by libraryPreferences.localBadge().asState()
val showLanguageBadges by libraryPreferences.languageBadge().asState() val showLanguageBadges by libraryPreferences.languageBadge().asState()
// SY -->
val showStartReadingButton by libraryPreferences.startReadingButton().asState()
// SY <--
var activeCategory: Int by libraryPreferences.lastUsedCategory().asState() var activeCategory: Int by libraryPreferences.lastUsedCategory().asState()
val showContinueReadingButton by libraryPreferences.showContinueReadingButton().asState()
val isDownloadOnly: Boolean by preferences.downloadedOnly().asState() val isDownloadOnly: Boolean by preferences.downloadedOnly().asState()
val isIncognitoMode: Boolean by preferences.incognitoMode().asState() val isIncognitoMode: Boolean by preferences.incognitoMode().asState()
@ -581,6 +582,10 @@ class LibraryPresenter(
.reduce { set1, set2 -> set1.intersect(set2) } .reduce { set1, set2 -> set1.intersect(set2) }
} }
suspend fun getNextUnreadChapter(manga: Manga): Chapter? {
return getChaptersByMangaId.await(manga.id).getNextUnread(manga, downloadManager)
}
/** /**
* Returns the mix (non-common) categories for the given list of manga. * Returns the mix (non-common) categories for the given list of manga.
* *

View File

@ -327,21 +327,15 @@ class LibrarySettingsSheet(
private val displayGroup: DisplayGroup private val displayGroup: DisplayGroup
private val badgeGroup: BadgeGroup private val badgeGroup: BadgeGroup
// SY -->
private val buttonsGroup: ButtonsGroup
// SY <--
private val tabsGroup: TabsGroup private val tabsGroup: TabsGroup
private val otherGroup: OtherGroup
init { init {
displayGroup = DisplayGroup() displayGroup = DisplayGroup()
badgeGroup = BadgeGroup() badgeGroup = BadgeGroup()
// SY -->
buttonsGroup = ButtonsGroup()
// SY <--
tabsGroup = TabsGroup() tabsGroup = TabsGroup()
setGroups(listOf(displayGroup, badgeGroup, /* SY --> */ buttonsGroup, /* SY <-- */ tabsGroup)) otherGroup = OtherGroup()
setGroups(listOf(displayGroup, badgeGroup, tabsGroup, otherGroup))
} }
// Refreshes Display Setting selections // Refreshes Display Setting selections
@ -444,30 +438,6 @@ class LibrarySettingsSheet(
} }
} }
// SY -->
inner class ButtonsGroup : Group {
private val startReadingButton = Item.CheckboxGroup(R.string.action_start_reading_button, this)
override val header = Item.Header(R.string.buttons_header)
override val items = listOf(startReadingButton)
override val footer = null
override fun initModels() {
startReadingButton.checked = libraryPreferences.startReadingButton().get()
}
override fun onItemClicked(item: Item) {
item as Item.CheckboxGroup
item.checked = !item.checked
when (item) {
startReadingButton -> libraryPreferences.startReadingButton().set((item.checked))
else -> Unit
}
adapter.notifyItemChanged(item)
}
}
// SY <--
inner class TabsGroup : Group { inner class TabsGroup : Group {
private val showTabs = Item.CheckboxGroup(R.string.action_display_show_tabs, this) private val showTabs = Item.CheckboxGroup(R.string.action_display_show_tabs, this)
private val showNumberOfItems = Item.CheckboxGroup(R.string.action_display_show_number_of_items, this) private val showNumberOfItems = Item.CheckboxGroup(R.string.action_display_show_number_of_items, this)
@ -492,6 +462,28 @@ class LibrarySettingsSheet(
adapter.notifyItemChanged(item) adapter.notifyItemChanged(item)
} }
} }
inner class OtherGroup : Group {
private val showContinueReadingButton = Item.CheckboxGroup(R.string.action_display_show_continue_reading_button, this)
override val header = Item.Header(R.string.other_header)
override val items = listOf(showContinueReadingButton)
override val footer = null
override fun initModels() {
showContinueReadingButton.checked = libraryPreferences.showContinueReadingButton().get()
}
override fun onItemClicked(item: Item) {
item as Item.CheckboxGroup
item.checked = !item.checked
when (item) {
showContinueReadingButton -> libraryPreferences.showContinueReadingButton().set(item.checked)
else -> {}
}
adapter.notifyItemChanged(item)
}
}
} }
// SY --> // SY -->

View File

@ -17,6 +17,7 @@ import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
import eu.kanade.domain.chapter.interactor.UpdateChapter import eu.kanade.domain.chapter.interactor.UpdateChapter
import eu.kanade.domain.chapter.model.ChapterUpdate import eu.kanade.domain.chapter.model.ChapterUpdate
import eu.kanade.domain.chapter.model.applyFilters
import eu.kanade.domain.chapter.model.toDbChapter import eu.kanade.domain.chapter.model.toDbChapter
import eu.kanade.domain.download.service.DownloadPreferences import eu.kanade.domain.download.service.DownloadPreferences
import eu.kanade.domain.library.service.LibraryPreferences import eu.kanade.domain.library.service.LibraryPreferences
@ -38,7 +39,6 @@ import eu.kanade.domain.manga.interactor.UpdateMergedSettings
import eu.kanade.domain.manga.model.MangaUpdate import eu.kanade.domain.manga.model.MangaUpdate
import eu.kanade.domain.manga.model.MergeMangaSettingsUpdate import eu.kanade.domain.manga.model.MergeMangaSettingsUpdate
import eu.kanade.domain.manga.model.PagePreview import eu.kanade.domain.manga.model.PagePreview
import eu.kanade.domain.manga.model.TriStateFilter
import eu.kanade.domain.manga.model.isLocal import eu.kanade.domain.manga.model.isLocal
import eu.kanade.domain.manga.model.toDbManga import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.domain.track.interactor.DeleteTrack import eu.kanade.domain.track.interactor.DeleteTrack
@ -66,6 +66,7 @@ import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.util.chapter.getChapterSort import eu.kanade.tachiyomi.util.chapter.getChapterSort
import eu.kanade.tachiyomi.util.chapter.getNextUnread
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchNonCancellable import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import eu.kanade.tachiyomi.util.lang.toRelativeString import eu.kanade.tachiyomi.util.lang.toRelativeString
@ -1054,24 +1055,7 @@ class MangaPresenter(
*/ */
fun getNextUnreadChapter(): DomainChapter? { fun getNextUnreadChapter(): DomainChapter? {
val successState = successState ?: return null val successState = successState ?: return null
// SY --> return successState.chapters.getNextUnread(successState.manga)
if (successState.manga.isEhBasedManga()) {
return successState.processedChapters.map { it.chapter }.let { chapters ->
if (successState.manga.sortDescending()) {
chapters.firstOrNull()
} else {
chapters.lastOrNull()
}
}
}
// SY <--
return successState.processedChapters.map { it.chapter }.let { chapters ->
if (successState.manga.sortDescending()) {
chapters.findLast { !it.read }
} else {
chapters.find { !it.read }
}
}
} }
fun getUnreadChapters(): List<DomainChapter> { fun getUnreadChapters(): List<DomainChapter> {
@ -1650,44 +1634,6 @@ sealed class MangaScreenState {
val processedChapters: Sequence<ChapterItem> val processedChapters: Sequence<ChapterItem>
get() = chapters.applyFilters(manga) get() = chapters.applyFilters(manga)
/**
* Applies the view filters to the list of chapters obtained from the database.
* @return an observable of the list of chapters filtered and sorted.
*/
private fun List<ChapterItem>.applyFilters(manga: DomainManga): Sequence<ChapterItem> {
val isLocalManga = manga.isLocal()
val unreadFilter = manga.unreadFilter
val downloadedFilter = manga.downloadedFilter
val bookmarkedFilter = manga.bookmarkedFilter
val filteredScanlators = manga.filteredScanlators.orEmpty()
return asSequence()
.filter { (chapter) ->
when (unreadFilter) {
TriStateFilter.DISABLED -> true
TriStateFilter.ENABLED_IS -> !chapter.read
TriStateFilter.ENABLED_NOT -> chapter.read
}
}
.filter { (chapter) ->
when (bookmarkedFilter) {
TriStateFilter.DISABLED -> true
TriStateFilter.ENABLED_IS -> chapter.bookmark
TriStateFilter.ENABLED_NOT -> !chapter.bookmark
}
}
.filter {
when (downloadedFilter) {
TriStateFilter.DISABLED -> true
TriStateFilter.ENABLED_IS -> it.isDownloaded || isLocalManga
TriStateFilter.ENABLED_NOT -> !it.isDownloaded && !isLocalManga
}
}
.filter { (chapter) ->
filteredScanlators.isEmpty() || MdUtil.getScanlators(chapter.scanlator).any { group -> filteredScanlators.contains(group) }
}
.sortedWith { (chapter1), (chapter2) -> getChapterSort(manga).invoke(chapter1, chapter2) }
}
} }
} }

View File

@ -0,0 +1,52 @@
package eu.kanade.tachiyomi.util.chapter
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.domain.chapter.model.applyFilters
import eu.kanade.domain.manga.model.Manga
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.ui.manga.ChapterItem
import exh.source.isEhBasedManga
/**
* Gets next unread chapter with filters and sorting applied
*/
fun List<Chapter>.getNextUnread(manga: Manga, downloadManager: DownloadManager): Chapter? {
return applyFilters(manga, downloadManager).let { chapters ->
// SY -->
if (manga.isEhBasedManga()) {
return@let if (manga.sortDescending()) {
chapters.firstOrNull()?.takeUnless { it.read }
} else {
chapters.lastOrNull()?.takeUnless { it.read }
}
}
// SY <--
if (manga.sortDescending()) {
chapters.findLast { !it.read }
} else {
chapters.find { !it.read }
}
}
}
/**
* Gets next unread chapter with filters and sorting applied
*/
fun List<ChapterItem>.getNextUnread(manga: Manga): Chapter? {
return applyFilters(manga).let { chapters ->
// SY -->
if (manga.isEhBasedManga()) {
return@let if (manga.sortDescending()) {
chapters.firstOrNull()?.takeUnless { it.chapter.read }
} else {
chapters.lastOrNull()?.takeUnless { it.chapter.read }
}
}
// SY <--
if (manga.sortDescending()) {
chapters.findLast { !it.chapter.read }
} else {
chapters.find { !it.chapter.read }
}
}?.chapter
}

View File

@ -108,6 +108,7 @@
<string name="action_display_language_badge">Language</string> <string name="action_display_language_badge">Language</string>
<string name="action_display_show_tabs">Show category tabs</string> <string name="action_display_show_tabs">Show category tabs</string>
<string name="action_display_show_number_of_items">Show number of items</string> <string name="action_display_show_number_of_items">Show number of items</string>
<string name="action_display_show_continue_reading_button">Show continue reading button</string>
<string name="action_disable">Disable</string> <string name="action_disable">Disable</string>
<string name="action_pin">Pin</string> <string name="action_pin">Pin</string>
<string name="action_unpin">Unpin</string> <string name="action_unpin">Unpin</string>
@ -579,6 +580,7 @@
<string name="downloaded_chapters">Downloaded chapters</string> <string name="downloaded_chapters">Downloaded chapters</string>
<string name="badges_header">Badges</string> <string name="badges_header">Badges</string>
<string name="tabs_header">Tabs</string> <string name="tabs_header">Tabs</string>
<string name="other_header">Other</string>
<!-- Catalogue fragment --> <!-- Catalogue fragment -->
<!-- missing prompt after Compose rewrite #7901 --> <!-- missing prompt after Compose rewrite #7901 -->