Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates grouping #610

Merged
merged 3 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ enum class MangaCover(val ratio: Float) {
modifier = Modifier
.size(
when (size) {
Size.Big -> 16.dp
Size.Medium -> 24.dp
else -> 32.dp
Size.Big -> COVER_TEMPLATE_SIZE_BIG
Size.Medium -> COVER_TEMPLATE_SIZE_MEDIUM
else -> COVER_TEMPLATE_SIZE_NORMAL
},
)
.align(Alignment.Center),
Expand All @@ -122,9 +122,9 @@ enum class MangaCover(val ratio: Float) {
modifier = Modifier
.size(
when (size) {
Size.Big -> 16.dp
Size.Medium -> 24.dp
else -> 32.dp
Size.Big -> COVER_TEMPLATE_SIZE_BIG
Size.Medium -> COVER_TEMPLATE_SIZE_MEDIUM
else -> COVER_TEMPLATE_SIZE_NORMAL
},
)
.align(Alignment.Center),
Expand All @@ -149,6 +149,12 @@ enum class MangaCover(val ratio: Float) {
contentScale = scale,
)
}

companion object {
val COVER_TEMPLATE_SIZE_BIG = 16.dp
val COVER_TEMPLATE_SIZE_MEDIUM = 24.dp
val COVER_TEMPLATE_SIZE_NORMAL = 32.dp
}
}

enum class MangaCoverHide(private val ratio: Float) {
Expand Down Expand Up @@ -200,7 +206,7 @@ enum class MangaCoverHide(private val ratio: Float) {
}
}

internal val RatioSwitchToPanorama = 0.75f
internal const val RatioSwitchToPanorama = 0.75f

