feat(talk): меню сообщения — Копировать/Копировать ссылку/Переслать в «Личные заметки» (P1 talk.diff)
This commit is contained in:
@@ -804,6 +804,9 @@ fun TalkMessageActionSheet(
|
||||
onEdit: (TalkMessage) -> Unit,
|
||||
onDelete: (TalkMessage) -> Unit,
|
||||
onReaction: (TalkMessage, String) -> Unit,
|
||||
onCopy: (TalkMessage) -> Unit,
|
||||
onCopyLink: (TalkMessage) -> Unit,
|
||||
onForwardNoteToSelf: (TalkMessage) -> Unit,
|
||||
) {
|
||||
if (message == null) return
|
||||
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
@@ -831,6 +834,14 @@ fun TalkMessageActionSheet(
|
||||
F7TextButton(text = emoji, onClick = { onReaction(message, emoji) })
|
||||
}
|
||||
}
|
||||
if (!message.isSystemMessage) {
|
||||
F7TextButton(text = "Копировать", onClick = { onCopy(message) })
|
||||
F7TextButton(text = "Копировать ссылку", onClick = { onCopyLink(message) })
|
||||
F7TextButton(
|
||||
text = "Переслать в «Личные заметки»",
|
||||
onClick = { onForwardNoteToSelf(message) },
|
||||
)
|
||||
}
|
||||
if (canModify) {
|
||||
F7TextButton(text = "Изменить", onClick = { onEdit(message) })
|
||||
F7TextButton(text = "Удалить", onClick = { onDelete(message) })
|
||||
|
||||
@@ -3,6 +3,7 @@ package ru.forbion.f7cloud.feature.talk
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.clickable
|
||||
@@ -45,7 +46,9 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.ViewModel
|
||||
@@ -292,6 +295,7 @@ fun TalkScreen(
|
||||
onReaction = { msg, emoji -> vm.addReaction(session, msg.id, emoji) },
|
||||
onDeleteMessage = { vm.deleteMessage(session, it.id) },
|
||||
onEditMessage = { msg, text -> vm.editMessage(session, msg.id, text) },
|
||||
onForwardNoteToSelf = { vm.forwardToNoteToSelf(session, it) },
|
||||
onMentionQuery = { vm.setMentionQuery(session, it) },
|
||||
onMentionSelected = { mention ->
|
||||
draft = insertMentionIntoDraft(draft, mention)
|
||||
@@ -430,6 +434,7 @@ private fun ChatContent(
|
||||
onReaction: (TalkMessage, String) -> Unit,
|
||||
onDeleteMessage: (TalkMessage) -> Unit,
|
||||
onEditMessage: (TalkMessage, String) -> Unit,
|
||||
onForwardNoteToSelf: (TalkMessage) -> Unit,
|
||||
onMentionQuery: (String?) -> Unit,
|
||||
onMentionSelected: (TalkMention) -> Unit,
|
||||
onClearReply: () -> Unit,
|
||||
@@ -441,6 +446,8 @@ private fun ChatContent(
|
||||
var editDraft by remember { mutableStateOf("") }
|
||||
val listState = rememberLazyListState()
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val clipboard = LocalClipboardManager.current
|
||||
val chatItems = remember(state.messages, state.openRoomLastReadMessageId, state.collapseSystemMessages) {
|
||||
buildChatItems(
|
||||
messages = state.messages,
|
||||
@@ -507,6 +514,24 @@ private fun ChatContent(
|
||||
onReaction(msg, emoji)
|
||||
actionMessage = null
|
||||
},
|
||||
onCopy = { msg ->
|
||||
clipboard.setText(AnnotatedString(msg.displayText))
|
||||
Toast.makeText(context, "Скопировано", Toast.LENGTH_SHORT).show()
|
||||
actionMessage = null
|
||||
},
|
||||
onCopyLink = { msg ->
|
||||
val token = state.selectedRoomToken
|
||||
if (token != null) {
|
||||
clipboard.setText(AnnotatedString(TalkUrls.messageLink(session, token, msg.id)))
|
||||
Toast.makeText(context, "Ссылка скопирована", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
actionMessage = null
|
||||
},
|
||||
onForwardNoteToSelf = { msg ->
|
||||
onForwardNoteToSelf(msg)
|
||||
Toast.makeText(context, "Переслано в «Личные заметки»", Toast.LENGTH_SHORT).show()
|
||||
actionMessage = null
|
||||
},
|
||||
)
|
||||
|
||||
editingMessage?.let { message ->
|
||||
|
||||
@@ -19,4 +19,10 @@ object TalkUrls {
|
||||
val base = session.serverUrl.trimEnd('/')
|
||||
return "$base/index.php/core/preview?fileId=$fileId&x=$size&y=$size&a=1&mode=cover&forceIcon=0"
|
||||
}
|
||||
|
||||
/** Веб-ссылка на сообщение (/call/<token>#message_<id>). */
|
||||
fun messageLink(session: AuthSession, token: String, messageId: Long): String {
|
||||
val base = session.serverUrl.trimEnd('/')
|
||||
return "$base/index.php/call/$token#message_$messageId"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,6 +594,28 @@ class TalkViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
/** Переслать сообщение в «Личные заметки» (note-to-self, type 6). */
|
||||
fun forwardToNoteToSelf(session: AuthSession, message: TalkMessage) {
|
||||
val text = message.displayText.trim()
|
||||
if (text.isEmpty()) return
|
||||
val noteRoom = _state.value.rooms.find { it.type == ROOM_TYPE_NOTE_TO_SELF }
|
||||
if (noteRoom == null) {
|
||||
_state.value = _state.value.copy(
|
||||
error = "«Личные заметки» недоступны",
|
||||
)
|
||||
return
|
||||
}
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
runCatching { repository.sendMessage(session, noteRoom.token, text) }
|
||||
.onFailure { t ->
|
||||
_state.value = _state.value.copy(
|
||||
error = t.message ?: "Не удалось переслать",
|
||||
unauthorized = t is UnauthorizedException,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteMessage(session: AuthSession, messageId: Long) {
|
||||
val token = _state.value.selectedRoomToken ?: return
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
@@ -749,5 +771,8 @@ class TalkViewModel(
|
||||
companion object {
|
||||
private const val BACKGROUND_POLL_DELAY_MS = 5_000L
|
||||
private const val POLL_ERROR_DELAY_MS = 5_000L
|
||||
|
||||
/** spreed conversation type: note-to-self (Личные заметки). */
|
||||
private const val ROOM_TYPE_NOTE_TO_SELF = 6
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user