|
|
@@ -33,7 +33,7 @@ import androidx.compose.material.icons.filled.Search
|
|
|
import androidx.compose.material.icons.filled.Timeline
|
|
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
|
|
-import androidx.compose.material3.MaterialTheme
|
|
|
+import androidx.compose.material3.HorizontalDivider
|
|
|
import androidx.compose.material3.SnackbarHost
|
|
|
import androidx.compose.material3.SnackbarHostState
|
|
|
import androidx.compose.material3.Surface
|
|
|
@@ -41,6 +41,7 @@ import androidx.compose.runtime.Composable
|
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
|
import androidx.compose.runtime.derivedStateOf
|
|
|
import androidx.compose.runtime.getValue
|
|
|
+import androidx.compose.runtime.key
|
|
|
import androidx.compose.runtime.mutableStateOf
|
|
|
import androidx.compose.runtime.produceState
|
|
|
import androidx.compose.runtime.remember
|
|
|
@@ -54,6 +55,7 @@ import androidx.compose.ui.draw.rotate
|
|
|
import androidx.compose.ui.geometry.Offset
|
|
|
import androidx.compose.ui.graphics.Color
|
|
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
|
+import androidx.compose.ui.platform.LocalContext
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
import androidx.compose.ui.semantics.Role
|
|
|
import androidx.compose.ui.semantics.contentDescription
|
|
|
@@ -77,13 +79,11 @@ import io.legado.app.ui.theme.adaptiveContentPaddingOnlyVertical
|
|
|
import io.legado.app.ui.theme.adaptiveHorizontalPadding
|
|
|
import io.legado.app.ui.theme.fadingEdge
|
|
|
import io.legado.app.ui.widget.components.AppScaffold
|
|
|
-import io.legado.app.ui.widget.components.CollapsibleHeader
|
|
|
import io.legado.app.ui.widget.components.EmptyMessage
|
|
|
import io.legado.app.ui.widget.components.SearchBar
|
|
|
import io.legado.app.ui.widget.components.alert.AppAlertDialog
|
|
|
import io.legado.app.ui.widget.components.card.GlassCard
|
|
|
import io.legado.app.ui.widget.components.card.TextCard
|
|
|
-import io.legado.app.ui.widget.components.checkBox.AppCheckbox
|
|
|
import io.legado.app.ui.widget.components.checkBox.CheckboxItem
|
|
|
import io.legado.app.ui.widget.components.heatmap.HeatmapCalendarEndAction
|
|
|
import io.legado.app.ui.widget.components.heatmap.HeatmapCalendarStartAction
|
|
|
@@ -152,6 +152,9 @@ fun ReadRecordRouteScreen(
|
|
|
onScanRepair = { viewModel.onIntent(ReadRecordIntent.ScanRepair) },
|
|
|
onRepairDatabase = { viewModel.onIntent(ReadRecordIntent.RepairDatabase) },
|
|
|
effects = viewModel.effects,
|
|
|
+ onSetSkipDeleteConfirm = { enabled ->
|
|
|
+ viewModel.onIntent(ReadRecordIntent.SetSkipDeleteConfirm(enabled))
|
|
|
+ },
|
|
|
)
|
|
|
}
|
|
|
|
|
|
@@ -169,11 +172,12 @@ fun ReadRecordScreen(
|
|
|
effects: Flow<ReadRecordEffect> = emptyFlow(),
|
|
|
onScanRepair: () -> Unit = {},
|
|
|
onRepairDatabase: () -> Unit = {},
|
|
|
+ onSetSkipDeleteConfirm: (Boolean) -> Unit = {},
|
|
|
) {
|
|
|
val snackbarHostState = remember { SnackbarHostState() }
|
|
|
val scope = rememberCoroutineScope()
|
|
|
+ val context = LocalContext.current
|
|
|
val noMergeCandidatesMessage = stringResource(R.string.no_merge_candidates)
|
|
|
- val operationFailedMessage = stringResource(R.string.operation_failed)
|
|
|
|
|
|
val displayMode = state.displayMode
|
|
|
val readRecordEnabled = state.readRecordEnabled
|
|
|
@@ -189,19 +193,19 @@ fun ReadRecordScreen(
|
|
|
LaunchedEffect(Unit) {
|
|
|
effects.collectLatest { effect ->
|
|
|
when (effect) {
|
|
|
- is ReadRecordEffect.ShowError -> {
|
|
|
- snackbarHostState.showSnackbar(effect.message.ifBlank { operationFailedMessage })
|
|
|
+ is ReadRecordEffect.ShowMessage -> {
|
|
|
+ snackbarHostState.showSnackbar(context.getString(effect.messageRes))
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- var skipDeleteConfirm by remember { mutableStateOf(false) }
|
|
|
+ var skipDeleteConfirmForPage by remember { mutableStateOf(false) }
|
|
|
var pendingDeleteAction by remember { mutableStateOf<(() -> Unit)?>(null) }
|
|
|
var pendingDeleteCount by remember { mutableStateOf(1) }
|
|
|
var mergeDialogData by remember { mutableStateOf<Pair<ReadRecord, List<ReadRecord>>?>(null) }
|
|
|
val onConfirmDelete: (Int, () -> Unit) -> Unit = { count, action ->
|
|
|
- if (skipDeleteConfirm) {
|
|
|
+ if (skipDeleteConfirmForPage || state.skipDeleteConfirm) {
|
|
|
action()
|
|
|
} else {
|
|
|
pendingDeleteCount = count
|
|
|
@@ -468,6 +472,7 @@ fun ReadRecordScreen(
|
|
|
show = showActionsSheet,
|
|
|
showCalendar = showCalendar,
|
|
|
readRecordEnabled = readRecordEnabled,
|
|
|
+ skipDeleteConfirm = state.skipDeleteConfirm,
|
|
|
onDismissRequest = { showActionsSheet = false },
|
|
|
onToggleCalendar = {
|
|
|
showCalendar = !showCalendar
|
|
|
@@ -484,7 +489,12 @@ fun ReadRecordScreen(
|
|
|
}
|
|
|
},
|
|
|
onScanRepair = { showActionsSheet = false; onScanRepair() },
|
|
|
- onRepairDatabase = { showActionsSheet = false; onRepairDatabase() }
|
|
|
+ onRepairDatabase = { showActionsSheet = false; onRepairDatabase() },
|
|
|
+ onResetDeleteConfirm = {
|
|
|
+ showActionsSheet = false
|
|
|
+ skipDeleteConfirmForPage = false
|
|
|
+ onIntent(ReadRecordIntent.RestoreDeleteConfirmation)
|
|
|
+ }
|
|
|
)
|
|
|
|
|
|
state.repairReport?.let { report ->
|
|
|
@@ -504,16 +514,21 @@ fun ReadRecordScreen(
|
|
|
}
|
|
|
|
|
|
var skipDeleteConfirmTemp by remember(pendingDeleteAction != null) { mutableStateOf(false) }
|
|
|
+ var skipDeleteConfirmLongTermTemp by remember(pendingDeleteAction != null) { mutableStateOf(false) }
|
|
|
|
|
|
AppAlertDialog(
|
|
|
data = pendingDeleteAction,
|
|
|
- onDismissRequest = { pendingDeleteAction = null },
|
|
|
+ onDismissRequest = {
|
|
|
+ pendingDeleteAction = null
|
|
|
+ },
|
|
|
title = stringResource(R.string.confirm_delete_read_record),
|
|
|
content = { _ ->
|
|
|
Column {
|
|
|
AppText(
|
|
|
if (pendingDeleteCount == -1) {
|
|
|
stringResource(R.string.clear_read_records_message)
|
|
|
+ } else if (pendingDeleteCount == 0) {
|
|
|
+ stringResource(R.string.delete_reading_period_message)
|
|
|
} else if (pendingDeleteCount > 1) {
|
|
|
stringResource(R.string.delete_selected_read_records_message, pendingDeleteCount)
|
|
|
} else {
|
|
|
@@ -523,9 +538,21 @@ fun ReadRecordScreen(
|
|
|
if (pendingDeleteCount != -1) {
|
|
|
Spacer(modifier = Modifier.height(8.dp))
|
|
|
CheckboxItem(
|
|
|
- title = stringResource(R.string.do_not_remind_again),
|
|
|
+ title = stringResource(R.string.do_not_remind_again_this_page),
|
|
|
checked = skipDeleteConfirmTemp,
|
|
|
- onCheckedChange = { skipDeleteConfirmTemp = it }
|
|
|
+ onCheckedChange = { checked ->
|
|
|
+ skipDeleteConfirmTemp = checked
|
|
|
+ if (checked) skipDeleteConfirmLongTermTemp = false
|
|
|
+ },
|
|
|
+ )
|
|
|
+ Spacer(modifier = Modifier.height(8.dp))
|
|
|
+ CheckboxItem(
|
|
|
+ title = stringResource(R.string.do_not_remind_again_long_term),
|
|
|
+ checked = skipDeleteConfirmLongTermTemp,
|
|
|
+ onCheckedChange = { checked ->
|
|
|
+ skipDeleteConfirmLongTermTemp = checked
|
|
|
+ if (checked) skipDeleteConfirmTemp = false
|
|
|
+ },
|
|
|
)
|
|
|
}
|
|
|
}
|
|
|
@@ -535,7 +562,10 @@ fun ReadRecordScreen(
|
|
|
action.invoke()
|
|
|
pendingDeleteAction = null
|
|
|
if (pendingDeleteCount != -1) {
|
|
|
- skipDeleteConfirm = skipDeleteConfirmTemp
|
|
|
+ skipDeleteConfirmForPage = skipDeleteConfirmTemp || skipDeleteConfirmLongTermTemp
|
|
|
+ if (skipDeleteConfirmLongTermTemp) {
|
|
|
+ onSetSkipDeleteConfirm(true)
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
dismissText = stringResource(R.string.cancel),
|
|
|
@@ -622,42 +652,18 @@ fun ReadRecordScreen(
|
|
|
val candidateKey = candidate.mergeKey()
|
|
|
val isChecked = selectedMergeKeys.contains(candidateKey)
|
|
|
|
|
|
- GlassCard(
|
|
|
- modifier = Modifier
|
|
|
- .fillMaxWidth()
|
|
|
- .padding(vertical = 4.dp),
|
|
|
- ) {
|
|
|
- Box(modifier = Modifier
|
|
|
- .fillMaxWidth()
|
|
|
- .padding(12.dp)) {
|
|
|
- Column(modifier = Modifier
|
|
|
- .fillMaxWidth()
|
|
|
- .padding(end = 48.dp)) {
|
|
|
- AppText(text = candidate.bookName)
|
|
|
- AppText(
|
|
|
- text = author,
|
|
|
- style = LegadoTheme.typography.bodySmall,
|
|
|
- color = LegadoTheme.colorScheme.onSurfaceVariant,
|
|
|
- )
|
|
|
- AppText(
|
|
|
- text = formatDuring(candidate.readTime),
|
|
|
- style = LegadoTheme.typography.bodySmall,
|
|
|
- color = LegadoTheme.colorScheme.onSurfaceVariant,
|
|
|
- )
|
|
|
+ CheckboxItem(
|
|
|
+ title = candidate.bookName,
|
|
|
+ description = "$author · ${formatDuring(candidate.readTime)}",
|
|
|
+ checked = isChecked,
|
|
|
+ onCheckedChange = { checked ->
|
|
|
+ selectedMergeKeys = if (checked) {
|
|
|
+ selectedMergeKeys + candidateKey
|
|
|
+ } else {
|
|
|
+ selectedMergeKeys - candidateKey
|
|
|
}
|
|
|
- AppCheckbox(
|
|
|
- checked = isChecked,
|
|
|
- onCheckedChange = { checked ->
|
|
|
- selectedMergeKeys = if (checked) {
|
|
|
- selectedMergeKeys + candidateKey
|
|
|
- } else {
|
|
|
- selectedMergeKeys - candidateKey
|
|
|
- }
|
|
|
- },
|
|
|
- modifier = Modifier.align(Alignment.CenterEnd),
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
+ },
|
|
|
+ )
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -682,12 +688,14 @@ private fun ReadRecordActionsSheet(
|
|
|
show: Boolean,
|
|
|
showCalendar: Boolean,
|
|
|
readRecordEnabled: Boolean,
|
|
|
+ skipDeleteConfirm: Boolean,
|
|
|
onDismissRequest: () -> Unit,
|
|
|
onToggleCalendar: () -> Unit,
|
|
|
onReadRecordEnabledChange: (Boolean) -> Unit,
|
|
|
onClearReadRecords: () -> Unit,
|
|
|
onScanRepair: () -> Unit,
|
|
|
onRepairDatabase: () -> Unit,
|
|
|
+ onResetDeleteConfirm: () -> Unit,
|
|
|
) {
|
|
|
AppModalBottomSheet(
|
|
|
show = show,
|
|
|
@@ -726,6 +734,14 @@ private fun ReadRecordActionsSheet(
|
|
|
imageVector = Icons.Default.Merge,
|
|
|
onClick = onRepairDatabase
|
|
|
)
|
|
|
+ if (skipDeleteConfirm) {
|
|
|
+ CompactClickableSettingItem(
|
|
|
+ title = stringResource(R.string.restore_delete_confirmation),
|
|
|
+ description = stringResource(R.string.restore_delete_confirmation_summary),
|
|
|
+ imageVector = Icons.Default.Delete,
|
|
|
+ onClick = onResetDeleteConfirm,
|
|
|
+ )
|
|
|
+ }
|
|
|
CompactClickableSettingItem(
|
|
|
title = stringResource(R.string.clear_read_records),
|
|
|
description = stringResource(R.string.clear_read_records_summary),
|
|
|
@@ -939,49 +955,65 @@ fun LazyListScope.renderListByMode(
|
|
|
DisplayMode.AGGREGATE -> {
|
|
|
state.groupedRecords.forEach { (date, details) ->
|
|
|
item(key = "header_$date") {
|
|
|
- DateHeader(date, details.sumOf { it.readTime })
|
|
|
- }
|
|
|
- items(
|
|
|
- items = details,
|
|
|
- key = { "agg_item_${date}|${it.deviceId}_${it.bookName}_${it.bookAuthor}_${it.date}" }
|
|
|
- ) { detail ->
|
|
|
- val itemKey = detail.selectionKey()
|
|
|
- val isSelected = selectedItemKeys.contains(itemKey)
|
|
|
- val itemContent: @Composable (Modifier) -> Unit = { modifier ->
|
|
|
- ReadRecordItem(
|
|
|
- detail,
|
|
|
- loadBookCover,
|
|
|
- onClick = {
|
|
|
+ GlassCard(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .animateItem()
|
|
|
+ .adaptiveHorizontalPadding()
|
|
|
+ .padding(vertical = 8.dp),
|
|
|
+ cornerRadius = 12.dp,
|
|
|
+ containerColor = LegadoTheme.colorScheme.surfaceContainerLow,
|
|
|
+ ) {
|
|
|
+ DateHeader(date, details.sumOf { it.readTime })
|
|
|
+ HorizontalDivider(
|
|
|
+ color = LegadoTheme.colorScheme.surface,
|
|
|
+ )
|
|
|
+ details.forEachIndexed { index, detail ->
|
|
|
+ if (index > 0) {
|
|
|
+ HorizontalDivider(
|
|
|
+ color = LegadoTheme.colorScheme.surface,
|
|
|
+ )
|
|
|
+ }
|
|
|
+ key(detail.selectionKey()) {
|
|
|
+ val itemKey = detail.selectionKey()
|
|
|
+ val isSelected = selectedItemKeys.contains(itemKey)
|
|
|
+ val itemContent: @Composable (Modifier) -> Unit = { modifier ->
|
|
|
+ ReadRecordItem(
|
|
|
+ detail,
|
|
|
+ loadBookCover,
|
|
|
+ onClick = {
|
|
|
+ if (inSelectionMode) {
|
|
|
+ onToggleSelection(itemKey)
|
|
|
+ } else {
|
|
|
+ onBookClick(detail.bookName, detail.bookAuthor)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLongClick = { onEnterSelection(itemKey) },
|
|
|
+ inSelectionMode = inSelectionMode,
|
|
|
+ isSelected = isSelected,
|
|
|
+ modifier = modifier,
|
|
|
+ )
|
|
|
+ }
|
|
|
+ val deleteActionDescription = stringResource(R.string.del_read_record)
|
|
|
if (inSelectionMode) {
|
|
|
- onToggleSelection(itemKey)
|
|
|
+ itemContent(Modifier)
|
|
|
} else {
|
|
|
- onBookClick(detail.bookName, detail.bookAuthor)
|
|
|
- }
|
|
|
- },
|
|
|
- onLongClick = { onEnterSelection(itemKey) },
|
|
|
- inSelectionMode = inSelectionMode,
|
|
|
- isSelected = isSelected,
|
|
|
- modifier = modifier
|
|
|
- )
|
|
|
- }
|
|
|
- val deleteActionDescription = stringResource(R.string.del_read_record)
|
|
|
- if (inSelectionMode) {
|
|
|
- itemContent(Modifier.animateItem())
|
|
|
- } else {
|
|
|
- SwipeActionContainer(
|
|
|
- modifier = Modifier.animateItem(),
|
|
|
- startAction = SwipeAction(
|
|
|
- icon = Icons.Default.Delete,
|
|
|
- background = LegadoTheme.colorScheme.error,
|
|
|
- onSwipe = {
|
|
|
- onConfirmDelete(1) {
|
|
|
- onIntent(ReadRecordIntent.DeleteDetail(detail))
|
|
|
+ SwipeActionContainer(
|
|
|
+ startAction = SwipeAction(
|
|
|
+ icon = Icons.Default.Delete,
|
|
|
+ background = LegadoTheme.colorScheme.error,
|
|
|
+ onSwipe = {
|
|
|
+ onConfirmDelete(1) {
|
|
|
+ onIntent(ReadRecordIntent.DeleteDetail(detail))
|
|
|
+ }
|
|
|
+ },
|
|
|
+ contentDescription = deleteActionDescription,
|
|
|
+ )
|
|
|
+ ) {
|
|
|
+ itemContent(Modifier)
|
|
|
}
|
|
|
- },
|
|
|
- contentDescription = deleteActionDescription
|
|
|
- )
|
|
|
- ) {
|
|
|
- itemContent(Modifier)
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -990,46 +1022,62 @@ fun LazyListScope.renderListByMode(
|
|
|
|
|
|
DisplayMode.TIMELINE -> {
|
|
|
state.timelineRecords.forEach { (date, sessions) ->
|
|
|
- item(key = "timeline_header_$date") { DateHeader(date) }
|
|
|
- items(items = sessions, key = { "timeline_item_${date}|${it.id}" }) { session ->
|
|
|
- val itemKey = session.selectionKey()
|
|
|
- val isSelected = selectedItemKeys.contains(itemKey)
|
|
|
- val itemContent: @Composable (Modifier) -> Unit = { modifier ->
|
|
|
- TimelineSessionItem(
|
|
|
- item = TimelineItem(session, true),
|
|
|
- onBookClick = { bookName, bookAuthor ->
|
|
|
+ item(key = "timeline_header_$date") {
|
|
|
+ GlassCard(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .animateItem()
|
|
|
+ .adaptiveHorizontalPadding()
|
|
|
+ .padding(vertical = 8.dp),
|
|
|
+ cornerRadius = 12.dp,
|
|
|
+ containerColor = LegadoTheme.colorScheme.surfaceContainerLow,
|
|
|
+ ) {
|
|
|
+ DateHeader(date)
|
|
|
+ HorizontalDivider(
|
|
|
+ color = LegadoTheme.colorScheme.surface,
|
|
|
+ )
|
|
|
+ sessions.forEach { session ->
|
|
|
+ key(session.id) {
|
|
|
+ val itemKey = session.selectionKey()
|
|
|
+ val isSelected = selectedItemKeys.contains(itemKey)
|
|
|
+ val itemContent: @Composable (Modifier) -> Unit = { modifier ->
|
|
|
+ TimelineSessionItem(
|
|
|
+ item = TimelineItem(session, true),
|
|
|
+ onBookClick = { bookName, bookAuthor ->
|
|
|
+ if (inSelectionMode) {
|
|
|
+ onToggleSelection(itemKey)
|
|
|
+ } else {
|
|
|
+ onBookClick(bookName, bookAuthor)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLongClick = { onEnterSelection(itemKey) },
|
|
|
+ inSelectionMode = inSelectionMode,
|
|
|
+ isSelected = isSelected,
|
|
|
+ loadBookCover = loadBookCover,
|
|
|
+ loadChapterTitle = loadChapterTitle,
|
|
|
+ modifier = modifier,
|
|
|
+ )
|
|
|
+ }
|
|
|
+ val deleteActionDescription = stringResource(R.string.del_read_record)
|
|
|
if (inSelectionMode) {
|
|
|
- onToggleSelection(itemKey)
|
|
|
+ itemContent(Modifier)
|
|
|
} else {
|
|
|
- onBookClick(bookName, bookAuthor)
|
|
|
- }
|
|
|
- },
|
|
|
- onLongClick = { onEnterSelection(itemKey) },
|
|
|
- inSelectionMode = inSelectionMode,
|
|
|
- isSelected = isSelected,
|
|
|
- loadBookCover = loadBookCover,
|
|
|
- loadChapterTitle = loadChapterTitle,
|
|
|
- modifier = modifier
|
|
|
- )
|
|
|
- }
|
|
|
- val deleteActionDescription = stringResource(R.string.del_read_record)
|
|
|
- if (inSelectionMode) {
|
|
|
- itemContent(Modifier.animateItem())
|
|
|
- } else {
|
|
|
- SwipeActionContainer(
|
|
|
- modifier = Modifier.animateItem(),
|
|
|
- startAction = SwipeAction(
|
|
|
- icon = Icons.Default.Delete,
|
|
|
- background = LegadoTheme.colorScheme.error,
|
|
|
- onSwipe = {
|
|
|
- onConfirmDelete(1) {
|
|
|
- onIntent(ReadRecordIntent.DeleteSession(session))
|
|
|
+ SwipeActionContainer(
|
|
|
+ startAction = SwipeAction(
|
|
|
+ icon = Icons.Default.Delete,
|
|
|
+ background = LegadoTheme.colorScheme.error,
|
|
|
+ onSwipe = {
|
|
|
+ onConfirmDelete(0) {
|
|
|
+ onIntent(ReadRecordIntent.DeleteSession(session))
|
|
|
+ }
|
|
|
+ },
|
|
|
+ contentDescription = deleteActionDescription,
|
|
|
+ )
|
|
|
+ ) {
|
|
|
+ itemContent(Modifier)
|
|
|
}
|
|
|
- },
|
|
|
- contentDescription = deleteActionDescription
|
|
|
- )
|
|
|
- ) {
|
|
|
- itemContent(Modifier)
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -1186,11 +1234,11 @@ fun LatestReadItem(
|
|
|
),
|
|
|
// 脱敏时整行不给:这里拼的是阅读时长 + 最后读到的章节(内容级信息)
|
|
|
text = if (locked) AnnotatedString("") else buildAnnotatedString {
|
|
|
- withStyle(style = SpanStyle(color = MaterialTheme.colorScheme.outline)) {
|
|
|
+ withStyle(style = SpanStyle(color = LegadoTheme.colorScheme.outline)) {
|
|
|
append(formatDuring(record.readTime))
|
|
|
append(" • ")
|
|
|
}
|
|
|
- withStyle(style = SpanStyle(color = MaterialTheme.colorScheme.primary)) {
|
|
|
+ withStyle(style = SpanStyle(color = LegadoTheme.colorScheme.primary)) {
|
|
|
append(lastReadText)
|
|
|
}
|
|
|
},
|
|
|
@@ -1246,11 +1294,11 @@ fun TimelineSessionItem(
|
|
|
|
|
|
val nodeRadius = 4.dp
|
|
|
val lineWidth = 2.dp
|
|
|
- val timelineX = 24.dp
|
|
|
+ val timelineX = 16.dp
|
|
|
val contentPaddingStart = 32.dp
|
|
|
|
|
|
- val lineColor = MaterialTheme.colorScheme.surfaceContainerHigh
|
|
|
- val nodeColor = MaterialTheme.colorScheme.primary
|
|
|
+ val lineColor = LegadoTheme.colorScheme.surface
|
|
|
+ val nodeColor = LegadoTheme.colorScheme.primary
|
|
|
|
|
|
Box(
|
|
|
modifier = modifier
|
|
|
@@ -1293,7 +1341,7 @@ fun TimelineSessionItem(
|
|
|
Row(
|
|
|
modifier = Modifier
|
|
|
.fillMaxWidth()
|
|
|
- .padding(start = contentPaddingStart, end = 16.dp, top = 8.dp, bottom = 8.dp),
|
|
|
+ .padding(start = contentPaddingStart, end = 16.dp, top = 12.dp, bottom = 12.dp),
|
|
|
verticalAlignment = Alignment.CenterVertically
|
|
|
) {
|
|
|
Column(
|
|
|
@@ -1302,7 +1350,7 @@ fun TimelineSessionItem(
|
|
|
) {
|
|
|
AppText(
|
|
|
text = endTimeText,
|
|
|
- style = LegadoTheme.typography.bodySmall
|
|
|
+ style = LegadoTheme.typography.labelSmallEmphasized
|
|
|
)
|
|
|
}
|
|
|
|
|
|
@@ -1338,7 +1386,7 @@ fun TimelineSessionItem(
|
|
|
AppText(
|
|
|
text = if (locked) "" else author,
|
|
|
style = LegadoTheme.typography.bodySmall,
|
|
|
- color = MaterialTheme.colorScheme.outline,
|
|
|
+ color = LegadoTheme.colorScheme.outline,
|
|
|
maxLines = 1,
|
|
|
overflow = TextOverflow.Ellipsis
|
|
|
)
|
|
|
@@ -1346,7 +1394,7 @@ fun TimelineSessionItem(
|
|
|
AppText(
|
|
|
text = if (locked) "" else chapterTitle.orEmpty(),
|
|
|
style = LegadoTheme.typography.labelSmall,
|
|
|
- color = MaterialTheme.colorScheme.outline,
|
|
|
+ color = LegadoTheme.colorScheme.outline,
|
|
|
maxLines = 1,
|
|
|
overflow = TextOverflow.Ellipsis
|
|
|
)
|
|
|
@@ -1398,7 +1446,7 @@ fun ReadRecordItem(
|
|
|
contentDescription = if (locked) "" else itemDescription
|
|
|
role = Role.Button
|
|
|
}
|
|
|
- .adaptiveHorizontalPadding(vertical = 8.dp),
|
|
|
+ .padding(all = 12.dp),
|
|
|
verticalAlignment = Alignment.CenterVertically
|
|
|
) {
|
|
|
if (locked) {
|
|
|
@@ -1427,12 +1475,15 @@ fun ReadRecordItem(
|
|
|
AppText(
|
|
|
text = if (locked) "" else detail.bookName,
|
|
|
style = LegadoTheme.typography.titleMedium,
|
|
|
- maxLines = 1
|
|
|
+ maxLines = 1,
|
|
|
+ overflow = TextOverflow.Ellipsis,
|
|
|
)
|
|
|
AppText(
|
|
|
text = if (locked) "" else author,
|
|
|
style = LegadoTheme.typography.bodySmall,
|
|
|
- color = MaterialTheme.colorScheme.outline,
|
|
|
+ color = LegadoTheme.colorScheme.onSurfaceVariant,
|
|
|
+ maxLines = 1,
|
|
|
+ overflow = TextOverflow.Ellipsis,
|
|
|
)
|
|
|
Spacer(modifier = Modifier.height(8.dp))
|
|
|
AppText(
|
|
|
@@ -1440,8 +1491,10 @@ fun ReadRecordItem(
|
|
|
R.string.reading_time_with_value,
|
|
|
formatDuring(detail.readTime)
|
|
|
),
|
|
|
- color = MaterialTheme.colorScheme.outline,
|
|
|
- style = LegadoTheme.typography.labelSmall
|
|
|
+ color = LegadoTheme.colorScheme.primary,
|
|
|
+ style = LegadoTheme.typography.labelMedium,
|
|
|
+ maxLines = 1,
|
|
|
+ overflow = TextOverflow.Ellipsis,
|
|
|
)
|
|
|
}
|
|
|
}
|
|
|
@@ -1452,29 +1505,27 @@ fun DateHeader(
|
|
|
date: String,
|
|
|
dailyTotalTime: Long? = null
|
|
|
) {
|
|
|
- CollapsibleHeader(
|
|
|
- modifier = Modifier.adaptiveHorizontalPadding(),
|
|
|
- showIcon = false,
|
|
|
- isCollapsed = false,
|
|
|
- onToggle = { },
|
|
|
- title = "",
|
|
|
- titleContent = {
|
|
|
- val dateText = formatFriendlyDate(date)
|
|
|
- AppText(
|
|
|
- text = dateText,
|
|
|
- style = LegadoTheme.typography.bodyMedium,
|
|
|
- fontWeight = FontWeight.Bold,
|
|
|
- color = LegadoTheme.colorScheme.primary
|
|
|
+ Row(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxWidth()
|
|
|
+ .padding(all = 12.dp),
|
|
|
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
|
|
|
+ verticalAlignment = Alignment.CenterVertically,
|
|
|
+ ) {
|
|
|
+ AppText(
|
|
|
+ text = formatFriendlyDate(date),
|
|
|
+ modifier = Modifier.weight(1f),
|
|
|
+ style = LegadoTheme.typography.titleSmallEmphasized,
|
|
|
+ color = LegadoTheme.colorScheme.primary,
|
|
|
+ maxLines = 1,
|
|
|
+ overflow = TextOverflow.Ellipsis,
|
|
|
+ )
|
|
|
+ dailyTotalTime?.let { total ->
|
|
|
+ TextCard(
|
|
|
+ text = stringResource(R.string.read_duration_done, formatDuring(total))
|
|
|
)
|
|
|
- dailyTotalTime?.let { total ->
|
|
|
- AppText(
|
|
|
- text = stringResource(R.string.read_duration_done, formatDuring(total)),
|
|
|
- style = LegadoTheme.typography.bodySmall,
|
|
|
- color = LegadoTheme.colorScheme.onSurface
|
|
|
- )
|
|
|
- }
|
|
|
}
|
|
|
- )
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Composable
|
|
|
@@ -1510,7 +1561,7 @@ fun ReadingSummaryCard(
|
|
|
role = Role.Button
|
|
|
}
|
|
|
.adaptiveHorizontalPadding(vertical = 8.dp),
|
|
|
- containerColor = LegadoTheme.colorScheme.surfaceContainer
|
|
|
+ containerColor = LegadoTheme.colorScheme.surfaceContainerLow
|
|
|
) {
|
|
|
Row(
|
|
|
modifier = Modifier
|