mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-08 23:54:39 +00:00
Merge pull request #3383 from vitorpamplona/claude/amethyst-draft-signing-bug-9cx0zx
Fix draft deletion by holding strong reference to draft notes
This commit is contained in:
@@ -2045,6 +2045,14 @@ class Account(
|
||||
extraNotesToBroadcast.forEach { client.publish(it, relays) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The live [AddressableNote] backing a draft tag for this account. It is the same cached
|
||||
* note that draft events are consumed into, so its `event` tracks the draft over time. The
|
||||
* composer holds onto it (via DraftTagState) so [LocalCache]'s weak reference can't collect
|
||||
* it before a deletion needs it, which would otherwise orphan the draft on the relays.
|
||||
*/
|
||||
fun getOrCreateDraftNote(draftTag: String): AddressableNote = cache.getOrCreateAddressableNote(DraftWrapEvent.createAddress(signer.pubKey, draftTag))
|
||||
|
||||
suspend fun createAndSendDraftIgnoreErrors(
|
||||
draftTag: String,
|
||||
template: EventTemplate<out Event>,
|
||||
@@ -2081,18 +2089,25 @@ class Account(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun deleteDraftIgnoreErrors(draftTag: String) {
|
||||
suspend fun deleteDraftIgnoreErrors(draftNote: AddressableNote?) {
|
||||
try {
|
||||
deleteDraftInner(draftTag)
|
||||
deleteDraftInner(draftNote)
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun deleteDraftInner(draftTag: String) {
|
||||
suspend fun deleteDraftInner(draftNote: AddressableNote?) {
|
||||
if (!isWriteable()) return
|
||||
|
||||
val extraRelays = cache.getAddressableNoteIfExists(DraftWrapEvent.createAddressTag(signer.pubKey, draftTag))?.relays ?: emptyList()
|
||||
// Only a real, still-present draft needs a deletion signed. The note's event is null when
|
||||
// no draft was ever saved (e.g. auto-drafts disabled) and already empty once it has been
|
||||
// deleted — in both cases there is nothing to delete, so we avoid prompting the signer.
|
||||
val draftEvent = draftNote?.event as? DraftWrapEvent
|
||||
if (draftEvent == null || draftEvent.isDeleted()) return
|
||||
|
||||
val draftTag = draftNote.dTag()
|
||||
val extraRelays = draftNote.relays
|
||||
|
||||
val deletedDraft = DraftWrapEvent.createDeletedEvent(draftTag, signer)
|
||||
val deletionEvent = signer.sign(DeletionEvent.build(listOf(deletedDraft)))
|
||||
|
||||
+12
-4
@@ -39,6 +39,7 @@ import com.vitorpamplona.amethyst.commons.ui.text.insertUrlAtCursor
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.replaceCurrentWord
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.setTextAndPlaceCursorAtBeginning
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
@@ -136,11 +137,17 @@ open class CommentPostViewModel :
|
||||
IExpiration {
|
||||
val draftTag = DraftTagState()
|
||||
|
||||
// Strong reference to the live cache note for the current draft tag (derived from the
|
||||
// versions flow below), so LocalCache cannot weakly collect it before a deletion needs it.
|
||||
var draftNote: AddressableNote? = null
|
||||
private set
|
||||
|
||||
init {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
draftTag.versions.collectLatest {
|
||||
// don't save the first
|
||||
if (it > 0) {
|
||||
draftNote = account.getOrCreateDraftNote(draftTag.current)
|
||||
sendDraftSync()
|
||||
}
|
||||
}
|
||||
@@ -261,6 +268,7 @@ open class CommentPostViewModel :
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
if (oldTag != null) {
|
||||
draftTag.set(oldTag)
|
||||
draftNote = account.getOrCreateDraftNote(oldTag)
|
||||
}
|
||||
loadFromDraft(innerNote)
|
||||
}
|
||||
@@ -489,7 +497,7 @@ open class CommentPostViewModel :
|
||||
}
|
||||
}
|
||||
|
||||
val version = draftTag.current
|
||||
val draftToDelete = draftNote
|
||||
val anonymous = wantsAnonymousPost
|
||||
cancel()
|
||||
|
||||
@@ -500,14 +508,14 @@ open class CommentPostViewModel :
|
||||
}
|
||||
|
||||
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(version)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftToDelete)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendDraftSync() {
|
||||
if (message.text.toString().isBlank()) {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftTag.current)
|
||||
} else {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftNote)
|
||||
} else if (accountViewModel.settings.automaticallyCreateDrafts()) {
|
||||
val attachments = mutableSetOf<Event>()
|
||||
nip95attachments.forEach {
|
||||
attachments.add(it.first)
|
||||
|
||||
+11
-3
@@ -37,6 +37,7 @@ import com.vitorpamplona.amethyst.commons.ui.text.currentWord
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.insertUrlAtCursor
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.replaceCurrentWord
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
@@ -126,6 +127,11 @@ class ChatNewMessageViewModel :
|
||||
IExpiration {
|
||||
val draftTag = DraftTagState()
|
||||
|
||||
// Strong reference to the live cache note for the current draft tag (derived from the
|
||||
// versions flow below), so LocalCache cannot weakly collect it before a deletion needs it.
|
||||
var draftNote: AddressableNote? = null
|
||||
private set
|
||||
|
||||
lateinit var accountViewModel: AccountViewModel
|
||||
lateinit var account: Account
|
||||
|
||||
@@ -134,6 +140,7 @@ class ChatNewMessageViewModel :
|
||||
draftTag.versions.collectLatest {
|
||||
// don't save the first
|
||||
if (it > 0) {
|
||||
draftNote = account.getOrCreateDraftNote(draftTag.current)
|
||||
accountViewModel.launchSigner {
|
||||
sendDraftSync()
|
||||
}
|
||||
@@ -327,6 +334,7 @@ class ChatNewMessageViewModel :
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
if (oldTag != null) {
|
||||
draftTag.set(oldTag)
|
||||
draftNote = account.getOrCreateDraftNote(oldTag)
|
||||
}
|
||||
loadFromDraft(innerNote)
|
||||
}
|
||||
@@ -418,17 +426,17 @@ class ChatNewMessageViewModel :
|
||||
}
|
||||
|
||||
suspend fun sendPostSync() {
|
||||
val version = draftTag.current
|
||||
val draftToDelete = draftNote
|
||||
innerSendPost(null)
|
||||
cancel()
|
||||
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(version)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftToDelete)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendDraftSync() {
|
||||
if (message.text.toString().isBlank()) {
|
||||
account.deleteDraftIgnoreErrors(draftTag.current)
|
||||
account.deleteDraftIgnoreErrors(draftNote)
|
||||
} else if (accountViewModel.settings.automaticallyCreateDrafts()) {
|
||||
innerSendPost(draftTag.current)
|
||||
}
|
||||
|
||||
+11
-3
@@ -43,6 +43,7 @@ import com.vitorpamplona.amethyst.commons.ui.text.currentWord
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.insertUrlAtCursor
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.replaceCurrentWord
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
@@ -112,11 +113,17 @@ open class ChannelNewMessageViewModel :
|
||||
IExpiration {
|
||||
val draftTag = DraftTagState()
|
||||
|
||||
// Strong reference to the live cache note for the current draft tag (derived from the
|
||||
// versions flow below), so LocalCache cannot weakly collect it before a deletion needs it.
|
||||
var draftNote: AddressableNote? = null
|
||||
private set
|
||||
|
||||
init {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
draftTag.versions.collectLatest {
|
||||
// don't save the first
|
||||
if (it > 0) {
|
||||
draftNote = account.getOrCreateDraftNote(draftTag.current)
|
||||
accountViewModel.launchSigner {
|
||||
sendDraftSync()
|
||||
}
|
||||
@@ -229,6 +236,7 @@ open class ChannelNewMessageViewModel :
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
if (oldTag != null) {
|
||||
draftTag.set(oldTag)
|
||||
draftNote = account.getOrCreateDraftNote(oldTag)
|
||||
}
|
||||
loadFromDraft(innerNote)
|
||||
}
|
||||
@@ -301,20 +309,20 @@ open class ChannelNewMessageViewModel :
|
||||
val template = createTemplate() ?: return
|
||||
val channelRelays = channel?.relays() ?: emptySet()
|
||||
|
||||
val version = draftTag.current
|
||||
val draftToDelete = draftNote
|
||||
cancel()
|
||||
|
||||
accountViewModel.account.signAndSendPrivatelyOrBroadcast(template) {
|
||||
channelRelays.toList()
|
||||
}
|
||||
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(version)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftToDelete)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendDraftSync() {
|
||||
if (message.text.toString().isBlank()) {
|
||||
account.deleteDraftIgnoreErrors(draftTag.current)
|
||||
account.deleteDraftIgnoreErrors(draftNote)
|
||||
} else if (accountViewModel.settings.automaticallyCreateDrafts()) {
|
||||
val attachments = mutableSetOf<Event>()
|
||||
nip95attachments.forEach {
|
||||
|
||||
+11
-3
@@ -39,6 +39,7 @@ import com.vitorpamplona.amethyst.commons.ui.text.currentWord
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.insertUrlAtCursor
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.replaceCurrentWord
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
@@ -128,6 +129,11 @@ class LongFormPostViewModel :
|
||||
IExpiration {
|
||||
val draftTag = DraftTagState()
|
||||
|
||||
// Strong reference to the live cache note for the current draft tag (derived from the
|
||||
// versions flow below), so LocalCache cannot weakly collect it before a deletion needs it.
|
||||
var draftNote: AddressableNote? = null
|
||||
private set
|
||||
|
||||
lateinit var accountViewModel: AccountViewModel
|
||||
lateinit var account: Account
|
||||
|
||||
@@ -136,6 +142,7 @@ class LongFormPostViewModel :
|
||||
draftTag.versions.collectLatest {
|
||||
// don't save the first
|
||||
if (it > 0) {
|
||||
draftNote = account.getOrCreateDraftNote(draftTag.current)
|
||||
accountViewModel.launchSigner {
|
||||
sendDraftSync()
|
||||
}
|
||||
@@ -237,6 +244,7 @@ class LongFormPostViewModel :
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
if (oldTag != null) {
|
||||
draftTag.set(oldTag)
|
||||
draftNote = account.getOrCreateDraftNote(oldTag)
|
||||
}
|
||||
loadFromDraft(innerNote)
|
||||
}
|
||||
@@ -324,7 +332,7 @@ class LongFormPostViewModel :
|
||||
suspend fun sendPostSync() {
|
||||
val template = createTemplate() ?: return
|
||||
|
||||
val version = draftTag.current
|
||||
val draftToDelete = draftNote
|
||||
cancel()
|
||||
|
||||
if (accountViewModel.settings.useTrackedBroadcasts()) {
|
||||
@@ -342,13 +350,13 @@ class LongFormPostViewModel :
|
||||
}
|
||||
|
||||
accountViewModel.launchSigner {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(version)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftToDelete)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendDraftSync() {
|
||||
if (message.text.toString().isBlank() && title.text.isBlank()) {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftTag.current)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftNote)
|
||||
} else if (accountViewModel.settings.automaticallyCreateDrafts()) {
|
||||
val template = createTemplate() ?: return
|
||||
accountViewModel.account.createAndSendDraftIgnoreErrors(draftTag.current, template, emptySet())
|
||||
|
||||
+11
-3
@@ -38,6 +38,7 @@ import com.vitorpamplona.amethyst.commons.ui.text.currentWord
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.insertUrlAtCursor
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.replaceCurrentWord
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
@@ -114,6 +115,11 @@ open class NewProductViewModel :
|
||||
IExpiration {
|
||||
val draftTag = DraftTagState()
|
||||
|
||||
// Strong reference to the live cache note for the current draft tag (derived from the
|
||||
// versions flow below), so LocalCache cannot weakly collect it before a deletion needs it.
|
||||
var draftNote: AddressableNote? = null
|
||||
private set
|
||||
|
||||
lateinit var accountViewModel: AccountViewModel
|
||||
lateinit var account: Account
|
||||
|
||||
@@ -122,6 +128,7 @@ open class NewProductViewModel :
|
||||
draftTag.versions.collectLatest {
|
||||
// don't save the first
|
||||
if (it > 0) {
|
||||
draftNote = account.getOrCreateDraftNote(draftTag.current)
|
||||
accountViewModel.launchSigner {
|
||||
sendDraftSync()
|
||||
}
|
||||
@@ -218,6 +225,7 @@ open class NewProductViewModel :
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
if (oldTag != null) {
|
||||
draftTag.set(oldTag)
|
||||
draftNote = account.getOrCreateDraftNote(oldTag)
|
||||
}
|
||||
loadFromDraft(innerNote)
|
||||
}
|
||||
@@ -315,18 +323,18 @@ open class NewProductViewModel :
|
||||
suspend fun sendPostSync() {
|
||||
val template = createTemplate() ?: return
|
||||
|
||||
val version = draftTag.current
|
||||
val draftToDelete = draftNote
|
||||
cancel()
|
||||
|
||||
accountViewModel.account.signAndSendPrivatelyOrBroadcast(template, relayList = { relayList })
|
||||
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(version)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftToDelete)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendDraftSync() {
|
||||
if (message.text.toString().isBlank()) {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftTag.current)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftNote)
|
||||
} else if (accountViewModel.settings.automaticallyCreateDrafts()) {
|
||||
val template = createTemplate() ?: return
|
||||
accountViewModel.account.createAndSendDraftIgnoreErrors(draftTag.current, template)
|
||||
|
||||
+13
-5
@@ -41,6 +41,7 @@ import com.vitorpamplona.amethyst.commons.ui.text.insertUrlAtCursor
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.replaceCurrentWord
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.setTextAndPlaceCursorAtBeginning
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.BooleanType
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
@@ -183,6 +184,11 @@ open class ShortNotePostViewModel :
|
||||
IExpiration {
|
||||
val draftTag = DraftTagState()
|
||||
|
||||
// Strong reference to the live cache note for the current draft tag (derived from the
|
||||
// versions flow below), so LocalCache cannot weakly collect it before a deletion needs it.
|
||||
var draftNote: AddressableNote? = null
|
||||
private set
|
||||
|
||||
lateinit var accountViewModel: AccountViewModel
|
||||
lateinit var account: Account
|
||||
|
||||
@@ -191,6 +197,7 @@ open class ShortNotePostViewModel :
|
||||
draftTag.versions.collectLatest {
|
||||
// don't save the first
|
||||
if (it > 0) {
|
||||
draftNote = account.getOrCreateDraftNote(draftTag.current)
|
||||
accountViewModel.launchSigner {
|
||||
sendDraftSync()
|
||||
}
|
||||
@@ -483,6 +490,7 @@ open class ShortNotePostViewModel :
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
if (oldTag != null) {
|
||||
draftTag.set(oldTag)
|
||||
draftNote = account.getOrCreateDraftNote(oldTag)
|
||||
}
|
||||
loadFromDraft(innerNote)
|
||||
}
|
||||
@@ -889,7 +897,7 @@ open class ShortNotePostViewModel :
|
||||
}
|
||||
}
|
||||
|
||||
val version = draftTag.current
|
||||
val draftToDelete = draftNote
|
||||
val anonymous = wantsAnonymousPost
|
||||
val scheduledFor = scheduledForSec
|
||||
val privately = wantsPrivateNote
|
||||
@@ -903,7 +911,7 @@ open class ShortNotePostViewModel :
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
accountViewModel.account.sendPrivateNote(template as EventTemplate<TextNoteEvent>)
|
||||
accountViewModel.launchSigner {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(version)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftToDelete)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -935,7 +943,7 @@ open class ShortNotePostViewModel :
|
||||
),
|
||||
)
|
||||
accountViewModel.launchSigner {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(version)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftToDelete)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -961,13 +969,13 @@ open class ShortNotePostViewModel :
|
||||
}
|
||||
|
||||
accountViewModel.launchSigner {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(version)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftToDelete)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendDraftSync() {
|
||||
if (message.text.toString().isBlank()) {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftTag.current)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftNote)
|
||||
} else if (accountViewModel.settings.automaticallyCreateDrafts()) {
|
||||
val attachments = mutableSetOf<Event>()
|
||||
nip95attachments.forEach {
|
||||
|
||||
+10
-3
@@ -118,11 +118,17 @@ open class NestNewMessageViewModel :
|
||||
IExpiration {
|
||||
val draftTag = DraftTagState()
|
||||
|
||||
// Strong reference to the live cache note for the current draft tag (derived from the
|
||||
// versions flow below), so LocalCache cannot weakly collect it before a deletion needs it.
|
||||
var draftNote: AddressableNote? = null
|
||||
private set
|
||||
|
||||
init {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
draftTag.versions.collectLatest {
|
||||
// don't save the first
|
||||
if (it > 0) {
|
||||
draftNote = account.getOrCreateDraftNote(draftTag.current)
|
||||
accountViewModel.launchSigner {
|
||||
sendDraftSync()
|
||||
}
|
||||
@@ -235,6 +241,7 @@ open class NestNewMessageViewModel :
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
if (oldTag != null) {
|
||||
draftTag.set(oldTag)
|
||||
draftNote = account.getOrCreateDraftNote(oldTag)
|
||||
}
|
||||
loadFromDraft(innerNote)
|
||||
}
|
||||
@@ -303,7 +310,7 @@ open class NestNewMessageViewModel :
|
||||
suspend fun sendPostSync() {
|
||||
val template = createTemplate() ?: return
|
||||
|
||||
val version = draftTag.current
|
||||
val draftToDelete = draftNote
|
||||
cancel()
|
||||
|
||||
// Broadcast to the user's default relays — the nest has no
|
||||
@@ -312,13 +319,13 @@ open class NestNewMessageViewModel :
|
||||
// `account.signAndComputeBroadcast(...)`.
|
||||
accountViewModel.account.signAndComputeBroadcast(template)
|
||||
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(version)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftToDelete)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendDraftSync() {
|
||||
if (message.text.toString().isBlank()) {
|
||||
account.deleteDraftIgnoreErrors(draftTag.current)
|
||||
account.deleteDraftIgnoreErrors(draftNote)
|
||||
} else if (accountViewModel.settings.automaticallyCreateDrafts()) {
|
||||
val attachments = mutableSetOf<Event>()
|
||||
nip95attachments.forEach {
|
||||
|
||||
+11
-3
@@ -38,6 +38,7 @@ import com.vitorpamplona.amethyst.commons.ui.text.currentWord
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.insertUrlAtCursor
|
||||
import com.vitorpamplona.amethyst.commons.ui.text.replaceCurrentWord
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
@@ -129,6 +130,11 @@ class NewPublicMessageViewModel :
|
||||
IExpiration {
|
||||
val draftTag = DraftTagState()
|
||||
|
||||
// Strong reference to the live cache note for the current draft tag (derived from the
|
||||
// versions flow below), so LocalCache cannot weakly collect it before a deletion needs it.
|
||||
var draftNote: AddressableNote? = null
|
||||
private set
|
||||
|
||||
lateinit var accountViewModel: AccountViewModel
|
||||
lateinit var account: Account
|
||||
|
||||
@@ -137,6 +143,7 @@ class NewPublicMessageViewModel :
|
||||
draftTag.versions.collectLatest {
|
||||
// don't save the first
|
||||
if (it > 0) {
|
||||
draftNote = account.getOrCreateDraftNote(draftTag.current)
|
||||
accountViewModel.launchSigner {
|
||||
sendDraftSync()
|
||||
}
|
||||
@@ -262,6 +269,7 @@ class NewPublicMessageViewModel :
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
if (oldTag != null) {
|
||||
draftTag.set(oldTag)
|
||||
draftNote = account.getOrCreateDraftNote(oldTag)
|
||||
}
|
||||
loadFromDraft(innerNote)
|
||||
}
|
||||
@@ -340,18 +348,18 @@ class NewPublicMessageViewModel :
|
||||
}
|
||||
}
|
||||
|
||||
val version = draftTag.current
|
||||
val draftToDelete = draftNote
|
||||
cancel()
|
||||
|
||||
accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast)
|
||||
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(version)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftToDelete)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendDraftSync() {
|
||||
if (message.text.toString().isBlank()) {
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftTag.current)
|
||||
accountViewModel.account.deleteDraftIgnoreErrors(draftNote)
|
||||
} else if (accountViewModel.settings.automaticallyCreateDrafts()) {
|
||||
val broadcast = mutableSetOf<Event>()
|
||||
nip95attachments.forEach {
|
||||
|
||||
Reference in New Issue
Block a user