From 170c000d65f05f743e2c883f4f720471eea44272 Mon Sep 17 00:00:00 2001 From: imkunet Date: Thu, 19 Sep 2024 06:16:22 -0400 Subject: [PATCH] Design revision see the Discord for more details --- .../presentation/manga/MangaNotesScreen.kt | 31 +++-- .../kanade/presentation/manga/MangaScreen.kt | 125 +++++++++++------- .../manga/MangaScreenConstants.kt | 1 - .../manga/components/MangaInfoHeader.kt | 46 +++++-- .../manga/components/MangaNotesSection.kt | 81 +++++++----- 5 files changed, 176 insertions(+), 108 deletions(-) diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaNotesScreen.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaNotesScreen.kt index 4d36d4e0f..03a7702ec 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaNotesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaNotesScreen.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Check @@ -123,21 +124,23 @@ fun MangaNotesScreen( enter = fadeIn(), exit = fadeOut(), ) { - RichText( - modifier = Modifier - .verticalScroll(rememberScrollState()) - .fillMaxWidth() - .padding( - horizontal = MaterialTheme.padding.medium, - vertical = paddingValues.calculateTopPadding() + MaterialTheme.padding.medium, + SelectionContainer { + RichText( + modifier = Modifier + .verticalScroll(rememberScrollState()) + .fillMaxWidth() + .padding( + horizontal = MaterialTheme.padding.medium, + vertical = paddingValues.calculateTopPadding() + MaterialTheme.padding.medium, + ), + style = RichTextStyle( + stringStyle = RichTextStringStyle( + linkStyle = SpanStyle(color = MaterialTheme.colorScheme.primary), + ), ), - style = RichTextStyle( - stringStyle = RichTextStringStyle( - linkStyle = SpanStyle(color = MaterialTheme.colorScheme.primary), - ), - ), - ) { - Markdown(content = state.notes.orEmpty()) + ) { + Markdown(content = state.notes.orEmpty()) + } } } } diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt index 2d8ac8f49..f5bddc966 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt @@ -5,6 +5,7 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column 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.verticalScroll import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material3.Icon 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.LocalHapticFeedback import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastAll import androidx.compose.ui.util.fastAny 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.MangaChapterListItem 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.MissingChapterCountListItem import eu.kanade.presentation.util.formatChapterNumber @@ -336,27 +338,47 @@ private fun MangaScreenSmallImpl( }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, floatingActionButton = { - val isFABVisible = remember(chapters) { - chapters.fastAny { !it.chapter.read } && !isAnySelected - } - AnimatedVisibility( - visible = isFABVisible, - enter = fadeIn(), - exit = fadeOut(), + Column( + horizontalAlignment = Alignment.End, + verticalArrangement = Arrangement.spacedBy(4.dp), ) { - 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(), - ) + AnimatedVisibility( + visible = !isAnySelected, + enter = fadeIn(), + exit = fadeOut(), + ) { + ExtendedFloatingActionButton( + text = { Text(stringResource(MR.strings.action_notes)) }, + icon = { Icon(imageVector = Icons.Filled.Edit, contentDescription = null) }, + onClick = onNotesEditClicked, + 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 -> @@ -424,18 +446,10 @@ private fun MangaScreenSmallImpl( defaultExpandState = state.isFromSource, description = state.manga.description, tagsProvider = { state.manga.genre }, + noteContent = state.manga.notes, onTagSearch = onTagSearch, onCopyTagToClipboard = onCopyTagToClipboard, - ) - } - - item( - key = MangaScreenItem.NOTES_SECTION, - contentType = MangaScreenItem.NOTES_SECTION, - ) { - MangaNotesSection( onClickNotes = onNotesEditClicked, - content = state.manga.notes, ) } @@ -599,21 +613,39 @@ fun MangaScreenLargeImpl( 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, - ), + Column( + horizontalAlignment = Alignment.End, + verticalArrangement = Arrangement.spacedBy(4.dp), + ) { + AnimatedVisibility( + visible = !isAnySelected, + enter = fadeIn(), + 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, - expanded = chapterListState.shouldExpandFAB(), - ) + } + + 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 -> @@ -663,12 +695,10 @@ fun MangaScreenLargeImpl( defaultExpandState = true, description = state.manga.description, tagsProvider = { state.manga.genre }, + noteContent = state.manga.notes, onTagSearch = onTagSearch, onCopyTagToClipboard = onCopyTagToClipboard, - ) - MangaNotesSection( onClickNotes = onNotesEditClicked, - content = state.manga.notes, ) } }, @@ -788,6 +818,7 @@ private fun LazyListScope.sharedChapterItems( is ChapterList.MissingCount -> { MissingChapterCountListItem(count = item.count) } + is ChapterList.Item -> { MangaChapterListItem( title = if (manga.displayMode == Manga.CHAPTER_DISPLAY_NUMBER) { diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaScreenConstants.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaScreenConstants.kt index 785038c78..22a6664d0 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreenConstants.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreenConstants.kt @@ -17,7 +17,6 @@ enum class MangaScreenItem { INFO_BOX, ACTION_ROW, DESCRIPTION_WITH_TAG, - NOTES_SECTION, CHAPTER_HEADER, CHAPTER, } diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt index 6a1376463..7031b8052 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaInfoHeader.kt @@ -236,8 +236,10 @@ fun ExpandableMangaDescription( defaultExpandState: Boolean, description: String?, tagsProvider: () -> List?, + noteContent: String?, onTagSearch: (String) -> Unit, onCopyTagToClipboard: (tag: String) -> Unit, + onClickNotes: () -> Unit, modifier: Modifier = Modifier, ) { Column(modifier = modifier) { @@ -255,6 +257,8 @@ fun ExpandableMangaDescription( expandedDescription = desc, shrunkDescription = trimmedDescription, expanded = expanded, + noteContent = noteContent, + onNotesEditClicked = onClickNotes, modifier = Modifier .padding(top = 8.dp) .padding(horizontal = 16.dp) @@ -559,7 +563,9 @@ private fun ColumnScope.MangaContentInfo( private fun MangaSummary( expandedDescription: String, shrunkDescription: String, + noteContent: String?, expanded: Boolean, + onNotesEditClicked: () -> Unit, modifier: Modifier = Modifier, ) { val animProgress by animateFloatAsState( @@ -571,25 +577,41 @@ private fun MangaSummary( contents = listOf( { 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, ) }, { - Text( - text = expandedDescription, - style = MaterialTheme.typography.bodyMedium, - ) + Column { + MangaNotesSection( + content = noteContent, + expanded = true, + onClickNotes = onNotesEditClicked, + ) + Text( + text = expandedDescription, + style = MaterialTheme.typography.bodyMedium, + ) + } }, { SelectionContainer { - Text( - text = if (expanded) expandedDescription else shrunkDescription, - maxLines = Int.MAX_VALUE, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onBackground, - modifier = Modifier.secondaryItemAlpha(), - ) + Column { + MangaNotesSection( + content = noteContent, + expanded = expanded, + onClickNotes = onNotesEditClicked, + ) + Text( + text = if (expanded) expandedDescription else shrunkDescription, + maxLines = Int.MAX_VALUE, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.secondaryItemAlpha(), + ) + } } }, { diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesSection.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesSection.kt index a20931187..aab99be98 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesSection.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesSection.kt @@ -1,5 +1,7 @@ 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.Column 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.material.icons.Icons import androidx.compose.material.icons.outlined.Edit +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -31,8 +34,9 @@ import tachiyomi.presentation.core.i18n.stringResource @Composable fun MangaNotesSection( - onClickNotes: () -> Unit, content: String?, + expanded: Boolean, + onClickNotes: () -> Unit, modifier: Modifier = Modifier, ) { Column(modifier.fillMaxWidth()) { @@ -42,10 +46,45 @@ fun MangaNotesSection( .fillMaxWidth(), ) { 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( modifier = Modifier - .fillMaxWidth() - .padding(MaterialTheme.padding.medium), + .fillMaxWidth(), style = RichTextStyle( stringStyle = RichTextStringStyle( linkStyle = SpanStyle(color = MaterialTheme.colorScheme.primary), @@ -54,38 +93,11 @@ fun MangaNotesSection( ) { Markdown(content = content) } - } - 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( - if (content.isNullOrBlank()) { - MR.strings.action_add_notes - } else { - MR.strings.action_edit_notes - }, - ), - ) - } + HorizontalDivider( + modifier = Modifier + .padding(vertical = 16.dp), + ) } } } @@ -96,6 +108,7 @@ fun MangaNotesSection( private fun MangaNotesSectionPreview() { MangaNotesSection( onClickNotes = {}, + expanded = true, content = "# Hello world\ntest1234 hi there!", ) }