- Adds support for Follow packs
- Enables top filter by pack as well.
This commit is contained in:
@@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.BuildConfig
|
||||
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage
|
||||
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
|
||||
import com.vitorpamplona.amethyst.model.Account.Companion.APP_SPECIFIC_DATA_D_TAG
|
||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||
import com.vitorpamplona.amethyst.service.location.LocationState
|
||||
import com.vitorpamplona.amethyst.service.ots.OtsResolverBuilder
|
||||
@@ -140,6 +141,7 @@ import com.vitorpamplona.quartz.nip47WalletConnect.Nip47WalletConnect
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Response
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.GeneralListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||
@@ -194,6 +196,7 @@ import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.toSet
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -697,9 +700,11 @@ class Account(
|
||||
LiveFollowList(authorsPlusMe = setOf(signer.pubKey))
|
||||
}
|
||||
} else {
|
||||
val peopleList = noteState.note.event as? GeneralListEvent
|
||||
if (peopleList != null) {
|
||||
waitToDecrypt(peopleList) ?: LiveFollowList(authorsPlusMe = setOf(signer.pubKey))
|
||||
val noteEvent = noteState.note.event
|
||||
if (noteEvent is GeneralListEvent) {
|
||||
waitToDecrypt(noteEvent) ?: LiveFollowList(authorsPlusMe = setOf(signer.pubKey))
|
||||
} else if (noteEvent is FollowListEvent) {
|
||||
LiveFollowList(authors = noteEvent.pubKeys().toSet(), authorsPlusMe = setOf(signer.pubKey) + noteEvent.pubKeys())
|
||||
} else {
|
||||
LiveFollowList(authorsPlusMe = setOf(signer.pubKey))
|
||||
}
|
||||
@@ -3622,10 +3627,15 @@ class Account(
|
||||
fun getAllPeopleLists(pubkey: HexKey): List<AddressableNote> =
|
||||
LocalCache.addressables
|
||||
.filter { _, addressableNote ->
|
||||
val event = (addressableNote.event as? PeopleListEvent)
|
||||
event != null &&
|
||||
event.pubKey == pubkey &&
|
||||
(event.hasAnyTaggedUser() || event.cachedPrivateTags()?.isNotEmpty() == true)
|
||||
val noteEvent = addressableNote.event
|
||||
|
||||
if (noteEvent is PeopleListEvent) {
|
||||
noteEvent.pubKey == pubkey && (noteEvent.hasAnyTaggedUser() || noteEvent.cachedPrivateTags()?.isNotEmpty() == true)
|
||||
} else if (noteEvent is FollowListEvent) {
|
||||
noteEvent.pubKey == pubkey && noteEvent.hasAnyTaggedUser()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun markAsRead(
|
||||
|
||||
@@ -109,6 +109,7 @@ import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentRequestEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||
@@ -828,6 +829,13 @@ object LocalCache : ILocalCache {
|
||||
consumeBaseReplaceable(event, relay)
|
||||
}
|
||||
|
||||
fun consume(
|
||||
event: FollowListEvent,
|
||||
relay: Relay?,
|
||||
) {
|
||||
consumeBaseReplaceable(event, relay)
|
||||
}
|
||||
|
||||
private fun consume(
|
||||
event: AdvertisedRelayListEvent,
|
||||
relay: Relay?,
|
||||
@@ -2622,6 +2630,7 @@ object LocalCache : ILocalCache {
|
||||
is FileServersEvent -> consume(event, relay)
|
||||
is FileStorageEvent -> consume(event, relay)
|
||||
is FileStorageHeaderEvent -> consume(event, relay)
|
||||
is FollowListEvent -> consume(event, relay)
|
||||
is GiftWrapEvent -> consume(event, relay)
|
||||
is GitIssueEvent -> consume(event, relay)
|
||||
is GitReplyEvent -> consume(event, relay)
|
||||
|
||||
+2
@@ -53,6 +53,7 @@ import com.vitorpamplona.quartz.nip38UserStatus.StatusEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip52Calendar.CalendarDateSlotEvent
|
||||
@@ -135,6 +136,7 @@ class AccountFilterAssembler(
|
||||
kinds =
|
||||
listOf(
|
||||
PeopleListEvent.KIND,
|
||||
FollowListEvent.KIND,
|
||||
MuteListEvent.KIND,
|
||||
BadgeProfilesEvent.KIND,
|
||||
EmojiPackSelectionEvent.KIND,
|
||||
|
||||
+2
@@ -55,6 +55,7 @@ import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent
|
||||
import com.vitorpamplona.quartz.nip30CustomEmoji.pack.EmojiPackEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
||||
@@ -226,6 +227,7 @@ class SearchFilterAssembler(
|
||||
listOf(
|
||||
InteractiveStoryPrologueEvent.KIND,
|
||||
InteractiveStorySceneEvent.KIND,
|
||||
FollowListEvent.KIND,
|
||||
),
|
||||
search = mySearchString,
|
||||
limit = 100,
|
||||
|
||||
+10
-1
@@ -70,6 +70,7 @@ import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@@ -252,7 +253,15 @@ fun RenderOption(option: Name) {
|
||||
) {
|
||||
val noteState by observeNote(option.note)
|
||||
|
||||
val name = (noteState?.note?.event as? PeopleListEvent)?.nameOrTitle() ?: option.note.dTag() ?: ""
|
||||
val noteEvent = noteState.note.event
|
||||
val name =
|
||||
if (noteEvent is PeopleListEvent) {
|
||||
noteEvent.nameOrTitle() ?: option.note.dTag()
|
||||
} else if (noteEvent is FollowListEvent) {
|
||||
noteEvent.nameOrTitle() ?: option.note.dTag()
|
||||
} else {
|
||||
option.note.dTag()
|
||||
}
|
||||
|
||||
Text(text = name, color = MaterialTheme.colorScheme.onSurface)
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ import com.vitorpamplona.amethyst.ui.note.elements.ShowForkInformation
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgo
|
||||
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayDMRelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayFollowList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayNIP65RelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayRelaySet
|
||||
@@ -181,6 +182,7 @@ import com.vitorpamplona.quartz.nip35Torrents.TorrentCommentEvent
|
||||
import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.RelaySetEvent
|
||||
@@ -624,6 +626,7 @@ private fun RenderNoteRow(
|
||||
is BadgeAwardEvent -> RenderBadgeAward(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is FhirResourceEvent -> RenderFhirResource(baseNote, accountViewModel, nav)
|
||||
is PeopleListEvent -> DisplayPeopleList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is FollowListEvent -> DisplayFollowList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is RelaySetEvent -> DisplayRelaySet(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is ChatMessageRelayListEvent -> DisplayDMRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
is AdvertisedRelayListEvent -> DisplayNIP65RelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* 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.types
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.ui.components.ShowMoreButton
|
||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||
import com.vitorpamplona.amethyst.ui.note.UserCompose
|
||||
import com.vitorpamplona.amethyst.ui.note.getGradient
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUserIds
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun DisplayFollowList(
|
||||
baseNote: Note,
|
||||
backgroundColor: MutableState<Color>,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
val noteEvent = baseNote.event as? FollowListEvent ?: return
|
||||
|
||||
var members by remember { mutableStateOf<ImmutableList<User>>(persistentListOf()) }
|
||||
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
|
||||
val toMembersShow =
|
||||
if (expanded) {
|
||||
members
|
||||
} else {
|
||||
members.take(3)
|
||||
}
|
||||
|
||||
val name by remember { derivedStateOf { "#${noteEvent.nameOrTitle() ?: noteEvent.dTag()}" } }
|
||||
|
||||
Text(
|
||||
text = name,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(5.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
accountViewModel.loadUsers(noteEvent.taggedUserIds()) {
|
||||
members = it
|
||||
}
|
||||
}
|
||||
|
||||
Box {
|
||||
FlowRow(modifier = Modifier.padding(top = 5.dp)) {
|
||||
toMembersShow.forEach { user ->
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
UserCompose(
|
||||
user,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
|
||||
HorizontalDivider(
|
||||
thickness = DividerThickness,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (members.size > 3 && !expanded) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
modifier =
|
||||
Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.fillMaxWidth()
|
||||
.background(getGradient(backgroundColor)),
|
||||
) {
|
||||
ShowMoreButton { expanded = !expanded }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,7 @@ import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
|
||||
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
|
||||
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||
@@ -135,6 +136,7 @@ class FollowListState(
|
||||
(
|
||||
(
|
||||
noteEvent is PeopleListEvent ||
|
||||
noteEvent is FollowListEvent ||
|
||||
noteEvent is MuteListEvent ||
|
||||
noteEvent is ContactListEvent
|
||||
) ||
|
||||
@@ -288,13 +290,22 @@ class ResourceName(
|
||||
class PeopleListName(
|
||||
val note: AddressableNote,
|
||||
) : Name() {
|
||||
override fun name() = (note.event as? PeopleListEvent)?.nameOrTitle() ?: note.dTag() ?: ""
|
||||
override fun name(): String {
|
||||
val noteEvent = note.event
|
||||
return if (noteEvent is PeopleListEvent) {
|
||||
noteEvent.nameOrTitle() ?: note.dTag()
|
||||
} else if (noteEvent is FollowListEvent) {
|
||||
noteEvent.nameOrTitle() ?: note.dTag()
|
||||
} else {
|
||||
note.dTag()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CommunityName(
|
||||
val note: AddressableNote,
|
||||
) : Name() {
|
||||
override fun name() = "/n/${(note.dTag() ?: "")}"
|
||||
override fun name() = "/n/${(note.dTag())}"
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ open class DiscoverChatFeedFilter(
|
||||
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
||||
|
||||
fun buildFilterParams(account: Account): FilterByListParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
userHex = account.userProfile().pubkeyHex,
|
||||
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
||||
followLists = account.liveDiscoveryFollowLists.value,
|
||||
|
||||
+2
-2
@@ -44,7 +44,7 @@ open class DiscoverCommunityFeedFilter(
|
||||
|
||||
override fun feed(): List<Note> {
|
||||
val filterParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
userHex = account.userProfile().pubkeyHex,
|
||||
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
||||
followLists = account.liveDiscoveryFollowLists.value,
|
||||
@@ -73,7 +73,7 @@ open class DiscoverCommunityFeedFilter(
|
||||
protected open fun innerApplyFilter(collection: Collection<Note>): Set<Note> {
|
||||
// here, we need to look for CommunityDefinition in new collection AND new CommunityDefinition from Post Approvals
|
||||
val filterParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
userHex = account.userProfile().pubkeyHex,
|
||||
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
||||
followLists = account.liveDiscoveryFollowLists.value,
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ open class DiscoverLiveFeedFilter(
|
||||
|
||||
protected open fun innerApplyFilter(collection: Collection<Note>): Set<Note> {
|
||||
val filterParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
userHex = account.userProfile().pubkeyHex,
|
||||
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
||||
followLists = account.liveDiscoveryFollowLists.value,
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ open class DiscoverMarketplaceFeedFilter(
|
||||
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
||||
|
||||
fun buildFilterParams(account: Account): FilterByListParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
account.userProfile().pubkeyHex,
|
||||
account.settings.defaultDiscoveryFollowList.value,
|
||||
account.liveDiscoveryFollowLists.value,
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ open class DiscoverNIP89FeedFilter(
|
||||
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
||||
|
||||
fun buildFilterParams(account: Account): FilterByListParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
account.userProfile().pubkeyHex,
|
||||
account.settings.defaultDiscoveryFollowList.value,
|
||||
account.liveDiscoveryFollowLists.value,
|
||||
|
||||
+3
-3
@@ -43,8 +43,8 @@ open class NIP90ContentDiscoveryResponseFilter(
|
||||
open fun followList(): String = account.settings.defaultDiscoveryFollowList.value
|
||||
|
||||
override fun showHiddenKey(): Boolean =
|
||||
followList() == PeopleListEvent.Companion.blockListFor(account.userProfile().pubkeyHex) ||
|
||||
followList() == MuteListEvent.Companion.blockListFor(account.userProfile().pubkeyHex)
|
||||
followList() == PeopleListEvent.blockListFor(account.userProfile().pubkeyHex) ||
|
||||
followList() == MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
||||
|
||||
fun acceptableEvent(note: Note): Boolean {
|
||||
val noteEvent = note.event
|
||||
@@ -72,7 +72,7 @@ open class NIP90ContentDiscoveryResponseFilter(
|
||||
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
||||
|
||||
fun buildFilterParams(account: Account): FilterByListParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
account.userProfile().pubkeyHex,
|
||||
account.settings.defaultDiscoveryFollowList.value,
|
||||
account.liveDiscoveryFollowLists.value,
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ class HomeConversationsFeedFilter(
|
||||
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
||||
|
||||
fun buildFilterParams(account: Account): FilterByListParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
userHex = account.userProfile().pubkeyHex,
|
||||
selectedListName = account.settings.defaultHomeFollowList.value,
|
||||
followLists = account.liveHomeFollowLists.value,
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ class HomeNewThreadFeedFilter(
|
||||
account.settings.defaultHomeFollowList.value == MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
||||
|
||||
fun buildFilterParams(account: Account): FilterByListParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
userHex = account.userProfile().pubkeyHex,
|
||||
selectedListName = account.settings.defaultHomeFollowList.value,
|
||||
followLists = account.liveHomeFollowLists.value,
|
||||
|
||||
+3
-3
@@ -57,12 +57,12 @@ class NotificationFeedFilter(
|
||||
|
||||
override fun showHiddenKey(): Boolean =
|
||||
account.settings.defaultNotificationFollowList.value ==
|
||||
PeopleListEvent.Companion.blockListFor(account.userProfile().pubkeyHex) ||
|
||||
PeopleListEvent.blockListFor(account.userProfile().pubkeyHex) ||
|
||||
account.settings.defaultNotificationFollowList.value ==
|
||||
MuteListEvent.Companion.blockListFor(account.userProfile().pubkeyHex)
|
||||
MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
||||
|
||||
fun buildFilterParams(account: Account): FilterByListParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
userHex = account.userProfile().pubkeyHex,
|
||||
selectedListName = account.settings.defaultNotificationFollowList.value,
|
||||
followLists = account.liveNotificationFollowLists.value,
|
||||
|
||||
+2
@@ -41,6 +41,7 @@ import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip35Torrents.TorrentCommentEvent
|
||||
import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
||||
@@ -179,6 +180,7 @@ class UserProfileFilterAssembler(
|
||||
listOf(
|
||||
BookmarkListEvent.KIND,
|
||||
PeopleListEvent.KIND,
|
||||
FollowListEvent.KIND,
|
||||
AppRecommendationEvent.KIND,
|
||||
),
|
||||
authors = listOf(state.user.pubkeyHex),
|
||||
|
||||
+3
-3
@@ -40,8 +40,8 @@ class UserProfileGalleryFeedFilter(
|
||||
override fun feedKey(): String = account.userProfile().pubkeyHex + "-" + "ProfileGallery"
|
||||
|
||||
override fun showHiddenKey(): Boolean =
|
||||
account.settings.defaultStoriesFollowList.value == PeopleListEvent.Companion.blockListFor(account.userProfile().pubkeyHex) ||
|
||||
account.settings.defaultStoriesFollowList.value == MuteListEvent.Companion.blockListFor(account.userProfile().pubkeyHex)
|
||||
account.settings.defaultStoriesFollowList.value == PeopleListEvent.blockListFor(account.userProfile().pubkeyHex) ||
|
||||
account.settings.defaultStoriesFollowList.value == MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
||||
|
||||
override fun feed(): List<Note> {
|
||||
val params = buildFilterParams(account)
|
||||
@@ -77,7 +77,7 @@ class UserProfileGalleryFeedFilter(
|
||||
}
|
||||
|
||||
fun buildFilterParams(account: Account): FilterByListParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
userHex = account.userProfile().pubkeyHex,
|
||||
selectedListName = account.settings.defaultStoriesFollowList.value,
|
||||
followLists = account.liveStoriesFollowLists.value,
|
||||
|
||||
+4
@@ -118,6 +118,7 @@ import com.vitorpamplona.amethyst.ui.note.types.AudioHeader
|
||||
import com.vitorpamplona.amethyst.ui.note.types.AudioTrackHeader
|
||||
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayDMRelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayFollowList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayNIP65RelayList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
|
||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayRelaySet
|
||||
@@ -196,6 +197,7 @@ import com.vitorpamplona.quartz.nip35Torrents.TorrentCommentEvent
|
||||
import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.RelaySetEvent
|
||||
@@ -531,6 +533,8 @@ private fun FullBleedNoteCompose(
|
||||
FileStorageHeaderDisplay(baseNote, roundedCorner = true, ContentScale.FillWidth, accountViewModel = accountViewModel)
|
||||
} else if (noteEvent is PeopleListEvent) {
|
||||
DisplayPeopleList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
} else if (noteEvent is FollowListEvent) {
|
||||
DisplayFollowList(baseNote, backgroundColor, accountViewModel, nav)
|
||||
} else if (noteEvent is AudioTrackEvent) {
|
||||
AudioTrackHeader(noteEvent, baseNote, ContentScale.FillWidth, accountViewModel, nav)
|
||||
} else if (noteEvent is AudioHeaderEvent) {
|
||||
|
||||
+3
-3
@@ -45,8 +45,8 @@ class VideoFeedFilter(
|
||||
override fun feedKey(): String = account.userProfile().pubkeyHex + "-" + account.settings.defaultStoriesFollowList.value
|
||||
|
||||
override fun showHiddenKey(): Boolean =
|
||||
account.settings.defaultStoriesFollowList.value == PeopleListEvent.Companion.blockListFor(account.userProfile().pubkeyHex) ||
|
||||
account.settings.defaultStoriesFollowList.value == MuteListEvent.Companion.blockListFor(account.userProfile().pubkeyHex)
|
||||
account.settings.defaultStoriesFollowList.value == PeopleListEvent.blockListFor(account.userProfile().pubkeyHex) ||
|
||||
account.settings.defaultStoriesFollowList.value == MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
||||
|
||||
override fun feed(): List<Note> {
|
||||
val params = buildFilterParams(account)
|
||||
@@ -120,7 +120,7 @@ class VideoFeedFilter(
|
||||
}
|
||||
|
||||
fun buildFilterParams(account: Account): FilterByListParams =
|
||||
FilterByListParams.Companion.create(
|
||||
FilterByListParams.create(
|
||||
userHex = account.userProfile().pubkeyHex,
|
||||
selectedListName = account.settings.defaultStoriesFollowList.value,
|
||||
followLists = account.liveStoriesFollowLists.value,
|
||||
|
||||
@@ -70,10 +70,12 @@ import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||
import com.vitorpamplona.quartz.nip38UserStatus.StatusEvent
|
||||
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
|
||||
import com.vitorpamplona.quartz.nip46RemoteSigner.NostrConnectEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentRequestEvent
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||
@@ -197,6 +199,7 @@ class EventFactory {
|
||||
FileStorageEvent.KIND -> FileStorageEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
FileStorageHeaderEvent.KIND -> FileStorageHeaderEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
FhirResourceEvent.KIND -> FhirResourceEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
FollowListEvent.KIND -> FollowListEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GenericRepostEvent.KIND -> GenericRepostEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GiftWrapEvent.KIND -> GiftWrapEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
GitIssueEvent.KIND -> GitIssueEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
@@ -220,9 +223,7 @@ class EventFactory {
|
||||
MetadataEvent.KIND -> MetadataEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
MuteListEvent.KIND -> MuteListEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
NNSEvent.KIND -> NNSEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
com.vitorpamplona.quartz.nip46RemoteSigner.NostrConnectEvent.KIND ->
|
||||
com.vitorpamplona.quartz.nip46RemoteSigner
|
||||
.NostrConnectEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
NostrConnectEvent.KIND -> NostrConnectEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
NIP90StatusEvent.KIND -> NIP90StatusEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
NIP90ContentDiscoveryRequestEvent.KIND -> NIP90ContentDiscoveryRequestEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
NIP90ContentDiscoveryResponseEvent.KIND -> NIP90ContentDiscoveryResponseEvent(id, pubKey, createdAt, tags, content, sig)
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* 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.quartz.nip51Lists
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.core.BaseAddressableEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip31Alts.AltTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.DescriptionTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.ImageTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.ImageTag.Companion.parse
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.NameTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.TitleTag
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
@Immutable
|
||||
class FollowListEvent(
|
||||
id: HexKey,
|
||||
pubKey: HexKey,
|
||||
createdAt: Long,
|
||||
tags: Array<Array<String>>,
|
||||
content: String,
|
||||
sig: HexKey,
|
||||
) : BaseAddressableEvent(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||
fun pubKeys() = tags.mapNotNull(PTag::parseKey)
|
||||
|
||||
fun pubKeyHints() = tags.mapNotNull(PTag::parseAsHint)
|
||||
|
||||
fun name() = tags.firstNotNullOfOrNull(NameTag::parse)
|
||||
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
|
||||
fun description() = tags.firstNotNullOfOrNull(DescriptionTag::parse)
|
||||
|
||||
fun nameOrTitle() = name() ?: title()
|
||||
|
||||
fun image() = tags.firstNotNullOfOrNull(ImageTag::parse)
|
||||
|
||||
companion object {
|
||||
const val KIND = 39089
|
||||
const val ALT = "List of people to follow"
|
||||
|
||||
fun createListWithUser(
|
||||
name: String,
|
||||
pubKeyHex: String,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (FollowListEvent) -> Unit,
|
||||
) {
|
||||
create(
|
||||
content = "",
|
||||
tags = arrayOf(arrayOf("d", name), arrayOf("p", pubKeyHex)),
|
||||
signer = signer,
|
||||
createdAt = createdAt,
|
||||
onReady = onReady,
|
||||
)
|
||||
}
|
||||
|
||||
fun addUsers(
|
||||
earlierVersion: FollowListEvent,
|
||||
listPubKeyHex: List<String>,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (FollowListEvent) -> Unit,
|
||||
) {
|
||||
create(
|
||||
content = earlierVersion.content,
|
||||
tags =
|
||||
earlierVersion.tags.plus(
|
||||
listPubKeyHex.map { arrayOf("p", it) },
|
||||
),
|
||||
signer = signer,
|
||||
createdAt = createdAt,
|
||||
onReady = onReady,
|
||||
)
|
||||
}
|
||||
|
||||
fun addUser(
|
||||
earlierVersion: FollowListEvent,
|
||||
pubKeyHex: String,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (FollowListEvent) -> Unit,
|
||||
) = addUsers(earlierVersion, listOf(pubKeyHex), signer, createdAt, onReady)
|
||||
|
||||
fun removeUser(
|
||||
earlierVersion: FollowListEvent,
|
||||
pubKeyHex: String,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (FollowListEvent) -> Unit,
|
||||
) {
|
||||
create(
|
||||
content = earlierVersion.content,
|
||||
tags =
|
||||
earlierVersion.tags
|
||||
.filter { it.size > 1 && !(it[0] == "p" && it[1] == pubKeyHex) }
|
||||
.toTypedArray(),
|
||||
signer = signer,
|
||||
createdAt = createdAt,
|
||||
onReady = onReady,
|
||||
)
|
||||
}
|
||||
|
||||
fun create(
|
||||
content: String,
|
||||
tags: Array<Array<String>>,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (FollowListEvent) -> Unit,
|
||||
) {
|
||||
val newTags =
|
||||
if (tags.any { it.size > 1 && it[0] == "alt" }) {
|
||||
tags
|
||||
} else {
|
||||
tags + AltTag.assemble(ALT)
|
||||
}
|
||||
|
||||
signer.sign(createdAt, KIND, newTags, content, onReady)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,8 @@ import com.vitorpamplona.quartz.nip01Core.tags.events.ETag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohashes
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.HashtagTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.DescriptionTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.ImageTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.NameTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.TitleTag
|
||||
import kotlinx.collections.immutable.ImmutableSet
|
||||
@@ -63,6 +65,10 @@ abstract class GeneralListEvent(
|
||||
@Deprecated("NIP-51 has deprecated Title. Use name instead", ReplaceWith("name()"))
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
|
||||
fun description() = tags.firstNotNullOfOrNull(DescriptionTag::parse)
|
||||
|
||||
fun image() = tags.firstNotNullOfOrNull(ImageTag::parse)
|
||||
|
||||
fun nameOrTitle() = name() ?: title()
|
||||
|
||||
fun filterTagList(
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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.quartz.nip51Lists.tags
|
||||
|
||||
class DescriptionTag {
|
||||
companion object {
|
||||
const val TAG_NAME = "description"
|
||||
|
||||
@JvmStatic
|
||||
fun parse(tag: Array<String>): String? {
|
||||
if (tag.size < 2 || tag[0] != TAG_NAME || tag[1].isEmpty()) return null
|
||||
return tag[1]
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun assemble(name: String) = arrayOf(TAG_NAME, name)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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.quartz.nip51Lists.tags
|
||||
|
||||
class ImageTag {
|
||||
companion object {
|
||||
const val TAG_NAME = "image"
|
||||
|
||||
@JvmStatic
|
||||
fun parse(tag: Array<String>): String? {
|
||||
if (tag.size < 2 || tag[0] != TAG_NAME || tag[1].isEmpty()) return null
|
||||
return tag[1]
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun assemble(name: String) = arrayOf(TAG_NAME, name)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user