mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-06-28 07:46:04 +02:00
238 lines
9.4 KiB
Kotlin
238 lines
9.4 KiB
Kotlin
package eu.kanade.presentation.updates
|
|
|
|
import androidx.compose.foundation.combinedClickable
|
|
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.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.material3.Icon
|
|
import androidx.compose.material3.LocalContentColor
|
|
import androidx.compose.material3.MaterialTheme
|
|
import androidx.compose.material3.Text
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.compose.runtime.mutableIntStateOf
|
|
import androidx.compose.runtime.remember
|
|
import androidx.compose.runtime.setValue
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
|
import androidx.compose.ui.platform.LocalDensity
|
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
|
import androidx.compose.ui.text.font.FontStyle
|
|
import androidx.compose.ui.text.style.TextOverflow
|
|
import androidx.compose.ui.unit.dp
|
|
import eu.kanade.presentation.components.relativeDateText
|
|
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.util.relativeTimeSpanString
|
|
import eu.kanade.tachiyomi.data.download.model.Download
|
|
import eu.kanade.tachiyomi.ui.updates.UpdatesItem
|
|
import tachiyomi.domain.updates.model.UpdatesWithRelations
|
|
import tachiyomi.i18n.MR
|
|
import tachiyomi.presentation.core.components.ListGroupHeader
|
|
import tachiyomi.presentation.core.components.material.ReadItemAlpha
|
|
import tachiyomi.presentation.core.components.material.padding
|
|
import tachiyomi.presentation.core.i18n.stringResource
|
|
import tachiyomi.presentation.core.util.selectedBackground
|
|
|
|
internal fun LazyListScope.updatesLastUpdatedItem(
|
|
lastUpdated: Long,
|
|
) {
|
|
item(key = "updates-lastUpdated") {
|
|
Box(
|
|
modifier = Modifier
|
|
.animateItemPlacement()
|
|
.padding(horizontal = MaterialTheme.padding.medium, vertical = MaterialTheme.padding.small),
|
|
) {
|
|
Text(
|
|
text = stringResource(MR.strings.updates_last_update_info, relativeTimeSpanString(lastUpdated)),
|
|
fontStyle = FontStyle.Italic,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
internal fun LazyListScope.updatesUiItems(
|
|
uiModels: List<UpdatesUiModel>,
|
|
selectionMode: Boolean,
|
|
onUpdateSelected: (UpdatesItem, Boolean, Boolean, Boolean) -> Unit,
|
|
onClickCover: (UpdatesItem) -> Unit,
|
|
onClickUpdate: (UpdatesItem) -> Unit,
|
|
onDownloadChapter: (List<UpdatesItem>, ChapterDownloadAction) -> Unit,
|
|
) {
|
|
items(
|
|
items = uiModels,
|
|
contentType = {
|
|
when (it) {
|
|
is UpdatesUiModel.Header -> "header"
|
|
is UpdatesUiModel.Item -> "item"
|
|
}
|
|
},
|
|
key = {
|
|
when (it) {
|
|
is UpdatesUiModel.Header -> "updatesHeader-${it.hashCode()}"
|
|
is UpdatesUiModel.Item -> "updates-${it.item.update.mangaId}-${it.item.update.chapterId}"
|
|
}
|
|
},
|
|
) { item ->
|
|
when (item) {
|
|
is UpdatesUiModel.Header -> {
|
|
ListGroupHeader(
|
|
modifier = Modifier.animateItemPlacement(),
|
|
text = relativeDateText(item.date),
|
|
)
|
|
}
|
|
is UpdatesUiModel.Item -> {
|
|
val updatesItem = item.item
|
|
UpdatesUiItem(
|
|
modifier = Modifier.animateItemPlacement(),
|
|
update = updatesItem.update,
|
|
selected = updatesItem.selected,
|
|
readProgress = updatesItem.update.lastPageRead
|
|
.takeIf { !updatesItem.update.read && it > 0L }
|
|
?.let {
|
|
stringResource(
|
|
MR.strings.chapter_progress,
|
|
it + 1,
|
|
)
|
|
},
|
|
onLongClick = {
|
|
onUpdateSelected(updatesItem, !updatesItem.selected, true, true)
|
|
},
|
|
onClick = {
|
|
when {
|
|
selectionMode -> onUpdateSelected(updatesItem, !updatesItem.selected, true, false)
|
|
else -> onClickUpdate(updatesItem)
|
|
}
|
|
},
|
|
onClickCover = { onClickCover(updatesItem) }.takeIf { !selectionMode },
|
|
onDownloadChapter = { action: ChapterDownloadAction ->
|
|
onDownloadChapter(listOf(updatesItem), action)
|
|
}.takeIf { !selectionMode },
|
|
downloadStateProvider = updatesItem.downloadStateProvider,
|
|
downloadProgressProvider = updatesItem.downloadProgressProvider,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun UpdatesUiItem(
|
|
update: UpdatesWithRelations,
|
|
selected: Boolean,
|
|
readProgress: String?,
|
|
onClick: () -> Unit,
|
|
onLongClick: () -> Unit,
|
|
onClickCover: (() -> Unit)?,
|
|
onDownloadChapter: ((ChapterDownloadAction) -> Unit)?,
|
|
// Download Indicator
|
|
downloadStateProvider: () -> Download.State,
|
|
downloadProgressProvider: () -> Int,
|
|
modifier: Modifier = Modifier,
|
|
) {
|
|
val haptic = LocalHapticFeedback.current
|
|
val textAlpha = if (update.read) ReadItemAlpha else 1f
|
|
|
|
Row(
|
|
modifier = modifier
|
|
.selectedBackground(selected)
|
|
.combinedClickable(
|
|
onClick = onClick,
|
|
onLongClick = {
|
|
onLongClick()
|
|
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
|
},
|
|
)
|
|
.height(56.dp)
|
|
.padding(horizontal = MaterialTheme.padding.medium),
|
|
verticalAlignment = Alignment.CenterVertically,
|
|
) {
|
|
MangaCover.Square(
|
|
modifier = Modifier
|
|
.padding(vertical = 6.dp)
|
|
.fillMaxHeight(),
|
|
data = update.coverData,
|
|
onClick = onClickCover,
|
|
)
|
|
|
|
Column(
|
|
modifier = Modifier
|
|
.padding(horizontal = MaterialTheme.padding.medium)
|
|
.weight(1f),
|
|
) {
|
|
Text(
|
|
text = update.mangaTitle,
|
|
maxLines = 1,
|
|
style = MaterialTheme.typography.bodyMedium,
|
|
color = LocalContentColor.current.copy(alpha = textAlpha),
|
|
overflow = TextOverflow.Ellipsis,
|
|
)
|
|
|
|
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 = ReadItemAlpha),
|
|
overflow = TextOverflow.Ellipsis,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
ChapterDownloadIndicator(
|
|
enabled = onDownloadChapter != null,
|
|
modifier = Modifier.padding(start = 4.dp),
|
|
downloadStateProvider = downloadStateProvider,
|
|
downloadProgressProvider = downloadProgressProvider,
|
|
onClick = { onDownloadChapter?.invoke(it) },
|
|
)
|
|
}
|
|
}
|