diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/draftTags/DraftTagState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/draftTags/DraftTagState.kt index 45da21281..363f34e36 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/draftTags/DraftTagState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/draftTags/DraftTagState.kt @@ -44,6 +44,7 @@ class DraftTagState { fun rotate() { set(newTag()) + _versions.update { 0 } } fun set(existingTag: String) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/CommentPostViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/CommentPostViewModel.kt index 61cf44742..4a5f30a01 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/CommentPostViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/nip22Comments/CommentPostViewModel.kt @@ -125,8 +125,8 @@ open class CommentPostViewModel : } } - var accountViewModel: AccountViewModel? = null - var account: Account? = null + lateinit var accountViewModel: AccountViewModel + lateinit var account: Account var externalIdentity by mutableStateOf(null) var replyingTo: Note? by mutableStateOf(null) @@ -175,11 +175,11 @@ open class CommentPostViewModel : var wantsZapraiser by mutableStateOf(false) override val zapRaiserAmount = mutableStateOf(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) { this.accountViewModel = accountVM @@ -199,8 +199,6 @@ open class CommentPostViewModel : } fun editFromDraft(draft: Note) { - val accountViewModel = accountViewModel ?: return - val noteEvent = draft.event val noteAuthor = draft.author @@ -223,8 +221,6 @@ open class CommentPostViewModel : } open fun quote(quote: Note) { - val accountViewModel = accountViewModel ?: return - message = TextFieldValue(message.text + "\nnostr:${quote.toNEvent()}") quote.author?.let { quotedUser -> @@ -259,8 +255,8 @@ open class CommentPostViewModel : val scope = draftEvent.scope() ?: return this.externalIdentity = scope - canAddInvoice = accountViewModel?.userProfile()?.info?.lnAddress() != null - canAddZapRaiser = accountViewModel?.userProfile()?.info?.lnAddress() != null + canAddInvoice = accountViewModel.userProfile().info?.lnAddress() != null + canAddZapRaiser = accountViewModel.userProfile().info?.lnAddress() != null multiOrchestrator = null val localForwardZapTo = draftEvent.tags.filter { it.size > 1 && it[0] == "zap" } @@ -316,16 +312,15 @@ open class CommentPostViewModel : } } - accountViewModel?.account?.signAndComputeBroadcast(template, extraNotesToBroadcast) - - accountViewModel?.deleteDraft(draftTag.current) + val version = draftTag.current cancel() + + accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast) + accountViewModel.deleteDraft(version) } suspend fun sendDraftSync() { - val accountViewModel = accountViewModel ?: return - if (message.text.isBlank()) { accountViewModel.account.deleteDraft(draftTag.current) } else { @@ -333,15 +328,13 @@ open class CommentPostViewModel : accountViewModel.account.createAndSendDraft(draftTag.current, template) nip95attachments.forEach { - account?.sendToPrivateOutboxAndLocal(it.first) - account?.sendToPrivateOutboxAndLocal(it.second) + account.sendToPrivateOutboxAndLocal(it.first) + account.sendToPrivateOutboxAndLocal(it.second) } } } private suspend fun createTemplate(): EventTemplate? { - val accountViewModel = accountViewModel ?: return null - val tagger = NewMessageTagger( message = message.text, @@ -351,7 +344,7 @@ open class CommentPostViewModel : 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 usedAttachments = iMetaAttachments.filterIsIn(urls.toSet()) @@ -432,7 +425,7 @@ open class CommentPostViewModel : context: Context, ) = try { uploadUnsafe(alt, contentWarningReason, mediaQuality, server, onError, context) - } catch (e: SignerExceptions.ReadOnlyException) { + } catch (_: SignerExceptions.ReadOnlyException) { onError( stringRes(context, R.string.read_only_user), stringRes(context, R.string.login_with_a_private_key_to_be_able_to_sign_events), @@ -448,7 +441,6 @@ open class CommentPostViewModel : context: Context, ) { viewModelScope.launch(Dispatchers.Default) { - val myAccount = account ?: return@launch val myMultiOrchestrator = multiOrchestrator ?: return@launch isUploadingImage = true @@ -459,16 +451,16 @@ open class CommentPostViewModel : contentWarningReason, MediaCompressor.Companion.intToCompressorQuality(mediaQuality), server, - myAccount, + account, context, ) if (results.allGood) { results.successful.forEach { state -> 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 - val note = nip95.let { it1 -> account?.consumeNip95(it1.first, it1.second) } + val note = nip95.let { it1 -> account.consumeNip95(it1.first, it1.second) } note?.let { message = message.insertUrlAtCursor("nostr:" + it.toNEvent()) @@ -520,6 +512,8 @@ open class CommentPostViewModel : } open fun cancel() { + draftTag.rotate() + message = TextFieldValue("") replyingTo = null @@ -550,8 +544,6 @@ open class CommentPostViewModel : iMetaAttachments.reset() emojiSuggestions?.reset() - - draftTag.rotate() } fun deleteMediaToUpload(selected: SelectedMediaProcessing) { @@ -623,8 +615,7 @@ open class CommentPostViewModel : iMetaAttachments.downloadAndPrepare(item.link.url) { Amethyst.Companion.instance.okHttpClients .getHttpClient( - accountViewModel?.account?.privacyState?.shouldUseTorForImageDownload(item.link.url) - ?: false, + accountViewModel.account.privacyState.shouldUseTorForImageDownload(item.link.url), ) } } @@ -662,7 +653,7 @@ open class CommentPostViewModel : override fun updateZapFromText() { viewModelScope.launch(Dispatchers.Default) { val tagger = - NewMessageTagger(message.text, emptyList(), emptyList(), accountViewModel!!) + NewMessageTagger(message.text, emptyList(), emptyList(), accountViewModel) tagger.run() tagger.pTags?.forEach { taggedUser -> if (!forwardZapTo.value.items.any { it.key == taggedUser }) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/ChatNewMessageViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/ChatNewMessageViewModel.kt index 6d713786e..91e17d0f4 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/ChatNewMessageViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/privateDM/send/ChatNewMessageViewModel.kt @@ -346,9 +346,10 @@ class ChatNewMessageViewModel : } suspend fun sendPostSync() { + val version = draftTag.current innerSendPost(null) - accountViewModel.deleteDraft(draftTag.current) cancel() + accountViewModel.deleteDraft(version) } suspend fun sendDraftSync() { @@ -495,6 +496,8 @@ class ChatNewMessageViewModel : } fun cancel() { + draftTag.rotate() + message = TextFieldValue("") subject = TextFieldValue("") @@ -522,8 +525,6 @@ class ChatNewMessageViewModel : iMetaAttachments.reset() emojiSuggestions?.reset() - - draftTag.rotate() } fun addToMessage(it: String) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt index 013260725..c91abed59 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/send/ChannelNewMessageViewModel.kt @@ -48,7 +48,6 @@ import com.vitorpamplona.amethyst.service.location.LocationState import com.vitorpamplona.amethyst.service.uploads.MediaCompressor import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator 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.note.creators.draftTags.DraftTagState import com.vitorpamplona.amethyst.ui.note.creators.emojiSuggestions.EmojiSuggestionState @@ -113,8 +112,8 @@ open class ChannelNewMessageViewModel : } } - var accountViewModel: AccountViewModel? = null - var account: Account? = null + lateinit var accountViewModel: AccountViewModel + lateinit var account: Account var channel: Channel? = null val replyTo = mutableStateOf(null) @@ -153,11 +152,11 @@ open class ChannelNewMessageViewModel : var wantsZapraiser by mutableStateOf(false) var zapRaiserAmount by mutableStateOf(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) { this.accountViewModel = accountVM @@ -171,10 +170,7 @@ open class ChannelNewMessageViewModel : this.emojiSuggestions?.reset() this.emojiSuggestions = EmojiSuggestionState(accountVM) - this.uploadState = - ChatFileUploadState( - account?.settings?.defaultFileServer ?: DEFAULT_MEDIA_SERVERS[0], - ) + this.uploadState = ChatFileUploadState(account.settings.defaultFileServer) } open fun load(channel: Channel) { @@ -197,7 +193,7 @@ open class ChannelNewMessageViewModel : if (noteEvent is DraftEvent && noteAuthor != null) { viewModelScope.launch(Dispatchers.IO) { - accountViewModel?.createTempDraftNote(noteEvent)?.let { innerNote -> + accountViewModel.createTempDraftNote(noteEvent)?.let { innerNote -> val oldTag = (draft.event as? AddressableEvent)?.dTag() if (oldTag != null) { draftTag.set(oldTag) @@ -243,14 +239,14 @@ open class ChannelNewMessageViewModel : if (draftEvent as? ChannelMessageEvent != null) { val replyId = draftEvent.reply()?.eventId if (replyId != null) { - accountViewModel?.checkGetOrCreateNote(replyId) { + accountViewModel.checkGetOrCreateNote(replyId) { replyTo.value = it } } } else if (draftEvent as? LiveActivitiesChatMessageEvent != null) { val replyId = draftEvent.reply()?.eventId if (replyId != null) { - accountViewModel?.checkGetOrCreateNote(replyId) { + accountViewModel.checkGetOrCreateNote(replyId) { replyTo.value = it } } @@ -274,18 +270,16 @@ open class ChannelNewMessageViewModel : val template = createTemplate() ?: return val channelRelays = channel?.relays() ?: emptySet() - accountViewModel?.account?.signAndSendPrivately(template, channelRelays) - - accountViewModel?.deleteDraft(draftTag.current) - + val version = draftTag.current cancel() + + accountViewModel.account.signAndSendPrivately(template, channelRelays) + accountViewModel.deleteDraft(version) } suspend fun sendDraftSync() { - val accountViewModel = accountViewModel ?: return - if (message.text.isBlank()) { - account?.deleteDraft(draftTag.current) + account.deleteDraft(draftTag.current) } else { val template = createTemplate() ?: return accountViewModel.account.createAndSendDraft(draftTag.current, template) @@ -302,7 +296,7 @@ open class ChannelNewMessageViewModel : onceUploaded: () -> Unit, ) = try { uploadUnsafe(onError, context, onceUploaded) - } catch (e: SignerExceptions.ReadOnlyException) { + } catch (_: SignerExceptions.ReadOnlyException) { onError( stringRes(context, R.string.read_only_user), stringRes(context, R.string.login_with_a_private_key_to_be_able_to_sign_events), @@ -315,7 +309,6 @@ open class ChannelNewMessageViewModel : onceUploaded: () -> Unit, ) { viewModelScope.launch(Dispatchers.Default) { - val myAccount = account ?: return@launch val uploadState = uploadState ?: return@launch val myMultiOrchestrator = uploadState.multiOrchestrator ?: return@launch @@ -328,26 +321,26 @@ open class ChannelNewMessageViewModel : uploadState.contentWarningReason, MediaCompressor.intToCompressorQuality(uploadState.mediaQualitySlider), uploadState.selectedServer, - myAccount, + account, context, ) if (results.allGood) { - results.successful.forEach { - if (it.result is UploadOrchestrator.OrchestratorResult.NIP95Result) { - val nip95 = myAccount.createNip95(it.result.bytes, headerInfo = it.result.fileHeader, uploadState.caption, uploadState.contentWarningReason) + results.successful.forEach { upload -> + if (upload.result is UploadOrchestrator.OrchestratorResult.NIP95Result) { + val nip95 = account.createNip95(upload.result.bytes, headerInfo = upload.result.fileHeader, uploadState.caption, uploadState.contentWarningReason) 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 { message = message.insertUrlAtCursor(it.toNostrUri()) } urlPreview = findUrlInMessage() - } else if (it.result is UploadOrchestrator.OrchestratorResult.ServerResult) { - iMetaAttachments.add(it.result, uploadState.caption, uploadState.contentWarningReason) + } else if (upload.result is UploadOrchestrator.OrchestratorResult.ServerResult) { + iMetaAttachments.add(upload.result, uploadState.caption, uploadState.contentWarningReason) - message = message.insertUrlAtCursor(it.result.url) + message = message.insertUrlAtCursor(upload.result.url) urlPreview = findUrlInMessage() } } @@ -367,8 +360,6 @@ open class ChannelNewMessageViewModel : private suspend fun createTemplate(): EventTemplate? { val channel = channel ?: return null - val accountViewModel = accountViewModel ?: return null - val tagger = NewMessageTagger( message = message.text, @@ -442,7 +433,7 @@ open class ChannelNewMessageViewModel : imetas(usedAttachments) } } else if (activity != null) { - val hint = EventHintBundle(activity, channelRelays.firstOrNull() ?: replyingToEvent?.relay) + val hint = EventHintBundle(activity, channelRelays.firstOrNull()) LiveActivitiesChatMessageEvent.message(tagger.message, hint) { hashtags(findHashtags(tagger.message)) @@ -491,6 +482,8 @@ open class ChannelNewMessageViewModel : } open fun cancel() { + draftTag.rotate() + message = TextFieldValue("") replyTo.value = null @@ -515,14 +508,6 @@ open class ChannelNewMessageViewModel : iMetaAttachments.reset() emojiSuggestions?.reset() - - draftTag.rotate() - } - - fun deleteDraft() { - viewModelScope.launch(Dispatchers.IO) { - accountViewModel?.deleteDraft(draftTag.current) - } } open fun findUrlInMessage(): String? = RichTextParser().parseValidUrls(message.text).firstOrNull() @@ -586,10 +571,11 @@ open class ChannelNewMessageViewModel : val wordToInsert = item.link.url + " " viewModelScope.launch(Dispatchers.IO) { - iMetaAttachments.downloadAndPrepare( - item.link.url, - { Amethyst.instance.okHttpClients.getHttpClient(accountViewModel?.account?.privacyState?.shouldUseTorForImageDownload(item.link.url) ?: false) }, - ) + iMetaAttachments.downloadAndPrepare(item.link.url) { + Amethyst.instance.okHttpClients.getHttpClient( + accountViewModel.account.privacyState.shouldUseTorForImageDownload(item.link.url), + ) + } } message = message.replaceCurrentWord(wordToInsert) @@ -636,7 +622,7 @@ open class ChannelNewMessageViewModel : fun updateZapFromText() { viewModelScope.launch(Dispatchers.Default) { - val tagger = NewMessageTagger(message.text, emptyList(), emptyList(), accountViewModel!!) + val tagger = NewMessageTagger(message.text, emptyList(), emptyList(), accountViewModel) tagger.run() tagger.pTags?.forEach { taggedUser -> if (!forwardZapTo.items.any { it.key == taggedUser }) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductViewModel.kt index 33b35373a..64b834bd7 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/NewProductViewModel.kt @@ -431,6 +431,8 @@ open class NewProductViewModel : } open fun cancel() { + draftTag.rotate() + message = TextFieldValue("") multiOrchestrator = null @@ -465,8 +467,6 @@ open class NewProductViewModel : emojiSuggestions?.reset() reloadRelaySet() - - draftTag.rotate() } fun reloadRelaySet() { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt index 5e1366a3b..19966349e 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/ShortNotePostViewModel.kt @@ -475,11 +475,11 @@ open class ShortNotePostViewModel : } } - accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast) - - accountViewModel.deleteDraft(draftTag.current) - + val version = draftTag.current cancel() + + accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast) + accountViewModel.deleteDraft(version) } suspend fun sendDraftSync() { @@ -586,7 +586,7 @@ open class ShortNotePostViewModel : context: Context, ) = try { uploadUnsafe(alt, contentWarningReason, mediaQuality, server, onError, context) - } catch (e: SignerExceptions.ReadOnlyException) { + } catch (_: SignerExceptions.ReadOnlyException) { onError( stringRes(context, R.string.read_only_user), 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() { + draftTag.rotate() + message = TextFieldValue("") forkedFromNote = null @@ -701,8 +703,6 @@ open class ShortNotePostViewModel : iMetaAttachments.reset() emojiSuggestions?.reset() - - draftTag.rotate() } fun deleteMediaToUpload(selected: SelectedMediaProcessing) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt index f42093791..948affe69 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/publicMessages/NewPublicMessageViewModel.kt @@ -309,10 +309,11 @@ class NewPublicMessageViewModel : } } - accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast) - accountViewModel.deleteDraft(draftTag.current) - + val version = draftTag.current cancel() + + accountViewModel.account.signAndComputeBroadcast(template, extraNotesToBroadcast) + accountViewModel.deleteDraft(version) } suspend fun sendDraftSync() { @@ -467,6 +468,8 @@ class NewPublicMessageViewModel : } fun cancel() { + draftTag.rotate() + toUsers = TextFieldValue("") message = TextFieldValue("") multiOrchestrator = null @@ -491,8 +494,6 @@ class NewPublicMessageViewModel : iMetaAttachments.reset() emojiSuggestions?.reset() - - draftTag.rotate() } fun deleteMediaToUpload(selected: SelectedMediaProcessing) {