Voice reply to VoiceEvent/VoiceReplyEvent (KIND 1222/1244) → Creates VoiceReplyEvent (KIND 1244)
Voice reply to TextNoteEvent (KIND 1) → Creates TextNoteEvent (KIND 1) with audio IMeta attachment and proper reply tags
This commit is contained in:
+39
-10
@@ -107,6 +107,9 @@ import com.vitorpamplona.quartz.nip01Core.tags.people.PubKeyReferenceTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser
|
||||
import com.vitorpamplona.quartz.nip03Timestamp.EmptyOtsResolverBuilder
|
||||
import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent
|
||||
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip10Notes.tags.markedETags
|
||||
import com.vitorpamplona.quartz.nip10Notes.tags.prepareETagsAsReplyTo
|
||||
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
|
||||
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
|
||||
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
|
||||
@@ -134,6 +137,7 @@ import com.vitorpamplona.quartz.nip59Giftwrap.seals.SealedRumorEvent
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.wraps.GiftWrapEvent
|
||||
import com.vitorpamplona.quartz.nip90Dvms.NIP90ContentDiscoveryResponseEvent
|
||||
import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag
|
||||
import com.vitorpamplona.quartz.nipA0VoiceMessages.AudioMeta
|
||||
import com.vitorpamplona.quartz.nipA0VoiceMessages.BaseVoiceEvent
|
||||
import com.vitorpamplona.quartz.utils.Hex
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
@@ -1154,8 +1158,6 @@ class AccountViewModel(
|
||||
context: Context,
|
||||
) {
|
||||
if (isWriteable()) {
|
||||
val hint = note.toEventHint<BaseVoiceEvent>() ?: return
|
||||
|
||||
launchSigner {
|
||||
val uploader = UploadOrchestrator()
|
||||
val result =
|
||||
@@ -1171,14 +1173,41 @@ class AccountViewModel(
|
||||
)
|
||||
|
||||
if (result is UploadingState.Finished && result.result is UploadOrchestrator.OrchestratorResult.ServerResult) {
|
||||
account.sendVoiceReplyMessage(
|
||||
result.result.url,
|
||||
result.result.fileHeader.mimeType ?: recording.mimeType,
|
||||
result.result.fileHeader.hash,
|
||||
recording.duration,
|
||||
recording.amplitudes,
|
||||
hint,
|
||||
)
|
||||
val audioMeta =
|
||||
AudioMeta(
|
||||
url = result.result.url,
|
||||
mimeType = result.result.fileHeader.mimeType ?: recording.mimeType,
|
||||
hash = result.result.fileHeader.hash,
|
||||
duration = recording.duration,
|
||||
waveform = recording.amplitudes,
|
||||
)
|
||||
|
||||
// Check if replying to a voice event
|
||||
val voiceHint = note.toEventHint<BaseVoiceEvent>()
|
||||
if (voiceHint != null) {
|
||||
// Create VoiceReplyEvent (KIND 1244) for voice-to-voice replies
|
||||
account.sendVoiceReplyMessage(
|
||||
result.result.url,
|
||||
result.result.fileHeader.mimeType ?: recording.mimeType,
|
||||
result.result.fileHeader.hash,
|
||||
recording.duration,
|
||||
recording.amplitudes,
|
||||
voiceHint,
|
||||
)
|
||||
} else {
|
||||
// Create TextNoteEvent (KIND 1) with audio IMeta for voice replies to regular notes
|
||||
val template =
|
||||
TextNoteEvent.build(audioMeta.url) {
|
||||
val replyingTo = note.toEventHint<TextNoteEvent>()
|
||||
if (replyingTo != null) {
|
||||
val tags = prepareETagsAsReplyTo(replyingTo, null)
|
||||
markedETags(tags)
|
||||
}
|
||||
// Add audio as IMeta attachment
|
||||
add(audioMeta.toIMetaArray())
|
||||
}
|
||||
account.signAndComputeBroadcast(template)
|
||||
}
|
||||
} else if (result is UploadingState.Error) {
|
||||
toastManager.toast(
|
||||
R.string.failed_to_upload_media_no_details,
|
||||
|
||||
+37
-6
@@ -542,18 +542,49 @@ open class ShortNotePostViewModel :
|
||||
voiceMetadata?.let { audioMeta ->
|
||||
// Only create voice reply if original note is also a voice message
|
||||
val originalVoiceHint = originalNote?.toEventHint<BaseVoiceEvent>()
|
||||
return if (originalVoiceHint != null) {
|
||||
// Create voice reply event
|
||||
VoiceReplyEvent.build(
|
||||
if (originalVoiceHint != null) {
|
||||
// Create voice reply event (KIND 1244)
|
||||
return VoiceReplyEvent.build(
|
||||
voiceMessage = audioMeta,
|
||||
replyingTo = originalVoiceHint,
|
||||
)
|
||||
} else {
|
||||
// Create root voice event (no reply or original is not a voice message)
|
||||
VoiceEvent.build(
|
||||
}
|
||||
// If no original note, create a standalone voice event (KIND 1222)
|
||||
if (originalNote == null) {
|
||||
return VoiceEvent.build(
|
||||
voiceMessage = audioMeta,
|
||||
)
|
||||
}
|
||||
// Otherwise, original note exists but is not a voice message
|
||||
// Create a TextNoteEvent (KIND 1) with audio as IMeta attachment
|
||||
return TextNoteEvent.build(audioMeta.url) {
|
||||
val replyingTo = originalNote?.toEventHint<TextNoteEvent>()
|
||||
if (replyingTo != null) {
|
||||
val tags = prepareETagsAsReplyTo(replyingTo, null)
|
||||
tags.forEach {
|
||||
val note = accountViewModel.getNoteIfExists(it.eventId)
|
||||
val ourAuthor = note?.author?.pubkeyHex
|
||||
val ourHint = note?.relayHintUrl()
|
||||
if (it.author == null || it.author?.isBlank() == true) {
|
||||
it.author = ourAuthor
|
||||
} else {
|
||||
if (ourAuthor != null && it.author != ourAuthor) {
|
||||
it.author = ourAuthor
|
||||
}
|
||||
}
|
||||
if (it.relay == null) {
|
||||
it.relay = ourHint
|
||||
} else {
|
||||
if (ourHint != null && it.relay != ourHint) {
|
||||
it.relay = ourHint
|
||||
}
|
||||
}
|
||||
}
|
||||
markedETags(tags)
|
||||
}
|
||||
// Add audio as IMeta attachment
|
||||
add(audioMeta.toIMetaArray())
|
||||
}
|
||||
}
|
||||
|
||||
val tagger =
|
||||
|
||||
+29
-7
@@ -37,6 +37,10 @@ import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
|
||||
import com.vitorpamplona.amethyst.ui.actions.uploads.RecordingResult
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip10Notes.tags.markedETags
|
||||
import com.vitorpamplona.quartz.nip10Notes.tags.prepareETagsAsReplyTo
|
||||
import com.vitorpamplona.quartz.nipA0VoiceMessages.AudioMeta
|
||||
import com.vitorpamplona.quartz.nipA0VoiceMessages.BaseVoiceEvent
|
||||
import com.vitorpamplona.quartz.nipA0VoiceMessages.VoiceReplyEvent
|
||||
@@ -200,12 +204,6 @@ class VoiceReplyViewModel : ViewModel() {
|
||||
is UploadingState.Finished -> {
|
||||
when (val orchestratorResult = result.result) {
|
||||
is UploadOrchestrator.OrchestratorResult.ServerResult -> {
|
||||
val hint = note.toEventHint<BaseVoiceEvent>()
|
||||
if (hint == null) {
|
||||
accountViewModel.toastManager.toast(uploadErrorTitle, uploadVoiceFailed)
|
||||
return
|
||||
}
|
||||
|
||||
val audioMeta =
|
||||
AudioMeta(
|
||||
url = orchestratorResult.url,
|
||||
@@ -215,7 +213,31 @@ class VoiceReplyViewModel : ViewModel() {
|
||||
waveform = recording.amplitudes,
|
||||
)
|
||||
|
||||
accountViewModel.account.signAndComputeBroadcast(VoiceReplyEvent.build(audioMeta, hint))
|
||||
// Check if replying to a voice event
|
||||
val voiceHint = note.toEventHint<BaseVoiceEvent>()
|
||||
if (voiceHint != null) {
|
||||
// Create VoiceReplyEvent (KIND 1244) for voice-to-voice replies
|
||||
accountViewModel.account.signAndComputeBroadcast(VoiceReplyEvent.build(audioMeta, voiceHint))
|
||||
} else {
|
||||
// Create TextNoteEvent (KIND 1) with audio IMeta for voice replies to regular notes
|
||||
val textHint = note.toEventHint<Event>()
|
||||
if (textHint == null) {
|
||||
accountViewModel.toastManager.toast(uploadErrorTitle, uploadVoiceFailed)
|
||||
return
|
||||
}
|
||||
|
||||
val template =
|
||||
TextNoteEvent.build(audioMeta.url) {
|
||||
val replyingTo = note.toEventHint<TextNoteEvent>()
|
||||
if (replyingTo != null) {
|
||||
val tags = prepareETagsAsReplyTo(replyingTo, null)
|
||||
markedETags(tags)
|
||||
}
|
||||
// Add audio as IMeta attachment
|
||||
add(audioMeta.toIMetaArray())
|
||||
}
|
||||
accountViewModel.account.signAndComputeBroadcast(template)
|
||||
}
|
||||
|
||||
if (server.type != ServerType.NIP95) {
|
||||
accountViewModel.account.settings.changeDefaultFileServer(server)
|
||||
|
||||
Reference in New Issue
Block a user