Draft event refactoring
This commit is contained in:
@@ -31,6 +31,7 @@ import com.vitorpamplona.amethyst.model.emphChat.EphemeralChatChannel
|
||||
import com.vitorpamplona.amethyst.model.emphChat.EphemeralChatListDecryptionCache
|
||||
import com.vitorpamplona.amethyst.model.emphChat.EphemeralChatListState
|
||||
import com.vitorpamplona.amethyst.model.localRelays.LocalRelayListState
|
||||
import com.vitorpamplona.amethyst.model.nip01UserMetadata.AccountHomeRelayState
|
||||
import com.vitorpamplona.amethyst.model.nip01UserMetadata.AccountOutboxRelayState
|
||||
import com.vitorpamplona.amethyst.model.nip01UserMetadata.NotificationInboxRelayState
|
||||
import com.vitorpamplona.amethyst.model.nip01UserMetadata.UserMetadataState
|
||||
@@ -130,16 +131,13 @@ import com.vitorpamplona.quartz.nip01Core.signers.EventTemplate
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.addressables.taggedAddresses
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.taggedEventIds
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohash
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohashes
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.hasAnyTaggedUser
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUserIds
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.references.references
|
||||
import com.vitorpamplona.quartz.nip04Dm.PrivateDMCache
|
||||
import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent
|
||||
import com.vitorpamplona.quartz.nip04Dm.messages.reply
|
||||
import com.vitorpamplona.quartz.nip09Deletions.DeletionEvent
|
||||
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip10Notes.content.findHashtags
|
||||
@@ -160,12 +158,10 @@ import com.vitorpamplona.quartz.nip19Bech32.entities.NProfile
|
||||
import com.vitorpamplona.quartz.nip19Bech32.entities.NPub
|
||||
import com.vitorpamplona.quartz.nip19Bech32.entities.NRelay
|
||||
import com.vitorpamplona.quartz.nip19Bech32.entities.NSec
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.EmojiUrlTag
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.emojis
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.contentWarning
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftBuilder
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEventCache
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Response
|
||||
@@ -217,6 +213,7 @@ import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import java.math.BigDecimal
|
||||
import java.util.Locale
|
||||
import kotlin.collections.forEach
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
@Stable
|
||||
@@ -297,6 +294,7 @@ class Account(
|
||||
val serverLists = MergedServerListState(fileStorageServers, blossomServers, scope)
|
||||
|
||||
// Relay settings
|
||||
val homeRelays = AccountHomeRelayState(nip65RelayList, privateStorageRelayList, localRelayList, scope)
|
||||
val outboxRelays = AccountOutboxRelayState(nip65RelayList, privateStorageRelayList, localRelayList, broadcastRelayList, scope)
|
||||
val dmRelays = DmInboxRelayState(dmRelayList, nip65RelayList, privateStorageRelayList, localRelayList, scope)
|
||||
val notificationRelays = NotificationInboxRelayState(nip65RelayList, localRelayList, scope)
|
||||
@@ -1141,103 +1139,42 @@ class Account(
|
||||
return event
|
||||
}
|
||||
|
||||
suspend fun <T : Event> signAndSend(
|
||||
draftTag: String?,
|
||||
template: EventTemplate<T>,
|
||||
relayList: Set<NormalizedRelayUrl>,
|
||||
broadcastNotes: List<Entity>,
|
||||
) = signAndSend(draftTag, template, relayList, mapEntitiesToNotes(broadcastNotes).toSet())
|
||||
|
||||
suspend fun <T : Event> signAndSend(
|
||||
draftTag: String?,
|
||||
template: EventTemplate<T>,
|
||||
relayList: Set<NormalizedRelayUrl>,
|
||||
broadcastNotes: Set<Note>,
|
||||
) {
|
||||
if (draftTag != null) {
|
||||
val rumor = RumorAssembler.assembleRumor(signer.pubKey, template)
|
||||
val draftEvent =
|
||||
DraftEvent.create(
|
||||
dTag = draftTag,
|
||||
innerEvent = rumor,
|
||||
anchorTagArray = emptyList(),
|
||||
signer = signer,
|
||||
)
|
||||
draftsDecryptionCache.preload(draftEvent, rumor)
|
||||
sendDraftEvent(draftEvent)
|
||||
} else {
|
||||
val it = signer.sign(template)
|
||||
cache.justConsumeMyOwnEvent(it)
|
||||
client.send(it, relayList = relayList)
|
||||
|
||||
broadcastNotes.forEach { it.event?.let { client.send(it, relayList = relayList) } }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun <T : Event> signAndSendNIP04Message(
|
||||
draftTag: String?,
|
||||
template: EventTemplate<T>,
|
||||
relayList: Set<NormalizedRelayUrl>,
|
||||
) {
|
||||
if (draftTag != null) {
|
||||
if (template.content.isEmpty()) {
|
||||
deleteDraft(draftTag)
|
||||
} else {
|
||||
val rumor = RumorAssembler.assembleRumor(signer.pubKey, template)
|
||||
val draftEvent = DraftEvent.create(draftTag, rumor, emptyList(), signer)
|
||||
draftsDecryptionCache.preload(draftEvent, rumor)
|
||||
sendDraftEvent(draftEvent)
|
||||
}
|
||||
} else {
|
||||
val newEvent = signer.sign(template)
|
||||
cache.justConsumeMyOwnEvent(newEvent)
|
||||
client.send(newEvent, relayList)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun <T : Event> signAndSendWithList(
|
||||
draftTag: String?,
|
||||
template: EventTemplate<T>,
|
||||
relayList: Collection<NormalizedRelayUrl>,
|
||||
broadcastNotes: Set<Note>,
|
||||
) {
|
||||
if (draftTag != null) {
|
||||
val rumor = RumorAssembler.assembleRumor(signer.pubKey, template)
|
||||
val draftEvent = DraftEvent.create(draftTag, rumor, emptyList(), signer)
|
||||
draftsDecryptionCache.preload(draftEvent, rumor)
|
||||
sendDraftEvent(draftEvent)
|
||||
} else {
|
||||
val event = signer.sign(template)
|
||||
cache.justConsumeMyOwnEvent(event)
|
||||
|
||||
val relaySet = relayList.toSet()
|
||||
|
||||
client.send(event, relayList = relaySet)
|
||||
broadcastNotes.forEach { it.event?.let { client.send(it, relayList = relaySet) } }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun createAndSendDraft(
|
||||
draftTag: String,
|
||||
template: EventTemplate<out Event>,
|
||||
broadcast: Set<Event> = emptySet(),
|
||||
) {
|
||||
val extraRelays = cache.getAddressableNoteIfExists(DraftWrapEvent.createAddressTag(signer.pubKey, draftTag))?.relays ?: emptyList()
|
||||
|
||||
val rumor = RumorAssembler.assembleRumor(signer.pubKey, template)
|
||||
val draftEvent = DraftBuilder.encryptAndSign(draftTag, rumor, signer)
|
||||
draftsDecryptionCache.preload(draftEvent, rumor)
|
||||
sendDraftEvent(draftEvent)
|
||||
|
||||
cache.justConsumeMyOwnEvent(draftEvent)
|
||||
|
||||
val relayList = (privateStorageRelayList.flow.value + localRelayList.flow.value + extraRelays).toSet()
|
||||
if (relayList.isNotEmpty()) {
|
||||
client.send(draftEvent, relayList)
|
||||
broadcast.forEach {
|
||||
client.send(it, relayList.toSet())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun deleteDraft(draftTag: String) {
|
||||
val key = DraftEvent.createAddressTag(userProfile().pubkeyHex, draftTag)
|
||||
cache.getAddressableNoteIfExists(key)?.let { note ->
|
||||
val noteEvent = note.event
|
||||
if (noteEvent is DraftEvent) {
|
||||
val deletedDraftEvent = noteEvent.createDeletedEvent(signer)
|
||||
client.send(deletedDraftEvent, outboxRelays.flow.value + note.relays)
|
||||
cache.justConsumeMyOwnEvent(deletedDraftEvent)
|
||||
val extraRelays = cache.getAddressableNoteIfExists(DraftWrapEvent.createAddressTag(signer.pubKey, draftTag))?.relays ?: emptyList()
|
||||
|
||||
delete(deletedDraftEvent, note.relays.toSet())
|
||||
}
|
||||
val deletedDraft = DraftWrapEvent.createDeletedEvent(draftTag, signer)
|
||||
val deletionEvent = signer.sign(DeletionEvent.build(listOf(deletedDraft)))
|
||||
|
||||
val relayList = (privateStorageRelayList.flow.value + localRelayList.flow.value + extraRelays).toSet()
|
||||
|
||||
cache.justConsumeMyOwnEvent(deletedDraft)
|
||||
cache.justConsumeMyOwnEvent(deletionEvent)
|
||||
|
||||
if (relayList.isNotEmpty()) {
|
||||
client.send(deletedDraft, relayList)
|
||||
client.send(deletionEvent, relayList)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1257,7 +1194,18 @@ class Account(
|
||||
currentSceneRelay = readingSceneRelay,
|
||||
)
|
||||
|
||||
sendToPrivateOutboxAndLocal(signer.sign(template))
|
||||
val event = signer.sign(template)
|
||||
|
||||
// updates relays that already have this replaceable.
|
||||
val noteRelays = cache.getAddressableNoteIfExists(event.address())?.relays ?: emptyList()
|
||||
|
||||
val relayList = privateStorageRelayList.flow.value + localRelayList.flow.value
|
||||
if (relayList.isNotEmpty()) {
|
||||
client.send(event, relayList + noteRelays)
|
||||
} else {
|
||||
client.send(event, outboxRelays.flow.value + noteRelays)
|
||||
}
|
||||
cache.justConsumeMyOwnEvent(event)
|
||||
}
|
||||
|
||||
suspend fun updateInteractiveStoryReadingState(
|
||||
@@ -1274,7 +1222,18 @@ class Account(
|
||||
currentSceneRelay = readingSceneRelay,
|
||||
)
|
||||
|
||||
sendToPrivateOutboxAndLocal(signer.sign(template))
|
||||
val event = signer.sign(template)
|
||||
|
||||
// updates relays that already have this replaceable.
|
||||
val noteRelays = cache.getAddressableNoteIfExists(event.address())?.relays ?: emptyList()
|
||||
|
||||
val relayList = privateStorageRelayList.flow.value + localRelayList.flow.value
|
||||
if (relayList.isNotEmpty()) {
|
||||
client.send(event, relayList + noteRelays)
|
||||
} else {
|
||||
client.send(event, outboxRelays.flow.value + noteRelays)
|
||||
}
|
||||
cache.justConsumeMyOwnEvent(event)
|
||||
}
|
||||
|
||||
fun mapEntitiesToNotes(entities: List<Entity>): List<Note> =
|
||||
@@ -1328,7 +1287,15 @@ class Account(
|
||||
contentWarningReason?.let { contentWarning(contentWarningReason) }
|
||||
}
|
||||
|
||||
signAndSend(draftTag, template, relayList, quotes)
|
||||
if (draftTag != null) {
|
||||
createAndSendDraft(draftTag, template)
|
||||
} else {
|
||||
val it = signer.sign(template)
|
||||
cache.justConsumeMyOwnEvent(it)
|
||||
client.send(it, relayList = relayList)
|
||||
|
||||
mapEntitiesToNotes(quotes).forEach { it.event?.let { client.send(it, relayList = relayList) } }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendInteractiveStoryScene(
|
||||
@@ -1363,29 +1330,42 @@ class Account(
|
||||
contentWarningReason?.let { contentWarning(contentWarningReason) }
|
||||
}
|
||||
|
||||
signAndSend(draftTag, template, relayList, mapEntitiesToNotes(quotes).toSet())
|
||||
val broadcastNotes = mapEntitiesToNotes(quotes).toSet()
|
||||
|
||||
if (draftTag != null) {
|
||||
createAndSendDraft(draftTag, template)
|
||||
} else {
|
||||
val it = signer.sign(template)
|
||||
cache.justConsumeMyOwnEvent(it)
|
||||
client.send(it, relayList = relayList)
|
||||
|
||||
broadcastNotes.forEach { it.event?.let { client.send(it, relayList = relayList) } }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendAddBounty(
|
||||
value: BigDecimal,
|
||||
bounty: Note,
|
||||
draftTag: String?,
|
||||
) {
|
||||
if (!isWriteable()) return
|
||||
|
||||
val event = bounty.event as? TextNoteEvent ?: return
|
||||
val eventAuthor = bounty.author ?: return
|
||||
val bountyEvent = bounty.event as? TextNoteEvent ?: return
|
||||
val bountyAuthor = bounty.author ?: return
|
||||
|
||||
val template =
|
||||
BountyAddValueEvent.build(
|
||||
value,
|
||||
EventHintBundle(event, bounty.relayHintUrl()),
|
||||
eventAuthor.toPTag(),
|
||||
amount = value,
|
||||
bountyRoot = EventHintBundle(bountyEvent, bounty.relayHintUrl()),
|
||||
bountyRootAuthor = bountyAuthor.toPTag(),
|
||||
)
|
||||
|
||||
val relays = bounty.relays + outboxRelays.flow.value
|
||||
val relays = (bounty.relays + outboxRelays.flow.value).toSet()
|
||||
|
||||
signAndSendWithList(draftTag, template, relays, setOf(bounty))
|
||||
val newEvent = signer.sign(template)
|
||||
cache.justConsumeMyOwnEvent(newEvent)
|
||||
|
||||
client.send(newEvent, relayList = relays)
|
||||
client.send(bountyEvent, relayList = relays)
|
||||
}
|
||||
|
||||
suspend fun sendEdit(
|
||||
@@ -1417,82 +1397,27 @@ class Account(
|
||||
broadcast.forEach { client.send(it, relayList) }
|
||||
}
|
||||
|
||||
suspend fun sendPrivateMessage(
|
||||
message: String,
|
||||
toUser: PTag,
|
||||
replyingTo: Note? = null,
|
||||
zapReceiver: List<ZapSplitSetup>? = null,
|
||||
contentWarningReason: String? = null,
|
||||
zapRaiserAmount: Long? = null,
|
||||
geohash: String? = null,
|
||||
imetas: List<IMetaTag>? = null,
|
||||
emojis: List<EmojiUrlTag>? = null,
|
||||
draftTag: String?,
|
||||
) {
|
||||
suspend fun sendNip04PrivateMessage(eventTemplate: EventTemplate<PrivateDmEvent>) {
|
||||
if (!isWriteable()) return
|
||||
|
||||
val encryptedContent =
|
||||
signer.nip04Encrypt(
|
||||
PrivateDmEvent.prepareMessageToEncrypt(message, imetas),
|
||||
toUser.pubKey,
|
||||
)
|
||||
val newEvent = signer.sign(eventTemplate)
|
||||
val recipient = newEvent.verifiedRecipientPubKey()
|
||||
val destinationRelays = recipient?.let { cache.getOrCreateUser(it).dmInboxRelays() } ?: emptyList()
|
||||
|
||||
val template =
|
||||
PrivateDmEvent.build(toUser, encryptedContent) {
|
||||
replyingTo?.let { reply(it.toEId()) }
|
||||
|
||||
geohash?.let { geohash(it) }
|
||||
zapRaiserAmount?.let { zapraiser(it) }
|
||||
zapReceiver?.let { zapSplits(it) }
|
||||
emojis?.let { emojis(it) }
|
||||
contentWarningReason?.let { contentWarning(contentWarningReason) }
|
||||
}
|
||||
|
||||
val destinationRelays = cache.getOrCreateUser(toUser.pubKey).dmInboxRelays()
|
||||
|
||||
signAndSendNIP04Message(draftTag, template, outboxRelays.flow.value + destinationRelays)
|
||||
cache.justConsumeMyOwnEvent(newEvent)
|
||||
client.send(newEvent, outboxRelays.flow.value + destinationRelays)
|
||||
}
|
||||
|
||||
suspend fun sendNIP17EncryptedFile(template: EventTemplate<ChatMessageEncryptedFileHeaderEvent>) {
|
||||
suspend fun sendNip17EncryptedFile(template: EventTemplate<ChatMessageEncryptedFileHeaderEvent>) {
|
||||
if (!isWriteable()) return
|
||||
|
||||
val wraps = NIP17Factory().createEncryptedFileNIP17(template, signer)
|
||||
broadcastPrivately(wraps)
|
||||
}
|
||||
|
||||
suspend fun sendNIP17PrivateMessage(
|
||||
template: EventTemplate<ChatMessageEvent>,
|
||||
draftTag: String? = null,
|
||||
) {
|
||||
if (draftTag != null) {
|
||||
if (template.content.isEmpty()) {
|
||||
deleteDraft(draftTag)
|
||||
} else {
|
||||
val rumor = RumorAssembler.assembleRumor(signer.pubKey, template)
|
||||
val draftEvent = DraftEvent.create(draftTag, rumor, emptyList(), signer)
|
||||
draftsDecryptionCache.preload(draftEvent, rumor)
|
||||
sendDraftEvent(draftEvent)
|
||||
}
|
||||
} else {
|
||||
val it = NIP17Factory().createMessageNIP17(template, signer)
|
||||
broadcastPrivately(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun sendDraftEvent(draftEvent: DraftEvent) {
|
||||
sendToPrivateOutboxAndLocal(draftEvent)
|
||||
}
|
||||
|
||||
fun sendToPrivateOutboxAndLocal(event: Event?) {
|
||||
if (event == null) return
|
||||
|
||||
val relayList = privateStorageRelayList.flow.value + localRelayList.flow.value
|
||||
if (relayList.isNotEmpty()) {
|
||||
client.send(event, relayList.toSet())
|
||||
} else {
|
||||
client.send(event, outboxRelays.flow.value)
|
||||
}
|
||||
cache.justConsumeMyOwnEvent(event)
|
||||
suspend fun sendNip17PrivateMessage(template: EventTemplate<ChatMessageEvent>) {
|
||||
val events = NIP17Factory().createMessageNIP17(template, signer)
|
||||
broadcastPrivately(events)
|
||||
}
|
||||
|
||||
suspend fun broadcastPrivately(signedEvents: NIP17Factory.Result) {
|
||||
@@ -1645,7 +1570,7 @@ class Account(
|
||||
privateDMDecryptionCache.cachedDM(event)
|
||||
} else if (event is LnZapRequestEvent && event.isPrivateZap()) {
|
||||
privateZapsDecryptionCache.cachedPrivateZap(event)?.content
|
||||
} else if (event is DraftEvent) {
|
||||
} else if (event is DraftWrapEvent) {
|
||||
draftsDecryptionCache.preCachedDraft(event)?.content
|
||||
} else {
|
||||
event.content
|
||||
@@ -1669,7 +1594,7 @@ class Account(
|
||||
} else {
|
||||
event.content
|
||||
}
|
||||
} else if (event is DraftEvent && isWriteable()) {
|
||||
} else if (event is DraftWrapEvent && isWriteable()) {
|
||||
draftsDecryptionCache.cachedDraft(event)?.content
|
||||
} else {
|
||||
event?.content
|
||||
|
||||
@@ -37,7 +37,7 @@ import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.list.ChannelListEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.list.tags.ChannelTag
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.privateOutbox.PrivateOutboxRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect
|
||||
@@ -89,7 +89,7 @@ val DefaultIndexerRelayList = setOf(Constants.purplepages, Constants.coracle, Co
|
||||
val DefaultSignerPermissions =
|
||||
listOf(
|
||||
Permission(CommandType.SIGN_EVENT, RelayAuthEvent.KIND),
|
||||
Permission(CommandType.SIGN_EVENT, DraftEvent.KIND),
|
||||
Permission(CommandType.SIGN_EVENT, DraftWrapEvent.KIND),
|
||||
Permission(CommandType.NIP04_ENCRYPT),
|
||||
Permission(CommandType.NIP04_DECRYPT),
|
||||
Permission(CommandType.NIP44_DECRYPT),
|
||||
|
||||
@@ -120,7 +120,7 @@ import com.vitorpamplona.quartz.nip34Git.reply.GitReplyEvent
|
||||
import com.vitorpamplona.quartz.nip34Git.repository.GitRepositoryEvent
|
||||
import com.vitorpamplona.quartz.nip35Torrents.TorrentCommentEvent
|
||||
import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.privateOutbox.PrivateOutboxRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip38UserStatus.StatusEvent
|
||||
import com.vitorpamplona.quartz.nip40Expiration.expiration
|
||||
@@ -2536,7 +2536,7 @@ object LocalCache : ILocalCache {
|
||||
}
|
||||
|
||||
fun consume(
|
||||
event: DraftEvent,
|
||||
event: DraftWrapEvent,
|
||||
relay: NormalizedRelayUrl?,
|
||||
wasVerified: Boolean,
|
||||
): Boolean = !event.isDeleted() && consumeBaseReplaceable(event, relay, wasVerified)
|
||||
@@ -2744,7 +2744,7 @@ object LocalCache : ILocalCache {
|
||||
is CommunityPostApprovalEvent -> consume(event, relay, wasVerified)
|
||||
is ContactListEvent -> consume(event, relay, wasVerified)
|
||||
is DeletionEvent -> consume(event, relay, wasVerified)
|
||||
is DraftEvent -> consume(event, relay, wasVerified)
|
||||
is DraftWrapEvent -> consume(event, relay, wasVerified)
|
||||
is EmojiPackEvent -> consume(event, relay, wasVerified)
|
||||
is EmojiPackSelectionEvent -> consume(event, relay, wasVerified)
|
||||
is EphemeralChatEvent -> consume(event, relay, wasVerified)
|
||||
|
||||
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.model
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.Stable
|
||||
import coil3.util.CoilUtils.result
|
||||
import com.vitorpamplona.amethyst.model.nip47WalletConnect.NwcSignerState
|
||||
import com.vitorpamplona.amethyst.model.nip51Lists.HiddenUsersState
|
||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||
@@ -53,7 +52,7 @@ import com.vitorpamplona.quartz.nip22Comments.CommentEvent
|
||||
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.isSensitiveOrNSFW
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentRequestEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.PayInvoiceMethod
|
||||
@@ -236,7 +235,7 @@ open class Note(
|
||||
|
||||
open fun createdAt() = event?.createdAt
|
||||
|
||||
fun isDraft() = event is DraftEvent
|
||||
fun isDraft() = event is DraftWrapEvent
|
||||
|
||||
fun loadEvent(
|
||||
event: Event,
|
||||
|
||||
+2
-2
@@ -44,8 +44,8 @@ class AccountOutboxRelayState(
|
||||
privateStorage.flow,
|
||||
local.flow,
|
||||
broadcast.flow,
|
||||
) { nip65Inbox, privateOutBox, localRelays, broadcastRelays ->
|
||||
nip65Inbox + privateOutBox + localRelays + broadcastRelays
|
||||
) { nip65Outbox, privateOutBox, localRelays, broadcastRelays ->
|
||||
nip65Outbox + privateOutBox + localRelays + broadcastRelays
|
||||
}.flowOn(Dispatchers.Default)
|
||||
.stateIn(
|
||||
scope,
|
||||
|
||||
+2
-2
@@ -24,13 +24,13 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.BookmarkListEvent
|
||||
import com.vitorpamplona.quartz.nip56Reports.ReportEvent
|
||||
|
||||
val ReportsAndBookmarksFromKeyKinds =
|
||||
listOf(
|
||||
DraftEvent.KIND,
|
||||
DraftWrapEvent.KIND,
|
||||
ReportEvent.KIND,
|
||||
BookmarkListEvent.KIND,
|
||||
)
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
|
||||
import com.vitorpamplona.quartz.nip22Comments.CommentEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.base.IsInPublicChatChannel
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
|
||||
@@ -63,7 +63,7 @@ fun routeFor(
|
||||
noteEvent: Event,
|
||||
loggedIn: Account,
|
||||
): Route? {
|
||||
if (noteEvent is DraftEvent) {
|
||||
if (noteEvent is DraftWrapEvent) {
|
||||
val innerEvent = loggedIn.draftsDecryptionCache.preCachedDraft(noteEvent)
|
||||
|
||||
if (innerEvent is IsInPublicChatChannel) {
|
||||
|
||||
@@ -187,7 +187,7 @@ import com.vitorpamplona.quartz.nip34Git.patch.GitPatchEvent
|
||||
import com.vitorpamplona.quartz.nip34Git.repository.GitRepositoryEvent
|
||||
import com.vitorpamplona.quartz.nip35Torrents.TorrentCommentEvent
|
||||
import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.followList.FollowListEvent
|
||||
@@ -552,7 +552,7 @@ fun InnerNoteWithReactions(
|
||||
}
|
||||
}
|
||||
|
||||
val isNotRepost = baseNote.event !is RepostEvent && baseNote.event !is GenericRepostEvent && baseNote.event !is DraftEvent
|
||||
val isNotRepost = baseNote.event !is RepostEvent && baseNote.event !is GenericRepostEvent && baseNote.event !is DraftWrapEvent
|
||||
|
||||
if (isNotRepost) {
|
||||
if (makeItShort) {
|
||||
@@ -568,7 +568,7 @@ fun InnerNoteWithReactions(
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (baseNote.event is DraftEvent) {
|
||||
if (baseNote.event is DraftWrapEvent) {
|
||||
Spacer(modifier = DoubleVertSpacer)
|
||||
}
|
||||
}
|
||||
@@ -647,7 +647,7 @@ private fun RenderNoteRow(
|
||||
is AppDefinitionEvent -> RenderAppDefinition(baseNote, accountViewModel, nav)
|
||||
is AudioTrackEvent -> RenderAudioTrack(baseNote, ContentScale.FillWidth, accountViewModel, nav)
|
||||
is AudioHeaderEvent -> RenderAudioHeader(baseNote, ContentScale.FillWidth, accountViewModel, nav)
|
||||
is DraftEvent -> RenderDraft(baseNote, quotesLeft, unPackReply, backgroundColor, accountViewModel, nav)
|
||||
is DraftWrapEvent -> RenderDraft(baseNote, quotesLeft, unPackReply, backgroundColor, accountViewModel, nav)
|
||||
is ReactionEvent -> RenderReaction(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||
is RepostEvent -> RenderRepost(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||
is GenericRepostEvent -> RenderRepost(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||
@@ -901,7 +901,7 @@ fun ObserveDraftEvent(
|
||||
accountViewModel: AccountViewModel,
|
||||
render: @Composable (Note) -> Unit,
|
||||
) {
|
||||
val noteEvent by observeNoteEvent<DraftEvent>(note, accountViewModel)
|
||||
val noteEvent by observeNoteEvent<DraftWrapEvent>(note, accountViewModel)
|
||||
|
||||
noteEvent?.let {
|
||||
val innerNote by produceCachedStateAsync(cache = accountViewModel.draftNoteCache, key = it)
|
||||
|
||||
@@ -179,7 +179,6 @@ class AddBountyAmountViewModel : ViewModel() {
|
||||
myAccount.sendAddBounty(
|
||||
newValue,
|
||||
bountyInner,
|
||||
draftTag = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+8
-7
@@ -82,7 +82,7 @@ import com.vitorpamplona.quartz.nip30CustomEmoji.EmojiUrlTag
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.emojis
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.contentWarning
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.isSensitive
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.zapSplits
|
||||
import com.vitorpamplona.quartz.nip57Zaps.zapraiser.zapraiser
|
||||
import com.vitorpamplona.quartz.nip57Zaps.zapraiser.zapraiserAmount
|
||||
@@ -202,7 +202,7 @@ open class CommentPostViewModel :
|
||||
val noteEvent = draft.event
|
||||
val noteAuthor = draft.author
|
||||
|
||||
if (noteEvent is DraftEvent && noteAuthor != null) {
|
||||
if (noteEvent is DraftWrapEvent && noteAuthor != null) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.createTempDraftNote(noteEvent)?.let { innerNote ->
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
@@ -324,13 +324,14 @@ open class CommentPostViewModel :
|
||||
if (message.text.isBlank()) {
|
||||
accountViewModel.account.deleteDraft(draftTag.current)
|
||||
} else {
|
||||
val template = createTemplate() ?: return
|
||||
accountViewModel.account.createAndSendDraft(draftTag.current, template)
|
||||
|
||||
val attachments = mutableSetOf<Event>()
|
||||
nip95attachments.forEach {
|
||||
account.sendToPrivateOutboxAndLocal(it.first)
|
||||
account.sendToPrivateOutboxAndLocal(it.second)
|
||||
attachments.add(it.first)
|
||||
attachments.add(it.second)
|
||||
}
|
||||
|
||||
val template = createTemplate() ?: return
|
||||
accountViewModel.account.createAndSendDraft(draftTag.current, template, attachments)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -115,7 +115,7 @@ import com.vitorpamplona.quartz.nip19Bech32.entities.NPub
|
||||
import com.vitorpamplona.quartz.nip19Bech32.entities.NRelay
|
||||
import com.vitorpamplona.quartz.nip19Bech32.entities.NSec
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.base.IsInPublicChatChannel
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Response
|
||||
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.BookmarkListEvent
|
||||
@@ -1510,7 +1510,7 @@ class AccountViewModel(
|
||||
account.deleteDraft(draftTag)
|
||||
}
|
||||
|
||||
suspend fun createTempDraftNote(noteEvent: DraftEvent): Note? = draftNoteCache.update(noteEvent)
|
||||
suspend fun createTempDraftNote(noteEvent: DraftWrapEvent): Note? = draftNoteCache.update(noteEvent)
|
||||
|
||||
fun createTempDraftNote(
|
||||
innerEvent: Event,
|
||||
@@ -1691,8 +1691,8 @@ class AccountViewModel(
|
||||
|
||||
class CachedDraftNotes(
|
||||
val accountViewModel: AccountViewModel,
|
||||
) : GenericBaseCacheAsync<DraftEvent, Note>(20) {
|
||||
override suspend fun compute(key: DraftEvent): Note? =
|
||||
) : GenericBaseCacheAsync<DraftWrapEvent, Note>(20) {
|
||||
override suspend fun compute(key: DraftWrapEvent): Note? =
|
||||
withContext(Dispatchers.IO) {
|
||||
val decrypted = accountViewModel.account.draftsDecryptionCache.cachedDraft(key)
|
||||
if (decrypted != null) {
|
||||
|
||||
+6
-6
@@ -32,7 +32,7 @@ import com.vitorpamplona.quartz.nip01Core.core.IEvent
|
||||
import com.vitorpamplona.quartz.nip03Timestamp.OtsEvent
|
||||
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||
@@ -74,7 +74,7 @@ class EventProcessor(
|
||||
when (event) {
|
||||
is ChatroomKeyable -> chatHandler.add(event, eventNote, publicNote)
|
||||
is OtsEvent -> otsHandler.add(event, eventNote, publicNote)
|
||||
is DraftEvent -> draftHandler.add(event, eventNote, publicNote)
|
||||
is DraftWrapEvent -> draftHandler.add(event, eventNote, publicNote)
|
||||
is GiftWrapEvent -> giftWrapHandler.add(event, eventNote, publicNote)
|
||||
is SealedRumorEvent -> sealHandler.add(event, eventNote, publicNote)
|
||||
is LnZapRequestEvent -> zapRequest.add(event, eventNote, publicNote)
|
||||
@@ -98,7 +98,7 @@ class EventProcessor(
|
||||
when (event) {
|
||||
is ChatroomKeyable -> chatHandler.delete(event, note)
|
||||
is OtsEvent -> otsHandler.delete(event, note)
|
||||
is DraftEvent -> draftHandler.delete(event, note)
|
||||
is DraftWrapEvent -> draftHandler.delete(event, note)
|
||||
is GiftWrapEvent -> giftWrapHandler.delete(event, note)
|
||||
is SealedRumorEvent -> sealHandler.delete(event, note)
|
||||
is LnZapRequestEvent -> zapRequest.delete(event, note)
|
||||
@@ -129,7 +129,7 @@ class EventProcessor(
|
||||
val deletedDrafts =
|
||||
newNotes.mapNotNull { note ->
|
||||
val event = note.event
|
||||
if (event is DraftEvent &&
|
||||
if (event is DraftWrapEvent &&
|
||||
event.isDeleted() &&
|
||||
!cache.deletionIndex.hasBeenDeleted(event)
|
||||
) {
|
||||
@@ -193,9 +193,9 @@ class OtsEventHandler(
|
||||
class DraftEventHandler(
|
||||
private val account: Account,
|
||||
private val cache: LocalCache,
|
||||
) : EventHandler<DraftEvent> {
|
||||
) : EventHandler<DraftWrapEvent> {
|
||||
override suspend fun add(
|
||||
event: DraftEvent,
|
||||
event: DraftWrapEvent,
|
||||
eventNote: Note,
|
||||
publicNote: Note,
|
||||
) {
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ import com.vitorpamplona.amethyst.ui.note.creators.draftTags.DraftTagState
|
||||
import com.vitorpamplona.amethyst.ui.screen.SaveableFeedState
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
|
||||
@Composable
|
||||
fun RefreshingChatroomFeedView(
|
||||
@@ -129,7 +129,7 @@ fun ChatFeedLoaded(
|
||||
) {
|
||||
itemsIndexed(items.list, key = { _, item -> item.idHex }) { index, item ->
|
||||
val noteEvent = item.event
|
||||
if (avoidDraft == null || noteEvent !is DraftEvent || noteEvent.dTag() !in avoidDraft.usedDraftTags) {
|
||||
if (avoidDraft == null || noteEvent !is DraftWrapEvent || noteEvent.dTag() !in avoidDraft.usedDraftTags) {
|
||||
ChatroomMessageCompose(
|
||||
baseNote = item,
|
||||
routeForLastRead = routeForLastRead,
|
||||
|
||||
+4
-4
@@ -82,7 +82,7 @@ import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
|
||||
import com.vitorpamplona.quartz.nip17Dm.files.ChatMessageEncryptedFileHeaderEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.hasZapSplitSetup
|
||||
import com.vitorpamplona.quartz.nip57Zaps.zapraiser.zapraiserAmount
|
||||
|
||||
@@ -162,7 +162,7 @@ fun NormalChatNote(
|
||||
|
||||
ChatBubbleLayout(
|
||||
isLoggedInUser = isLoggedInUser,
|
||||
isDraft = note.event is DraftEvent,
|
||||
isDraft = note.event is DraftWrapEvent,
|
||||
innerQuote = innerQuote,
|
||||
isComplete = accountViewModel.settings.featureSet == FeatureSetType.COMPLETE,
|
||||
hasDetailsToShow = note.zaps.isNotEmpty() || note.zapPayments.isNotEmpty() || note.reactions.isNotEmpty(),
|
||||
@@ -289,7 +289,7 @@ private fun MessageBubbleLines(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
if (baseNote.event !is DraftEvent) {
|
||||
if (baseNote.event !is DraftWrapEvent) {
|
||||
RenderReplyRow(
|
||||
note = baseNote,
|
||||
innerQuote = innerQuote,
|
||||
@@ -388,7 +388,7 @@ fun NoteRow(
|
||||
when (note.event) {
|
||||
is ChannelCreateEvent -> RenderCreateChannelNote(note, bgColor, accountViewModel, nav)
|
||||
is ChannelMetadataEvent -> RenderChangeChannelMetadataNote(note, bgColor, accountViewModel, nav)
|
||||
is DraftEvent -> RenderDraftEvent(note, canPreview, innerQuote, onWantsToReply, onWantsToEditDraft, bgColor, accountViewModel, nav)
|
||||
is DraftWrapEvent -> RenderDraftEvent(note, canPreview, innerQuote, onWantsToReply, onWantsToEditDraft, bgColor, accountViewModel, nav)
|
||||
is ChatMessageEncryptedFileHeaderEvent -> RenderEncryptedFile(note, bgColor, accountViewModel, nav)
|
||||
else -> RenderRegularTextNote(note, canPreview, innerQuote, bgColor, accountViewModel, nav)
|
||||
}
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ fun NewChatroomSubjectDialog(
|
||||
groupName.value.ifBlank { null }?.let { changeSubject(it) }
|
||||
}
|
||||
|
||||
accountViewModel.account.sendNIP17PrivateMessage(template)
|
||||
accountViewModel.account.sendNip17PrivateMessage(template)
|
||||
}
|
||||
|
||||
onClose()
|
||||
|
||||
+25
-13
@@ -79,7 +79,7 @@ import com.vitorpamplona.quartz.nip30CustomEmoji.EmojiUrlTag
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.emojis
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.contentWarning
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.isSensitive
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.ZapSplitSetup
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.zapSplitSetup
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.zapSplits
|
||||
@@ -252,7 +252,7 @@ class ChatNewMessageViewModel :
|
||||
val noteEvent = draft.event
|
||||
val noteAuthor = draft.author
|
||||
|
||||
if (noteEvent is DraftEvent && noteAuthor != null) {
|
||||
if (noteEvent is DraftWrapEvent && noteAuthor != null) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.createTempDraftNote(noteEvent)?.let { innerNote ->
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
@@ -421,7 +421,7 @@ class ChatNewMessageViewModel :
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun innerSendPost(dTag: String?) {
|
||||
private suspend fun innerSendPost(draftTag: String?) {
|
||||
val room = room ?: return
|
||||
|
||||
val urls = findURLs(message.text)
|
||||
@@ -468,19 +468,31 @@ class ChatNewMessageViewModel :
|
||||
}
|
||||
}
|
||||
|
||||
accountViewModel.account.sendNIP17PrivateMessage(template, dTag)
|
||||
if (draftTag != null) {
|
||||
accountViewModel.account.createAndSendDraft(draftTag, template)
|
||||
} else {
|
||||
accountViewModel.account.sendNip17PrivateMessage(template)
|
||||
}
|
||||
} else {
|
||||
accountViewModel.account.sendPrivateMessage(
|
||||
message = message,
|
||||
toUser = room.users.first().let { LocalCache.getOrCreateUser(it).toPTag() },
|
||||
replyingTo = replyTo.value,
|
||||
contentWarningReason = null,
|
||||
imetas = usedAttachments,
|
||||
draftTag = dTag,
|
||||
)
|
||||
val toUser = room.users.first().let { LocalCache.getOrCreateUser(it).toPTag() }
|
||||
|
||||
val template =
|
||||
PrivateDmEvent.build(
|
||||
toUser = toUser,
|
||||
message = message,
|
||||
imetas = usedAttachments,
|
||||
replyingTo = replyTo.value?.toEId(),
|
||||
signer = accountViewModel.account.signer,
|
||||
)
|
||||
|
||||
if (draftTag != null) {
|
||||
accountViewModel.account.createAndSendDraft(draftTag, template)
|
||||
} else {
|
||||
accountViewModel.account.sendNip04PrivateMessage(template)
|
||||
}
|
||||
}
|
||||
|
||||
if (dTag == null) {
|
||||
if (draftTag == null) {
|
||||
ChatFileSender(room, accountViewModel.account).sendAll(uploadsWaitingToBeSent)
|
||||
}
|
||||
}
|
||||
|
||||
+14
-13
@@ -24,6 +24,7 @@ import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.service.uploads.UploadOrchestrator
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.privateDM.send.IMetaAttachments
|
||||
import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent
|
||||
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey
|
||||
import com.vitorpamplona.quartz.nip17Dm.files.ChatMessageEncryptedFileHeaderEvent
|
||||
import com.vitorpamplona.quartz.nip17Dm.files.encryption.AESGCM
|
||||
@@ -48,7 +49,7 @@ class ChatFileSender(
|
||||
contentWarningReason: String?,
|
||||
cipher: AESGCM,
|
||||
) {
|
||||
account.sendNIP17EncryptedFile(
|
||||
account.sendNip17EncryptedFile(
|
||||
ChatMessageEncryptedFileHeaderEvent.build(
|
||||
url = result.url,
|
||||
to = chatroom.users.map { LocalCache.getOrCreateUser(it).toPTag() },
|
||||
@@ -89,18 +90,18 @@ class ChatFileSender(
|
||||
val iMetaAttachments = IMetaAttachments()
|
||||
iMetaAttachments.add(result, caption, contentWarningReason)
|
||||
|
||||
account.sendPrivateMessage(
|
||||
message = result.url,
|
||||
toUser = chatroom.users.first().let { LocalCache.getOrCreateUser(it).toPTag() },
|
||||
replyingTo = null,
|
||||
zapReceiver = null,
|
||||
contentWarningReason = null,
|
||||
zapRaiserAmount = null,
|
||||
geohash = null,
|
||||
imetas = iMetaAttachments.iMetaAttachments,
|
||||
emojis = null,
|
||||
draftTag = null,
|
||||
)
|
||||
val toUser = chatroom.users.first().let { LocalCache.getOrCreateUser(it).toPTag() }
|
||||
|
||||
val template =
|
||||
PrivateDmEvent.build(
|
||||
toUser = toUser,
|
||||
message = result.url,
|
||||
imetas = iMetaAttachments.iMetaAttachments,
|
||||
replyingTo = null,
|
||||
signer = account.signer,
|
||||
)
|
||||
|
||||
account.sendNip04PrivateMessage(template)
|
||||
}
|
||||
|
||||
suspend fun sendAll(uploads: List<SuccessfulUploads>) {
|
||||
|
||||
+9
-3
@@ -82,7 +82,7 @@ import com.vitorpamplona.quartz.nip30CustomEmoji.CustomEmoji
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.EmojiUrlTag
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.emojis
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.isSensitive
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.chat.notify
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.ZapSplitSetup
|
||||
@@ -191,7 +191,7 @@ open class ChannelNewMessageViewModel :
|
||||
val noteEvent = draft.event
|
||||
val noteAuthor = draft.author
|
||||
|
||||
if (noteEvent is DraftEvent && noteAuthor != null) {
|
||||
if (noteEvent is DraftWrapEvent && noteAuthor != null) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.createTempDraftNote(noteEvent)?.let { innerNote ->
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
@@ -281,8 +281,14 @@ open class ChannelNewMessageViewModel :
|
||||
if (message.text.isBlank()) {
|
||||
account.deleteDraft(draftTag.current)
|
||||
} else {
|
||||
val attachments = mutableSetOf<Event>()
|
||||
nip95attachments.forEach {
|
||||
attachments.add(it.first)
|
||||
attachments.add(it.second)
|
||||
}
|
||||
|
||||
val template = createTemplate() ?: return
|
||||
accountViewModel.account.createAndSendDraft(draftTag.current, template)
|
||||
accountViewModel.account.createAndSendDraft(draftTag.current, template, attachments)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -86,7 +86,7 @@ import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
|
||||
@Composable
|
||||
fun ChatroomHeaderCompose(
|
||||
@@ -113,7 +113,7 @@ fun ChatroomComposeChannelOrUser(
|
||||
nav: INav,
|
||||
) {
|
||||
val baseNoteEvent = baseNote.event
|
||||
if (baseNoteEvent is DraftEvent) {
|
||||
if (baseNoteEvent is DraftWrapEvent) {
|
||||
ObserveDraftEvent(baseNote, accountViewModel) { innerNote ->
|
||||
ChatroomEntry(innerNote, accountViewModel, nav)
|
||||
}
|
||||
|
||||
+2
-2
@@ -78,7 +78,7 @@ import com.vitorpamplona.quartz.nip30CustomEmoji.EmojiUrlTag
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.emojis
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.contentWarning
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.isSensitive
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.zapSplits
|
||||
import com.vitorpamplona.quartz.nip57Zaps.zapraiser.zapraiser
|
||||
import com.vitorpamplona.quartz.nip57Zaps.zapraiser.zapraiserAmount
|
||||
@@ -192,7 +192,7 @@ open class NewProductViewModel :
|
||||
val noteEvent = draft.event
|
||||
val noteAuthor = draft.author
|
||||
|
||||
if (noteEvent is DraftEvent && noteAuthor != null) {
|
||||
if (noteEvent is DraftWrapEvent && noteAuthor != null) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.createTempDraftNote(noteEvent)?.let { innerNote ->
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
|
||||
+2
-2
@@ -25,7 +25,7 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
|
||||
class DraftEventsFeedFilter(
|
||||
val account: Account,
|
||||
@@ -48,7 +48,7 @@ class DraftEventsFeedFilter(
|
||||
|
||||
fun acceptableEvent(it: Note): Boolean {
|
||||
val noteEvent = it.event
|
||||
return noteEvent is DraftEvent && noteEvent.pubKey == account.userProfile().pubkeyHex
|
||||
return noteEvent is DraftWrapEvent && noteEvent.pubKey == account.userProfile().pubkeyHex
|
||||
}
|
||||
|
||||
override fun sort(items: Set<Note>): List<Note> = items.sortedWith(DefaultFeedOrder)
|
||||
|
||||
+8
-9
@@ -96,7 +96,7 @@ import com.vitorpamplona.quartz.nip30CustomEmoji.emojis
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.contentWarning
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.isSensitive
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.isSensitiveOrNSFW
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.ZapSplitSetup
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.ZapSplitSetupLnAddress
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.zapSplitSetup
|
||||
@@ -241,7 +241,7 @@ open class ShortNotePostViewModel :
|
||||
val noteEvent = draft?.event
|
||||
val noteAuthor = draft?.author
|
||||
|
||||
if (draft != null && noteEvent is DraftEvent && noteAuthor != null) {
|
||||
if (draft != null && noteEvent is DraftWrapEvent && noteAuthor != null) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.createTempDraftNote(noteEvent)?.let { innerNote ->
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
@@ -483,18 +483,17 @@ open class ShortNotePostViewModel :
|
||||
}
|
||||
|
||||
suspend fun sendDraftSync() {
|
||||
val accountViewModel = accountViewModel
|
||||
|
||||
if (message.text.isBlank()) {
|
||||
accountViewModel.account.deleteDraft(draftTag.current)
|
||||
} else {
|
||||
val template = createTemplate() ?: return
|
||||
accountViewModel.account.createAndSendDraft(draftTag.current, template)
|
||||
|
||||
val attachments = mutableSetOf<Event>()
|
||||
nip95attachments.forEach {
|
||||
account.sendToPrivateOutboxAndLocal(it.first)
|
||||
account.sendToPrivateOutboxAndLocal(it.second)
|
||||
attachments.add(it.first)
|
||||
attachments.add(it.second)
|
||||
}
|
||||
|
||||
val template = createTemplate() ?: return
|
||||
accountViewModel.account.createAndSendDraft(draftTag.current, template, attachments)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-9
@@ -85,7 +85,7 @@ import com.vitorpamplona.quartz.nip30CustomEmoji.EmojiUrlTag
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.emojis
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.contentWarning
|
||||
import com.vitorpamplona.quartz.nip36SensitiveContent.isSensitive
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.ZapSplitSetup
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.zapSplitSetup
|
||||
import com.vitorpamplona.quartz.nip57Zaps.splits.zapSplits
|
||||
@@ -235,7 +235,7 @@ class NewPublicMessageViewModel :
|
||||
val noteEvent = draft.event
|
||||
val noteAuthor = draft.author
|
||||
|
||||
if (noteEvent is DraftEvent && noteAuthor != null) {
|
||||
if (noteEvent is DraftWrapEvent && noteAuthor != null) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
accountViewModel.createTempDraftNote(noteEvent)?.let { innerNote ->
|
||||
val oldTag = (draft.event as? AddressableEvent)?.dTag()
|
||||
@@ -323,18 +323,17 @@ class NewPublicMessageViewModel :
|
||||
}
|
||||
|
||||
suspend fun sendDraftSync() {
|
||||
val accountViewModel = accountViewModel
|
||||
|
||||
if (message.text.isBlank()) {
|
||||
accountViewModel.account.deleteDraft(draftTag.current)
|
||||
} else {
|
||||
val template = createTemplate() ?: return
|
||||
accountViewModel.account.createAndSendDraft(draftTag.current, template)
|
||||
|
||||
val broadcast = mutableSetOf<Event>()
|
||||
nip95attachments.forEach {
|
||||
account.sendToPrivateOutboxAndLocal(it.first)
|
||||
account.sendToPrivateOutboxAndLocal(it.second)
|
||||
broadcast.add(it.first)
|
||||
broadcast.add(it.second)
|
||||
}
|
||||
|
||||
val template = createTemplate() ?: return
|
||||
accountViewModel.account.createAndSendDraft(draftTag.current, template, broadcast)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -208,7 +208,7 @@ import com.vitorpamplona.quartz.nip34Git.patch.GitPatchEvent
|
||||
import com.vitorpamplona.quartz.nip34Git.repository.GitRepositoryEvent
|
||||
import com.vitorpamplona.quartz.nip35Torrents.TorrentCommentEvent
|
||||
import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.followList.FollowListEvent
|
||||
@@ -641,7 +641,7 @@ private fun FullBleedNoteCompose(
|
||||
RenderGitIssueEvent(baseNote, makeItShort = false, canPreview = true, quotesLeft = 3, backgroundColor = backgroundColor, accountViewModel = accountViewModel, nav = nav)
|
||||
} else if (noteEvent is AppDefinitionEvent) {
|
||||
RenderAppDefinition(baseNote, accountViewModel, nav)
|
||||
} else if (noteEvent is DraftEvent) {
|
||||
} else if (noteEvent is DraftWrapEvent) {
|
||||
RenderDraft(baseNote, 3, true, backgroundColor, accountViewModel, nav)
|
||||
} else if (noteEvent is HighlightEvent) {
|
||||
RenderHighlight(baseNote, false, canPreview, quotesLeft = 3, backgroundColor, accountViewModel, nav)
|
||||
|
||||
Reference in New Issue
Block a user