Show missing chapter count between two chapters in chapter list (#10096)
* Show missing chapter count between two chapters in chapter list Closes #8460 * Fix crash * Lint * Review changes * Lint
This commit is contained in:
@@ -5,9 +5,11 @@ import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
@@ -26,7 +28,9 @@ import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
@@ -44,6 +48,7 @@ import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.util.fastAll
|
||||
import androidx.compose.ui.util.fastAny
|
||||
@@ -61,7 +66,7 @@ import eu.kanade.presentation.util.formatChapterNumber
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.download.model.Download
|
||||
import eu.kanade.tachiyomi.source.getNameForMangaInfo
|
||||
import eu.kanade.tachiyomi.ui.manga.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.manga.ChapterList
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaScreenModel
|
||||
import eu.kanade.tachiyomi.util.lang.toRelativeString
|
||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||
@@ -75,8 +80,10 @@ import tachiyomi.presentation.core.components.VerticalFastScroller
|
||||
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
|
||||
import tachiyomi.presentation.core.components.material.PullRefresh
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.util.isScrolledToEnd
|
||||
import tachiyomi.presentation.core.util.isScrollingUp
|
||||
import tachiyomi.presentation.core.util.secondaryItemAlpha
|
||||
import java.text.DateFormat
|
||||
import java.util.Date
|
||||
|
||||
@@ -92,7 +99,7 @@ fun MangaScreen(
|
||||
chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
|
||||
onBackClicked: () -> Unit,
|
||||
onChapterClicked: (Chapter) -> Unit,
|
||||
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
|
||||
onDownloadChapter: ((List<ChapterList.Item>, ChapterDownloadAction) -> Unit)?,
|
||||
onAddToLibraryClicked: () -> Unit,
|
||||
onWebViewClicked: (() -> Unit)?,
|
||||
onWebViewLongClicked: (() -> Unit)?,
|
||||
@@ -123,10 +130,10 @@ fun MangaScreen(
|
||||
onMultiDeleteClicked: (List<Chapter>) -> Unit,
|
||||
|
||||
// For chapter swipe
|
||||
onChapterSwipe: (ChapterItem, LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
onChapterSwipe: (ChapterList.Item, LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
|
||||
// Chapter selection
|
||||
onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit,
|
||||
onChapterSelected: (ChapterList.Item, Boolean, Boolean, Boolean) -> Unit,
|
||||
onAllChapterSelected: (Boolean) -> Unit,
|
||||
onInvertSelection: () -> Unit,
|
||||
) {
|
||||
@@ -225,7 +232,7 @@ private fun MangaScreenSmallImpl(
|
||||
chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
|
||||
onBackClicked: () -> Unit,
|
||||
onChapterClicked: (Chapter) -> Unit,
|
||||
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
|
||||
onDownloadChapter: ((List<ChapterList.Item>, ChapterDownloadAction) -> Unit)?,
|
||||
onAddToLibraryClicked: () -> Unit,
|
||||
onWebViewClicked: (() -> Unit)?,
|
||||
onWebViewLongClicked: (() -> Unit)?,
|
||||
@@ -257,16 +264,17 @@ private fun MangaScreenSmallImpl(
|
||||
onMultiDeleteClicked: (List<Chapter>) -> Unit,
|
||||
|
||||
// For chapter swipe
|
||||
onChapterSwipe: (ChapterItem, LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
onChapterSwipe: (ChapterList.Item, LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
|
||||
// Chapter selection
|
||||
onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit,
|
||||
onChapterSelected: (ChapterList.Item, Boolean, Boolean, Boolean) -> Unit,
|
||||
onAllChapterSelected: (Boolean) -> Unit,
|
||||
onInvertSelection: () -> Unit,
|
||||
) {
|
||||
val chapterListState = rememberLazyListState()
|
||||
|
||||
val chapters = remember(state) { state.processedChapters }
|
||||
val listItem = remember(state) { state.chapterListItems }
|
||||
|
||||
val isAnySelected by remember {
|
||||
derivedStateOf {
|
||||
@@ -447,7 +455,8 @@ private fun MangaScreenSmallImpl(
|
||||
|
||||
sharedChapterItems(
|
||||
manga = state.manga,
|
||||
chapters = chapters,
|
||||
chapters = listItem,
|
||||
isAnyChapterSelected = chapters.fastAny { it.selected },
|
||||
dateRelativeTime = dateRelativeTime,
|
||||
dateFormat = dateFormat,
|
||||
chapterSwipeStartAction = chapterSwipeStartAction,
|
||||
@@ -474,7 +483,7 @@ fun MangaScreenLargeImpl(
|
||||
chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
|
||||
onBackClicked: () -> Unit,
|
||||
onChapterClicked: (Chapter) -> Unit,
|
||||
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
|
||||
onDownloadChapter: ((List<ChapterList.Item>, ChapterDownloadAction) -> Unit)?,
|
||||
onAddToLibraryClicked: () -> Unit,
|
||||
onWebViewClicked: (() -> Unit)?,
|
||||
onWebViewLongClicked: (() -> Unit)?,
|
||||
@@ -506,10 +515,10 @@ fun MangaScreenLargeImpl(
|
||||
onMultiDeleteClicked: (List<Chapter>) -> Unit,
|
||||
|
||||
// For swipe actions
|
||||
onChapterSwipe: (ChapterItem, LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
onChapterSwipe: (ChapterList.Item, LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
|
||||
// Chapter selection
|
||||
onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit,
|
||||
onChapterSelected: (ChapterList.Item, Boolean, Boolean, Boolean) -> Unit,
|
||||
onAllChapterSelected: (Boolean) -> Unit,
|
||||
onInvertSelection: () -> Unit,
|
||||
) {
|
||||
@@ -517,6 +526,7 @@ fun MangaScreenLargeImpl(
|
||||
val density = LocalDensity.current
|
||||
|
||||
val chapters = remember(state) { state.processedChapters }
|
||||
val listItem = remember(state) { state.chapterListItems }
|
||||
|
||||
val isAnySelected by remember {
|
||||
derivedStateOf {
|
||||
@@ -688,7 +698,8 @@ fun MangaScreenLargeImpl(
|
||||
|
||||
sharedChapterItems(
|
||||
manga = state.manga,
|
||||
chapters = chapters,
|
||||
chapters = listItem,
|
||||
isAnyChapterSelected = chapters.fastAny { it.selected },
|
||||
dateRelativeTime = dateRelativeTime,
|
||||
dateFormat = dateFormat,
|
||||
chapterSwipeStartAction = chapterSwipeStartAction,
|
||||
@@ -708,12 +719,12 @@ fun MangaScreenLargeImpl(
|
||||
|
||||
@Composable
|
||||
private fun SharedMangaBottomActionMenu(
|
||||
selected: List<ChapterItem>,
|
||||
selected: List<ChapterList.Item>,
|
||||
modifier: Modifier = Modifier,
|
||||
onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit,
|
||||
onMultiMarkAsReadClicked: (List<Chapter>, markAsRead: Boolean) -> Unit,
|
||||
onMarkPreviousAsReadClicked: (Chapter) -> Unit,
|
||||
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
|
||||
onDownloadChapter: ((List<ChapterList.Item>, ChapterDownloadAction) -> Unit)?,
|
||||
onMultiDeleteClicked: (List<Chapter>) -> Unit,
|
||||
fillFraction: Float,
|
||||
) {
|
||||
@@ -750,92 +761,123 @@ private fun SharedMangaBottomActionMenu(
|
||||
|
||||
private fun LazyListScope.sharedChapterItems(
|
||||
manga: Manga,
|
||||
chapters: List<ChapterItem>,
|
||||
chapters: List<ChapterList>,
|
||||
isAnyChapterSelected: Boolean,
|
||||
dateRelativeTime: Boolean,
|
||||
dateFormat: DateFormat,
|
||||
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
|
||||
chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
|
||||
onChapterClicked: (Chapter) -> Unit,
|
||||
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
|
||||
onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit,
|
||||
onChapterSwipe: (ChapterItem, LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
onDownloadChapter: ((List<ChapterList.Item>, ChapterDownloadAction) -> Unit)?,
|
||||
onChapterSelected: (ChapterList.Item, Boolean, Boolean, Boolean) -> Unit,
|
||||
onChapterSwipe: (ChapterList.Item, LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
) {
|
||||
items(
|
||||
items = chapters,
|
||||
key = { "chapter-${it.chapter.id}" },
|
||||
key = { item ->
|
||||
when (item) {
|
||||
is ChapterList.MissingCount -> "missing-count-${item.id}"
|
||||
is ChapterList.Item -> "chapter-${item.id}"
|
||||
}
|
||||
},
|
||||
contentType = { MangaScreenItem.CHAPTER },
|
||||
) { chapterItem ->
|
||||
) { item ->
|
||||
val haptic = LocalHapticFeedback.current
|
||||
val context = LocalContext.current
|
||||
|
||||
MangaChapterListItem(
|
||||
title = if (manga.displayMode == Manga.CHAPTER_DISPLAY_NUMBER) {
|
||||
stringResource(
|
||||
R.string.display_mode_chapter,
|
||||
formatChapterNumber(chapterItem.chapter.chapterNumber),
|
||||
)
|
||||
} else {
|
||||
chapterItem.chapter.name
|
||||
},
|
||||
date = chapterItem.chapter.dateUpload
|
||||
.takeIf { it > 0L }
|
||||
?.let {
|
||||
Date(it).toRelativeString(
|
||||
context,
|
||||
dateRelativeTime,
|
||||
dateFormat,
|
||||
when (item) {
|
||||
is ChapterList.MissingCount -> {
|
||||
Row(
|
||||
modifier = Modifier.padding(
|
||||
horizontal = MaterialTheme.padding.medium,
|
||||
vertical = MaterialTheme.padding.small,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.medium),
|
||||
) {
|
||||
HorizontalDivider(modifier = Modifier.weight(1f))
|
||||
Text(
|
||||
text = pluralStringResource(
|
||||
id = R.plurals.missing_chapters,
|
||||
count = item.count,
|
||||
item.count,
|
||||
),
|
||||
modifier = Modifier.secondaryItemAlpha(),
|
||||
)
|
||||
},
|
||||
readProgress = chapterItem.chapter.lastPageRead
|
||||
.takeIf { !chapterItem.chapter.read && it > 0L }
|
||||
?.let {
|
||||
stringResource(
|
||||
R.string.chapter_progress,
|
||||
it + 1,
|
||||
)
|
||||
},
|
||||
scanlator = chapterItem.chapter.scanlator.takeIf { !it.isNullOrBlank() },
|
||||
read = chapterItem.chapter.read,
|
||||
bookmark = chapterItem.chapter.bookmark,
|
||||
selected = chapterItem.selected,
|
||||
downloadIndicatorEnabled = chapters.fastAll { !it.selected },
|
||||
downloadStateProvider = { chapterItem.downloadState },
|
||||
downloadProgressProvider = { chapterItem.downloadProgress },
|
||||
chapterSwipeStartAction = chapterSwipeStartAction,
|
||||
chapterSwipeEndAction = chapterSwipeEndAction,
|
||||
onLongClick = {
|
||||
onChapterSelected(chapterItem, !chapterItem.selected, true, true)
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
onClick = {
|
||||
onChapterItemClick(
|
||||
chapterItem = chapterItem,
|
||||
chapters = chapters,
|
||||
onToggleSelection = { onChapterSelected(chapterItem, !chapterItem.selected, true, false) },
|
||||
onChapterClicked = onChapterClicked,
|
||||
HorizontalDivider(modifier = Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
is ChapterList.Item -> {
|
||||
MangaChapterListItem(
|
||||
title = if (manga.displayMode == Manga.CHAPTER_DISPLAY_NUMBER) {
|
||||
stringResource(
|
||||
R.string.display_mode_chapter,
|
||||
formatChapterNumber(item.chapter.chapterNumber),
|
||||
)
|
||||
} else {
|
||||
item.chapter.name
|
||||
},
|
||||
date = item.chapter.dateUpload
|
||||
.takeIf { it > 0L }
|
||||
?.let {
|
||||
Date(it).toRelativeString(
|
||||
context,
|
||||
dateRelativeTime,
|
||||
dateFormat,
|
||||
)
|
||||
},
|
||||
readProgress = item.chapter.lastPageRead
|
||||
.takeIf { !item.chapter.read && it > 0L }
|
||||
?.let {
|
||||
stringResource(
|
||||
R.string.chapter_progress,
|
||||
it + 1,
|
||||
)
|
||||
},
|
||||
scanlator = item.chapter.scanlator.takeIf { !it.isNullOrBlank() },
|
||||
read = item.chapter.read,
|
||||
bookmark = item.chapter.bookmark,
|
||||
selected = item.selected,
|
||||
downloadIndicatorEnabled = !isAnyChapterSelected,
|
||||
downloadStateProvider = { item.downloadState },
|
||||
downloadProgressProvider = { item.downloadProgress },
|
||||
chapterSwipeStartAction = chapterSwipeStartAction,
|
||||
chapterSwipeEndAction = chapterSwipeEndAction,
|
||||
onLongClick = {
|
||||
onChapterSelected(item, !item.selected, true, true)
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
onClick = {
|
||||
onChapterItemClick(
|
||||
chapterItem = item,
|
||||
isAnyChapterSelected = isAnyChapterSelected,
|
||||
onToggleSelection = { onChapterSelected(item, !item.selected, true, false) },
|
||||
onChapterClicked = onChapterClicked,
|
||||
)
|
||||
},
|
||||
onDownloadClick = if (onDownloadChapter != null) {
|
||||
{ onDownloadChapter(listOf(item), it) }
|
||||
} else {
|
||||
null
|
||||
},
|
||||
onChapterSwipe = {
|
||||
onChapterSwipe(item, it)
|
||||
},
|
||||
)
|
||||
},
|
||||
onDownloadClick = if (onDownloadChapter != null) {
|
||||
{ onDownloadChapter(listOf(chapterItem), it) }
|
||||
} else {
|
||||
null
|
||||
},
|
||||
onChapterSwipe = {
|
||||
onChapterSwipe(chapterItem, it)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onChapterItemClick(
|
||||
chapterItem: ChapterItem,
|
||||
chapters: List<ChapterItem>,
|
||||
chapterItem: ChapterList.Item,
|
||||
isAnyChapterSelected: Boolean,
|
||||
onToggleSelection: (Boolean) -> Unit,
|
||||
onChapterClicked: (Chapter) -> Unit,
|
||||
) {
|
||||
when {
|
||||
chapterItem.selected -> onToggleSelection(false)
|
||||
chapters.fastAny { it.selected } -> onToggleSelection(true)
|
||||
isAnyChapterSelected -> onToggleSelection(true)
|
||||
else -> onChapterClicked(chapterItem.chapter)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user