Vitor Pamplona
2025-08-22 16:29:49 -04:00
parent 0d3c60b9c2
commit c1d8aac030
12 changed files with 71 additions and 53 deletions
@@ -212,6 +212,7 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import java.math.BigDecimal
import java.util.Locale
import kotlin.coroutines.cancellation.CancellationException
@OptIn(DelicateCoroutinesApi::class)
@Stable
@@ -1140,7 +1141,19 @@ class Account(
return event
}
suspend fun createAndSendDraft(
suspend fun createAndSendDraftIgnoreErrors(
draftTag: String,
template: EventTemplate<out Event>,
broadcast: Set<Event> = emptySet(),
) {
try {
createAndSendDraftInner(draftTag, template, broadcast)
} catch (e: Exception) {
if (e is CancellationException) throw e
}
}
suspend fun createAndSendDraftInner(
draftTag: String,
template: EventTemplate<out Event>,
broadcast: Set<Event> = emptySet(),
@@ -1164,7 +1177,15 @@ class Account(
}
}
suspend fun deleteDraft(draftTag: String) {
suspend fun deleteDraftIgnoreErrors(draftTag: String) {
try {
deleteDraftInner(draftTag)
} catch (e: Exception) {
if (e is CancellationException) throw e
}
}
suspend fun deleteDraftInner(draftTag: String) {
if (!isWriteable()) return
val extraRelays = cache.getAddressableNoteIfExists(DraftWrapEvent.createAddressTag(signer.pubKey, draftTag))?.relays ?: emptyList()
@@ -1293,7 +1314,7 @@ class Account(
}
if (draftTag != null) {
createAndSendDraft(draftTag, template)
createAndSendDraftIgnoreErrors(draftTag, template)
} else {
val it = signer.sign(template)
cache.justConsumeMyOwnEvent(it)
@@ -1338,7 +1359,7 @@ class Account(
val broadcastNotes = mapEntitiesToNotes(quotes).toSet()
if (draftTag != null) {
createAndSendDraft(draftTag, template)
createAndSendDraftIgnoreErrors(draftTag, template)
} else {
val it = signer.sign(template)
cache.justConsumeMyOwnEvent(it)
@@ -317,12 +317,14 @@ open class CommentPostViewModel :
cancel()
accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast)
accountViewModel.account.deleteDraft(version)
accountViewModel.viewModelScope.launch {
accountViewModel.account.deleteDraftIgnoreErrors(version)
}
}
suspend fun sendDraftSync() {
if (message.text.isBlank()) {
accountViewModel.account.deleteDraft(draftTag.current)
accountViewModel.account.deleteDraftIgnoreErrors(draftTag.current)
} else {
val attachments = mutableSetOf<Event>()
nip95attachments.forEach {
@@ -331,7 +333,7 @@ open class CommentPostViewModel :
}
val template = createTemplate() ?: return
accountViewModel.account.createAndSendDraft(draftTag.current, template, attachments)
accountViewModel.account.createAndSendDraftIgnoreErrors(draftTag.current, template, attachments)
}
}
@@ -45,7 +45,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Note
@@ -86,7 +85,6 @@ import com.vitorpamplona.amethyst.ui.theme.replyModifier
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@Composable
@@ -144,16 +142,16 @@ fun GenericCommentPostScreen(
onCancel = {
// uses the accountViewModel scope to avoid cancelling this
// function when the postViewModel is released
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
accountViewModel.runIOCatching {
postViewModel.sendDraftSync()
nav.popBack()
postViewModel.cancel()
}
nav.popBack()
},
onPost = {
// uses the accountViewModel scope to avoid cancelling this
// function when the postViewModel is released
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
accountViewModel.runIOCatching {
postViewModel.sendPostSync()
nav.popBack()
}
@@ -351,12 +351,14 @@ class ChatNewMessageViewModel :
val version = draftTag.current
innerSendPost(null)
cancel()
accountViewModel.account.deleteDraft(version)
accountViewModel.viewModelScope.launch {
accountViewModel.account.deleteDraftIgnoreErrors(version)
}
}
suspend fun sendDraftSync() {
if (message.text.isBlank()) {
account.deleteDraft(draftTag.current)
account.deleteDraftIgnoreErrors(draftTag.current)
} else {
innerSendPost(draftTag.current)
}
@@ -471,7 +473,7 @@ class ChatNewMessageViewModel :
}
if (draftTag != null) {
accountViewModel.account.createAndSendDraft(draftTag, template)
accountViewModel.account.createAndSendDraftIgnoreErrors(draftTag, template)
} else {
accountViewModel.account.sendNip17PrivateMessage(template)
}
@@ -488,7 +490,7 @@ class ChatNewMessageViewModel :
)
if (draftTag != null) {
accountViewModel.account.createAndSendDraft(draftTag, template)
accountViewModel.account.createAndSendDraftIgnoreErrors(draftTag, template)
} else {
accountViewModel.account.sendNip04PrivateMessage(template)
}
@@ -175,10 +175,9 @@ fun NewGroupDMScreen(
// function when the postViewModel is released
accountViewModel.runIOCatching {
postViewModel.sendDraftSync()
delay(100)
nav.popBack()
postViewModel.cancel()
}
nav.popBack()
},
onPost = {
// uses the accountViewModel scope to avoid cancelling this
@@ -188,7 +187,6 @@ fun NewGroupDMScreen(
postViewModel.room?.let {
nav.nav(routeToMessage(it, null, null, null, accountViewModel))
}
postViewModel.cancel()
}
nav.popBack()
},
@@ -276,12 +276,14 @@ open class ChannelNewMessageViewModel :
cancel()
accountViewModel.account.signAndSendPrivately(template, channelRelays)
accountViewModel.account.deleteDraft(version)
accountViewModel.viewModelScope.launch {
accountViewModel.account.deleteDraftIgnoreErrors(version)
}
}
suspend fun sendDraftSync() {
if (message.text.isBlank()) {
account.deleteDraft(draftTag.current)
account.deleteDraftIgnoreErrors(draftTag.current)
} else {
val attachments = mutableSetOf<Event>()
nip95attachments.forEach {
@@ -290,7 +292,7 @@ open class ChannelNewMessageViewModel :
}
val template = createTemplate() ?: return
accountViewModel.account.createAndSendDraft(draftTag.current, template, attachments)
accountViewModel.account.createAndSendDraftIgnoreErrors(draftTag.current, template, attachments)
}
}
@@ -142,22 +142,19 @@ fun NewProductScreen(
titleRes = R.string.new_product,
isActive = postViewModel::canPost,
onCancel = {
try {
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
postViewModel.sendDraftSync()
nav.popBack()
postViewModel.cancel()
}
} catch (e: SignerExceptions.ReadOnlyException) {
// do nothing.
// uses the accountViewModel scope to avoid cancelling this
// function when the postViewModel is released
accountViewModel.runIOCatching {
postViewModel.sendDraftSync()
postViewModel.cancel()
}
nav.popBack()
},
onPost = {
try {
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
postViewModel.sendPostSync()
nav.popBack()
postViewModel.cancel()
}
} catch (e: SignerExceptions.ReadOnlyException) {
accountViewModel.toastManager.toast(
@@ -293,24 +293,23 @@ open class NewProductViewModel :
val accountViewModel = accountViewModel ?: return
val template = createTemplate() ?: return
accountViewModel.account.signAndSendPrivatelyOrBroadcast(
template,
relayList = { relayList },
)
accountViewModel.account.deleteDraft(draftTag.current)
val version = draftTag.current
cancel()
accountViewModel.account.signAndSendPrivatelyOrBroadcast(template, relayList = { relayList })
accountViewModel.viewModelScope.launch {
accountViewModel.account.deleteDraftIgnoreErrors(version)
}
}
suspend fun sendDraftSync() {
val accountViewModel = accountViewModel ?: return
if (message.text.isBlank()) {
accountViewModel.account.deleteDraft(draftTag.current)
accountViewModel.account.deleteDraftIgnoreErrors(draftTag.current)
} else {
val template = createTemplate() ?: return
accountViewModel.account.createAndSendDraft(draftTag.current, template)
accountViewModel.account.createAndSendDraftIgnoreErrors(draftTag.current, template)
}
}
@@ -98,7 +98,6 @@ import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
@OptIn(ExperimentalMaterial3Api::class, FlowPreview::class)
@@ -174,7 +173,6 @@ private fun NewPostScreenInner(
// function when the postViewModel is released
accountViewModel.runIOCatching {
postViewModel.sendPostSync()
delay(100)
nav.popBack()
}
},
@@ -183,9 +181,9 @@ private fun NewPostScreenInner(
// function when the postViewModel is released
accountViewModel.runIOCatching {
postViewModel.sendDraftSync()
nav.popBack()
postViewModel.cancel()
}
nav.popBack()
},
)
},
@@ -483,12 +483,14 @@ open class ShortNotePostViewModel :
cancel()
accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast)
accountViewModel.account.deleteDraft(version)
accountViewModel.viewModelScope.launch {
accountViewModel.account.deleteDraftIgnoreErrors(version)
}
}
suspend fun sendDraftSync() {
if (message.text.isBlank()) {
accountViewModel.account.deleteDraft(draftTag.current)
accountViewModel.account.deleteDraftIgnoreErrors(draftTag.current)
} else {
val attachments = mutableSetOf<Event>()
nip95attachments.forEach {
@@ -497,7 +499,7 @@ open class ShortNotePostViewModel :
}
val template = createTemplate() ?: return
accountViewModel.account.createAndSendDraft(draftTag.current, template, attachments)
accountViewModel.account.createAndSendDraftIgnoreErrors(draftTag.current, template, attachments)
}
}
@@ -138,10 +138,9 @@ fun NewPublicMessageScreen(
// function when the postViewModel is released
accountViewModel.runIOCatching {
postViewModel.sendDraftSync()
delay(100)
nav.popBack()
postViewModel.cancel()
}
nav.popBack()
},
onPost = {
// uses the accountViewModel scope to avoid cancelling this
@@ -149,9 +148,7 @@ fun NewPublicMessageScreen(
accountViewModel.runIOCatching {
postViewModel.sendPostSync()
nav.popBack()
postViewModel.cancel()
}
nav.popBack()
},
)
},
@@ -321,12 +321,14 @@ class NewPublicMessageViewModel :
cancel()
accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast)
accountViewModel.account.deleteDraft(version)
accountViewModel.viewModelScope.launch {
accountViewModel.account.deleteDraftIgnoreErrors(version)
}
}
suspend fun sendDraftSync() {
if (message.text.isBlank()) {
accountViewModel.account.deleteDraft(draftTag.current)
accountViewModel.account.deleteDraftIgnoreErrors(draftTag.current)
} else {
val broadcast = mutableSetOf<Event>()
nip95attachments.forEach {
@@ -335,7 +337,7 @@ class NewPublicMessageViewModel :
}
val template = createTemplate() ?: return
accountViewModel.account.createAndSendDraft(draftTag.current, template, broadcast)
accountViewModel.account.createAndSendDraftIgnoreErrors(draftTag.current, template, broadcast)
}
}