From 349b3972789936d3019b1af854e4ef1ec567cd7f Mon Sep 17 00:00:00 2001
From: HuanCheng65 <22636177+HuanCheng65@users.noreply.github.com>
Date: Sat, 30 Sep 2023 01:26:43 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E8=87=AA=E7=94=B1=E5=A4=8D=E5=88=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../post/ui/page/dialogs/CopyDialogPage.kt | 177 ++++++++++++++++++
.../post/ui/page/subposts/SubPostsPage.kt | 30 ++-
.../tieba/post/ui/page/thread/ThreadPage.kt | 47 +++--
.../tieba/post/ui/widgets/compose/Buttons.kt | 17 +-
.../tieba/post/ui/widgets/compose/Toolbar.kt | 52 ++---
app/src/main/res/values/strings.xml | 2 +
6 files changed, 273 insertions(+), 52 deletions(-)
create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/ui/page/dialogs/CopyDialogPage.kt
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 @@
隐藏回贴入口
应用图标使用动态取色
当前正在使用的应用图标暂不支持动态取色
+ 复制全部
+ 复制