Design revision

see the Discord for more details
This commit is contained in:
imkunet 2024-09-19 06:16:22 -04:00
parent 0e0a9aac5b
commit 170c000d65
No known key found for this signature in database
GPG Key ID: 32E0ECFB90A68C42
5 changed files with 176 additions and 108 deletions

View File

@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Check
@ -123,21 +124,23 @@ fun MangaNotesScreen(
enter = fadeIn(), enter = fadeIn(),
exit = fadeOut(), exit = fadeOut(),
) { ) {
RichText( SelectionContainer {
modifier = Modifier RichText(
.verticalScroll(rememberScrollState()) modifier = Modifier
.fillMaxWidth() .verticalScroll(rememberScrollState())
.padding( .fillMaxWidth()
horizontal = MaterialTheme.padding.medium, .padding(
vertical = paddingValues.calculateTopPadding() + MaterialTheme.padding.medium, horizontal = MaterialTheme.padding.medium,
vertical = paddingValues.calculateTopPadding() + MaterialTheme.padding.medium,
),
style = RichTextStyle(
stringStyle = RichTextStringStyle(
linkStyle = SpanStyle(color = MaterialTheme.colorScheme.primary),
),
), ),
style = RichTextStyle( ) {
stringStyle = RichTextStringStyle( Markdown(content = state.notes.orEmpty())
linkStyle = SpanStyle(color = MaterialTheme.colorScheme.primary), }
),
),
) {
Markdown(content = state.notes.orEmpty())
} }
} }
} }

View File

