feat(updates-screen): Swipe actions for chapter updates (#915)
* feat(updates-screen): Swipe actions for chapter updates * Smaller cover size & add option to hide cover images (debug menu) * Correctly apply passed-in modifier * Memoize `getSwipeAction(...)`` invocations with Compose’s `remember` (keyed on the action and state) to avoid recreating those objects on every recomposition
This commit is contained in:
parent
a3abccb34b
commit
c52de8c472
8 changed files with 336 additions and 179 deletions
|
|
@ -27,10 +27,12 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.presentation.manga.components.MangaCover
|
||||
import eu.kanade.presentation.manga.components.MangaCoverHide
|
||||
import eu.kanade.presentation.manga.components.RatioSwitchToPanorama
|
||||
import eu.kanade.presentation.theme.TachiyomiPreviewTheme
|
||||
import eu.kanade.presentation.util.formatChapterNumber
|
||||
import eu.kanade.tachiyomi.util.lang.toTimestampString
|
||||
import exh.debug.DebugToggles
|
||||
import tachiyomi.domain.history.model.HistoryWithRelations
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
|
|
@ -63,37 +65,46 @@ fun HistoryItem(
|
|||
val coverIsWide = coverRatio.floatValue <= RatioSwitchToPanorama
|
||||
val bgColor = mangaCover.dominantCoverColors?.first?.let { Color(it) }
|
||||
val onBgColor = mangaCover.dominantCoverColors?.second
|
||||
if (usePanoramaCover && coverIsWide) {
|
||||
MangaCover.Panorama(
|
||||
if (DebugToggles.HIDE_COVER_IMAGE_ONLY_SHOW_COLOR.enabled) {
|
||||
MangaCoverHide.Book(
|
||||
modifier = Modifier.fillMaxHeight(),
|
||||
data = mangaCover,
|
||||
onClick = onClickCover,
|
||||
// KMK -->
|
||||
bgColor = bgColor,
|
||||
tint = onBgColor,
|
||||
size = MangaCover.Size.Medium,
|
||||
onCoverLoaded = { _, result ->
|
||||
val image = result.result.image
|
||||
coverRatio.floatValue = image.height.toFloat() / image.width
|
||||
},
|
||||
// KMK <--
|
||||
)
|
||||
} else {
|
||||
// KMK <--
|
||||
MangaCover.Book(
|
||||
modifier = Modifier.fillMaxHeight(),
|
||||
data = mangaCover,
|
||||
onClick = onClickCover,
|
||||
// KMK -->
|
||||
bgColor = bgColor,
|
||||
tint = onBgColor,
|
||||
size = MangaCover.Size.Medium,
|
||||
onCoverLoaded = { _, result ->
|
||||
val image = result.result.image
|
||||
coverRatio.floatValue = image.height.toFloat() / image.width
|
||||
},
|
||||
if (usePanoramaCover && coverIsWide) {
|
||||
MangaCover.Panorama(
|
||||
modifier = Modifier.fillMaxHeight(),
|
||||
data = mangaCover,
|
||||
onClick = onClickCover,
|
||||
// KMK -->
|
||||
bgColor = bgColor,
|
||||
tint = onBgColor,
|
||||
size = MangaCover.Size.Medium,
|
||||
onCoverLoaded = { _, result ->
|
||||
val image = result.result.image
|
||||
coverRatio.floatValue = image.height.toFloat() / image.width
|
||||
},
|
||||
// KMK <--
|
||||
)
|
||||
} else {
|
||||
// KMK <--
|
||||
)
|
||||
MangaCover.Book(
|
||||
modifier = Modifier.fillMaxHeight(),
|
||||
data = mangaCover,
|
||||
onClick = onClickCover,
|
||||
// KMK -->
|
||||
bgColor = bgColor,
|
||||
tint = onBgColor,
|
||||
size = MangaCover.Size.Medium,
|
||||
onCoverLoaded = { _, result ->
|
||||
val image = result.result.image
|
||||
coverRatio.floatValue = image.height.toFloat() / image.width
|
||||
},
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ private fun Modifier.commonClickable(
|
|||
),
|
||||
)
|
||||
|
||||
private val IndicatorSize = 26.dp
|
||||
internal val IndicatorSize = 26.dp
|
||||
private val IndicatorPadding = 2.dp
|
||||
|
||||
// To match composable parameter name when used later
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Column
|
|||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.sizeIn
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Bookmark
|
||||
|
|
@ -68,27 +69,36 @@ fun MangaChapterListItem(
|
|||
onChapterSwipe: (LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val start = getSwipeAction(
|
||||
action = chapterSwipeStartAction,
|
||||
read = read,
|
||||
bookmark = bookmark,
|
||||
downloadState = downloadStateProvider(),
|
||||
background = MaterialTheme.colorScheme.primaryContainer,
|
||||
onSwipe = { onChapterSwipe(chapterSwipeStartAction) },
|
||||
)
|
||||
val end = getSwipeAction(
|
||||
action = chapterSwipeEndAction,
|
||||
read = read,
|
||||
bookmark = bookmark,
|
||||
downloadState = downloadStateProvider(),
|
||||
background = MaterialTheme.colorScheme.primaryContainer,
|
||||
onSwipe = { onChapterSwipe(chapterSwipeEndAction) },
|
||||
)
|
||||
// KMK -->
|
||||
val swipeBackground = MaterialTheme.colorScheme.primaryContainer
|
||||
val swipeStart = remember(chapterSwipeStartAction, read, bookmark, downloadStateProvider()) {
|
||||
// KMK <--
|
||||
getSwipeAction(
|
||||
action = chapterSwipeStartAction,
|
||||
read = read,
|
||||
bookmark = bookmark,
|
||||
downloadState = downloadStateProvider(),
|
||||
background = swipeBackground,
|
||||
onSwipe = { onChapterSwipe(chapterSwipeStartAction) },
|
||||
)
|
||||
}
|
||||
// KMK -->
|
||||
val swipeEnd = remember(chapterSwipeEndAction, read, bookmark, downloadStateProvider()) {
|
||||
// KMK <--
|
||||
getSwipeAction(
|
||||
action = chapterSwipeEndAction,
|
||||
read = read,
|
||||
bookmark = bookmark,
|
||||
downloadState = downloadStateProvider(),
|
||||
background = swipeBackground,
|
||||
onSwipe = { onChapterSwipe(chapterSwipeEndAction) },
|
||||
)
|
||||
}
|
||||
|
||||
SwipeableActionsBox(
|
||||
modifier = Modifier.clipToBounds(),
|
||||
startActions = listOfNotNull(start),
|
||||
endActions = listOfNotNull(end),
|
||||
startActions = listOfNotNull(swipeStart),
|
||||
endActions = listOfNotNull(swipeEnd),
|
||||
swipeThreshold = swipeActionThreshold,
|
||||
backgroundUntilSwipeThreshold = MaterialTheme.colorScheme.surfaceContainerLowest,
|
||||
) {
|
||||
|
|
@ -200,7 +210,7 @@ fun MangaChapterListItem(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getSwipeAction(
|
||||
internal fun getSwipeAction(
|
||||
action: LibraryPreferences.ChapterSwipeAction,
|
||||
read: Boolean,
|
||||
bookmark: Boolean,
|
||||
|
|
@ -243,7 +253,9 @@ private fun swipeAction(
|
|||
return me.saket.swipe.SwipeAction(
|
||||
icon = {
|
||||
Icon(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.size(IndicatorSize),
|
||||
imageVector = icon,
|
||||
tint = contentColorFor(background),
|
||||
contentDescription = null,
|
||||
|
|
@ -255,4 +267,4 @@ private fun swipeAction(
|
|||
)
|
||||
}
|
||||
|
||||
private val swipeActionThreshold = 56.dp
|
||||
internal val swipeActionThreshold = 56.dp
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ import androidx.compose.ui.semantics.Role
|
|||
import androidx.compose.ui.unit.dp
|
||||
import coil3.compose.AsyncImagePainter
|
||||
import coil3.compose.SubcomposeAsyncImage
|
||||
import eu.kanade.presentation.manga.components.MangaCover.Companion.COVER_TEMPLATE_SIZE_BIG
|
||||
import eu.kanade.presentation.manga.components.MangaCover.Companion.COVER_TEMPLATE_SIZE_MEDIUM
|
||||
import eu.kanade.presentation.manga.components.MangaCover.Companion.COVER_TEMPLATE_SIZE_NORMAL
|
||||
import eu.kanade.presentation.manga.components.MangaCover.Size
|
||||
import eu.kanade.tachiyomi.R
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import tachiyomi.domain.manga.model.asMangaCover
|
||||
|
|
@ -175,6 +179,7 @@ enum class MangaCoverHide(private val ratio: Float) {
|
|||
bgColor: Color? = CoverPlaceholderColor,
|
||||
/** onBackground color, which used for loading/error indicator */
|
||||
@ColorInt tint: Int? = null,
|
||||
size: Size = Size.Normal,
|
||||
) {
|
||||
val modifierColored = modifier
|
||||
.aspectRatio(ratio)
|
||||
|
|
@ -198,7 +203,13 @@ enum class MangaCoverHide(private val ratio: Float) {
|
|||
imageVector = ImageVector.vectorResource(R.drawable.ic_baseline_menu_book_24),
|
||||
contentDescription = contentDescription,
|
||||
modifier = Modifier
|
||||
.size(32.dp)
|
||||
.size(
|
||||
when (size) {
|
||||
Size.Big -> COVER_TEMPLATE_SIZE_BIG
|
||||
Size.Medium -> COVER_TEMPLATE_SIZE_MEDIUM
|
||||
else -> COVER_TEMPLATE_SIZE_NORMAL
|
||||
},
|
||||
)
|
||||
.align(Alignment.Center),
|
||||
colorFilter = ColorFilter.tint(
|
||||
tint?.let { Color(it) } ?: CoverPlaceholderOnBgColor,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import eu.kanade.tachiyomi.ui.updates.UpdatesScreenModel
|
|||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.kmk.KMR
|
||||
import tachiyomi.presentation.core.components.FastScrollLazyColumn
|
||||
|
|
@ -60,6 +61,11 @@ fun UpdateScreen(
|
|||
onMultiBookmarkClicked: (List<UpdatesItem>, bookmark: Boolean) -> Unit,
|
||||
onMultiMarkAsReadClicked: (List<UpdatesItem>, read: Boolean) -> Unit,
|
||||
onMultiDeleteClicked: (List<UpdatesItem>) -> Unit,
|
||||
// KMK -->
|
||||
updateSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
|
||||
updateSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
|
||||
onUpdateSwipe: (UpdatesItem, LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
// KMK <--
|
||||
onUpdateSelected: (UpdatesItem, /* KMK --> */ UpdatesScreenModel.UpdateSelectionOptions /* KMK <-- */) -> Unit,
|
||||
onOpenChapter: (UpdatesItem) -> Unit,
|
||||
// KMK -->
|
||||
|
|
@ -143,6 +149,11 @@ fun UpdateScreen(
|
|||
onClickCover = onClickCover,
|
||||
onClickUpdate = onOpenChapter,
|
||||
onDownloadChapter = onDownloadChapter,
|
||||
// KMK -->
|
||||
updateSwipeStartAction = updateSwipeStartAction,
|
||||
updateSwipeEndAction = updateSwipeEndAction,
|
||||
onUpdateSwipe = onUpdateSwipe,
|
||||
// KMK <--
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
|
|
@ -48,7 +49,10 @@ import eu.kanade.presentation.manga.components.ChapterDownloadAction
|
|||
import eu.kanade.presentation.manga.components.ChapterDownloadIndicator
|
||||
import eu.kanade.presentation.manga.components.DotSeparatorText
|
||||
import eu.kanade.presentation.manga.components.MangaCover
|
||||
import eu.kanade.presentation.manga.components.MangaCoverHide
|
||||
import eu.kanade.presentation.manga.components.RatioSwitchToPanorama
|
||||
import eu.kanade.presentation.manga.components.getSwipeAction
|
||||
import eu.kanade.presentation.manga.components.swipeActionThreshold
|
||||
import eu.kanade.presentation.util.animateItemFastScroll
|
||||
import eu.kanade.presentation.util.relativeTimeSpanString
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
|
@ -56,7 +60,10 @@ import eu.kanade.tachiyomi.data.download.model.Download
|
|||
import eu.kanade.tachiyomi.ui.updates.UpdatesItem
|
||||
import eu.kanade.tachiyomi.ui.updates.UpdatesScreenModel.UpdateSelectionOptions
|
||||
import eu.kanade.tachiyomi.ui.updates.groupByDateAndManga
|
||||
import exh.debug.DebugToggles
|
||||
import me.saket.swipe.SwipeableActionsBox
|
||||
import mihon.feature.upcoming.DateHeading
|
||||
import tachiyomi.domain.library.service.LibraryPreferences
|
||||
import tachiyomi.domain.updates.model.UpdatesWithRelations
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.DISABLED_ALPHA
|
||||
|
|
@ -96,6 +103,11 @@ internal fun LazyListScope.updatesUiItems(
|
|||
onClickCover: (UpdatesItem) -> Unit,
|
||||
onClickUpdate: (UpdatesItem) -> Unit,
|
||||
onDownloadChapter: (List<UpdatesItem>, ChapterDownloadAction) -> Unit,
|
||||
// KMK -->
|
||||
updateSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
|
||||
updateSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
|
||||
onUpdateSwipe: (UpdatesItem, LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
// KMK <--
|
||||
) {
|
||||
items(
|
||||
items = uiModels,
|
||||
|
|
@ -191,6 +203,11 @@ internal fun LazyListScope.updatesUiItems(
|
|||
downloadStateProvider = updatesItem.downloadStateProvider,
|
||||
downloadProgressProvider = updatesItem.downloadProgressProvider,
|
||||
// KMK -->
|
||||
updateSwipeStartAction = updateSwipeStartAction,
|
||||
updateSwipeEndAction = updateSwipeEndAction,
|
||||
onUpdateSwipe = {
|
||||
onUpdateSwipe(updatesItem, it)
|
||||
},
|
||||
isLeader = isLeader,
|
||||
isExpandable = item.isExpandable,
|
||||
expanded = isExpanded,
|
||||
|
|
@ -217,6 +234,9 @@ private fun UpdatesUiItem(
|
|||
downloadStateProvider: () -> Download.State,
|
||||
downloadProgressProvider: () -> Int,
|
||||
// KMK -->
|
||||
updateSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
|
||||
updateSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
|
||||
onUpdateSwipe: (LibraryPreferences.ChapterSwipeAction) -> Unit,
|
||||
isLeader: Boolean,
|
||||
isExpandable: Boolean,
|
||||
expanded: Boolean,
|
||||
|
|
@ -231,152 +251,193 @@ private fun UpdatesUiItem(
|
|||
val haptic = LocalHapticFeedback.current
|
||||
val textAlpha = if (update.read) DISABLED_ALPHA else 1f
|
||||
|
||||
Row(
|
||||
modifier = modifier
|
||||
.selectedBackground(selected)
|
||||
.combinedClickable(
|
||||
onClick = onClick,
|
||||
onLongClick = {
|
||||
onLongClick()
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
)
|
||||
.padding(
|
||||
// KMK -->
|
||||
vertical = if (isLeader) MaterialTheme.padding.extraSmall else 0.dp,
|
||||
// KMK <--
|
||||
horizontal = MaterialTheme.padding.medium,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
// KMK -->
|
||||
val mangaCover = update.coverData
|
||||
val coverIsWide = coverRatio.floatValue <= RatioSwitchToPanorama
|
||||
val bgColor = mangaCover.dominantCoverColors?.first?.let { Color(it) }
|
||||
val onBgColor = mangaCover.dominantCoverColors?.second
|
||||
if (isLeader) {
|
||||
if (usePanoramaCover && coverIsWide) {
|
||||
MangaCover.Panorama(
|
||||
modifier = Modifier
|
||||
.padding(top = MaterialTheme.padding.small)
|
||||
.width(UpdateItemPanoramaWidth),
|
||||
data = mangaCover,
|
||||
onClick = onClickCover,
|
||||
// KMK -->
|
||||
bgColor = bgColor,
|
||||
tint = onBgColor,
|
||||
size = MangaCover.Size.Medium,
|
||||
onCoverLoaded = { _, result ->
|
||||
val image = result.result.image
|
||||
coverRatio.floatValue = image.height.toFloat() / image.width
|
||||
},
|
||||
// KMK <--
|
||||
)
|
||||
} else {
|
||||
// KMK <--
|
||||
MangaCover.Book(
|
||||
modifier = Modifier
|
||||
// KMK -->
|
||||
.padding(top = MaterialTheme.padding.small)
|
||||
.width(UpdateItemWidth),
|
||||
// KMK <--
|
||||
data = mangaCover,
|
||||
onClick = onClickCover,
|
||||
// KMK -->
|
||||
bgColor = bgColor,
|
||||
tint = onBgColor,
|
||||
size = MangaCover.Size.Medium,
|
||||
onCoverLoaded = { _, result ->
|
||||
val image = result.result.image
|
||||
coverRatio.floatValue = image.height.toFloat() / image.width
|
||||
},
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(if (usePanoramaCover && coverIsWide) UpdateItemPanoramaWidth else UpdateItemWidth),
|
||||
)
|
||||
// KMK <--
|
||||
}
|
||||
// KMK -->
|
||||
val swipeBackground = MaterialTheme.colorScheme.primaryContainer
|
||||
val swipeStart = remember(updateSwipeStartAction, update.read, update.bookmark, downloadStateProvider()) {
|
||||
getSwipeAction(
|
||||
action = updateSwipeStartAction,
|
||||
read = update.read,
|
||||
bookmark = update.bookmark,
|
||||
downloadState = downloadStateProvider(),
|
||||
background = swipeBackground,
|
||||
onSwipe = { onUpdateSwipe(updateSwipeStartAction) },
|
||||
)
|
||||
}
|
||||
val swipeEnd = remember(updateSwipeEndAction, update.read, update.bookmark, downloadStateProvider()) {
|
||||
getSwipeAction(
|
||||
action = updateSwipeEndAction,
|
||||
read = update.read,
|
||||
bookmark = update.bookmark,
|
||||
downloadState = downloadStateProvider(),
|
||||
background = swipeBackground,
|
||||
onSwipe = { onUpdateSwipe(updateSwipeEndAction) },
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
SwipeableActionsBox(
|
||||
modifier = modifier.clipToBounds(),
|
||||
startActions = listOfNotNull(swipeStart),
|
||||
endActions = listOfNotNull(swipeEnd),
|
||||
swipeThreshold = swipeActionThreshold,
|
||||
backgroundUntilSwipeThreshold = MaterialTheme.colorScheme.surfaceContainerLowest,
|
||||
) {
|
||||
// KMK <--
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = MaterialTheme.padding.medium)
|
||||
.weight(1f),
|
||||
.selectedBackground(selected)
|
||||
.combinedClickable(
|
||||
onClick = onClick,
|
||||
onLongClick = {
|
||||
onLongClick()
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
)
|
||||
.padding(top = if (isLeader) MaterialTheme.padding.small else 0.dp)
|
||||
.padding(
|
||||
// KMK -->
|
||||
vertical = if (isLeader) MaterialTheme.padding.extraSmall else 0.dp,
|
||||
// KMK <--
|
||||
horizontal = MaterialTheme.padding.medium,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
// KMK -->
|
||||
val mangaCover = update.coverData
|
||||
val coverIsWide = coverRatio.floatValue <= RatioSwitchToPanorama
|
||||
val bgColor = mangaCover.dominantCoverColors?.first?.let { Color(it) }
|
||||
val onBgColor = mangaCover.dominantCoverColors?.second
|
||||
if (isLeader) {
|
||||
// KMK <--
|
||||
Text(
|
||||
text = update.mangaTitle,
|
||||
maxLines = 1,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = LocalContentColor.current.copy(alpha = textAlpha),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
if (DebugToggles.HIDE_COVER_IMAGE_ONLY_SHOW_COLOR.enabled) {
|
||||
MangaCoverHide.Book(
|
||||
modifier = Modifier
|
||||
.width(UpdateItemWidth),
|
||||
bgColor = bgColor ?: (MaterialTheme.colorScheme.surface.takeIf { selected }),
|
||||
tint = onBgColor,
|
||||
size = MangaCover.Size.Medium,
|
||||
)
|
||||
} else {
|
||||
if (usePanoramaCover && coverIsWide) {
|
||||
MangaCover.Panorama(
|
||||
modifier = Modifier
|
||||
.width(UpdateItemPanoramaWidth),
|
||||
data = mangaCover,
|
||||
onClick = onClickCover,
|
||||
// KMK -->
|
||||
bgColor = bgColor,
|
||||
tint = onBgColor,
|
||||
size = MangaCover.Size.Medium,
|
||||
onCoverLoaded = { _, result ->
|
||||
val image = result.result.image
|
||||
coverRatio.floatValue = image.height.toFloat() / image.width
|
||||
},
|
||||
// KMK <--
|
||||
)
|
||||
} else {
|
||||
// KMK <--
|
||||
MangaCover.Book(
|
||||
modifier = Modifier
|
||||
// KMK -->
|
||||
.width(UpdateItemWidth),
|
||||
// KMK <--
|
||||
data = mangaCover,
|
||||
onClick = onClickCover,
|
||||
// KMK -->
|
||||
bgColor = bgColor,
|
||||
tint = onBgColor,
|
||||
size = MangaCover.Size.Medium,
|
||||
onCoverLoaded = { _, result ->
|
||||
val image = result.result.image
|
||||
coverRatio.floatValue = image.height.toFloat() / image.width
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(if (usePanoramaCover && coverIsWide) UpdateItemPanoramaWidth else UpdateItemWidth),
|
||||
)
|
||||
// KMK <--
|
||||
}
|
||||
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
var textHeight by remember { mutableIntStateOf(0) }
|
||||
if (!update.read) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Circle,
|
||||
contentDescription = stringResource(MR.strings.unread),
|
||||
modifier = Modifier
|
||||
.height(8.dp)
|
||||
.padding(end = 4.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
if (update.bookmark) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Bookmark,
|
||||
contentDescription = stringResource(MR.strings.action_filter_bookmarked),
|
||||
modifier = Modifier
|
||||
.sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
}
|
||||
Text(
|
||||
text = update.chapterName,
|
||||
maxLines = 1,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = LocalContentColor.current.copy(alpha = textAlpha),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
onTextLayout = { textHeight = it.size.height },
|
||||
modifier = Modifier
|
||||
.weight(weight = 1f, fill = false),
|
||||
)
|
||||
if (readProgress != null) {
|
||||
DotSeparatorText()
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = MaterialTheme.padding.medium)
|
||||
.weight(1f),
|
||||
) {
|
||||
// KMK -->
|
||||
if (isLeader) {
|
||||
// KMK <--
|
||||
Text(
|
||||
text = readProgress,
|
||||
text = update.mangaTitle,
|
||||
maxLines = 1,
|
||||
color = LocalContentColor.current.copy(alpha = DISABLED_ALPHA),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = LocalContentColor.current.copy(alpha = textAlpha),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
if (isLeader && isExpandable) {
|
||||
CollapseButton(
|
||||
expanded = expanded,
|
||||
collapseToggle = { collapseToggle(update.groupByDateAndManga()) },
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
var textHeight by remember { mutableIntStateOf(0) }
|
||||
if (!update.read) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Circle,
|
||||
contentDescription = stringResource(MR.strings.unread),
|
||||
modifier = Modifier
|
||||
.height(8.dp)
|
||||
.padding(end = 4.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
if (update.bookmark) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Bookmark,
|
||||
contentDescription = stringResource(MR.strings.action_filter_bookmarked),
|
||||
modifier = Modifier
|
||||
.sizeIn(maxHeight = with(LocalDensity.current) { textHeight.toDp() - 2.dp }),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
}
|
||||
Text(
|
||||
text = update.chapterName,
|
||||
maxLines = 1,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = LocalContentColor.current.copy(alpha = textAlpha),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
onTextLayout = { textHeight = it.size.height },
|
||||
modifier = Modifier
|
||||
.weight(weight = 1f, fill = false),
|
||||
)
|
||||
if (readProgress != null) {
|
||||
DotSeparatorText()
|
||||
Text(
|
||||
text = readProgress,
|
||||
maxLines = 1,
|
||||
color = LocalContentColor.current.copy(alpha = DISABLED_ALPHA),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// KMK -->
|
||||
if (isLeader && isExpandable) {
|
||||
CollapseButton(
|
||||
expanded = expanded,
|
||||
collapseToggle = { collapseToggle(update.groupByDateAndManga()) },
|
||||
)
|
||||
}
|
||||
// KMK <--
|
||||
|
||||
ChapterDownloadIndicator(
|
||||
enabled = onDownloadChapter != null,
|
||||
modifier = Modifier.padding(start = 4.dp),
|
||||
downloadStateProvider = downloadStateProvider,
|
||||
downloadProgressProvider = downloadProgressProvider,
|
||||
onClick = { onDownloadChapter?.invoke(it) },
|
||||
)
|
||||
}
|
||||
// KMK <--
|
||||
|
||||
ChapterDownloadIndicator(
|
||||
enabled = onDownloadChapter != null,
|
||||
modifier = Modifier.padding(start = 4.dp),
|
||||
downloadStateProvider = downloadStateProvider,
|
||||
downloadProgressProvider = downloadProgressProvider,
|
||||
onClick = { onDownloadChapter?.invoke(it) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -412,6 +473,6 @@ fun CollapseButton(
|
|||
|
||||
private val IndicatorSize = MaterialTheme.padding.large
|
||||
|
||||
private val UpdateItemPanoramaWidth = 126.dp // Book cover
|
||||
private val UpdateItemWidth = 56.dp
|
||||
private val UpdateItemPanoramaWidth = 108.dp // Book cover
|
||||
private val UpdateItemWidth = 48.dp
|
||||
// KMK <--
|
||||
|
|
|
|||
|
|
@ -432,6 +432,52 @@ class UpdatesScreenModel(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
val chapterSwipeStartAction by libraryPreferences.swipeToEndAction().asState(screenModelScope)
|
||||
val chapterSwipeEndAction by libraryPreferences.swipeToStartAction().asState(screenModelScope)
|
||||
|
||||
/**
|
||||
* @throws IllegalStateException if the swipe action is [LibraryPreferences.ChapterSwipeAction.Disabled]
|
||||
*/
|
||||
fun updateSwipe(updateItem: UpdatesItem, swipeAction: LibraryPreferences.ChapterSwipeAction) {
|
||||
screenModelScope.launch {
|
||||
executeUpdateSwipeAction(updateItem, swipeAction)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IllegalStateException if the swipe action is [LibraryPreferences.ChapterSwipeAction.Disabled]
|
||||
*/
|
||||
private fun executeUpdateSwipeAction(
|
||||
updateItem: UpdatesItem,
|
||||
swipeAction: LibraryPreferences.ChapterSwipeAction,
|
||||
) {
|
||||
val update = updateItem.update
|
||||
when (swipeAction) {
|
||||
LibraryPreferences.ChapterSwipeAction.ToggleRead -> {
|
||||
markUpdatesRead(listOf(updateItem), !update.read)
|
||||
}
|
||||
LibraryPreferences.ChapterSwipeAction.ToggleBookmark -> {
|
||||
bookmarkUpdates(listOf(updateItem), !update.bookmark)
|
||||
}
|
||||
LibraryPreferences.ChapterSwipeAction.Download -> {
|
||||
val downloadAction = when (updateItem.downloadStateProvider()) {
|
||||
Download.State.ERROR,
|
||||
Download.State.NOT_DOWNLOADED,
|
||||
-> ChapterDownloadAction.START_NOW
|
||||
Download.State.QUEUE,
|
||||
Download.State.DOWNLOADING,
|
||||
-> ChapterDownloadAction.CANCEL
|
||||
Download.State.DOWNLOADED -> ChapterDownloadAction.DELETE
|
||||
}
|
||||
downloadChapters(
|
||||
items = listOf(updateItem),
|
||||
action = downloadAction,
|
||||
)
|
||||
}
|
||||
LibraryPreferences.ChapterSwipeAction.Disabled -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
// KMK <--
|
||||
|
||||
@Immutable
|
||||
|
|
|
|||
|
|
@ -88,6 +88,11 @@ data object UpdatesTab : Tab {
|
|||
onMultiBookmarkClicked = screenModel::bookmarkUpdates,
|
||||
onMultiMarkAsReadClicked = screenModel::markUpdatesRead,
|
||||
onMultiDeleteClicked = screenModel::showConfirmDeleteChapters,
|
||||
// KMK -->
|
||||
updateSwipeStartAction = screenModel.chapterSwipeStartAction,
|
||||
updateSwipeEndAction = screenModel.chapterSwipeEndAction,
|
||||
onUpdateSwipe = screenModel::updateSwipe,
|
||||
// KMK <--
|
||||
onUpdateSelected = screenModel::toggleSelection,
|
||||
onOpenChapter = {
|
||||
val intent = ReaderActivity.newIntent(context, it.update.mangaId, it.update.chapterId)
|
||||
|
|
|
|||
Loading…
Reference in a new issue