diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/dialogs/CopyDialogPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/dialogs/CopyDialogPage.kt new file mode 100644 index 00000000..5aedc17d --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/dialogs/CopyDialogPage.kt @@ -0,0 +1,177 @@ +package com.huanchengfly.tieba.post.ui.page.dialogs + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.Close +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.DialogProperties +import com.huanchengfly.tieba.post.R +import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme +import com.huanchengfly.tieba.post.ui.widgets.compose.Button +import com.huanchengfly.tieba.post.ui.widgets.compose.TitleCentredToolbar +import com.huanchengfly.tieba.post.utils.TiebaUtil +import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.navigation.DestinationsNavigator +import com.ramcosta.composedestinations.spec.DestinationStyle + +@Destination +@Composable +fun CopyTextPage( + text: String, + navigator: DestinationsNavigator, +) { + val context = LocalContext.current + CopyTextPageContent( + text = text, + onCopy = { + TiebaUtil.copyText(context, it) + }, + onCancel = { + navigator.navigateUp() + } + ) +} + +object CopyTextDialogStyle : DestinationStyle.Dialog { + override val properties: DialogProperties + get() = DialogProperties( + usePlatformDefaultWidth = false, + ) + +} + +@Destination( + style = CopyTextDialogStyle::class +) +@Composable +fun CopyTextDialogPage( + text: String, + navigator: DestinationsNavigator, +) { + val context = LocalContext.current + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .fillMaxSize() + .background(color = ExtendedTheme.colors.windowBackground) + ) { + CopyTextPageContent( + text = text, + onCopy = { + TiebaUtil.copyText(context, it) + }, + onCancel = { + navigator.navigateUp() + } + ) + } +} + +@Composable +private fun CopyTextPageContent( + text: String, + onCopy: (String) -> Unit, + onCancel: () -> Unit, +) { + Column( + modifier = Modifier + .fillMaxWidth() + .background(color = ExtendedTheme.colors.windowBackground) + .systemBarsPadding() + .padding(bottom = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + TitleCentredToolbar( + title = { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + text = stringResource(id = R.string.title_copy), + style = MaterialTheme.typography.h6, + fontWeight = FontWeight.Bold + ) + Text( + text = stringResource(id = R.string.tip_copy_text), + style = MaterialTheme.typography.caption + ) + } + }, + navigationIcon = { + IconButton(onClick = onCancel) { + Icon( + imageVector = Icons.Rounded.Close, + contentDescription = stringResource(id = R.string.btn_close) + ) + } + } + ) + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .verticalScroll(rememberScrollState()) + .weight(1f), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + SelectionContainer { + Text( + text = text, + modifier = Modifier.fillMaxWidth(), + style = MaterialTheme.typography.body1 + ) + } + } + Button( + modifier = Modifier.fillMaxWidth(), + onClick = { + onCopy(text) + onCancel() + } + ) { + Text(text = stringResource(id = R.string.btn_copy_all)) + } + Button( + modifier = Modifier.fillMaxWidth(), + onClick = { + onCancel() + }, + colors = ButtonDefaults.buttonColors( + backgroundColor = ExtendedTheme.colors.text.copy(alpha = 0.1f), + contentColor = ExtendedTheme.colors.text + ) + ) { + Text(text = stringResource(id = R.string.btn_close)) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/subposts/SubPostsPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/subposts/SubPostsPage.kt index 7d5e3496..ed9fdc0e 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/subposts/SubPostsPage.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/subposts/SubPostsPage.kt @@ -49,6 +49,7 @@ import com.huanchengfly.tieba.post.arch.wrapImmutable import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme import com.huanchengfly.tieba.post.ui.page.LocalNavigator import com.huanchengfly.tieba.post.ui.page.ProvideNavigator +import com.huanchengfly.tieba.post.ui.page.destinations.CopyTextDialogPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.ReplyPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.ThreadPageDestination import com.huanchengfly.tieba.post.ui.page.thread.PostAgreeBtn @@ -142,6 +143,7 @@ internal fun SubPostsContent( loadFromSubPost: Boolean = false, isSheet: Boolean = false ) { + val context = LocalContext.current val navigator = LocalNavigator.current val account = LocalAccount.current @@ -406,6 +408,11 @@ internal fun SubPostsContent( ) ) }, + onMenuCopyClick = { + navigator.navigate( + CopyTextDialogPageDestination(it) + ) + }, ) { deleteSubPost = null confirmDeleteDialogState.show() @@ -465,6 +472,12 @@ internal fun SubPostsContent( ) ) }, + onMenuCopyClick = { + navigator.navigate( + CopyTextDialogPageDestination(it) + ) +// TiebaUtil.copyText(context, it) + }, onMenuDeleteClick = { deleteSubPost = it.wrapImmutable() confirmDeleteDialogState.show() @@ -499,6 +512,7 @@ private fun SubPostItem( canDelete: (SubPostList) -> Boolean = { false }, onAgree: (SubPostList) -> Unit = {}, onReplyClick: (SubPostList) -> Unit = {}, + onMenuCopyClick: ((String) -> Unit)? = null, onMenuDeleteClick: ((SubPostList) -> Unit)? = null, ) { val (subPost, contentRenders, blocked) = item @@ -532,15 +546,15 @@ private fun SubPostItem( Text(text = stringResource(id = R.string.btn_reply)) } } - DropdownMenuItem( - onClick = { - TiebaUtil.copyText( - context, - contentRenders.joinToString("\n") { it.toString() }) - menuState.expanded = false + if (onMenuCopyClick != null) { + DropdownMenuItem( + onClick = { + onMenuCopyClick(contentRenders.joinToString("\n") { it.toString() }) + menuState.expanded = false + } + ) { + Text(text = stringResource(id = R.string.menu_copy)) } - ) { - Text(text = stringResource(id = R.string.menu_copy)) } DropdownMenuItem( onClick = { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt index 5c8e5a15..c50b6e31 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/page/thread/ThreadPage.kt @@ -102,7 +102,6 @@ import com.huanchengfly.tieba.post.api.models.protos.ThreadInfo import com.huanchengfly.tieba.post.api.models.protos.User import com.huanchengfly.tieba.post.api.models.protos.bawuType import com.huanchengfly.tieba.post.api.models.protos.plainText -import com.huanchengfly.tieba.post.api.models.protos.renders import com.huanchengfly.tieba.post.api.retrofit.exception.getErrorMessage import com.huanchengfly.tieba.post.arch.GlobalEvent import com.huanchengfly.tieba.post.arch.ImmutableHolder @@ -123,6 +122,7 @@ import com.huanchengfly.tieba.post.ui.common.theme.compose.invertChipContent import com.huanchengfly.tieba.post.ui.common.theme.compose.pullRefreshIndicator import com.huanchengfly.tieba.post.ui.common.theme.compose.threadBottomBar import com.huanchengfly.tieba.post.ui.page.ProvideNavigator +import com.huanchengfly.tieba.post.ui.page.destinations.CopyTextPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.ForumPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.ReplyPageDestination import com.huanchengfly.tieba.post.ui.page.destinations.SubPostsSheetPageDestination @@ -873,6 +873,11 @@ fun ThreadPage( ) } }, + onMenuCopyClick = { + navigator.navigate( + CopyTextPageDestination(it) + ) + }, onMenuFavoriteClick = { val isPostCollected = it.id == thread?.get { collectMarkPid.toLongOrNull() } @@ -1209,6 +1214,11 @@ fun ThreadPage( ) ) }, + onMenuCopyClick = { + navigator.navigate( + CopyTextPageDestination(it) + ) + }, onMenuFavoriteClick = { viewModel.send( ThreadUiIntent.AddFavorite( @@ -1540,6 +1550,7 @@ fun PostCard( onReplyClick: (Post) -> Unit = {}, onSubPostReplyClick: ((Post, SubPostList) -> Unit)? = null, onOpenSubPosts: (subPostId: Long) -> Unit = {}, + onMenuCopyClick: ((String) -> Unit)? = null, onMenuFavoriteClick: ((Post) -> Unit)? = null, onMenuDeleteClick: ((Post) -> Unit)? = null, ) { @@ -1591,13 +1602,15 @@ fun PostCard( Text(text = stringResource(id = R.string.btn_reply)) } } - DropdownMenuItem( - onClick = { - TiebaUtil.copyText(context, post.content.plainText) - menuState.expanded = false + if (onMenuCopyClick != null) { + DropdownMenuItem( + onClick = { + onMenuCopyClick(post.content.plainText) + menuState.expanded = false + } + ) { + Text(text = stringResource(id = R.string.menu_copy)) } - ) { - Text(text = stringResource(id = R.string.menu_copy)) } DropdownMenuItem( onClick = { @@ -1744,6 +1757,9 @@ fun PostCard( onSubPostReplyClick?.invoke(post, it) }, onOpenSubPosts = onOpenSubPosts, + onMenuCopyClick = { + onMenuCopyClick?.invoke(it.content.plainText) + } ) } } @@ -1781,6 +1797,7 @@ private fun SubPostItem( modifier: Modifier = Modifier, onReplyClick: ((SubPostList) -> Unit)?, onOpenSubPosts: (Long) -> Unit, + onMenuCopyClick: ((SubPostList) -> Unit)?, ) { val context = LocalContext.current val menuState = rememberMenuState() @@ -1797,15 +1814,15 @@ private fun SubPostItem( Text(text = stringResource(id = R.string.title_reply)) } } - DropdownMenuItem( - onClick = { - TiebaUtil.copyText( - context, - subPostList.get { content.renders.joinToString(" ") { it.toString() } }) - menuState.expanded = false + if (onMenuCopyClick != null) { + DropdownMenuItem( + onClick = { + onMenuCopyClick(subPostList.get()) + menuState.expanded = false + } + ) { + Text(text = stringResource(id = R.string.menu_copy)) } - ) { - Text(text = stringResource(id = R.string.menu_copy)) } DropdownMenuItem( onClick = { diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Buttons.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Buttons.kt index 4038a068..5a0e53c2 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Buttons.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Buttons.kt @@ -1,6 +1,8 @@ package com.huanchengfly.tieba.post.ui.widgets.compose import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.LocalIndication +import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues @@ -47,23 +49,26 @@ fun Button( ) { val contentColor by colors.contentColor(enabled) Surface( - onClick = onClick, - modifier = modifier, - enabled = enabled, + modifier = Modifier + .clickable( + onClick = onClick, + enabled = enabled, + interactionSource = interactionSource, + indication = LocalIndication.current + ) + .then(modifier), shape = shape, color = colors.backgroundColor(enabled).value, contentColor = contentColor.copy(alpha = 1f), border = border, elevation = elevation?.elevation(enabled, interactionSource)?.value ?: 0.dp, - interactionSource = interactionSource, ) { CompositionLocalProvider(LocalContentAlpha provides contentColor.alpha) { ProvideTextStyle( value = MaterialTheme.typography.button ) { Row( - Modifier - .padding(contentPadding), + Modifier.padding(contentPadding), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, content = content diff --git a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Toolbar.kt b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Toolbar.kt index 7f8e2893..fb7de00a 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Toolbar.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/ui/widgets/compose/Toolbar.kt @@ -27,6 +27,7 @@ import androidx.compose.material.DropdownMenuItem import androidx.compose.material.Icon import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme +import androidx.compose.material.ProvideTextStyle import androidx.compose.material.Text import androidx.compose.material.TopAppBar import androidx.compose.material.icons.Icons @@ -209,7 +210,7 @@ fun TitleCentredToolbar( ) { TitleCentredToolbar( title = { - Text(text = title, fontWeight = FontWeight.Bold, style = MaterialTheme.typography.h6) + Text(text = title) }, modifier = modifier, insets = insets, @@ -241,11 +242,13 @@ fun TitleCentredToolbar( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxHeight() ) { - navigationIcon?.invoke() + ProvideContentColor(color = ExtendedTheme.colors.onTopBar) { + navigationIcon?.invoke() - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.weight(1f)) - actions() + actions() + } } Row( @@ -255,8 +258,10 @@ fun TitleCentredToolbar( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { - ProvideContentColor(color = ExtendedTheme.colors.onTopBar) { - title() + ProvideTextStyle(value = MaterialTheme.typography.h6.copy(fontWeight = FontWeight.Bold)) { + ProvideContentColor(color = ExtendedTheme.colors.onTopBar) { + title() + } } } } @@ -275,21 +280,12 @@ fun Toolbar( actions: @Composable RowScope.() -> Unit = {}, content: (@Composable ColumnScope.() -> Unit)? = null, ) { - TopAppBarContainer( - topBar = { - TopAppBar( - title = { - ProvideContentColor(color = ExtendedTheme.colors.onTopBar) { - Text(text = title, fontWeight = FontWeight.Bold) - } - }, - actions = actions, - navigationIcon = navigationIcon, - backgroundColor = ExtendedTheme.colors.topBar, - contentColor = ExtendedTheme.colors.onTopBar, - elevation = 0.dp - ) + Toolbar( + title = { + Text(text = title) }, + navigationIcon = navigationIcon, + actions = actions, content = content ) } @@ -305,10 +301,20 @@ fun Toolbar( topBar = { TopAppBar( title = { - ProvideContentColor(color = ExtendedTheme.colors.onTopBar, content = title) + ProvideTextStyle(value = MaterialTheme.typography.h6.copy(fontWeight = FontWeight.Bold)) { + ProvideContentColor(color = ExtendedTheme.colors.onTopBar, content = title) + } + }, + actions = { + ProvideContentColor(color = ExtendedTheme.colors.onTopBar) { + actions() + } + }, + navigationIcon = { + ProvideContentColor(color = ExtendedTheme.colors.onTopBar) { + navigationIcon?.invoke() + } }, - actions = actions, - navigationIcon = navigationIcon, backgroundColor = ExtendedTheme.colors.topBar, contentColor = ExtendedTheme.colors.onTopBar, elevation = 0.dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7cdff28a..df1f18c6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -729,4 +729,6 @@ 隐藏回贴入口 应用图标使用动态取色 当前正在使用的应用图标暂不支持动态取色 + 复制全部 + 复制