Skip to content

Commit 529d147

Browse files
committed
feat(chat): add "Copy message link" to message actions
Add a "Copy message link" option to the long-press message actions bottom sheet. It copies a link in the same format the web client uses ({baseUrl}/call/{token}#message_{messageId}) to the clipboard, so the link can be shared (e.g. by email) and opened in the browser, landing on the referenced message. Resolves: #2361 Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: Jan C. Borchardt <925062+jancborchardt@users.noreply.github.com>
1 parent c73c507 commit 529d147

3 files changed

Lines changed: 43 additions & 0 deletions

File tree

app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,7 @@ class ChatActivity :
948948
onForward = { forwardMessage(msg) },
949949
onEdit = { messageInputViewModel.edit(msg) },
950950
onCopy = { copyMessage(msg) },
951+
onCopyMessageLink = { copyMessageLink(msg) },
951952
onMarkAsUnread = { markAsUnread(msg) },
952953
onRemind = { remindMeLater(msg) },
953954
onPin = { pinMessage(msg) },
@@ -3512,6 +3513,27 @@ class ChatActivity :
35123513
clipboardManager.setPrimaryClip(clipData)
35133514
}
35143515

3516+
fun copyMessageLink(message: ChatMessage) {
3517+
val baseUrl = conversationUser?.baseUrl
3518+
if (baseUrl.isNullOrEmpty()) {
3519+
Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show()
3520+
return
3521+
}
3522+
3523+
// Matches the web client link format: {baseUrl}/call/{token}#message_{messageId}
3524+
val messageLink = "$baseUrl/call/$roomToken#message_${message.jsonMessageId}"
3525+
3526+
val clipboardManager =
3527+
getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
3528+
val clipData = ClipData.newPlainText(
3529+
resources?.getString(R.string.nc_app_product_name),
3530+
messageLink
3531+
)
3532+
clipboardManager.setPrimaryClip(clipData)
3533+
3534+
Snackbar.make(binding.root, R.string.nc_common_copy_success, Snackbar.LENGTH_SHORT).show()
3535+
}
3536+
35153537
fun translateMessage(message: ChatMessage?) {
35163538
val bundle = Bundle()
35173539
bundle.putString(BundleKeys.KEY_TRANSLATE_MESSAGE, message?.getRichText())

app/src/main/java/com/nextcloud/talk/chat/ui/MessageActionsBottomSheet.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ data class MessageActionsState(
129129
val showForward: Boolean,
130130
val showEdit: Boolean,
131131
val showCopy: Boolean,
132+
val showCopyMessageLink: Boolean,
132133
val showMarkAsUnread: Boolean,
133134
val showRemind: Boolean,
134135
val showPin: Boolean,
@@ -242,6 +243,8 @@ internal fun buildMessageActionsState(
242243
isOnline,
243244
showEdit = isMessageEditable,
244245
showCopy = !message.isDeleted,
246+
showCopyMessageLink = !message.isDeleted &&
247+
ChatMessage.MessageType.SYSTEM_MESSAGE != messageType,
245248
showMarkAsUnread = hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.CHAT_READ_MARKER) &&
246249
ChatMessage.MessageType.SYSTEM_MESSAGE != messageType &&
247250
isOnline,
@@ -279,6 +282,7 @@ fun MessageActionsBottomSheet(
279282
onForward: () -> Unit,
280283
onEdit: () -> Unit,
281284
onCopy: () -> Unit,
285+
onCopyMessageLink: () -> Unit,
282286
onMarkAsUnread: () -> Unit,
283287
onRemind: () -> Unit,
284288
onPin: () -> Unit,
@@ -306,6 +310,7 @@ fun MessageActionsBottomSheet(
306310
onForward = onForward,
307311
onEdit = onEdit,
308312
onCopy = onCopy,
313+
onCopyMessageLink = onCopyMessageLink,
309314
onMarkAsUnread = onMarkAsUnread,
310315
onRemind = onRemind,
311316
onPin = onPin,
@@ -332,6 +337,7 @@ internal fun MessageActionsSheetContent(
332337
onForward: () -> Unit,
333338
onEdit: () -> Unit,
334339
onCopy: () -> Unit,
340+
onCopyMessageLink: () -> Unit,
335341
onMarkAsUnread: () -> Unit,
336342
onRemind: () -> Unit,
337343
onPin: () -> Unit,
@@ -436,6 +442,16 @@ internal fun MessageActionsSheetContent(
436442
}
437443
)
438444
}
445+
if (actionsState.showCopyMessageLink) {
446+
MessageActionItem(
447+
iconRes = R.drawable.ic_link,
448+
text = stringResource(R.string.nc_copy_message_link),
449+
onClick = {
450+
onCopyMessageLink()
451+
onDismiss()
452+
}
453+
)
454+
}
439455
if (actionsState.showMarkAsUnread) {
440456
MessageActionItem(
441457
iconRes = R.drawable.ic_mark_chat_unread_24px,
@@ -808,6 +824,7 @@ private fun PreviewMessageActionsSheetContent() {
808824
showForward = true,
809825
showEdit = true,
810826
showCopy = true,
827+
showCopyMessageLink = true,
811828
showMarkAsUnread = true,
812829
showRemind = true,
813830
showPin = true,
@@ -830,6 +847,7 @@ private fun PreviewMessageActionsSheetContent() {
830847
onForward = {},
831848
onEdit = {},
832849
onCopy = {},
850+
onCopyMessageLink = {},
833851
onMarkAsUnread = {},
834852
onRemind = {},
835853
onPin = {},
@@ -864,6 +882,7 @@ private fun PreviewMessageActionsSheetPinned() {
864882
showForward = false,
865883
showEdit = false,
866884
showCopy = true,
885+
showCopyMessageLink = true,
867886
showMarkAsUnread = false,
868887
showRemind = false,
869888
showPin = true,
@@ -882,6 +901,7 @@ private fun PreviewMessageActionsSheetPinned() {
882901
onForward = {},
883902
onEdit = {},
884903
onCopy = {},
904+
onCopyMessageLink = {},
885905
onMarkAsUnread = {},
886906
onRemind = {},
887907
onPin = {},

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,7 @@ How to translate with transifex:
562562

563563
<!-- Chat -->
564564
<string name="nc_copy_message">Copy</string>
565+
<string name="nc_copy_message_link">Copy message link</string>
565566
<string name="nc_forward_message">Forward</string>
566567
<string name="nc_reply">Reply</string>
567568
<string name="nc_reply_privately">Reply privately</string>

0 commit comments

Comments
 (0)