mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-09-16 23:24:58 +00:00
Merge branch 'stable'
This commit is contained in:
+36
-19
@@ -497,8 +497,8 @@ fun ComposeView(
|
||||
}
|
||||
}
|
||||
|
||||
fun clearCurrentDraft() {
|
||||
if (chatModel.draftChatId.value == draftChatId(chat.id, chatScope)) {
|
||||
fun clearCurrentDraft(forChat: Chat = chat) {
|
||||
if (chatModel.draftChatId.value == draftChatId(forChat.id, chatScope)) {
|
||||
chatModel.draft.value = null
|
||||
chatModel.draftChatId.value = null
|
||||
}
|
||||
@@ -575,9 +575,10 @@ fun ComposeView(
|
||||
}
|
||||
|
||||
// TODO [short links] connectCheckLinkPreview
|
||||
fun checkLinkPreview(): MsgContent {
|
||||
val msgText = composeState.value.message.text
|
||||
return when (val composePreview = composeState.value.preview) {
|
||||
// the state is passed in by a send that must not read the current one - see sendMessageAsync
|
||||
fun checkLinkPreview(cs: ComposeState = composeState.value): MsgContent {
|
||||
val msgText = cs.message.text
|
||||
return when (val composePreview = cs.preview) {
|
||||
is ComposePreview.CLinkPreview -> {
|
||||
val parsedMsg = parseToMarkdown(msgText)
|
||||
val url = getMessageLinks(parsedMsg).first
|
||||
@@ -680,8 +681,12 @@ fun ComposeView(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendMessageAsync(text: String?, live: Boolean, ttl: Int?, sign: Boolean = false): List<ChatItem>? {
|
||||
val cs = composeState.value
|
||||
// toChat is the chat the message was composed in - it differs from the one this view shows only for the live message
|
||||
// committed by a chat switch, which has no context item, so the forwarding, editing and reporting branches below
|
||||
// cannot run with a different chat. cs is that send's state, captured before the switch replaced it.
|
||||
suspend fun sendMessageAsync(text: String?, live: Boolean, ttl: Int?, sign: Boolean = false, toChat: Chat = chat, cs: ComposeState = composeState.value): List<ChatItem>? {
|
||||
// a send for another chat may not write to composeState, even after that chat is opened again - it was handed over
|
||||
fun composeIsForSend(): Boolean = toChat.id == chat.id
|
||||
var sent: List<ChatItem>?
|
||||
var lastMessageFailedToSend: ComposeState? = null
|
||||
val msgText = text ?: cs.message.text
|
||||
@@ -731,8 +736,8 @@ fun ComposeView(
|
||||
|
||||
fun updateMsgContent(msgContent: MsgContent): MsgContent {
|
||||
return when (msgContent) {
|
||||
is MsgContent.MCText -> checkLinkPreview()
|
||||
is MsgContent.MCLink -> checkLinkPreview()
|
||||
is MsgContent.MCText -> checkLinkPreview(cs)
|
||||
is MsgContent.MCLink -> checkLinkPreview(cs)
|
||||
is MsgContent.MCImage -> MsgContent.MCImage(msgText, image = msgContent.image)
|
||||
is MsgContent.MCVideo -> MsgContent.MCVideo(msgText, image = msgContent.image, duration = msgContent.duration)
|
||||
is MsgContent.MCVoice -> MsgContent.MCVoice(msgText, duration = msgContent.duration)
|
||||
@@ -789,12 +794,12 @@ fun ComposeView(
|
||||
}
|
||||
|
||||
val liveMessage = cs.liveMessage
|
||||
if (!live) {
|
||||
if (!live && composeIsForSend()) {
|
||||
if (liveMessage != null) composeState.value = cs.copy(liveMessage = null)
|
||||
sending()
|
||||
}
|
||||
if (!cs.forwarding || chatModel.draft.value?.forwarding == true) {
|
||||
clearCurrentDraft()
|
||||
clearCurrentDraft(toChat)
|
||||
}
|
||||
|
||||
if (cs.contextItem is ComposeContextItem.ForwardingItems) {
|
||||
@@ -805,6 +810,8 @@ fun ComposeView(
|
||||
if (cs.message.text.isNotEmpty()) {
|
||||
sent?.mapIndexed { index, message ->
|
||||
if (index == sent!!.lastIndex) {
|
||||
// the current state, not cs: forwarding is never reached from the chat switch, and keeps what was typed
|
||||
// while it was in flight
|
||||
send(chat, checkLinkPreview(), quoted = message.id, live = false, ttl = ttl, mentions = cs.memberMentions, sign = sign)
|
||||
} else {
|
||||
message
|
||||
@@ -818,7 +825,7 @@ fun ComposeView(
|
||||
sent = if (updatedMessage != null) listOf(updatedMessage) else null
|
||||
lastMessageFailedToSend = if (updatedMessage == null) constructFailedMessage(cs) else null
|
||||
} else if (liveMessage != null && liveMessage.sent) {
|
||||
val updatedMessage = updateMessage(liveMessage.chatItem, chat, live)
|
||||
val updatedMessage = updateMessage(liveMessage.chatItem, toChat, live)
|
||||
sent = if (updatedMessage != null) listOf(updatedMessage) else null
|
||||
} else if (cs.contextItem is ComposeContextItem.ReportedItem) {
|
||||
sent = sendReport(cs.contextItem.reason, cs.contextItem.chatItem.id)
|
||||
@@ -828,7 +835,7 @@ fun ComposeView(
|
||||
val remoteHost = chatModel.currentRemoteHost.value
|
||||
when (val preview = cs.preview) {
|
||||
ComposePreview.NoPreview -> msgs.add(MsgContent.MCText(msgText))
|
||||
is ComposePreview.CLinkPreview -> msgs.add(checkLinkPreview())
|
||||
is ComposePreview.CLinkPreview -> msgs.add(checkLinkPreview(cs))
|
||||
is ComposePreview.ChatLinkPreview -> {
|
||||
val linkStr = preview.chatLink.connLinkStr
|
||||
val text = if (msgText.isEmpty()) linkStr else "$msgText\n$linkStr"
|
||||
@@ -919,7 +926,7 @@ fun ComposeView(
|
||||
localPath = file.filePath
|
||||
)
|
||||
}
|
||||
val sendResult = send(chat, content, if (index == 0) quotedItemId else null, file,
|
||||
val sendResult = send(toChat, content, if (index == 0) quotedItemId else null, file,
|
||||
live = if (content !is MsgContent.MCVoice && index == msgs.lastIndex) live else false,
|
||||
ttl = ttl,
|
||||
mentions = cs.memberMentions,
|
||||
@@ -941,7 +948,7 @@ fun ComposeView(
|
||||
// cleared or restored. On Main, so that these checks and changes are not interleaved with the user switching
|
||||
// chats or typing.
|
||||
withContext(Dispatchers.Main) {
|
||||
val chatIsOpen = chatModel.chatId.value == chat.id
|
||||
val chatIsOpen = composeIsForSend() && chatModel.chatId.value == chat.id
|
||||
// a live message is held in the compose state of the chat it is sent to, but only while that chat is the one open
|
||||
val liveSend = live || cs.liveMessage != null
|
||||
val sentMessageInCompose = chatIsOpen && (liveSend || composeState.value.inProgress)
|
||||
@@ -956,7 +963,7 @@ fun ComposeView(
|
||||
if (wasForwarding && chatModel.draftChatId.value == draftChatId(chat.chatInfo.id, chatScope) && forwardingFromChatId != chat.chatInfo.id && draft != null) {
|
||||
if (sentMessageInCompose) composeState.value = draft
|
||||
} else {
|
||||
clearCurrentDraft()
|
||||
clearCurrentDraft(toChat)
|
||||
// liveSend excluded: a failing keystroke send would otherwise write a draft on every attempt
|
||||
if (!sentMessageInCompose && !liveSend && lastFailed != null) {
|
||||
// the message was not sent, so it is restored in the chat it was composed in, or kept as its draft if another chat is open
|
||||
@@ -972,9 +979,11 @@ fun ComposeView(
|
||||
return sent
|
||||
}
|
||||
|
||||
fun sendMessage(ttl: Int?, sign: Boolean = false) {
|
||||
// toChat and composed are for the chat switch, which hands the compose state over to the chat it opened; passing
|
||||
// toChat without doing that leaves the sent message in the input
|
||||
fun sendMessage(ttl: Int?, sign: Boolean = false, toChat: Chat = chat, composed: ComposeState? = null) {
|
||||
withLongRunningApi(slow = 120_000) {
|
||||
sendMessageAsync(null, false, ttl, sign)
|
||||
sendMessageAsync(null, false, ttl, sign, toChat, composed ?: composeState.value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1339,10 +1348,18 @@ fun ComposeView(
|
||||
KeyChangeEffect(chatModel.chatId.value) { prevChatId ->
|
||||
val cs = composeState.value
|
||||
if (cs.liveMessage != null && (cs.message.text.isNotEmpty() || cs.liveMessage.sent)) {
|
||||
sendMessage(null)
|
||||
// the chat is already switched, so the live message goes to the chat with the id it had before the switch
|
||||
val liveMessageChat = if (prevChatId == null || prevChatId == chat.id) chat else chatsCtx.getChat(prevChatId)
|
||||
// if that chat is gone there is nowhere to send it, and it must not be sent to the chat opened instead
|
||||
// cs is captured on this thread, before the compose state is replaced below
|
||||
if (liveMessageChat != null) sendMessage(null, toChat = liveMessageChat, composed = cs) else clearState()
|
||||
resetLinkPreview()
|
||||
clearPrevDraft(prevChatId)
|
||||
deleteUnusedFiles()
|
||||
// the sent message belongs to the chat it was composed in; the chat opened next shows its own draft
|
||||
val draft = chatModel.draft.value
|
||||
composeState.value = if (draft != null && chatModel.draftChatId.value == draftChatId(chatModel.chatId.value, chatScope)) draft
|
||||
else ComposeState(useLinkPreviews = useLinkPreviews)
|
||||
} else if (cs.inProgress) {
|
||||
clearPrevDraft(prevChatId)
|
||||
// the message being sent must not be kept in the compose state, it is shared with the chat opened next;
|
||||
|
||||
Reference in New Issue
Block a user