@ -5,6 +5,7 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
@ -25,6 +26,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHost
@ -44,6 +46,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastAll import androidx.compose.ui.util.fastAll
import androidx.compose.ui.util.fastAny import androidx.compose.ui.util.fastAny
import androidx.compose.ui.util.fastMap import androidx.compose.ui.util.fastMap
@ -55,7 +58,6 @@ import eu.kanade.presentation.manga.components.MangaActionRow
import eu.kanade.presentation.manga.components.MangaBottomActionMenu import eu.kanade.presentation.manga.components.MangaBottomActionMenu
import eu.kanade.presentation.manga.components.MangaChapterListItem import eu.kanade.presentation.manga.components.MangaChapterListItem
import eu.kanade.presentation.manga.components.MangaInfoBox import eu.kanade.presentation.manga.components.MangaInfoBox
import eu.kanade.presentation.manga.components.MangaNotesSection
import eu.kanade.presentation.manga.components.MangaToolbar import eu.kanade.presentation.manga.components.MangaToolbar
import eu.kanade.presentation.manga.components.MissingChapterCountListItem import eu.kanade.presentation.manga.components.MissingChapterCountListItem
import eu.kanade.presentation.util.formatChapterNumber import eu.kanade.presentation.util.formatChapterNumber
@ -336,27 +338,47 @@ private fun MangaScreenSmallImpl(
}, },
snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
floatingActionButton = { floatingActionButton = {
val isFABVisible = remember(chapters) { Column(
chapters.fastAny { !it.chapter.read } && !isAnySelected horizontalAlignment = Alignment.End,
} verticalArrangement = Arrangement.spacedBy(4.dp),
AnimatedVisibility(
visible = isFABVisible,
enter = fadeIn(),
exit = fadeOut(),
) { ) {
ExtendedFloatingActionButton( AnimatedVisibility(
text = { visible = !isAnySelected,
val isReading = remember(state.chapters) { enter = fadeIn(),
state.chapters.fastAny { it.chapter.read } exit = fadeOut(),
} ) {
Text( ExtendedFloatingActionButton(
text = stringResource(if (isReading) MR.strings.action_resume else MR.strings.action_start), text = { Text(stringResource(MR.strings.action_notes)) },
) icon = { Icon(imageVector = Icons.Filled.Edit, contentDescription = null) },
}, onClick = onNotesEditClicked,
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) }, expanded = chapterListState.shouldExpandFAB(),
onClick = onContinueReading, )
expanded = chapterListState.shouldExpandFAB(), }
)
val isFABVisible = remember(chapters) {
chapters.fastAny { !it.chapter.read } && !isAnySelected
}
AnimatedVisibility(
visible = isFABVisible,
enter = fadeIn(),
exit = fadeOut(),
) {
ExtendedFloatingActionButton(
text = {
val isReading = remember(state.chapters) {
state.chapters.fastAny { it.chapter.read }
}
Text(
text = stringResource(
if (isReading) MR.strings.action_resume else MR.strings.action_start,
),
)
},
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
onClick = onContinueReading,
expanded = chapterListState.shouldExpandFAB(),
)
}
} }
}, },
) { contentPadding -> ) { contentPadding ->
@ -424,18 +446,10 @@ private fun MangaScreenSmallImpl(
defaultExpandState = state.isFromSource, defaultExpandState = state.isFromSource,
description = state.manga.description, description = state.manga.description,
tagsProvider = { state.manga.genre }, tagsProvider = { state.manga.genre },
noteContent = state.manga.notes,
onTagSearch = onTagSearch, onTagSearch = onTagSearch,
onCopyTagToClipboard = onCopyTagToClipboard, onCopyTagToClipboard = onCopyTagToClipboard,
)
}
item(
key = MangaScreenItem.NOTES_SECTION,
contentType = MangaScreenItem.NOTES_SECTION,
) {
MangaNotesSection(
onClickNotes = onNotesEditClicked, onClickNotes = onNotesEditClicked,
content = state.manga.notes,
) )
} }
@ -599,21 +613,39 @@ fun MangaScreenLargeImpl(
enter = fadeIn(), enter = fadeIn(),
exit = fadeOut(), exit = fadeOut(),
) { ) {
ExtendedFloatingActionButton( Column(
text = { horizontalAlignment = Alignment.End,
val isReading = remember(state.chapters) { verticalArrangement = Arrangement.spacedBy(4.dp),
state.chapters.fastAny { it.chapter.read } ) {
} AnimatedVisibility(
Text( visible = !isAnySelected,
text = stringResource( enter = fadeIn(),
if (isReading) MR.strings.action_resume else MR.strings.action_start, exit = fadeOut(),
), ) {
ExtendedFloatingActionButton(
text = { Text(stringResource(MR.strings.action_notes)) },
icon = { Icon(imageVector = Icons.Filled.Edit, contentDescription = null) },
onClick = onNotesEditClicked,
expanded = chapterListState.shouldExpandFAB(),
) )
}, }
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
onClick = onContinueReading, ExtendedFloatingActionButton(
expanded = chapterListState.shouldExpandFAB(), text = {
) val isReading = remember(state.chapters) {
state.chapters.fastAny { it.chapter.read }
}
Text(
text = stringResource(
if (isReading) MR.strings.action_resume else MR.strings.action_start,
),
)
},
icon = { Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null) },
onClick = onContinueReading,
expanded = chapterListState.shouldExpandFAB(),
)
}
} }
}, },
) { contentPadding -> ) { contentPadding ->
@ -663,12 +695,10 @@ fun MangaScreenLargeImpl(
defaultExpandState = true, defaultExpandState = true,
description = state.manga.description, description = state.manga.description,
tagsProvider = { state.manga.genre }, tagsProvider = { state.manga.genre },
noteContent = state.manga.notes,
onTagSearch = onTagSearch, onTagSearch = onTagSearch,
onCopyTagToClipboard = onCopyTagToClipboard, onCopyTagToClipboard = onCopyTagToClipboard,
)
MangaNotesSection(
onClickNotes = onNotesEditClicked, onClickNotes = onNotesEditClicked,
content = state.manga.notes,
) )
} }
}, },
@ -788,6 +818,7 @@ private fun LazyListScope.sharedChapterItems(
is ChapterList.MissingCount -> { is ChapterList.MissingCount -> {
MissingChapterCountListItem(count = item.count) MissingChapterCountListItem(count = item.count)
} }
is ChapterList.Item -> { is ChapterList.Item -> {
MangaChapterListItem( MangaChapterListItem(
title = if (manga.displayMode == Manga.CHAPTER_DISPLAY_NUMBER) { title = if (manga.displayMode == Manga.CHAPTER_DISPLAY_NUMBER) {

View File

@ -17,7 +17,6 @@ enum class MangaScreenItem {
INFO_BOX, INFO_BOX,
ACTION_ROW, ACTION_ROW,
DESCRIPTION_WITH_TAG, DESCRIPTION_WITH_TAG,
NOTES_SECTION,
CHAPTER_HEADER, CHAPTER_HEADER,
CHAPTER, CHAPTER,
} }

View File

@ -236,8 +236,10 @@ fun ExpandableMangaDescription(
defaultExpandState: Boolean, defaultExpandState: Boolean,
description: String?, description: String?,
tagsProvider: () -> List<String>?, tagsProvider: () -> List<String>?,
noteContent: String?,
onTagSearch: (String) -> Unit, onTagSearch: (String) -> Unit,
onCopyTagToClipboard: (tag: String) -> Unit, onCopyTagToClipboard: (tag: String) -> Unit,
onClickNotes: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
Column(modifier = modifier) { Column(modifier = modifier) {
@ -255,6 +257,8 @@ fun ExpandableMangaDescription(
expandedDescription = desc, expandedDescription = desc,
shrunkDescription = trimmedDescription, shrunkDescription = trimmedDescription,
expanded = expanded, expanded = expanded,
noteContent = noteContent,
onNotesEditClicked = onClickNotes,
modifier = Modifier modifier = Modifier
.padding(top = 8.dp) .padding(top = 8.dp)
.padding(horizontal = 16.dp) .padding(horizontal = 16.dp)
@ -559,7 +563,9 @@ private fun ColumnScope.MangaContentInfo(
private fun MangaSummary( private fun MangaSummary(
expandedDescription: String, expandedDescription: String,
shrunkDescription: String, shrunkDescription: String,
noteContent: String?,
expanded: Boolean, expanded: Boolean,
onNotesEditClicked: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val animProgress by animateFloatAsState( val animProgress by animateFloatAsState(
@ -571,25 +577,41 @@ private fun MangaSummary(
contents = listOf( contents = listOf(
{ {
Text( Text(
text = "\n\n", // Shows at least 3 lines // Shows at least 3 lines if no notes
// when there are notes show 6
text = if (noteContent.isNullOrBlank()) "\n\n" else "\n\n\n\n\n",
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
) )
}, },
{ {
Text( Column {
text = expandedDescription, MangaNotesSection(
style = MaterialTheme.typography.bodyMedium, content = noteContent,
) expanded = true,
onClickNotes = onNotesEditClicked,
)
Text(
text = expandedDescription,
style = MaterialTheme.typography.bodyMedium,
)
}
}, },
{ {
SelectionContainer { SelectionContainer {
Text( Column {
text = if (expanded) expandedDescription else shrunkDescription, MangaNotesSection(
maxLines = Int.MAX_VALUE, content = noteContent,
style = MaterialTheme.typography.bodyMedium, expanded = expanded,
color = MaterialTheme.colorScheme.onBackground, onClickNotes = onNotesEditClicked,
modifier = Modifier.secondaryItemAlpha(), )
) Text(
text = if (expanded) expandedDescription else shrunkDescription,
maxLines = Int.MAX_VALUE,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.secondaryItemAlpha(),
)
}
} }
}, },
{ {

View File

@ -1,5 +1,7 @@
package eu.kanade.presentation.manga.components package eu.kanade.presentation.manga.components
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -9,6 +11,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Edit import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -31,8 +34,9 @@ import tachiyomi.presentation.core.i18n.stringResource
@Composable @Composable
fun MangaNotesSection( fun MangaNotesSection(
onClickNotes: () -> Unit,
content: String?, content: String?,
expanded: Boolean,
onClickNotes: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
Column(modifier.fillMaxWidth()) { Column(modifier.fillMaxWidth()) {
@ -42,10 +46,45 @@ fun MangaNotesSection(
.fillMaxWidth(), .fillMaxWidth(),
) { ) {
if (!content.isNullOrBlank()) { if (!content.isNullOrBlank()) {
Column(
modifier = Modifier
.animateContentSize(
animationSpec = spring(),
alignment = Alignment.Center,
),
) {
if (expanded) {
Button(
onClick = onClickNotes,
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
contentColor = MaterialTheme.colorScheme.primary,
),
shape = RoundedCornerShape(8.dp),
modifier = Modifier
.padding(horizontal = 16.dp, vertical = 4.dp),
) {
Row(
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.extraSmall),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.Outlined.Edit,
contentDescription = null,
modifier = Modifier
.size(16.dp),
)
Text(
stringResource(MR.strings.action_edit_notes),
)
}
}
}
}
RichText( RichText(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth(),
.padding(MaterialTheme.padding.medium),
style = RichTextStyle( style = RichTextStyle(
stringStyle = RichTextStringStyle( stringStyle = RichTextStringStyle(
linkStyle = SpanStyle(color = MaterialTheme.colorScheme.primary), linkStyle = SpanStyle(color = MaterialTheme.colorScheme.primary),
@ -54,38 +93,11 @@ fun MangaNotesSection(
) { ) {
Markdown(content = content) Markdown(content = content)
} }
}
Button( HorizontalDivider(
onClick = onClickNotes, modifier = Modifier
colors = ButtonDefaults.buttonColors( .padding(vertical = 16.dp),
containerColor = Color.Transparent, )
contentColor = MaterialTheme.colorScheme.primary,
),
shape = RoundedCornerShape(8.dp),
modifier = Modifier
.padding(horizontal = 16.dp, vertical = 4.dp),
) {
Row(
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.padding.extraSmall),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.Outlined.Edit,
contentDescription = null,
modifier = Modifier
.size(16.dp),
)
Text(
stringResource(
if (content.isNullOrBlank()) {
MR.strings.action_add_notes
} else {
MR.strings.action_edit_notes
},
),
)
}
} }
} }
} }
@ -96,6 +108,7 @@ fun MangaNotesSection(
private fun MangaNotesSectionPreview() { private fun MangaNotesSectionPreview() {
MangaNotesSection( MangaNotesSection(
onClickNotes = {}, onClickNotes = {},
expanded = true,
content = "# Hello world\ntest1234 hi there!", content = "# Hello world\ntest1234 hi there!",
) )
} }