Adds support for Custom Reaction selection on new posts and direct GIF url usage.
This commit is contained in:
@@ -31,6 +31,7 @@ import com.fasterxml.jackson.module.kotlin.readValue
|
|||||||
import com.fonfon.kgeohash.GeoHash
|
import com.fonfon.kgeohash.GeoHash
|
||||||
import com.vitorpamplona.amethyst.Amethyst
|
import com.vitorpamplona.amethyst.Amethyst
|
||||||
import com.vitorpamplona.amethyst.BuildConfig
|
import com.vitorpamplona.amethyst.BuildConfig
|
||||||
|
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage
|
||||||
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
|
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
|
||||||
import com.vitorpamplona.amethyst.service.LocationState
|
import com.vitorpamplona.amethyst.service.LocationState
|
||||||
import com.vitorpamplona.amethyst.service.NostrLnZapPaymentResponseDataSource
|
import com.vitorpamplona.amethyst.service.NostrLnZapPaymentResponseDataSource
|
||||||
@@ -1063,6 +1064,80 @@ class Account(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class EmojiMedia(
|
||||||
|
val code: String,
|
||||||
|
val url: MediaUrlImage,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getEmojiPackSelection(): EmojiPackSelectionEvent? = getEmojiPackSelectionNote().event as? EmojiPackSelectionEvent
|
||||||
|
|
||||||
|
fun getEmojiPackSelectionFlow(): StateFlow<NoteState> = getEmojiPackSelectionNote().flow().metadata.stateFlow
|
||||||
|
|
||||||
|
fun getEmojiPackSelectionNote(): AddressableNote = LocalCache.getOrCreateAddressableNote(EmojiPackSelectionEvent.createAddressATag(userProfile().pubkeyHex))
|
||||||
|
|
||||||
|
fun convertEmojiSelectionPack(selection: EmojiPackSelectionEvent?): List<StateFlow<NoteState>>? =
|
||||||
|
selection?.taggedAddresses()?.map {
|
||||||
|
LocalCache
|
||||||
|
.getOrCreateAddressableNote(it)
|
||||||
|
.flow()
|
||||||
|
.metadata.stateFlow
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
val liveEmojiSelectionPack: StateFlow<List<StateFlow<NoteState>>?> by lazy {
|
||||||
|
getEmojiPackSelectionFlow()
|
||||||
|
.transformLatest {
|
||||||
|
emit(convertEmojiSelectionPack(it.note.event as? EmojiPackSelectionEvent))
|
||||||
|
}.flowOn(Dispatchers.Default)
|
||||||
|
.stateIn(
|
||||||
|
scope,
|
||||||
|
SharingStarted.Eagerly,
|
||||||
|
runBlocking(Dispatchers.Default) {
|
||||||
|
convertEmojiSelectionPack(getEmojiPackSelection())
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun convertEmojiPack(pack: EmojiPackEvent): List<EmojiMedia> =
|
||||||
|
pack.taggedEmojis().map {
|
||||||
|
EmojiMedia(it.code, MediaUrlImage(it.url))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun mergePack(list: Array<NoteState>): List<EmojiMedia> =
|
||||||
|
list
|
||||||
|
.mapNotNull {
|
||||||
|
val ev = it.note.event as? EmojiPackEvent
|
||||||
|
if (ev != null) {
|
||||||
|
convertEmojiPack(ev)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}.flatten()
|
||||||
|
.distinctBy { it.url }
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
val myEmojis by lazy {
|
||||||
|
liveEmojiSelectionPack
|
||||||
|
.transformLatest { emojiList ->
|
||||||
|
if (emojiList != null) {
|
||||||
|
emitAll(
|
||||||
|
combineTransform(emojiList) {
|
||||||
|
emit(mergePack(it))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
emit(emptyList())
|
||||||
|
}
|
||||||
|
}.flowOn(Dispatchers.Default)
|
||||||
|
.stateIn(
|
||||||
|
scope,
|
||||||
|
SharingStarted.Eagerly,
|
||||||
|
runBlocking(Dispatchers.Default) {
|
||||||
|
mergePack(convertEmojiSelectionPack(getEmojiPackSelection())?.map { it.value }?.toTypedArray() ?: emptyArray())
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun addPaymentRequestIfNew(paymentRequest: PaymentRequest) {
|
fun addPaymentRequestIfNew(paymentRequest: PaymentRequest) {
|
||||||
if (
|
if (
|
||||||
!this.transientPaymentRequests.value.contains(paymentRequest) &&
|
!this.transientPaymentRequests.value.contains(paymentRequest) &&
|
||||||
@@ -2110,6 +2185,7 @@ class Account(
|
|||||||
relayList: List<RelaySetupInfo>,
|
relayList: List<RelaySetupInfo>,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
draftTag: String?,
|
draftTag: String?,
|
||||||
) {
|
) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
@@ -2137,6 +2213,7 @@ class Account(
|
|||||||
directMentions = directMentions,
|
directMentions = directMentions,
|
||||||
geohash = geohash,
|
geohash = geohash,
|
||||||
imetas = imetas,
|
imetas = imetas,
|
||||||
|
emojis = emojis,
|
||||||
signer = signer,
|
signer = signer,
|
||||||
isDraft = draftTag != null,
|
isDraft = draftTag != null,
|
||||||
) {
|
) {
|
||||||
@@ -2177,6 +2254,7 @@ class Account(
|
|||||||
relayList: List<RelaySetupInfo>,
|
relayList: List<RelaySetupInfo>,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
draftTag: String?,
|
draftTag: String?,
|
||||||
) {
|
) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
@@ -2199,6 +2277,7 @@ class Account(
|
|||||||
directMentions = directMentions,
|
directMentions = directMentions,
|
||||||
geohash = geohash,
|
geohash = geohash,
|
||||||
imetas = imetas,
|
imetas = imetas,
|
||||||
|
emojis = emojis,
|
||||||
forkedFrom = forkedFrom,
|
forkedFrom = forkedFrom,
|
||||||
signer = signer,
|
signer = signer,
|
||||||
isDraft = draftTag != null,
|
isDraft = draftTag != null,
|
||||||
@@ -2245,6 +2324,7 @@ class Account(
|
|||||||
relayList: List<RelaySetupInfo>,
|
relayList: List<RelaySetupInfo>,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
draftTag: String?,
|
draftTag: String?,
|
||||||
) {
|
) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
@@ -2265,6 +2345,7 @@ class Account(
|
|||||||
directMentions = directMentions,
|
directMentions = directMentions,
|
||||||
geohash = geohash,
|
geohash = geohash,
|
||||||
imetas = imetas,
|
imetas = imetas,
|
||||||
|
emojis = emojis,
|
||||||
forkedFrom = forkedFrom,
|
forkedFrom = forkedFrom,
|
||||||
signer = signer,
|
signer = signer,
|
||||||
isDraft = draftTag != null,
|
isDraft = draftTag != null,
|
||||||
@@ -2328,6 +2409,7 @@ class Account(
|
|||||||
directMentionsUsers: Set<User> = emptySet(),
|
directMentionsUsers: Set<User> = emptySet(),
|
||||||
directMentionsNotes: Set<Note> = emptySet(),
|
directMentionsNotes: Set<Note> = emptySet(),
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
zapReceiver: List<ZapSplitSetup>? = null,
|
zapReceiver: List<ZapSplitSetup>? = null,
|
||||||
wantsToMarkAsSensitive: Boolean = false,
|
wantsToMarkAsSensitive: Boolean = false,
|
||||||
@@ -2371,6 +2453,7 @@ class Account(
|
|||||||
addressesMentioned = addressesMentioned,
|
addressesMentioned = addressesMentioned,
|
||||||
eventsMentioned = eventsMentioned,
|
eventsMentioned = eventsMentioned,
|
||||||
imetas = imetas,
|
imetas = imetas,
|
||||||
|
emojis = emojis,
|
||||||
geohash = geohash,
|
geohash = geohash,
|
||||||
zapReceiver = zapReceiver,
|
zapReceiver = zapReceiver,
|
||||||
markAsSensitive = wantsToMarkAsSensitive,
|
markAsSensitive = wantsToMarkAsSensitive,
|
||||||
@@ -2403,6 +2486,7 @@ class Account(
|
|||||||
addressesMentioned = addressesMentioned,
|
addressesMentioned = addressesMentioned,
|
||||||
eventsMentioned = eventsMentioned,
|
eventsMentioned = eventsMentioned,
|
||||||
imetas = imetas,
|
imetas = imetas,
|
||||||
|
emojis = emojis,
|
||||||
geohash = geohash,
|
geohash = geohash,
|
||||||
zapReceiver = zapReceiver,
|
zapReceiver = zapReceiver,
|
||||||
markAsSensitive = wantsToMarkAsSensitive,
|
markAsSensitive = wantsToMarkAsSensitive,
|
||||||
@@ -2437,6 +2521,7 @@ class Account(
|
|||||||
directMentionsUsers: Set<User> = emptySet(),
|
directMentionsUsers: Set<User> = emptySet(),
|
||||||
directMentionsNotes: Set<Note> = emptySet(),
|
directMentionsNotes: Set<Note> = emptySet(),
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
zapReceiver: List<ZapSplitSetup>? = null,
|
zapReceiver: List<ZapSplitSetup>? = null,
|
||||||
wantsToMarkAsSensitive: Boolean = false,
|
wantsToMarkAsSensitive: Boolean = false,
|
||||||
zapRaiserAmount: Long? = null,
|
zapRaiserAmount: Long? = null,
|
||||||
@@ -2479,6 +2564,7 @@ class Account(
|
|||||||
addressesMentioned = addressesMentioned,
|
addressesMentioned = addressesMentioned,
|
||||||
eventsMentioned = eventsMentioned,
|
eventsMentioned = eventsMentioned,
|
||||||
imetas = imetas,
|
imetas = imetas,
|
||||||
|
emojis = emojis,
|
||||||
zapReceiver = zapReceiver,
|
zapReceiver = zapReceiver,
|
||||||
markAsSensitive = wantsToMarkAsSensitive,
|
markAsSensitive = wantsToMarkAsSensitive,
|
||||||
zapRaiserAmount = zapRaiserAmount,
|
zapRaiserAmount = zapRaiserAmount,
|
||||||
@@ -2683,6 +2769,7 @@ class Account(
|
|||||||
relayList: List<RelaySetupInfo>,
|
relayList: List<RelaySetupInfo>,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
draftTag: String?,
|
draftTag: String?,
|
||||||
) {
|
) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
@@ -2705,6 +2792,7 @@ class Account(
|
|||||||
directMentions = directMentions,
|
directMentions = directMentions,
|
||||||
geohash = geohash,
|
geohash = geohash,
|
||||||
imetas = imetas,
|
imetas = imetas,
|
||||||
|
emojis = emojis,
|
||||||
forkedFrom = forkedFrom,
|
forkedFrom = forkedFrom,
|
||||||
signer = signer,
|
signer = signer,
|
||||||
isDraft = draftTag != null,
|
isDraft = draftTag != null,
|
||||||
@@ -2775,6 +2863,7 @@ class Account(
|
|||||||
relayList: List<RelaySetupInfo>,
|
relayList: List<RelaySetupInfo>,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
draftTag: String?,
|
draftTag: String?,
|
||||||
) {
|
) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
@@ -2835,6 +2924,7 @@ class Account(
|
|||||||
directMentions: Set<HexKey>,
|
directMentions: Set<HexKey>,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
draftTag: String?,
|
draftTag: String?,
|
||||||
) {
|
) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
@@ -2853,6 +2943,7 @@ class Account(
|
|||||||
directMentions = directMentions,
|
directMentions = directMentions,
|
||||||
geohash = geohash,
|
geohash = geohash,
|
||||||
imetas = imetas,
|
imetas = imetas,
|
||||||
|
emojis = emojis,
|
||||||
signer = signer,
|
signer = signer,
|
||||||
isDraft = draftTag != null,
|
isDraft = draftTag != null,
|
||||||
) {
|
) {
|
||||||
@@ -2881,6 +2972,7 @@ class Account(
|
|||||||
zapRaiserAmount: Long? = null,
|
zapRaiserAmount: Long? = null,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
draftTag: String?,
|
draftTag: String?,
|
||||||
) {
|
) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
@@ -2899,6 +2991,7 @@ class Account(
|
|||||||
zapRaiserAmount = zapRaiserAmount,
|
zapRaiserAmount = zapRaiserAmount,
|
||||||
geohash = geohash,
|
geohash = geohash,
|
||||||
imetas = imetas,
|
imetas = imetas,
|
||||||
|
emojis = emojis,
|
||||||
signer = signer,
|
signer = signer,
|
||||||
isDraft = draftTag != null,
|
isDraft = draftTag != null,
|
||||||
) {
|
) {
|
||||||
@@ -3043,6 +3136,7 @@ class Account(
|
|||||||
zapRaiserAmount: Long? = null,
|
zapRaiserAmount: Long? = null,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
draftTag: String? = null,
|
draftTag: String? = null,
|
||||||
) {
|
) {
|
||||||
if (!isWriteable()) return
|
if (!isWriteable()) return
|
||||||
@@ -3061,6 +3155,7 @@ class Account(
|
|||||||
zapRaiserAmount = zapRaiserAmount,
|
zapRaiserAmount = zapRaiserAmount,
|
||||||
geohash = geohash,
|
geohash = geohash,
|
||||||
imetas = imetas,
|
imetas = imetas,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = draftTag,
|
draftTag = draftTag,
|
||||||
signer = signer,
|
signer = signer,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import com.vitorpamplona.quartz.encoders.Hex
|
|||||||
import com.vitorpamplona.quartz.encoders.HexKey
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
import com.vitorpamplona.quartz.encoders.IMetaTag
|
import com.vitorpamplona.quartz.encoders.IMetaTag
|
||||||
import com.vitorpamplona.quartz.encoders.IMetaTagBuilder
|
import com.vitorpamplona.quartz.encoders.IMetaTagBuilder
|
||||||
|
import com.vitorpamplona.quartz.encoders.Nip30CustomEmoji
|
||||||
import com.vitorpamplona.quartz.encoders.toNpub
|
import com.vitorpamplona.quartz.encoders.toNpub
|
||||||
import com.vitorpamplona.quartz.events.AddressableEvent
|
import com.vitorpamplona.quartz.events.AddressableEvent
|
||||||
import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
|
import com.vitorpamplona.quartz.events.AdvertisedRelayListEvent
|
||||||
@@ -65,6 +66,7 @@ import com.vitorpamplona.quartz.events.ClassifiedsEvent
|
|||||||
import com.vitorpamplona.quartz.events.CommentEvent
|
import com.vitorpamplona.quartz.events.CommentEvent
|
||||||
import com.vitorpamplona.quartz.events.CommunityDefinitionEvent
|
import com.vitorpamplona.quartz.events.CommunityDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.events.DraftEvent
|
import com.vitorpamplona.quartz.events.DraftEvent
|
||||||
|
import com.vitorpamplona.quartz.events.EmojiUrl
|
||||||
import com.vitorpamplona.quartz.events.Event
|
import com.vitorpamplona.quartz.events.Event
|
||||||
import com.vitorpamplona.quartz.events.FileStorageEvent
|
import com.vitorpamplona.quartz.events.FileStorageEvent
|
||||||
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
||||||
@@ -82,7 +84,12 @@ import kotlinx.collections.immutable.ImmutableList
|
|||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
@@ -120,6 +127,27 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
var userSuggestionAnchor: TextRange? = null
|
var userSuggestionAnchor: TextRange? = null
|
||||||
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
var userSuggestionsMainMessage: UserSuggestionAnchor? = null
|
||||||
|
|
||||||
|
val emojiSearch: MutableStateFlow<String> = MutableStateFlow("")
|
||||||
|
val emojiSuggestions: StateFlow<List<Account.EmojiMedia>> by lazy {
|
||||||
|
account!!
|
||||||
|
.myEmojis
|
||||||
|
.combine(emojiSearch) { list, search ->
|
||||||
|
if (search.length == 1) {
|
||||||
|
list
|
||||||
|
} else if (search.isNotEmpty()) {
|
||||||
|
val code = search.removePrefix(":")
|
||||||
|
list.filter { it.code.startsWith(code) }
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}.flowOn(Dispatchers.Default)
|
||||||
|
.stateIn(
|
||||||
|
viewModelScope,
|
||||||
|
SharingStarted.WhileSubscribed(5000),
|
||||||
|
emptyList(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// DMs
|
// DMs
|
||||||
var wantsDirectMessage by mutableStateOf(false)
|
var wantsDirectMessage by mutableStateOf(false)
|
||||||
var toUsers by mutableStateOf(TextFieldValue(""))
|
var toUsers by mutableStateOf(TextFieldValue(""))
|
||||||
@@ -196,6 +224,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
) {
|
) {
|
||||||
this.accountViewModel = accountViewModel
|
this.accountViewModel = accountViewModel
|
||||||
this.account = accountViewModel.account
|
this.account = accountViewModel.account
|
||||||
|
this.emojiSuggestions.value
|
||||||
|
|
||||||
val noteEvent = draft?.event
|
val noteEvent = draft?.event
|
||||||
val noteAuthor = draft?.author
|
val noteAuthor = draft?.author
|
||||||
@@ -552,6 +581,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val emojis = findEmoji(tagger.message, account?.myEmojis?.value)
|
||||||
val urls = findURLs(tagger.message)
|
val urls = findURLs(tagger.message)
|
||||||
val usedAttachments = iMetaAttachments.filter { it.url in urls.toSet() }
|
val usedAttachments = iMetaAttachments.filter { it.url in urls.toSet() }
|
||||||
|
|
||||||
@@ -569,6 +599,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
wantsToMarkAsSensitive = wantsToMarkAsSensitive,
|
wantsToMarkAsSensitive = wantsToMarkAsSensitive,
|
||||||
zapRaiserAmount = localZapRaiserAmount,
|
zapRaiserAmount = localZapRaiserAmount,
|
||||||
relayList = relayList,
|
relayList = relayList,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
} else if (wantsExclusiveGeoPost && geoHash != null && (originalNote == null || originalNote?.event is CommentEvent)) {
|
} else if (wantsExclusiveGeoPost && geoHash != null && (originalNote == null || originalNote?.event is CommentEvent)) {
|
||||||
@@ -583,6 +614,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
wantsToMarkAsSensitive = wantsToMarkAsSensitive,
|
wantsToMarkAsSensitive = wantsToMarkAsSensitive,
|
||||||
zapRaiserAmount = localZapRaiserAmount,
|
zapRaiserAmount = localZapRaiserAmount,
|
||||||
relayList = relayList,
|
relayList = relayList,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
} else if (originalNote?.channelHex() != null) {
|
} else if (originalNote?.channelHex() != null) {
|
||||||
@@ -597,6 +629,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
zapRaiserAmount = localZapRaiserAmount,
|
zapRaiserAmount = localZapRaiserAmount,
|
||||||
geohash = geoHash,
|
geohash = geoHash,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -611,6 +644,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
directMentions = tagger.directMentions,
|
directMentions = tagger.directMentions,
|
||||||
geohash = geoHash,
|
geohash = geoHash,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -639,6 +673,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
zapRaiserAmount = localZapRaiserAmount,
|
zapRaiserAmount = localZapRaiserAmount,
|
||||||
geohash = geoHash,
|
geohash = geoHash,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
} else if (!dmUsers.isNullOrEmpty()) {
|
} else if (!dmUsers.isNullOrEmpty()) {
|
||||||
@@ -654,6 +689,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
zapRaiserAmount = localZapRaiserAmount,
|
zapRaiserAmount = localZapRaiserAmount,
|
||||||
geohash = geoHash,
|
geohash = geoHash,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -708,6 +744,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
relayList = relayList,
|
relayList = relayList,
|
||||||
geohash = geoHash,
|
geohash = geoHash,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
} else if (originalNote?.event is TorrentCommentEvent) {
|
} else if (originalNote?.event is TorrentCommentEvent) {
|
||||||
@@ -747,6 +784,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
relayList = relayList,
|
relayList = relayList,
|
||||||
geohash = geoHash,
|
geohash = geoHash,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -776,6 +814,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
relayList = relayList,
|
relayList = relayList,
|
||||||
geohash = geoHash,
|
geohash = geoHash,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -795,6 +834,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
relayList = relayList,
|
relayList = relayList,
|
||||||
geohash = geoHash,
|
geohash = geoHash,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
} else if (wantsProduct) {
|
} else if (wantsProduct) {
|
||||||
@@ -814,6 +854,7 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
relayList = relayList,
|
relayList = relayList,
|
||||||
geohash = geoHash,
|
geohash = geoHash,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -851,12 +892,23 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
relayList = relayList,
|
relayList = relayList,
|
||||||
geohash = geoHash,
|
geohash = geoHash,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = localDraft,
|
draftTag = localDraft,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun findEmoji(
|
||||||
|
message: String,
|
||||||
|
myEmojiSet: List<Account.EmojiMedia>?,
|
||||||
|
): List<EmojiUrl> {
|
||||||
|
if (myEmojiSet == null) return emptyList()
|
||||||
|
return Nip30CustomEmoji.findAllEmojiCodes(message).mapNotNull { possibleEmoji ->
|
||||||
|
myEmojiSet.firstOrNull { it.code == possibleEmoji }?.let { EmojiUrl(it.code, it.url.url) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun upload(
|
fun upload(
|
||||||
alt: String?,
|
alt: String?,
|
||||||
sensitiveContent: Boolean,
|
sensitiveContent: Boolean,
|
||||||
@@ -978,6 +1030,10 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
userSuggestionAnchor = null
|
userSuggestionAnchor = null
|
||||||
userSuggestionsMainMessage = null
|
userSuggestionsMainMessage = null
|
||||||
|
|
||||||
|
if (emojiSearch.value.isNotEmpty()) {
|
||||||
|
emojiSearch.tryEmit("")
|
||||||
|
}
|
||||||
|
|
||||||
draftTag = UUID.randomUUID().toString()
|
draftTag = UUID.randomUUID().toString()
|
||||||
|
|
||||||
NostrSearchEventOrUserDataSource.clear()
|
NostrSearchEventOrUserDataSource.clear()
|
||||||
@@ -1029,6 +1085,14 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
NostrSearchEventOrUserDataSource.clear()
|
NostrSearchEventOrUserDataSource.clear()
|
||||||
userSuggestions = emptyList()
|
userSuggestions = emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lastWord.startsWith(":")) {
|
||||||
|
emojiSearch.tryEmit(lastWord)
|
||||||
|
} else {
|
||||||
|
if (emojiSearch.value.isNotBlank()) {
|
||||||
|
emojiSearch.tryEmit("")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
saveDraft()
|
saveDraft()
|
||||||
@@ -1132,6 +1196,54 @@ open class NewPostViewModel : ViewModel() {
|
|||||||
saveDraft()
|
saveDraft()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun autocompleteWithEmoji(item: Account.EmojiMedia) {
|
||||||
|
userSuggestionAnchor?.let {
|
||||||
|
val lastWord =
|
||||||
|
message.text
|
||||||
|
.substring(0, it.end)
|
||||||
|
.substringAfterLast("\n")
|
||||||
|
.substringAfterLast(" ")
|
||||||
|
val lastWordStart = it.end - lastWord.length
|
||||||
|
val wordToInsert = ":${item.code}:"
|
||||||
|
|
||||||
|
message =
|
||||||
|
TextFieldValue(
|
||||||
|
message.text.replaceRange(lastWordStart, it.end, wordToInsert),
|
||||||
|
TextRange(lastWordStart + wordToInsert.length, lastWordStart + wordToInsert.length),
|
||||||
|
)
|
||||||
|
|
||||||
|
userSuggestionAnchor = null
|
||||||
|
emojiSearch.tryEmit("")
|
||||||
|
}
|
||||||
|
|
||||||
|
saveDraft()
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun autocompleteWithEmojiUrl(item: Account.EmojiMedia) {
|
||||||
|
userSuggestionAnchor?.let {
|
||||||
|
val lastWord =
|
||||||
|
message.text
|
||||||
|
.substring(0, it.end)
|
||||||
|
.substringAfterLast("\n")
|
||||||
|
.substringAfterLast(" ")
|
||||||
|
val lastWordStart = it.end - lastWord.length
|
||||||
|
val wordToInsert = item.url.url + " "
|
||||||
|
|
||||||
|
message =
|
||||||
|
TextFieldValue(
|
||||||
|
message.text.replaceRange(lastWordStart, it.end, wordToInsert),
|
||||||
|
TextRange(lastWordStart + wordToInsert.length, lastWordStart + wordToInsert.length),
|
||||||
|
)
|
||||||
|
|
||||||
|
userSuggestionAnchor = null
|
||||||
|
emojiSearch.tryEmit("")
|
||||||
|
}
|
||||||
|
|
||||||
|
urlPreview = findUrlInMessage()
|
||||||
|
|
||||||
|
saveDraft()
|
||||||
|
}
|
||||||
|
|
||||||
private fun newStateMapPollOptions(): SnapshotStateMap<Int, String> = mutableStateMapOf(Pair(0, ""), Pair(1, ""))
|
private fun newStateMapPollOptions(): SnapshotStateMap<Int, String> = mutableStateMapOf(Pair(0, ""), Pair(1, ""))
|
||||||
|
|
||||||
fun canPost(): Boolean =
|
fun canPost(): Boolean =
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.note
|
||||||
|
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.content.MediaType.Companion.Text
|
||||||
|
import androidx.compose.foundation.layout.Arrangement.spacedBy
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.OpenInFull
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import androidx.lifecycle.distinctUntilChanged
|
||||||
|
import androidx.lifecycle.map
|
||||||
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import com.vitorpamplona.amethyst.model.Account
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.profile.gallery.UrlImageView
|
||||||
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
||||||
|
import com.vitorpamplona.quartz.events.EmojiPackSelectionEvent
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun WatchAndLoadMyEmojiList(accountViewModel: AccountViewModel) {
|
||||||
|
LoadAddressableNote(
|
||||||
|
EmojiPackSelectionEvent.createAddressATag(accountViewModel.userProfile().pubkeyHex),
|
||||||
|
accountViewModel,
|
||||||
|
) { emptyNote ->
|
||||||
|
emptyNote?.let { usersEmojiList ->
|
||||||
|
val collections by usersEmojiList
|
||||||
|
.live()
|
||||||
|
.metadata
|
||||||
|
.map { (it.note.event as? EmojiPackSelectionEvent)?.taggedAddresses()?.toImmutableList() }
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.observeAsState((usersEmojiList.event as? EmojiPackSelectionEvent)?.taggedAddresses()?.toImmutableList())
|
||||||
|
|
||||||
|
collections?.forEach {
|
||||||
|
LoadAddressableNote(aTag = it, accountViewModel) {
|
||||||
|
it?.live()?.metadata?.observeAsState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ShowEmojiSuggestionList(
|
||||||
|
emojiSuggestions: Flow<List<Account.EmojiMedia>>,
|
||||||
|
onSelect: (Account.EmojiMedia) -> Unit,
|
||||||
|
onFullSize: (Account.EmojiMedia) -> Unit,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
modifier: Modifier = Modifier.heightIn(0.dp, 200.dp),
|
||||||
|
) {
|
||||||
|
val suggestions by emojiSuggestions.collectAsStateWithLifecycle(emptyList())
|
||||||
|
|
||||||
|
if (suggestions.isNotEmpty()) {
|
||||||
|
LazyColumn(
|
||||||
|
contentPadding = PaddingValues(top = 10.dp),
|
||||||
|
modifier = modifier,
|
||||||
|
) {
|
||||||
|
items(suggestions) {
|
||||||
|
Row(
|
||||||
|
modifier =
|
||||||
|
Modifier.clickable { onSelect(it) }.padding(
|
||||||
|
start = 12.dp,
|
||||||
|
end = 12.dp,
|
||||||
|
top = 10.dp,
|
||||||
|
bottom = 10.dp,
|
||||||
|
),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = spacedBy(Size10dp),
|
||||||
|
) {
|
||||||
|
Box(Modifier.size(40.dp)) {
|
||||||
|
UrlImageView(it.url, accountViewModel)
|
||||||
|
}
|
||||||
|
Text(it.code, fontWeight = FontWeight.Bold, modifier = Modifier.weight(1f))
|
||||||
|
Box(Modifier.size(40.dp), contentAlignment = Alignment.Center) {
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
onFullSize(it)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.OpenInFull,
|
||||||
|
contentDescription = stringRes(R.string.use_direct_url),
|
||||||
|
modifier = Modifier.size(20.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HorizontalDivider(
|
||||||
|
thickness = DividerThickness,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -144,7 +144,6 @@ class UpdateReactionTypeViewModel : ViewModel() {
|
|||||||
?.value
|
?.value
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UpdateReactionTypeDialog(
|
fun UpdateReactionTypeDialog(
|
||||||
onClose: () -> Unit,
|
onClose: () -> Unit,
|
||||||
|
|||||||
@@ -157,8 +157,10 @@ import com.vitorpamplona.amethyst.ui.note.LoadCityName
|
|||||||
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
||||||
import com.vitorpamplona.amethyst.ui.note.PollIcon
|
import com.vitorpamplona.amethyst.ui.note.PollIcon
|
||||||
import com.vitorpamplona.amethyst.ui.note.RegularPostIcon
|
import com.vitorpamplona.amethyst.ui.note.RegularPostIcon
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.ShowEmojiSuggestionList
|
||||||
import com.vitorpamplona.amethyst.ui.note.ShowUserSuggestionList
|
import com.vitorpamplona.amethyst.ui.note.ShowUserSuggestionList
|
||||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.WatchAndLoadMyEmojiList
|
||||||
import com.vitorpamplona.amethyst.ui.note.ZapSplitIcon
|
import com.vitorpamplona.amethyst.ui.note.ZapSplitIcon
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatrooms.MyTextField
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatrooms.MyTextField
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsRow
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.settings.SettingsRow
|
||||||
@@ -209,6 +211,7 @@ fun NewPostScreen(
|
|||||||
nav: Nav,
|
nav: Nav,
|
||||||
) {
|
) {
|
||||||
val postViewModel: NewPostViewModel = viewModel()
|
val postViewModel: NewPostViewModel = viewModel()
|
||||||
|
postViewModel.account = accountViewModel.account
|
||||||
postViewModel.wantsDirectMessage = enableMessageInterface
|
postViewModel.wantsDirectMessage = enableMessageInterface
|
||||||
postViewModel.wantsToAddGeoHash = enableGeolocation
|
postViewModel.wantsToAddGeoHash = enableGeolocation
|
||||||
|
|
||||||
@@ -278,6 +281,8 @@ fun NewPostScreen(
|
|||||||
onDispose { activity.removeOnNewIntentListener(consumer) }
|
onDispose { activity.removeOnNewIntentListener(consumer) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WatchAndLoadMyEmojiList(accountViewModel)
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
@@ -575,6 +580,14 @@ fun NewPostScreen(
|
|||||||
modifier = Modifier.heightIn(0.dp, 300.dp),
|
modifier = Modifier.heightIn(0.dp, 300.dp),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ShowEmojiSuggestionList(
|
||||||
|
postViewModel.emojiSuggestions,
|
||||||
|
postViewModel::autocompleteWithEmoji,
|
||||||
|
postViewModel::autocompleteWithEmojiUrl,
|
||||||
|
accountViewModel,
|
||||||
|
modifier = Modifier.heightIn(0.dp, 300.dp),
|
||||||
|
)
|
||||||
|
|
||||||
BottomRowActions(postViewModel)
|
BottomRowActions(postViewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -130,6 +130,7 @@ import com.vitorpamplona.amethyst.ui.note.LikeReaction
|
|||||||
import com.vitorpamplona.amethyst.ui.note.LoadChannel
|
import com.vitorpamplona.amethyst.ui.note.LoadChannel
|
||||||
import com.vitorpamplona.amethyst.ui.note.NoteAuthorPicture
|
import com.vitorpamplona.amethyst.ui.note.NoteAuthorPicture
|
||||||
import com.vitorpamplona.amethyst.ui.note.NoteUsernameDisplay
|
import com.vitorpamplona.amethyst.ui.note.NoteUsernameDisplay
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.ShowEmojiSuggestionList
|
||||||
import com.vitorpamplona.amethyst.ui.note.ShowUserSuggestionList
|
import com.vitorpamplona.amethyst.ui.note.ShowUserSuggestionList
|
||||||
import com.vitorpamplona.amethyst.ui.note.UserPicture
|
import com.vitorpamplona.amethyst.ui.note.UserPicture
|
||||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||||
@@ -397,6 +398,7 @@ private suspend fun innerSendPost(
|
|||||||
|
|
||||||
val urls = findURLs(tagger.message)
|
val urls = findURLs(tagger.message)
|
||||||
val usedAttachments = newPostModel.iMetaAttachments.filter { it.url in urls.toSet() }
|
val usedAttachments = newPostModel.iMetaAttachments.filter { it.url in urls.toSet() }
|
||||||
|
val emojis = newPostModel.findEmoji(newPostModel.message.text, accountViewModel.account.myEmojis.value)
|
||||||
|
|
||||||
if (channel is PublicChatChannel) {
|
if (channel is PublicChatChannel) {
|
||||||
accountViewModel.account.sendChannelMessage(
|
accountViewModel.account.sendChannelMessage(
|
||||||
@@ -407,6 +409,7 @@ private suspend fun innerSendPost(
|
|||||||
directMentions = tagger.directMentions,
|
directMentions = tagger.directMentions,
|
||||||
wantsToMarkAsSensitive = false,
|
wantsToMarkAsSensitive = false,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = draftTag,
|
draftTag = draftTag,
|
||||||
)
|
)
|
||||||
} else if (channel is LiveActivitiesChannel) {
|
} else if (channel is LiveActivitiesChannel) {
|
||||||
@@ -417,6 +420,7 @@ private suspend fun innerSendPost(
|
|||||||
mentions = tagger.pTags,
|
mentions = tagger.pTags,
|
||||||
wantsToMarkAsSensitive = false,
|
wantsToMarkAsSensitive = false,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = draftTag,
|
draftTag = draftTag,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -485,6 +489,13 @@ fun EditFieldRow(
|
|||||||
accountViewModel,
|
accountViewModel,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ShowEmojiSuggestionList(
|
||||||
|
channelScreenModel.emojiSuggestions,
|
||||||
|
channelScreenModel::autocompleteWithEmoji,
|
||||||
|
channelScreenModel::autocompleteWithEmojiUrl,
|
||||||
|
accountViewModel,
|
||||||
|
)
|
||||||
|
|
||||||
MyTextField(
|
MyTextField(
|
||||||
value = channelScreenModel.message,
|
value = channelScreenModel.message,
|
||||||
onValueChange = { channelScreenModel.updateMessage(it) },
|
onValueChange = { channelScreenModel.updateMessage(it) },
|
||||||
|
|||||||
+10
@@ -95,6 +95,7 @@ import com.vitorpamplona.amethyst.ui.note.IncognitoIconOff
|
|||||||
import com.vitorpamplona.amethyst.ui.note.IncognitoIconOn
|
import com.vitorpamplona.amethyst.ui.note.IncognitoIconOn
|
||||||
import com.vitorpamplona.amethyst.ui.note.NonClickableUserPictures
|
import com.vitorpamplona.amethyst.ui.note.NonClickableUserPictures
|
||||||
import com.vitorpamplona.amethyst.ui.note.QuickActionAlertDialog
|
import com.vitorpamplona.amethyst.ui.note.QuickActionAlertDialog
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.ShowEmojiSuggestionList
|
||||||
import com.vitorpamplona.amethyst.ui.note.ShowUserSuggestionList
|
import com.vitorpamplona.amethyst.ui.note.ShowUserSuggestionList
|
||||||
import com.vitorpamplona.amethyst.ui.note.UserCompose
|
import com.vitorpamplona.amethyst.ui.note.UserCompose
|
||||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||||
@@ -517,6 +518,7 @@ private fun innerSendPost(
|
|||||||
) {
|
) {
|
||||||
val urls = findURLs(newPostModel.message.text)
|
val urls = findURLs(newPostModel.message.text)
|
||||||
val usedAttachments = newPostModel.iMetaAttachments.filter { it.url !in urls.toSet() }
|
val usedAttachments = newPostModel.iMetaAttachments.filter { it.url !in urls.toSet() }
|
||||||
|
val emojis = newPostModel.findEmoji(newPostModel.message.text, accountViewModel.account.myEmojis.value)
|
||||||
|
|
||||||
if (newPostModel.nip17 || room.users.size > 1 || replyTo.value?.event is NIP17Group) {
|
if (newPostModel.nip17 || room.users.size > 1 || replyTo.value?.event is NIP17Group) {
|
||||||
accountViewModel.account.sendNIP17PrivateMessage(
|
accountViewModel.account.sendNIP17PrivateMessage(
|
||||||
@@ -526,6 +528,7 @@ private fun innerSendPost(
|
|||||||
mentions = null,
|
mentions = null,
|
||||||
wantsToMarkAsSensitive = false,
|
wantsToMarkAsSensitive = false,
|
||||||
imetas = usedAttachments,
|
imetas = usedAttachments,
|
||||||
|
emojis = emojis,
|
||||||
draftTag = dTag,
|
draftTag = dTag,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -557,6 +560,13 @@ fun PrivateMessageEditFieldRow(
|
|||||||
accountViewModel,
|
accountViewModel,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ShowEmojiSuggestionList(
|
||||||
|
channelScreenModel.emojiSuggestions,
|
||||||
|
channelScreenModel::autocompleteWithEmoji,
|
||||||
|
channelScreenModel::autocompleteWithEmojiUrl,
|
||||||
|
accountViewModel,
|
||||||
|
)
|
||||||
|
|
||||||
MyTextField(
|
MyTextField(
|
||||||
value = channelScreenModel.message,
|
value = channelScreenModel.message,
|
||||||
onValueChange = { channelScreenModel.updateMessage(it) },
|
onValueChange = { channelScreenModel.updateMessage(it) },
|
||||||
|
|||||||
@@ -377,6 +377,8 @@
|
|||||||
<string name="add_caption">Add a Caption</string>
|
<string name="add_caption">Add a Caption</string>
|
||||||
<string name="add_caption_example">My lovely friend</string>
|
<string name="add_caption_example">My lovely friend</string>
|
||||||
|
|
||||||
|
<string name="use_direct_url">Use direct URL</string>
|
||||||
|
|
||||||
<string name="content_description">Description of the contents</string>
|
<string name="content_description">Description of the contents</string>
|
||||||
<string name="content_description_example">A blue boat in a white sandy beach at sunset</string>
|
<string name="content_description_example">A blue boat in a white sandy beach at sunset</string>
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,24 @@ class Nip30CustomEmoji {
|
|||||||
|
|
||||||
fun createEmojiMap(tags: ImmutableListOfLists<String>): Map<String, String> = tags.lists.filter { it.size > 2 && it[0] == "emoji" }.associate { ":${it[1]}:" to it[2] }
|
fun createEmojiMap(tags: ImmutableListOfLists<String>): Map<String, String> = tags.lists.filter { it.size > 2 && it[0] == "emoji" }.associate { ":${it[1]}:" to it[2] }
|
||||||
|
|
||||||
|
fun findAllEmojis(input: String): List<String> {
|
||||||
|
val matcher = customEmojiPattern.matcher(input)
|
||||||
|
val emojiNamesInOrder = mutableListOf<String>()
|
||||||
|
while (matcher.find()) {
|
||||||
|
emojiNamesInOrder.add(matcher.group())
|
||||||
|
}
|
||||||
|
return emojiNamesInOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findAllEmojiCodes(input: String): List<String> {
|
||||||
|
val matcher = customEmojiPattern.matcher(input)
|
||||||
|
val emojiNamesInOrder = mutableListOf<String>()
|
||||||
|
while (matcher.find()) {
|
||||||
|
matcher.group(1)?.let { emojiNamesInOrder.add(it) }
|
||||||
|
}
|
||||||
|
return emojiNamesInOrder
|
||||||
|
}
|
||||||
|
|
||||||
fun assembleAnnotatedList(
|
fun assembleAnnotatedList(
|
||||||
input: String,
|
input: String,
|
||||||
allTags: ImmutableListOfLists<String>?,
|
allTags: ImmutableListOfLists<String>?,
|
||||||
@@ -65,12 +83,7 @@ class Nip30CustomEmoji {
|
|||||||
input: String,
|
input: String,
|
||||||
emojiPairs: Map<String, String>,
|
emojiPairs: Map<String, String>,
|
||||||
): ImmutableList<Renderable>? {
|
): ImmutableList<Renderable>? {
|
||||||
val matcher = customEmojiPattern.matcher(input)
|
val emojiNamesInOrder = findAllEmojis(input)
|
||||||
val emojiNamesInOrder = mutableListOf<String>()
|
|
||||||
while (matcher.find()) {
|
|
||||||
emojiNamesInOrder.add(matcher.group())
|
|
||||||
}
|
|
||||||
|
|
||||||
if (emojiNamesInOrder.isEmpty()) {
|
if (emojiNamesInOrder.isEmpty()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class ChannelMessageEvent(
|
|||||||
directMentions: Set<HexKey> = emptySet(),
|
directMentions: Set<HexKey> = emptySet(),
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
isDraft: Boolean,
|
isDraft: Boolean,
|
||||||
onReady: (ChannelMessageEvent) -> Unit,
|
onReady: (ChannelMessageEvent) -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -88,6 +89,7 @@ class ChannelMessageEvent(
|
|||||||
imetas?.forEach {
|
imetas?.forEach {
|
||||||
tags.add(Nip92MediaAttachments.createTag(it))
|
tags.add(Nip92MediaAttachments.createTag(it))
|
||||||
}
|
}
|
||||||
|
emojis?.forEach { tags.add(it.toTagArray()) }
|
||||||
tags.add(
|
tags.add(
|
||||||
arrayOf("alt", ALT),
|
arrayOf("alt", ALT),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ class ChatMessageEvent(
|
|||||||
signer: NostrSigner,
|
signer: NostrSigner,
|
||||||
createdAt: Long = TimeUtils.now(),
|
createdAt: Long = TimeUtils.now(),
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
isDraft: Boolean,
|
isDraft: Boolean,
|
||||||
onReady: (ChatMessageEvent) -> Unit,
|
onReady: (ChatMessageEvent) -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -103,6 +104,7 @@ class ChatMessageEvent(
|
|||||||
imetas?.forEach {
|
imetas?.forEach {
|
||||||
tags.add(Nip92MediaAttachments.createTag(it))
|
tags.add(Nip92MediaAttachments.createTag(it))
|
||||||
}
|
}
|
||||||
|
emojis?.forEach { tags.add(it.toTagArray()) }
|
||||||
// tags.add(arrayOf("alt", alt))
|
// tags.add(arrayOf("alt", alt))
|
||||||
|
|
||||||
if (isDraft) {
|
if (isDraft) {
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ class ClassifiedsEvent(
|
|||||||
zapRaiserAmount: Long?,
|
zapRaiserAmount: Long?,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
signer: NostrSigner,
|
signer: NostrSigner,
|
||||||
createdAt: Long = TimeUtils.now(),
|
createdAt: Long = TimeUtils.now(),
|
||||||
isDraft: Boolean,
|
isDraft: Boolean,
|
||||||
@@ -190,9 +191,8 @@ class ClassifiedsEvent(
|
|||||||
}
|
}
|
||||||
zapRaiserAmount?.let { tags.add(arrayOf("zapraiser", "$it")) }
|
zapRaiserAmount?.let { tags.add(arrayOf("zapraiser", "$it")) }
|
||||||
geohash?.let { tags.addAll(geohashMipMap(it)) }
|
geohash?.let { tags.addAll(geohashMipMap(it)) }
|
||||||
imetas?.forEach {
|
imetas?.forEach { tags.add(Nip92MediaAttachments.createTag(it)) }
|
||||||
tags.add(Nip92MediaAttachments.createTag(it))
|
emojis?.forEach { tags.add(it.toTagArray()) }
|
||||||
}
|
|
||||||
tags.add(arrayOf("alt", ALT))
|
tags.add(arrayOf("alt", ALT))
|
||||||
|
|
||||||
if (isDraft) {
|
if (isDraft) {
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ class CommentEvent(
|
|||||||
addressesMentioned: Set<ATag> = emptySet(),
|
addressesMentioned: Set<ATag> = emptySet(),
|
||||||
eventsMentioned: Set<ETag> = emptySet(),
|
eventsMentioned: Set<ETag> = emptySet(),
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
zapReceiver: List<ZapSplitSetup>? = null,
|
zapReceiver: List<ZapSplitSetup>? = null,
|
||||||
markAsSensitive: Boolean = false,
|
markAsSensitive: Boolean = false,
|
||||||
@@ -120,7 +121,7 @@ class CommentEvent(
|
|||||||
tags.add(removeTrailingNullsAndEmptyOthers("e", replyingTo.event.id, replyingTo.relay, replyingTo.event.pubKey))
|
tags.add(removeTrailingNullsAndEmptyOthers("e", replyingTo.event.id, replyingTo.relay, replyingTo.event.pubKey))
|
||||||
tags.add(arrayOf("k", "${replyingTo.event.kind}"))
|
tags.add(arrayOf("k", "${replyingTo.event.kind}"))
|
||||||
|
|
||||||
create(msg, tags, usersMentioned, addressesMentioned, eventsMentioned, imetas, geohash, zapReceiver, markAsSensitive, zapRaiserAmount, isDraft, signer, createdAt, onReady)
|
create(msg, tags, usersMentioned, addressesMentioned, eventsMentioned, imetas, emojis, geohash, zapReceiver, markAsSensitive, zapRaiserAmount, isDraft, signer, createdAt, onReady)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun replyComment(
|
fun replyComment(
|
||||||
@@ -130,6 +131,7 @@ class CommentEvent(
|
|||||||
addressesMentioned: Set<ATag> = emptySet(),
|
addressesMentioned: Set<ATag> = emptySet(),
|
||||||
eventsMentioned: Set<ETag> = emptySet(),
|
eventsMentioned: Set<ETag> = emptySet(),
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
zapReceiver: List<ZapSplitSetup>? = null,
|
zapReceiver: List<ZapSplitSetup>? = null,
|
||||||
markAsSensitive: Boolean = false,
|
markAsSensitive: Boolean = false,
|
||||||
@@ -147,7 +149,7 @@ class CommentEvent(
|
|||||||
tags.add(removeTrailingNullsAndEmptyOthers("e", replyingTo.event.id, replyingTo.relay, replyingTo.event.pubKey))
|
tags.add(removeTrailingNullsAndEmptyOthers("e", replyingTo.event.id, replyingTo.relay, replyingTo.event.pubKey))
|
||||||
tags.add(arrayOf("k", "${replyingTo.event.kind}"))
|
tags.add(arrayOf("k", "${replyingTo.event.kind}"))
|
||||||
|
|
||||||
create(msg, tags, usersMentioned, addressesMentioned, eventsMentioned, imetas, geohash, zapReceiver, markAsSensitive, zapRaiserAmount, isDraft, signer, createdAt, onReady)
|
create(msg, tags, usersMentioned, addressesMentioned, eventsMentioned, imetas, emojis, geohash, zapReceiver, markAsSensitive, zapRaiserAmount, isDraft, signer, createdAt, onReady)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createGeoComment(
|
fun createGeoComment(
|
||||||
@@ -157,6 +159,7 @@ class CommentEvent(
|
|||||||
addressesMentioned: Set<ATag> = emptySet(),
|
addressesMentioned: Set<ATag> = emptySet(),
|
||||||
eventsMentioned: Set<ETag> = emptySet(),
|
eventsMentioned: Set<ETag> = emptySet(),
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
zapReceiver: List<ZapSplitSetup>? = null,
|
zapReceiver: List<ZapSplitSetup>? = null,
|
||||||
markAsSensitive: Boolean = false,
|
markAsSensitive: Boolean = false,
|
||||||
zapRaiserAmount: Long? = null,
|
zapRaiserAmount: Long? = null,
|
||||||
@@ -169,7 +172,7 @@ class CommentEvent(
|
|||||||
geohash?.let { tags.addAll(rootGeohashMipMap(it)) }
|
geohash?.let { tags.addAll(rootGeohashMipMap(it)) }
|
||||||
tags.add(arrayOf("K", "geo"))
|
tags.add(arrayOf("K", "geo"))
|
||||||
|
|
||||||
create(msg, tags, usersMentioned, addressesMentioned, eventsMentioned, imetas, null, zapReceiver, markAsSensitive, zapRaiserAmount, isDraft, signer, createdAt, onReady)
|
create(msg, tags, usersMentioned, addressesMentioned, eventsMentioned, imetas, emojis, null, zapReceiver, markAsSensitive, zapRaiserAmount, isDraft, signer, createdAt, onReady)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun create(
|
private fun create(
|
||||||
@@ -179,6 +182,7 @@ class CommentEvent(
|
|||||||
addressesMentioned: Set<ATag> = emptySet(),
|
addressesMentioned: Set<ATag> = emptySet(),
|
||||||
eventsMentioned: Set<ETag> = emptySet(),
|
eventsMentioned: Set<ETag> = emptySet(),
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
zapReceiver: List<ZapSplitSetup>? = null,
|
zapReceiver: List<ZapSplitSetup>? = null,
|
||||||
markAsSensitive: Boolean = false,
|
markAsSensitive: Boolean = false,
|
||||||
@@ -202,6 +206,8 @@ class CommentEvent(
|
|||||||
|
|
||||||
findURLs(msg).forEach { tags.add(arrayOf("r", it)) }
|
findURLs(msg).forEach { tags.add(arrayOf("r", it)) }
|
||||||
|
|
||||||
|
emojis?.forEach { tags.add(it.toTagArray()) }
|
||||||
|
|
||||||
zapReceiver?.forEach {
|
zapReceiver?.forEach {
|
||||||
tags.add(arrayOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString()))
|
tags.add(arrayOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ data class EmojiUrl(
|
|||||||
) {
|
) {
|
||||||
fun encode(): String = ":$code:$url"
|
fun encode(): String = ":$code:$url"
|
||||||
|
|
||||||
|
fun toTagArray() = arrayOf("emoji", code, url)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun decode(encodedEmojiSetup: String): EmojiUrl? {
|
fun decode(encodedEmojiSetup: String): EmojiUrl? {
|
||||||
val emojiParts = encodedEmojiSetup.split(":", limit = 3)
|
val emojiParts = encodedEmojiSetup.split(":", limit = 3)
|
||||||
@@ -71,5 +73,12 @@ data class EmojiUrl(
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun parse(tag: Array<String>): EmojiUrl? =
|
||||||
|
if (tag.size > 2 && tag[0] == "emoji") {
|
||||||
|
EmojiUrl(tag[1], tag[2])
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ class EmojiPackSelectionEvent(
|
|||||||
const val FIXED_D_TAG = ""
|
const val FIXED_D_TAG = ""
|
||||||
const val ALT = "Emoji selection"
|
const val ALT = "Emoji selection"
|
||||||
|
|
||||||
|
fun createAddressATag(pubKey: HexKey): ATag = ATag(KIND, pubKey, AdvertisedRelayListEvent.FIXED_D_TAG, null)
|
||||||
|
|
||||||
|
fun createAddressTag(pubKey: HexKey): String = ATag.assembleATag(KIND, pubKey, AdvertisedRelayListEvent.FIXED_D_TAG)
|
||||||
|
|
||||||
fun create(
|
fun create(
|
||||||
listOfEmojiPacks: List<ATag>?,
|
listOfEmojiPacks: List<ATag>?,
|
||||||
signer: NostrSigner,
|
signer: NostrSigner,
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ open class Event(
|
|||||||
ATag.parse(aTagValue, relay)
|
ATag.parse(aTagValue, relay)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun taggedEmojis() = tags.filter { it.size > 2 && it[0] == "emoji" }.map { EmojiUrl(it[1], it[2]) }
|
override fun taggedEmojis() = tags.filter { it.size > 2 && it[0] == "emoji" }.mapNotNull { EmojiUrl.parse(it) }
|
||||||
|
|
||||||
override fun isSensitive() =
|
override fun isSensitive() =
|
||||||
tags.any {
|
tags.any {
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ class GitReplyEvent(
|
|||||||
directMentions: Set<HexKey> = emptySet(),
|
directMentions: Set<HexKey> = emptySet(),
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
forkedFrom: Event? = null,
|
forkedFrom: Event? = null,
|
||||||
signer: NostrSigner,
|
signer: NostrSigner,
|
||||||
createdAt: Long = TimeUtils.now(),
|
createdAt: Long = TimeUtils.now(),
|
||||||
@@ -152,6 +153,7 @@ class GitReplyEvent(
|
|||||||
imetas?.forEach {
|
imetas?.forEach {
|
||||||
tags.add(Nip92MediaAttachments.createTag(it))
|
tags.add(Nip92MediaAttachments.createTag(it))
|
||||||
}
|
}
|
||||||
|
emojis?.forEach { tags.add(it.toTagArray()) }
|
||||||
tags.add(arrayOf("alt", "a git issue reply"))
|
tags.add(arrayOf("alt", "a git issue reply"))
|
||||||
|
|
||||||
if (isDraft) {
|
if (isDraft) {
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ open class InteractiveStoryBaseEvent(
|
|||||||
zapRaiserAmount: Long? = null,
|
zapRaiserAmount: Long? = null,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
): Array<Array<String>> {
|
): Array<Array<String>> {
|
||||||
val tags = mutableListOf<Array<String>>()
|
val tags = mutableListOf<Array<String>>()
|
||||||
findHashtags(content).forEach {
|
findHashtags(content).forEach {
|
||||||
@@ -75,6 +76,7 @@ open class InteractiveStoryBaseEvent(
|
|||||||
imetas?.forEach {
|
imetas?.forEach {
|
||||||
tags.add(Nip92MediaAttachments.createTag(it))
|
tags.add(Nip92MediaAttachments.createTag(it))
|
||||||
}
|
}
|
||||||
|
emojis?.forEach { tags.add(it.toTagArray()) }
|
||||||
return tags.toTypedArray()
|
return tags.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ class LiveActivitiesChatMessageEvent(
|
|||||||
zapRaiserAmount: Long?,
|
zapRaiserAmount: Long?,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
isDraft: Boolean,
|
isDraft: Boolean,
|
||||||
onReady: (LiveActivitiesChatMessageEvent) -> Unit,
|
onReady: (LiveActivitiesChatMessageEvent) -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -96,6 +97,7 @@ class LiveActivitiesChatMessageEvent(
|
|||||||
imetas?.forEach {
|
imetas?.forEach {
|
||||||
tags.add(Nip92MediaAttachments.createTag(it))
|
tags.add(Nip92MediaAttachments.createTag(it))
|
||||||
}
|
}
|
||||||
|
emojis?.forEach { tags.add(it.toTagArray()) }
|
||||||
tags.add(arrayOf("alt", ALT))
|
tags.add(arrayOf("alt", ALT))
|
||||||
|
|
||||||
if (isDraft) {
|
if (isDraft) {
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ class NIP17Factory {
|
|||||||
zapRaiserAmount: Long? = null,
|
zapRaiserAmount: Long? = null,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
draftTag: String? = null,
|
draftTag: String? = null,
|
||||||
onReady: (Result) -> Unit,
|
onReady: (Result) -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -100,6 +101,7 @@ class NIP17Factory {
|
|||||||
geohash = geohash,
|
geohash = geohash,
|
||||||
isDraft = draftTag != null,
|
isDraft = draftTag != null,
|
||||||
imetas = imetas,
|
imetas = imetas,
|
||||||
|
emojis = emojis,
|
||||||
) { senderMessage ->
|
) { senderMessage ->
|
||||||
if (draftTag != null) {
|
if (draftTag != null) {
|
||||||
onReady(
|
onReady(
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ class PollNoteEvent(
|
|||||||
zapRaiserAmount: Long?,
|
zapRaiserAmount: Long?,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
isDraft: Boolean,
|
isDraft: Boolean,
|
||||||
onReady: (PollNoteEvent) -> Unit,
|
onReady: (PollNoteEvent) -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -108,6 +109,7 @@ class PollNoteEvent(
|
|||||||
imetas?.forEach {
|
imetas?.forEach {
|
||||||
tags.add(Nip92MediaAttachments.createTag(it))
|
tags.add(Nip92MediaAttachments.createTag(it))
|
||||||
}
|
}
|
||||||
|
emojis?.forEach { tags.add(it.toTagArray()) }
|
||||||
tags.add(arrayOf("alt", ALT))
|
tags.add(arrayOf("alt", ALT))
|
||||||
|
|
||||||
if (isDraft) {
|
if (isDraft) {
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ class TextNoteEvent(
|
|||||||
directMentions: Set<HexKey> = emptySet(),
|
directMentions: Set<HexKey> = emptySet(),
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
forkedFrom: Event? = null,
|
forkedFrom: Event? = null,
|
||||||
signer: NostrSigner,
|
signer: NostrSigner,
|
||||||
createdAt: Long = TimeUtils.now(),
|
createdAt: Long = TimeUtils.now(),
|
||||||
@@ -123,9 +124,8 @@ class TextNoteEvent(
|
|||||||
}
|
}
|
||||||
zapRaiserAmount?.let { tags.add(arrayOf("zapraiser", "$it")) }
|
zapRaiserAmount?.let { tags.add(arrayOf("zapraiser", "$it")) }
|
||||||
geohash?.let { tags.addAll(geohashMipMap(it)) }
|
geohash?.let { tags.addAll(geohashMipMap(it)) }
|
||||||
imetas?.forEach {
|
imetas?.forEach { tags.add(Nip92MediaAttachments.createTag(it)) }
|
||||||
tags.add(Nip92MediaAttachments.createTag(it))
|
emojis?.forEach { tags.add(it.toTagArray()) }
|
||||||
}
|
|
||||||
|
|
||||||
if (isDraft) {
|
if (isDraft) {
|
||||||
signer.assembleRumor(createdAt, KIND, tags.toTypedArray(), msg, onReady)
|
signer.assembleRumor(createdAt, KIND, tags.toTypedArray(), msg, onReady)
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ class TorrentCommentEvent(
|
|||||||
zapRaiserAmount: Long?,
|
zapRaiserAmount: Long?,
|
||||||
geohash: String? = null,
|
geohash: String? = null,
|
||||||
imetas: List<IMetaTag>? = null,
|
imetas: List<IMetaTag>? = null,
|
||||||
|
emojis: List<EmojiUrl>? = null,
|
||||||
forkedFrom: Event? = null,
|
forkedFrom: Event? = null,
|
||||||
isDraft: Boolean,
|
isDraft: Boolean,
|
||||||
onReady: (TorrentCommentEvent) -> Unit,
|
onReady: (TorrentCommentEvent) -> Unit,
|
||||||
@@ -126,6 +127,7 @@ class TorrentCommentEvent(
|
|||||||
imetas?.forEach {
|
imetas?.forEach {
|
||||||
tags.add(Nip92MediaAttachments.createTag(it))
|
tags.add(Nip92MediaAttachments.createTag(it))
|
||||||
}
|
}
|
||||||
|
emojis?.forEach { tags.add(it.toTagArray()) }
|
||||||
tags.add(arrayOf("alt", ALT))
|
tags.add(arrayOf("alt", ALT))
|
||||||
|
|
||||||
if (isDraft) {
|
if (isDraft) {
|
||||||
|
|||||||
Reference in New Issue
Block a user