672 lines
29 KiB
Kotlin
Raw Normal View History

2022-06-25 22:03:48 +07:00
package eu.kanade.presentation.manga
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
2022-06-25 22:03:48 +07:00
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
2022-06-25 22:03:48 +07:00
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.lazy.LazyListScope
2022-06-25 22:03:48 +07:00
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
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.Icon
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
2022-06-25 22:03:48 +07:00
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
2022-06-25 22:03:48 +07:00
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.util.fastAll
import androidx.compose.ui.util.fastAny
import androidx.compose.ui.util.fastMap
2022-06-25 22:03:48 +07:00
import eu.kanade.domain.chapter.model.Chapter
import eu.kanade.presentation.components.ChapterDownloadAction
2022-06-25 22:03:48 +07:00
import eu.kanade.presentation.components.ExtendedFloatingActionButton
import eu.kanade.presentation.components.LazyColumn
import eu.kanade.presentation.components.MangaBottomActionMenu
2022-06-25 22:03:48 +07:00
import eu.kanade.presentation.components.Scaffold
import eu.kanade.presentation.components.SwipeRefresh
import eu.kanade.presentation.components.TwoPanelBox
2022-06-25 22:03:48 +07:00
import eu.kanade.presentation.components.VerticalFastScroller
import eu.kanade.presentation.manga.components.ChapterHeader
import eu.kanade.presentation.manga.components.ExpandableMangaDescription
import eu.kanade.presentation.manga.components.MangaActionRow
2022-06-25 22:03:48 +07:00
import eu.kanade.presentation.manga.components.MangaChapterListItem
import eu.kanade.presentation.manga.components.MangaInfoBox
import eu.kanade.presentation.manga.components.MangaToolbar
2022-06-25 22:03:48 +07:00
import eu.kanade.presentation.util.isScrolledToEnd
import eu.kanade.presentation.util.isScrollingUp
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.getNameForMangaInfo
import eu.kanade.tachiyomi.ui.manga.ChapterItem
import eu.kanade.tachiyomi.ui.manga.MangaScreenState
@Composable
fun MangaScreen(
state: MangaScreenState.Success,
snackbarHostState: SnackbarHostState,
2022-10-22 22:15:12 +08:00
isTabletUi: Boolean,
2022-06-25 22:03:48 +07:00
onBackClicked: () -> Unit,
onChapterClicked: (Chapter) -> Unit,
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
onAddToLibraryClicked: () -> Unit,
onWebViewClicked: (() -> Unit)?,
onTrackingClicked: (() -> Unit)?,
onTagClicked: (String) -> Unit,
onFilterButtonClicked: () -> Unit,
onRefresh: () -> Unit,
onContinueReading: () -> Unit,
onSearch: (query: String, global: Boolean) -> Unit,
// For cover dialog
onCoverClicked: () -> Unit,
// For top action menu
onShareClicked: (() -> Unit)?,
onDownloadActionClicked: ((DownloadAction) -> Unit)?,
onEditCategoryClicked: (() -> Unit)?,
onMigrateClicked: (() -> Unit)?,
// For bottom action menu
onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit,
onMultiMarkAsReadClicked: (List<Chapter>, markAsRead: Boolean) -> Unit,
onMarkPreviousAsReadClicked: (Chapter) -> Unit,
onMultiDeleteClicked: (List<Chapter>) -> Unit,
// Chapter selection
onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit,
onAllChapterSelected: (Boolean) -> Unit,
onInvertSelection: () -> Unit,
2022-06-25 22:03:48 +07:00
) {
2022-10-22 22:15:12 +08:00
if (!isTabletUi) {
2022-06-25 22:03:48 +07:00
MangaScreenSmallImpl(
state = state,
snackbarHostState = snackbarHostState,
onBackClicked = onBackClicked,
onChapterClicked = onChapterClicked,
onDownloadChapter = onDownloadChapter,
onAddToLibraryClicked = onAddToLibraryClicked,
onWebViewClicked = onWebViewClicked,
onTrackingClicked = onTrackingClicked,
onTagClicked = onTagClicked,
onFilterClicked = onFilterButtonClicked,
2022-06-25 22:03:48 +07:00
onRefresh = onRefresh,
onContinueReading = onContinueReading,
onSearch = onSearch,
onCoverClicked = onCoverClicked,
onShareClicked = onShareClicked,
onDownloadActionClicked = onDownloadActionClicked,
onEditCategoryClicked = onEditCategoryClicked,
onMigrateClicked = onMigrateClicked,
onMultiBookmarkClicked = onMultiBookmarkClicked,
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked,
onMultiDeleteClicked = onMultiDeleteClicked,
onChapterSelected = onChapterSelected,
onAllChapterSelected = onAllChapterSelected,
onInvertSelection = onInvertSelection,
2022-06-25 22:03:48 +07:00
)
} else {
MangaScreenLargeImpl(
state = state,
snackbarHostState = snackbarHostState,
onBackClicked = onBackClicked,
onChapterClicked = onChapterClicked,
onDownloadChapter = onDownloadChapter,
onAddToLibraryClicked = onAddToLibraryClicked,
onWebViewClicked = onWebViewClicked,
onTrackingClicked = onTrackingClicked,
onTagClicked = onTagClicked,
onFilterButtonClicked = onFilterButtonClicked,
onRefresh = onRefresh,
onContinueReading = onContinueReading,
onSearch = onSearch,
onCoverClicked = onCoverClicked,
onShareClicked = onShareClicked,
onDownloadActionClicked = onDownloadActionClicked,
onEditCategoryClicked = onEditCategoryClicked,
onMigrateClicked = onMigrateClicked,
onMultiBookmarkClicked = onMultiBookmarkClicked,
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked,
onMultiDeleteClicked = onMultiDeleteClicked,
onChapterSelected = onChapterSelected,
onAllChapterSelected = onAllChapterSelected,
onInvertSelection = onInvertSelection,
2022-06-25 22:03:48 +07:00
)
}
}
@Composable
private fun MangaScreenSmallImpl(
state: MangaScreenState.Success,
snackbarHostState: SnackbarHostState,
onBackClicked: () -> Unit,
onChapterClicked: (Chapter) -> Unit,
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
onAddToLibraryClicked: () -> Unit,
onWebViewClicked: (() -> Unit)?,
onTrackingClicked: (() -> Unit)?,
onTagClicked: (String) -> Unit,
onFilterClicked: () -> Unit,
2022-06-25 22:03:48 +07:00
onRefresh: () -> Unit,
onContinueReading: () -> Unit,
onSearch: (query: String, global: Boolean) -> Unit,
// For cover dialog
onCoverClicked: () -> Unit,
// For top action menu
onShareClicked: (() -> Unit)?,
onDownloadActionClicked: ((DownloadAction) -> Unit)?,
onEditCategoryClicked: (() -> Unit)?,
onMigrateClicked: (() -> Unit)?,
// For bottom action menu
onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit,
onMultiMarkAsReadClicked: (List<Chapter>, markAsRead: Boolean) -> Unit,
onMarkPreviousAsReadClicked: (Chapter) -> Unit,
onMultiDeleteClicked: (List<Chapter>) -> Unit,
// Chapter selection
onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit,
onAllChapterSelected: (Boolean) -> Unit,
onInvertSelection: () -> Unit,
2022-06-25 22:03:48 +07:00
) {
val chapterListState = rememberLazyListState()
val chapters = remember(state) { state.processedChapters.toList() }
2022-06-25 22:03:48 +07:00
val internalOnBackPressed = {
if (chapters.fastAny { it.selected }) {
onAllChapterSelected(false)
} else {
onBackClicked()
2022-06-25 22:03:48 +07:00
}
}
BackHandler(onBack = internalOnBackPressed)
2022-06-25 22:03:48 +07:00
Scaffold(
topBar = {
val firstVisibleItemIndex by remember {
derivedStateOf { chapterListState.firstVisibleItemIndex }
}
val firstVisibleItemScrollOffset by remember {
derivedStateOf { chapterListState.firstVisibleItemScrollOffset }
}
val animatedTitleAlpha by animateFloatAsState(
if (firstVisibleItemIndex > 0) 1f else 0f,
)
val animatedBgAlpha by animateFloatAsState(
if (firstVisibleItemIndex > 0 || firstVisibleItemScrollOffset > 0) 1f else 0f,
)
MangaToolbar(
title = state.manga.title,
titleAlphaProvider = { animatedTitleAlpha },
backgroundAlphaProvider = { animatedBgAlpha },
hasFilters = state.manga.chaptersFiltered(),
incognitoMode = state.isIncognitoMode,
downloadedOnlyMode = state.isDownloadedOnlyMode,
onBackClicked = internalOnBackPressed,
onClickFilter = onFilterClicked,
onClickShare = onShareClicked,
onClickDownload = onDownloadActionClicked,
onClickEditCategory = onEditCategoryClicked,
onClickMigrate = onMigrateClicked,
actionModeCounter = chapters.count { it.selected },
onSelectAll = { onAllChapterSelected(true) },
onInvertSelection = { onInvertSelection() },
)
},
bottomBar = {
SharedMangaBottomActionMenu(
selected = chapters.filter { it.selected },
onMultiBookmarkClicked = onMultiBookmarkClicked,
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked,
onDownloadChapter = onDownloadChapter,
onMultiDeleteClicked = onMultiDeleteClicked,
fillFraction = 1f,
)
},
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
floatingActionButton = {
AnimatedVisibility(
visible = chapters.fastAny { !it.chapter.read } && chapters.fastAll { !it.selected },
enter = fadeIn(),
exit = fadeOut(),
) {
ExtendedFloatingActionButton(
text = {
val id = if (chapters.fastAny { it.chapter.read }) {
R.string.action_resume
} else {
R.string.action_start
}
Text(text = stringResource(id))
2022-06-25 22:03:48 +07:00
},
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
onClick = onContinueReading,
expanded = chapterListState.isScrollingUp() || chapterListState.isScrolledToEnd(),
2022-06-25 22:03:48 +07:00
)
}
},
) { contentPadding ->
val topPadding = contentPadding.calculateTopPadding()
SwipeRefresh(
refreshing = state.isRefreshingData,
onRefresh = onRefresh,
enabled = chapters.fastAll { !it.selected },
indicatorPadding = contentPadding,
) {
val layoutDirection = LocalLayoutDirection.current
2022-06-25 22:03:48 +07:00
VerticalFastScroller(
listState = chapterListState,
topContentPadding = topPadding,
endContentPadding = contentPadding.calculateEndPadding(layoutDirection),
2022-06-25 22:03:48 +07:00
) {
LazyColumn(
modifier = Modifier.fillMaxHeight(),
state = chapterListState,
contentPadding = PaddingValues(
start = contentPadding.calculateStartPadding(layoutDirection),
end = contentPadding.calculateEndPadding(layoutDirection),
bottom = contentPadding.calculateBottomPadding(),
),
2022-06-25 22:03:48 +07:00
) {
item(
key = MangaScreenItem.INFO_BOX,
contentType = MangaScreenItem.INFO_BOX,
) {
MangaInfoBox(
2022-10-22 22:15:12 +08:00
isTabletUi = false,
appBarPadding = topPadding,
title = state.manga.title,
author = state.manga.author,
artist = state.manga.artist,
sourceName = remember { state.source.getNameForMangaInfo() },
isStubSource = remember { state.source is SourceManager.StubSource },
coverDataProvider = { state.manga },
status = state.manga.status,
onCoverClick = onCoverClicked,
doSearch = onSearch,
)
}
item(
key = MangaScreenItem.ACTION_ROW,
contentType = MangaScreenItem.ACTION_ROW,
) {
MangaActionRow(
favorite = state.manga.favorite,
trackingCount = state.trackingCount,
onAddToLibraryClicked = onAddToLibraryClicked,
onWebViewClicked = onWebViewClicked,
onTrackingClicked = onTrackingClicked,
onEditCategory = onEditCategoryClicked,
)
}
item(
key = MangaScreenItem.DESCRIPTION_WITH_TAG,
contentType = MangaScreenItem.DESCRIPTION_WITH_TAG,
) {
ExpandableMangaDescription(
defaultExpandState = state.isFromSource,
description = state.manga.description,
tagsProvider = { state.manga.genre },
onTagClicked = onTagClicked,
)
}
item(
key = MangaScreenItem.CHAPTER_HEADER,
contentType = MangaScreenItem.CHAPTER_HEADER,
) {
ChapterHeader(
chapterCount = chapters.size,
onClick = onFilterClicked,
)
}
sharedChapterItems(
chapters = chapters,
onChapterClicked = onChapterClicked,
onDownloadChapter = onDownloadChapter,
onChapterSelected = onChapterSelected,
)
2022-06-25 22:03:48 +07:00
}
}
}
}
}
@Composable
fun MangaScreenLargeImpl(
state: MangaScreenState.Success,
snackbarHostState: SnackbarHostState,
onBackClicked: () -> Unit,
onChapterClicked: (Chapter) -> Unit,
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
onAddToLibraryClicked: () -> Unit,
onWebViewClicked: (() -> Unit)?,
onTrackingClicked: (() -> Unit)?,
onTagClicked: (String) -> Unit,
onFilterButtonClicked: () -> Unit,
onRefresh: () -> Unit,
onContinueReading: () -> Unit,
onSearch: (query: String, global: Boolean) -> Unit,
// For cover dialog
onCoverClicked: () -> Unit,
// For top action menu
onShareClicked: (() -> Unit)?,
onDownloadActionClicked: ((DownloadAction) -> Unit)?,
onEditCategoryClicked: (() -> Unit)?,
onMigrateClicked: (() -> Unit)?,
// For bottom action menu
onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit,
onMultiMarkAsReadClicked: (List<Chapter>, markAsRead: Boolean) -> Unit,
onMarkPreviousAsReadClicked: (Chapter) -> Unit,
onMultiDeleteClicked: (List<Chapter>) -> Unit,
// Chapter selection
onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit,
onAllChapterSelected: (Boolean) -> Unit,
onInvertSelection: () -> Unit,
2022-06-25 22:03:48 +07:00
) {
val layoutDirection = LocalLayoutDirection.current
val density = LocalDensity.current
val chapters = remember(state) { state.processedChapters.toList() }
2022-06-25 22:03:48 +07:00
val insetPadding = WindowInsets.systemBars.only(WindowInsetsSides.Horizontal).asPaddingValues()
var topBarHeight by remember { mutableStateOf(0) }
2022-06-25 22:03:48 +07:00
SwipeRefresh(
refreshing = state.isRefreshingData,
2022-06-25 22:03:48 +07:00
onRefresh = onRefresh,
enabled = chapters.fastAll { !it.selected },
2022-06-25 22:03:48 +07:00
indicatorPadding = PaddingValues(
start = insetPadding.calculateStartPadding(layoutDirection),
top = with(density) { topBarHeight.toDp() },
end = insetPadding.calculateEndPadding(layoutDirection),
),
) {
val chapterListState = rememberLazyListState()
val internalOnBackPressed = {
if (chapters.fastAny { it.selected }) {
onAllChapterSelected(false)
2022-06-25 22:03:48 +07:00
} else {
onBackClicked()
}
}
BackHandler(onBack = internalOnBackPressed)
Scaffold(
topBar = {
MangaToolbar(
modifier = Modifier.onSizeChanged { topBarHeight = it.height },
2022-06-25 22:03:48 +07:00
title = state.manga.title,
titleAlphaProvider = { if (chapters.fastAny { it.selected }) 1f else 0f },
2022-06-25 22:03:48 +07:00
backgroundAlphaProvider = { 1f },
hasFilters = state.manga.chaptersFiltered(),
2022-06-25 22:03:48 +07:00
incognitoMode = state.isIncognitoMode,
downloadedOnlyMode = state.isDownloadedOnlyMode,
onBackClicked = internalOnBackPressed,
onClickFilter = onFilterButtonClicked,
onClickShare = onShareClicked,
onClickDownload = onDownloadActionClicked,
onClickEditCategory = onEditCategoryClicked,
onClickMigrate = onMigrateClicked,
actionModeCounter = chapters.count { it.selected },
onSelectAll = { onAllChapterSelected(true) },
onInvertSelection = { onInvertSelection() },
2022-06-25 22:03:48 +07:00
)
},
bottomBar = {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.BottomEnd,
) {
SharedMangaBottomActionMenu(
selected = chapters.filter { it.selected },
onMultiBookmarkClicked = onMultiBookmarkClicked,
onMultiMarkAsReadClicked = onMultiMarkAsReadClicked,
onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked,
onDownloadChapter = onDownloadChapter,
onMultiDeleteClicked = onMultiDeleteClicked,
fillFraction = 0.5f,
2022-06-25 22:03:48 +07:00
)
}
},
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
floatingActionButton = {
AnimatedVisibility(
visible = chapters.fastAny { !it.chapter.read } && chapters.fastAll { !it.selected },
2022-06-25 22:03:48 +07:00
enter = fadeIn(),
exit = fadeOut(),
) {
ExtendedFloatingActionButton(
text = {
val id = if (chapters.fastAny { it.chapter.read }) {
2022-06-25 22:03:48 +07:00
R.string.action_resume
} else {
R.string.action_start
}
Text(text = stringResource(id))
2022-06-25 22:03:48 +07:00
},
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
2022-06-25 22:03:48 +07:00
onClick = onContinueReading,
expanded = chapterListState.isScrollingUp() || chapterListState.isScrolledToEnd(),
)
}
},
) { contentPadding ->
TwoPanelBox(
modifier = Modifier.padding(
start = contentPadding.calculateStartPadding(layoutDirection),
end = contentPadding.calculateEndPadding(layoutDirection),
),
startContent = {
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.padding(bottom = contentPadding.calculateBottomPadding()),
) {
MangaInfoBox(
2022-10-22 22:15:12 +08:00
isTabletUi = true,
appBarPadding = contentPadding.calculateTopPadding(),
title = state.manga.title,
author = state.manga.author,
artist = state.manga.artist,
sourceName = remember { state.source.getNameForMangaInfo() },
isStubSource = remember { state.source is SourceManager.StubSource },
coverDataProvider = { state.manga },
status = state.manga.status,
onCoverClick = onCoverClicked,
doSearch = onSearch,
)
MangaActionRow(
favorite = state.manga.favorite,
trackingCount = state.trackingCount,
onAddToLibraryClicked = onAddToLibraryClicked,
onWebViewClicked = onWebViewClicked,
onTrackingClicked = onTrackingClicked,
onEditCategory = onEditCategoryClicked,
)
ExpandableMangaDescription(
defaultExpandState = true,
description = state.manga.description,
tagsProvider = { state.manga.genre },
onTagClicked = onTagClicked,
)
}
},
endContent = {
VerticalFastScroller(
listState = chapterListState,
topContentPadding = contentPadding.calculateTopPadding(),
2022-06-25 22:03:48 +07:00
) {
LazyColumn(
modifier = Modifier.fillMaxHeight(),
state = chapterListState,
contentPadding = PaddingValues(
top = contentPadding.calculateTopPadding(),
bottom = contentPadding.calculateBottomPadding(),
),
) {
item(
key = MangaScreenItem.CHAPTER_HEADER,
contentType = MangaScreenItem.CHAPTER_HEADER,
) {
ChapterHeader(
chapterCount = chapters.size,
onClick = onFilterButtonClicked,
)
}
sharedChapterItems(
chapters = chapters,
onChapterClicked = onChapterClicked,
onDownloadChapter = onDownloadChapter,
onChapterSelected = onChapterSelected,
2022-06-25 22:03:48 +07:00
)
}
}
},
)
2022-06-25 22:03:48 +07:00
}
}
}
@Composable
private fun SharedMangaBottomActionMenu(
selected: List<ChapterItem>,
modifier: Modifier = Modifier,
onMultiBookmarkClicked: (List<Chapter>, bookmarked: Boolean) -> Unit,
onMultiMarkAsReadClicked: (List<Chapter>, markAsRead: Boolean) -> Unit,
onMarkPreviousAsReadClicked: (Chapter) -> Unit,
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
onMultiDeleteClicked: (List<Chapter>) -> Unit,
fillFraction: Float,
) {
MangaBottomActionMenu(
visible = selected.isNotEmpty(),
modifier = modifier.fillMaxWidth(fillFraction),
onBookmarkClicked = {
onMultiBookmarkClicked.invoke(selected.fastMap { it.chapter }, true)
}.takeIf { selected.fastAny { !it.chapter.bookmark } },
onRemoveBookmarkClicked = {
onMultiBookmarkClicked.invoke(selected.fastMap { it.chapter }, false)
}.takeIf { selected.fastAll { it.chapter.bookmark } },
onMarkAsReadClicked = {
onMultiMarkAsReadClicked(selected.fastMap { it.chapter }, true)
}.takeIf { selected.fastAny { !it.chapter.read } },
onMarkAsUnreadClicked = {
onMultiMarkAsReadClicked(selected.fastMap { it.chapter }, false)
}.takeIf { selected.fastAny { it.chapter.read || it.chapter.lastPageRead > 0L } },
onMarkPreviousAsReadClicked = {
onMarkPreviousAsReadClicked(selected[0].chapter)
}.takeIf { selected.size == 1 },
onDownloadClicked = {
onDownloadChapter!!(selected.toList(), ChapterDownloadAction.START)
}.takeIf {
onDownloadChapter != null && selected.fastAny { it.downloadState != Download.State.DOWNLOADED }
},
onDeleteClicked = {
onMultiDeleteClicked(selected.fastMap { it.chapter })
}.takeIf {
onDownloadChapter != null && selected.fastAny { it.downloadState == Download.State.DOWNLOADED }
},
)
}
private fun LazyListScope.sharedChapterItems(
chapters: List<ChapterItem>,
onChapterClicked: (Chapter) -> Unit,
onDownloadChapter: ((List<ChapterItem>, ChapterDownloadAction) -> Unit)?,
onChapterSelected: (ChapterItem, Boolean, Boolean, Boolean) -> Unit,
) {
items(
items = chapters,
key = { "chapter-${it.chapter.id}" },
contentType = { MangaScreenItem.CHAPTER },
) { chapterItem ->
val haptic = LocalHapticFeedback.current
MangaChapterListItem(
title = chapterItem.chapterTitleString,
date = chapterItem.dateUploadString,
readProgress = chapterItem.readProgressString,
scanlator = chapterItem.chapter.scanlator.takeIf { !it.isNullOrBlank() },
read = chapterItem.chapter.read,
bookmark = chapterItem.chapter.bookmark,
selected = chapterItem.selected,
downloadStateProvider = { chapterItem.downloadState },
downloadProgressProvider = { chapterItem.downloadProgress },
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,
)
},
onDownloadClick = if (onDownloadChapter != null) {
{ onDownloadChapter(listOf(chapterItem), it) }
2022-09-10 23:57:03 -04:00
} else {
null
},
)
}
}
private fun onChapterItemClick(
2022-06-25 22:03:48 +07:00
chapterItem: ChapterItem,
chapters: List<ChapterItem>,
onToggleSelection: (Boolean) -> Unit,
2022-06-25 22:03:48 +07:00
onChapterClicked: (Chapter) -> Unit,
) {
when {
chapterItem.selected -> onToggleSelection(false)
chapters.fastAny { it.selected } -> onToggleSelection(true)
2022-06-25 22:03:48 +07:00
else -> onChapterClicked(chapterItem.chapter)
}
}