internal val CoverPlaceholderColor = Color(0x1F888888)
internal val CoverPlaceholderOnBgColor = Color(0x8F888888)
46 changes: 44 additions & 2 deletions app/src/main/java/eu/kanade/presentation/updates/UpdatesScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.CalendarMonth
import androidx.compose.material.icons.outlined.FlipToBack
import androidx.compose.material.icons.outlined.Panorama
import androidx.compose.material.icons.outlined.Refresh
import androidx.compose.material.icons.outlined.SelectAll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.TopAppBarScrollBehavior
Expand All @@ -27,10 +29,12 @@ import eu.kanade.presentation.manga.components.MangaBottomActionMenu
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.ui.updates.UpdatesItem
import eu.kanade.tachiyomi.ui.updates.UpdatesScreenModel
import eu.kanade.tachiyomi.ui.updates.groupByDateAndManga
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import tachiyomi.i18n.MR
import tachiyomi.i18n.kmk.KMR
import tachiyomi.presentation.core.components.FastScrollLazyColumn
import tachiyomi.presentation.core.components.material.PullRefresh
import tachiyomi.presentation.core.components.material.Scaffold
Expand Down Expand Up @@ -59,7 +63,13 @@ fun UpdateScreen(
onMultiDeleteClicked: (List<UpdatesItem>) -> Unit,
onUpdateSelected: (UpdatesItem, Boolean, Boolean, Boolean) -> Unit,
onOpenChapter: (UpdatesItem) -> Unit,
// KMK -->
collapseToggle: (key: String) -> Unit,
// KMK <--
) {
// KMK -->
val usePanoramaCover = remember { mutableStateOf(false) }
// KMK <--
BackHandler(enabled = state.selectionMode, onBack = { onSelectAll(false) })

Scaffold(
Expand All @@ -72,6 +82,10 @@ fun UpdateScreen(
onInvertSelection = { onInvertSelection() },
onCancelActionMode = { onSelectAll(false) },
scrollBehavior = scrollBehavior,
// KMK -->
usePanoramaCover = usePanoramaCover.value,
usePanoramaCoverClick = { usePanoramaCover.value = !usePanoramaCover.value },
// KMK
)
},
bottomBar = {
Expand Down Expand Up @@ -116,7 +130,19 @@ fun UpdateScreen(
updatesLastUpdatedItem(lastUpdated)

updatesUiItems(
uiModels = state.getUiModel(),
uiModels = state.getUiModel()
// KMK -->
.filter {
when (it) {
is UpdatesUiModel.Header, is UpdatesUiModel.Leader -> true
is UpdatesUiModel.Item ->
state.expandedState.contains(it.item.update.groupByDateAndManga())
}
},
expandedState = state.expandedState,
collapseToggle = collapseToggle,
usePanoramaCover = usePanoramaCover.value,
// KMK <--
selectionMode = state.selectionMode,
// SY -->
preserveReadingPosition = preserveReadingPosition,
Expand All @@ -143,6 +169,10 @@ private fun UpdatesAppBar(
onInvertSelection: () -> Unit,
onCancelActionMode: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior,
// KMK -->
usePanoramaCover: Boolean,
usePanoramaCoverClick: () -> Unit,
// KMK <--
modifier: Modifier = Modifier,
) {
AppBar(
Expand All @@ -151,6 +181,14 @@ private fun UpdatesAppBar(
actions = {
AppBarActions(
persistentListOf(
// KMK -->
AppBar.Action(
title = stringResource(KMR.strings.action_panorama_cover),
icon = Icons.Outlined.Panorama,
iconTint = MaterialTheme.colorScheme.primary.takeIf { usePanoramaCover },
onClick = usePanoramaCoverClick,
),
// KMK <--
AppBar.Action(
title = stringResource(MR.strings.action_view_upcoming),
icon = Icons.Outlined.CalendarMonth,
Expand Down Expand Up @@ -222,5 +260,9 @@ private fun UpdatesBottomBar(

sealed interface UpdatesUiModel {
data class Header(val date: LocalDate) : UpdatesUiModel
data class Item(val item: UpdatesItem) : UpdatesUiModel
open class Item(open val item: UpdatesItem, open val isExpandable: Boolean = false) : UpdatesUiModel
// KMK -->
/** The first [Item] in a group of chapters from same manga */
data class Leader(override val item: UpdatesItem, override val isExpandable: Boolean) : Item(item)
// KMK <--
}
135 changes: 119 additions & 16 deletions app/src/main/java/eu/kanade/presentation/updates/UpdatesUiItem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,27 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
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.foundation.layout.width
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Bookmark
import androidx.compose.material.icons.filled.Circle
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableFloatState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
Expand All @@ -38,10 +43,12 @@ 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.RatioSwitchToPanorama
import eu.kanade.presentation.util.animateItemFastScroll
import eu.kanade.presentation.util.relativeTimeSpanString
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.ui.updates.UpdatesItem
import eu.kanade.tachiyomi.ui.updates.groupByDateAndManga
import tachiyomi.domain.updates.model.UpdatesWithRelations
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.ListGroupHeader
Expand Down Expand Up @@ -69,6 +76,11 @@ internal fun LazyListScope.updatesLastUpdatedItem(

internal fun LazyListScope.updatesUiItems(
uiModels: List<UpdatesUiModel>,
// KMK -->
expandedState: Set<String>,
collapseToggle: (key: String) -> Unit,
usePanoramaCover: Boolean,
// KMK <--
selectionMode: Boolean,
// SY -->
preserveReadingPosition: Boolean,
Expand Down Expand Up @@ -96,7 +108,10 @@ internal fun LazyListScope.updatesUiItems(
when (item) {
is UpdatesUiModel.Header -> {
ListGroupHeader(
modifier = Modifier.animateItemFastScroll(),
modifier = Modifier.animateItemFastScroll()
// KMK -->
.padding(top = MaterialTheme.padding.extraSmall),
// KMK <--
text = relativeDateText(item.date),
)
}
Expand Down Expand Up @@ -135,6 +150,13 @@ internal fun LazyListScope.updatesUiItems(
}.takeIf { !selectionMode },
downloadStateProvider = updatesItem.downloadStateProvider,
downloadProgressProvider = updatesItem.downloadProgressProvider,
// KMK -->
isLeader = item is UpdatesUiModel.Leader,
isExpandable = item.isExpandable,
expanded = expandedState.contains(updatesItem.update.groupByDateAndManga()),
collapseToggle = collapseToggle,
usePanoramaCover = usePanoramaCover,
// KMK <--
)
}
}
Expand All @@ -153,6 +175,14 @@ private fun UpdatesUiItem(
// Download Indicator
downloadStateProvider: () -> Download.State,
downloadProgressProvider: () -> Int,
// KMK -->
isLeader: Boolean,
isExpandable: Boolean,
expanded: Boolean,
collapseToggle: (key: String) -> Unit,
usePanoramaCover: Boolean,
coverRatio: MutableFloatState = remember { mutableFloatStateOf(1f) },
// KMK <--
modifier: Modifier = Modifier,
) {
val haptic = LocalHapticFeedback.current
Expand All @@ -168,27 +198,64 @@ private fun UpdatesUiItem(
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
},
)
.height(56.dp)
.padding(horizontal = MaterialTheme.padding.medium),
.padding(
// KMK -->
vertical = MaterialTheme.padding.extraSmall,
// 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
// KMK <--
MangaCover.Square(
modifier = Modifier
.padding(vertical = 6.dp)
.fillMaxHeight(),
data = mangaCover,
onClick = onClickCover,
// KMK -->
bgColor = bgColor,
tint = onBgColor,
size = MangaCover.Size.Big,
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 <--
)
}

Column(
modifier = Modifier
Expand Down Expand Up @@ -247,6 +314,15 @@ private fun UpdatesUiItem(
}
}

// KMK -->
if (isLeader && isExpandable) {
CollapseButton(
expanded = expanded,
collapseToggle = { collapseToggle(update.groupByDateAndManga()) },
)
}
// KMK <--

ChapterDownloadIndicator(
enabled = onDownloadChapter != null,
modifier = Modifier.padding(start = 4.dp),
Expand All @@ -256,3 +332,30 @@ private fun UpdatesUiItem(
)
}
}

// KMK -->
@Composable
fun CollapseButton(
expanded: Boolean,
collapseToggle: () -> Unit,
modifier: Modifier = Modifier,
) {
Box(
modifier = modifier
.size(IndicatorSize),
contentAlignment = Alignment.Center,
) {
IconButton(onClick = { collapseToggle() }) {
Icon(
imageVector = if (expanded) Icons.Default.KeyboardArrowUp else Icons.Default.KeyboardArrowDown,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
)
}
}
}

private val IndicatorSize = 18.dp
private val UpdateItemPanoramaWidth = 126.dp
private val UpdateItemWidth = 56.dp
// KMK <--
Loading
Loading