Cleaning up the saving draft concurrency issues.

This commit is contained in:
Vitor Pamplona
2025-08-05 11:48:02 -04:00
parent a747f25906
commit f1b15cc3c5
7 changed files with 74 additions and 94 deletions

View File

@@ -44,6 +44,7 @@ class DraftTagState {
fun rotate() { fun rotate() {
set(newTag()) set(newTag())
_versions.update { 0 }
} }
fun set(existingTag: String) { fun set(existingTag: String) {

View File

@@ -125,8 +125,8 @@ open class CommentPostViewModel :
} }
} }
var accountViewModel: AccountViewModel? = null lateinit var accountViewModel: AccountViewModel
var account: Account? = null lateinit var account: Account
var externalIdentity by mutableStateOf<ExternalId?>(null) var externalIdentity by mutableStateOf<ExternalId?>(null)
var replyingTo: Note? by mutableStateOf(null) var replyingTo: Note? by mutableStateOf(null)
@@ -175,11 +175,11 @@ open class CommentPostViewModel :
var wantsZapraiser by mutableStateOf(false) var wantsZapraiser by mutableStateOf(false)
override val zapRaiserAmount = mutableStateOf<Long?>(null) override val zapRaiserAmount = mutableStateOf<Long?>(null)
fun lnAddress(): String? = account?.userProfile()?.info?.lnAddress() fun lnAddress(): String? = account.userProfile().info?.lnAddress()
fun hasLnAddress(): Boolean = account?.userProfile()?.info?.lnAddress() != null fun hasLnAddress(): Boolean = account.userProfile().info?.lnAddress() != null
fun user(): User? = account?.userProfile() fun user(): User? = account.userProfile()
open fun init(accountVM: AccountViewModel) { open fun init(accountVM: AccountViewModel) {
this.accountViewModel = accountVM this.accountViewModel = accountVM
@@ -199,8 +199,6 @@ open class CommentPostViewModel :
} }
fun editFromDraft(draft: Note) { fun editFromDraft(draft: Note) {
val accountViewModel = accountViewModel ?: return
val noteEvent = draft.event val noteEvent = draft.event
val noteAuthor = draft.author val noteAuthor = draft.author
@@ -223,8 +221,6 @@ open class CommentPostViewModel :
} }
open fun quote(quote: Note) { open fun quote(quote: Note) {
val accountViewModel = accountViewModel ?: return
message = TextFieldValue(message.text + "\nnostr:${quote.toNEvent()}") message = TextFieldValue(message.text + "\nnostr:${quote.toNEvent()}")
quote.author?.let { quotedUser -> quote.author?.let { quotedUser ->
@@ -259,8 +255,8 @@ open class CommentPostViewModel :
val scope = draftEvent.scope() ?: return val scope = draftEvent.scope() ?: return
this.externalIdentity = scope this.externalIdentity = scope
canAddInvoice = accountViewModel?.userProfile()?.info?.lnAddress() != null canAddInvoice = accountViewModel.userProfile().info?.lnAddress() != null
canAddZapRaiser = accountViewModel?.userProfile()?.info?.lnAddress() != null canAddZapRaiser = accountViewModel.userProfile().info?.lnAddress() != null
multiOrchestrator = null multiOrchestrator = null
val localForwardZapTo = draftEvent.tags.filter { it.size > 1 && it[0] == "zap" } val localForwardZapTo = draftEvent.tags.filter { it.size > 1 && it[0] == "zap" }
@@ -316,16 +312,15 @@ open class CommentPostViewModel :
} }
} }
accountViewModel?.account?.signAndComputeBroadcast(template, extraNotesToBroadcast) val version = draftTag.current
accountViewModel?.deleteDraft(draftTag.current)
cancel() cancel()
accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast)
accountViewModel.deleteDraft(version)
} }
suspend fun sendDraftSync() { suspend fun sendDraftSync() {
val accountViewModel = accountViewModel ?: return
if (message.text.isBlank()) { if (message.text.isBlank()) {
accountViewModel.account.deleteDraft(draftTag.current) accountViewModel.account.deleteDraft(draftTag.current)
} else { } else {
@@ -333,15 +328,13 @@ open class CommentPostViewModel :
accountViewModel.account.createAndSendDraft(draftTag.current, template) accountViewModel.account.createAndSendDraft(draftTag.current, template)
nip95attachments.forEach { nip95attachments.forEach {
account?.sendToPrivateOutboxAndLocal(it.first) account.sendToPrivateOutboxAndLocal(it.first)
account?.sendToPrivateOutboxAndLocal(it.second) account.sendToPrivateOutboxAndLocal(it.second)
} }
} }
} }
private suspend fun createTemplate(): EventTemplate<out Event>? { private suspend fun createTemplate(): EventTemplate<out Event>? {
val accountViewModel = accountViewModel ?: return null
val tagger = val tagger =
NewMessageTagger( NewMessageTagger(
message = message.text, message = message.text,
@@ -351,7 +344,7 @@ open class CommentPostViewModel :
val geoHash = (location?.value as? LocationState.LocationResult.Success)?.geoHash?.toString() val geoHash = (location?.value as? LocationState.LocationResult.Success)?.geoHash?.toString()
val emojis = findEmoji(tagger.message, account?.emoji?.myEmojis?.value) val emojis = findEmoji(tagger.message, account.emoji.myEmojis.value)
val urls = findURLs(tagger.message) val urls = findURLs(tagger.message)
val usedAttachments = iMetaAttachments.filterIsIn(urls.toSet()) val usedAttachments = iMetaAttachments.filterIsIn(urls.toSet())
@@ -432,7 +425,7 @@ open class CommentPostViewModel :
context: Context, context: Context,
) = try { ) = try {
uploadUnsafe(alt, contentWarningReason, mediaQuality, server, onError, context) uploadUnsafe(alt, contentWarningReason, mediaQuality, server, onError, context)
} catch (e: SignerExceptions.ReadOnlyException) { } catch (_: SignerExceptions.ReadOnlyException) {
onError( onError(
stringRes(context, R.string.read_only_user), stringRes(context, R.string.read_only_user),
stringRes(context, R.string.login_with_a_private_key_to_be_able_to_sign_events), stringRes(context, R.string.login_with_a_private_key_to_be_able_to_sign_events),
@@ -448,7 +441,6 @@ open class CommentPostViewModel :
context: Context, context: Context,
) { ) {
viewModelScope.launch(Dispatchers.Default) { viewModelScope.launch(Dispatchers.Default) {
val myAccount = account ?: return@launch
val myMultiOrchestrator = multiOrchestrator ?: return@launch val myMultiOrchestrator = multiOrchestrator ?: return@launch
isUploadingImage = true isUploadingImage = true
@@ -459,16 +451,16 @@ open class CommentPostViewModel :
contentWarningReason, contentWarningReason,
MediaCompressor.Companion.intToCompressorQuality(mediaQuality), MediaCompressor.Companion.intToCompressorQuality(mediaQuality),
server, server,
myAccount, account,
context, context,
) )
if (results.allGood) { if (results.allGood) {
results.successful.forEach { state -> results.successful.forEach { state ->
if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) { if (state.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
val nip95 = myAccount.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason) val nip95 = account.createNip95(state.result.bytes, headerInfo = state.result.fileHeader, alt, contentWarningReason)
nip95attachments = nip95attachments + nip95 nip95attachments = nip95attachments + nip95
val note = nip95.let { it1 -> account?.consumeNip95(it1.first, it1.second) } val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
note?.let { note?.let {
message = message.insertUrlAtCursor("nostr:" + it.toNEvent()) message = message.insertUrlAtCursor("nostr:" + it.toNEvent())
@@ -520,6 +512,8 @@ open class CommentPostViewModel :
} }
open fun cancel() { open fun cancel() {
draftTag.rotate()
message = TextFieldValue("") message = TextFieldValue("")
replyingTo = null replyingTo = null
@@ -550,8 +544,6 @@ open class CommentPostViewModel :
iMetaAttachments.reset() iMetaAttachments.reset()
emojiSuggestions?.reset() emojiSuggestions?.reset()
draftTag.rotate()
} }
fun deleteMediaToUpload(selected: SelectedMediaProcessing) { fun deleteMediaToUpload(selected: SelectedMediaProcessing) {
@@ -623,8 +615,7 @@ open class CommentPostViewModel :
iMetaAttachments.downloadAndPrepare(item.link.url) { iMetaAttachments.downloadAndPrepare(item.link.url) {
Amethyst.Companion.instance.okHttpClients Amethyst.Companion.instance.okHttpClients
.getHttpClient( .getHttpClient(
accountViewModel?.account?.privacyState?.shouldUseTorForImageDownload(item.link.url) accountViewModel.account.privacyState.shouldUseTorForImageDownload(item.link.url),
?: false,
) )
} }
} }
@@ -662,7 +653,7 @@ open class CommentPostViewModel :
override fun updateZapFromText() { override fun updateZapFromText() {
viewModelScope.launch(Dispatchers.Default) { viewModelScope.launch(Dispatchers.Default) {
val tagger = val tagger =
NewMessageTagger(message.text, emptyList(), emptyList(), accountViewModel!!) NewMessageTagger(message.text, emptyList(), emptyList(), accountViewModel)
tagger.run() tagger.run()
tagger.pTags?.forEach { taggedUser -> tagger.pTags?.forEach { taggedUser ->
if (!forwardZapTo.value.items.any { it.key == taggedUser }) { if (!forwardZapTo.value.items.any { it.key == taggedUser }) {

View File

@@ -346,9 +346,10 @@ class ChatNewMessageViewModel :
} }
suspend fun sendPostSync() { suspend fun sendPostSync() {
val version = draftTag.current
innerSendPost(null) innerSendPost(null)
accountViewModel.deleteDraft(draftTag.current)
cancel() cancel()
accountViewModel.deleteDraft(version)
} }
suspend fun sendDraftSync() { suspend fun sendDraftSync() {
@@ -495,6 +496,8 @@ class ChatNewMessageViewModel :
} }
fun cancel() { fun cancel() {
draftTag.rotate()
message = TextFieldValue("") message = TextFieldValue("")
subject = TextFieldValue("") subject = TextFieldValue("")
@@ -522,8 +525,6 @@ class ChatNewMessageViewModel :
iMetaAttachments.reset() iMetaAttachments.reset()
emojiSuggestions?.reset() emojiSuggestions?.reset()
draftTag.rotate()
} }
fun addToMessage(it: String) { fun addToMessage(it: String) {

View File

@@ -48,7 +48,6 @@ import com.vitorpamplona.amethyst.service.location.LocationState
import com.vitorpamplona.amethyst.service.uploads.MediaCompressor import com.vitorpamplona.amethyst.service.uploads.MediaCompressor
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
import com.vitorpamplona.amethyst.ui.actions.mediaServers.DEFAULT_MEDIA_SERVERS
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
import com.vitorpamplona.amethyst.ui.note.creators.draftTags.DraftTagState import com.vitorpamplona.amethyst.ui.note.creators.draftTags.DraftTagState
import com.vitorpamplona.amethyst.ui.note.creators.emojiSuggestions.EmojiSuggestionState import com.vitorpamplona.amethyst.ui.note.creators.emojiSuggestions.EmojiSuggestionState
@@ -113,8 +112,8 @@ open class ChannelNewMessageViewModel :
} }
} }
var accountViewModel: AccountViewModel? = null lateinit var accountViewModel: AccountViewModel
var account: Account? = null lateinit var account: Account
var channel: Channel? = null var channel: Channel? = null
val replyTo = mutableStateOf<Note?>(null) val replyTo = mutableStateOf<Note?>(null)
@@ -153,11 +152,11 @@ open class ChannelNewMessageViewModel :
var wantsZapraiser by mutableStateOf(false) var wantsZapraiser by mutableStateOf(false)
var zapRaiserAmount by mutableStateOf<Long?>(null) var zapRaiserAmount by mutableStateOf<Long?>(null)
fun lnAddress(): String? = account?.userProfile()?.info?.lnAddress() fun lnAddress(): String? = account.userProfile().info?.lnAddress()
fun hasLnAddress(): Boolean = account?.userProfile()?.info?.lnAddress() != null fun hasLnAddress(): Boolean = account.userProfile().info?.lnAddress() != null
fun user(): User? = account?.userProfile() fun user(): User? = account.userProfile()
open fun init(accountVM: AccountViewModel) { open fun init(accountVM: AccountViewModel) {
this.accountViewModel = accountVM this.accountViewModel = accountVM
@@ -171,10 +170,7 @@ open class ChannelNewMessageViewModel :
this.emojiSuggestions?.reset() this.emojiSuggestions?.reset()
this.emojiSuggestions = EmojiSuggestionState(accountVM) this.emojiSuggestions = EmojiSuggestionState(accountVM)
this.uploadState = this.uploadState = ChatFileUploadState(account.settings.defaultFileServer)
ChatFileUploadState(
account?.settings?.defaultFileServer ?: DEFAULT_MEDIA_SERVERS[0],
)
} }
open fun load(channel: Channel) { open fun load(channel: Channel) {
@@ -197,7 +193,7 @@ open class ChannelNewMessageViewModel :
if (noteEvent is DraftEvent && noteAuthor != null) { if (noteEvent is DraftEvent && noteAuthor != null) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
accountViewModel?.createTempDraftNote(noteEvent)?.let { innerNote -> accountViewModel.createTempDraftNote(noteEvent)?.let { innerNote ->
val oldTag = (draft.event as? AddressableEvent)?.dTag() val oldTag = (draft.event as? AddressableEvent)?.dTag()
if (oldTag != null) { if (oldTag != null) {
draftTag.set(oldTag) draftTag.set(oldTag)
@@ -243,14 +239,14 @@ open class ChannelNewMessageViewModel :
if (draftEvent as? ChannelMessageEvent != null) { if (draftEvent as? ChannelMessageEvent != null) {
val replyId = draftEvent.reply()?.eventId val replyId = draftEvent.reply()?.eventId
if (replyId != null) { if (replyId != null) {
accountViewModel?.checkGetOrCreateNote(replyId) { accountViewModel.checkGetOrCreateNote(replyId) {
replyTo.value = it replyTo.value = it
} }
} }
} else if (draftEvent as? LiveActivitiesChatMessageEvent != null) { } else if (draftEvent as? LiveActivitiesChatMessageEvent != null) {
val replyId = draftEvent.reply()?.eventId val replyId = draftEvent.reply()?.eventId
if (replyId != null) { if (replyId != null) {
accountViewModel?.checkGetOrCreateNote(replyId) { accountViewModel.checkGetOrCreateNote(replyId) {
replyTo.value = it replyTo.value = it
} }
} }
@@ -274,18 +270,16 @@ open class ChannelNewMessageViewModel :
val template = createTemplate() ?: return val template = createTemplate() ?: return
val channelRelays = channel?.relays() ?: emptySet() val channelRelays = channel?.relays() ?: emptySet()
accountViewModel?.account?.signAndSendPrivately(template, channelRelays) val version = draftTag.current
accountViewModel?.deleteDraft(draftTag.current)
cancel() cancel()
accountViewModel.account.signAndSendPrivately(template, channelRelays)
accountViewModel.deleteDraft(version)
} }
suspend fun sendDraftSync() { suspend fun sendDraftSync() {
val accountViewModel = accountViewModel ?: return
if (message.text.isBlank()) { if (message.text.isBlank()) {
account?.deleteDraft(draftTag.current) account.deleteDraft(draftTag.current)
} else { } else {
val template = createTemplate() ?: return val template = createTemplate() ?: return
accountViewModel.account.createAndSendDraft(draftTag.current, template) accountViewModel.account.createAndSendDraft(draftTag.current, template)
@@ -302,7 +296,7 @@ open class ChannelNewMessageViewModel :
onceUploaded: () -> Unit, onceUploaded: () -> Unit,
) = try { ) = try {
uploadUnsafe(onError, context, onceUploaded) uploadUnsafe(onError, context, onceUploaded)
} catch (e: SignerExceptions.ReadOnlyException) { } catch (_: SignerExceptions.ReadOnlyException) {
onError( onError(
stringRes(context, R.string.read_only_user), stringRes(context, R.string.read_only_user),
stringRes(context, R.string.login_with_a_private_key_to_be_able_to_sign_events), stringRes(context, R.string.login_with_a_private_key_to_be_able_to_sign_events),
@@ -315,7 +309,6 @@ open class ChannelNewMessageViewModel :
onceUploaded: () -> Unit, onceUploaded: () -> Unit,
) { ) {
viewModelScope.launch(Dispatchers.Default) { viewModelScope.launch(Dispatchers.Default) {
val myAccount = account ?: return@launch
val uploadState = uploadState ?: return@launch val uploadState = uploadState ?: return@launch
val myMultiOrchestrator = uploadState.multiOrchestrator ?: return@launch val myMultiOrchestrator = uploadState.multiOrchestrator ?: return@launch
@@ -328,26 +321,26 @@ open class ChannelNewMessageViewModel :
uploadState.contentWarningReason, uploadState.contentWarningReason,
MediaCompressor.intToCompressorQuality(uploadState.mediaQualitySlider), MediaCompressor.intToCompressorQuality(uploadState.mediaQualitySlider),
uploadState.selectedServer, uploadState.selectedServer,
myAccount, account,
context, context,
) )
if (results.allGood) { if (results.allGood) {
results.successful.forEach { results.successful.forEach { upload ->
if (it.result is UploadOrchestrator.OrchestratorResult.NIP95Result) { if (upload.result is UploadOrchestrator.OrchestratorResult.NIP95Result) {
val nip95 = myAccount.createNip95(it.result.bytes, headerInfo = it.result.fileHeader, uploadState.caption, uploadState.contentWarningReason) val nip95 = account.createNip95(upload.result.bytes, headerInfo = upload.result.fileHeader, uploadState.caption, uploadState.contentWarningReason)
nip95attachments = nip95attachments + nip95 nip95attachments = nip95attachments + nip95
val note = nip95.let { it1 -> account?.consumeNip95(it1.first, it1.second) } val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) }
note?.let { note?.let {
message = message.insertUrlAtCursor(it.toNostrUri()) message = message.insertUrlAtCursor(it.toNostrUri())
} }
urlPreview = findUrlInMessage() urlPreview = findUrlInMessage()
} else if (it.result is UploadOrchestrator.OrchestratorResult.ServerResult) { } else if (upload.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
iMetaAttachments.add(it.result, uploadState.caption, uploadState.contentWarningReason) iMetaAttachments.add(upload.result, uploadState.caption, uploadState.contentWarningReason)
message = message.insertUrlAtCursor(it.result.url) message = message.insertUrlAtCursor(upload.result.url)
urlPreview = findUrlInMessage() urlPreview = findUrlInMessage()
} }
} }
@@ -367,8 +360,6 @@ open class ChannelNewMessageViewModel :
private suspend fun createTemplate(): EventTemplate<out Event>? { private suspend fun createTemplate(): EventTemplate<out Event>? {
val channel = channel ?: return null val channel = channel ?: return null
val accountViewModel = accountViewModel ?: return null
val tagger = val tagger =
NewMessageTagger( NewMessageTagger(
message = message.text, message = message.text,
@@ -442,7 +433,7 @@ open class ChannelNewMessageViewModel :
imetas(usedAttachments) imetas(usedAttachments)
} }
} else if (activity != null) { } else if (activity != null) {
val hint = EventHintBundle(activity, channelRelays.firstOrNull() ?: replyingToEvent?.relay) val hint = EventHintBundle(activity, channelRelays.firstOrNull())
LiveActivitiesChatMessageEvent.message(tagger.message, hint) { LiveActivitiesChatMessageEvent.message(tagger.message, hint) {
hashtags(findHashtags(tagger.message)) hashtags(findHashtags(tagger.message))
@@ -491,6 +482,8 @@ open class ChannelNewMessageViewModel :
} }
open fun cancel() { open fun cancel() {
draftTag.rotate()
message = TextFieldValue("") message = TextFieldValue("")
replyTo.value = null replyTo.value = null
@@ -515,14 +508,6 @@ open class ChannelNewMessageViewModel :
iMetaAttachments.reset() iMetaAttachments.reset()
emojiSuggestions?.reset() emojiSuggestions?.reset()
draftTag.rotate()
}
fun deleteDraft() {
viewModelScope.launch(Dispatchers.IO) {
accountViewModel?.deleteDraft(draftTag.current)
}
} }
open fun findUrlInMessage(): String? = RichTextParser().parseValidUrls(message.text).firstOrNull() open fun findUrlInMessage(): String? = RichTextParser().parseValidUrls(message.text).firstOrNull()
@@ -586,10 +571,11 @@ open class ChannelNewMessageViewModel :
val wordToInsert = item.link.url + " " val wordToInsert = item.link.url + " "
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
iMetaAttachments.downloadAndPrepare( iMetaAttachments.downloadAndPrepare(item.link.url) {
item.link.url, Amethyst.instance.okHttpClients.getHttpClient(
{ Amethyst.instance.okHttpClients.getHttpClient(accountViewModel?.account?.privacyState?.shouldUseTorForImageDownload(item.link.url) ?: false) }, accountViewModel.account.privacyState.shouldUseTorForImageDownload(item.link.url),
) )
}
} }
message = message.replaceCurrentWord(wordToInsert) message = message.replaceCurrentWord(wordToInsert)
@@ -636,7 +622,7 @@ open class ChannelNewMessageViewModel :
fun updateZapFromText() { fun updateZapFromText() {
viewModelScope.launch(Dispatchers.Default) { viewModelScope.launch(Dispatchers.Default) {
val tagger = NewMessageTagger(message.text, emptyList(), emptyList(), accountViewModel!!) val tagger = NewMessageTagger(message.text, emptyList(), emptyList(), accountViewModel)
tagger.run() tagger.run()
tagger.pTags?.forEach { taggedUser -> tagger.pTags?.forEach { taggedUser ->
if (!forwardZapTo.items.any { it.key == taggedUser }) { if (!forwardZapTo.items.any { it.key == taggedUser }) {

View File

@@ -431,6 +431,8 @@ open class NewProductViewModel :
} }
open fun cancel() { open fun cancel() {
draftTag.rotate()
message = TextFieldValue("") message = TextFieldValue("")
multiOrchestrator = null multiOrchestrator = null
@@ -465,8 +467,6 @@ open class NewProductViewModel :
emojiSuggestions?.reset() emojiSuggestions?.reset()
reloadRelaySet() reloadRelaySet()
draftTag.rotate()
} }
fun reloadRelaySet() { fun reloadRelaySet() {

View File

@@ -475,11 +475,11 @@ open class ShortNotePostViewModel :
} }
} }
accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast) val version = draftTag.current
accountViewModel.deleteDraft(draftTag.current)
cancel() cancel()
accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast)
accountViewModel.deleteDraft(version)
} }
suspend fun sendDraftSync() { suspend fun sendDraftSync() {
@@ -586,7 +586,7 @@ open class ShortNotePostViewModel :
context: Context, context: Context,
) = try { ) = try {
uploadUnsafe(alt, contentWarningReason, mediaQuality, server, onError, context) uploadUnsafe(alt, contentWarningReason, mediaQuality, server, onError, context)
} catch (e: SignerExceptions.ReadOnlyException) { } catch (_: SignerExceptions.ReadOnlyException) {
onError( onError(
stringRes(context, R.string.read_only_user), stringRes(context, R.string.read_only_user),
stringRes(context, R.string.login_with_a_private_key_to_be_able_to_sign_events), stringRes(context, R.string.login_with_a_private_key_to_be_able_to_sign_events),
@@ -664,6 +664,8 @@ open class ShortNotePostViewModel :
} }
open fun cancel() { open fun cancel() {
draftTag.rotate()
message = TextFieldValue("") message = TextFieldValue("")
forkedFromNote = null forkedFromNote = null
@@ -701,8 +703,6 @@ open class ShortNotePostViewModel :
iMetaAttachments.reset() iMetaAttachments.reset()
emojiSuggestions?.reset() emojiSuggestions?.reset()
draftTag.rotate()
} }
fun deleteMediaToUpload(selected: SelectedMediaProcessing) { fun deleteMediaToUpload(selected: SelectedMediaProcessing) {

View File

@@ -309,10 +309,11 @@ class NewPublicMessageViewModel :
} }
} }
accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast) val version = draftTag.current
accountViewModel.deleteDraft(draftTag.current)
cancel() cancel()
accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast)
accountViewModel.deleteDraft(version)
} }
suspend fun sendDraftSync() { suspend fun sendDraftSync() {
@@ -467,6 +468,8 @@ class NewPublicMessageViewModel :
} }
fun cancel() { fun cancel() {
draftTag.rotate()
toUsers = TextFieldValue("") toUsers = TextFieldValue("")
message = TextFieldValue("") message = TextFieldValue("")
multiOrchestrator = null multiOrchestrator = null
@@ -491,8 +494,6 @@ class NewPublicMessageViewModel :
iMetaAttachments.reset() iMetaAttachments.reset()
emojiSuggestions?.reset() emojiSuggestions?.reset()
draftTag.rotate()
} }
fun deleteMediaToUpload(selected: SelectedMediaProcessing) { fun deleteMediaToUpload(selected: SelectedMediaProcessing) {