- 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.BuildConfig
|
||||||
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage
|
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.model.Account.Companion.APP_SPECIFIC_DATA_D_TAG
|
||||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||||
import com.vitorpamplona.amethyst.service.location.LocationState
|
import com.vitorpamplona.amethyst.service.location.LocationState
|
||||||
import com.vitorpamplona.amethyst.service.ots.OtsResolverBuilder
|
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.nip47WalletConnect.Response
|
||||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||||
|
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.GeneralListEvent
|
import com.vitorpamplona.quartz.nip51Lists.GeneralListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||||
@@ -194,6 +196,7 @@ import kotlinx.coroutines.flow.emitAll
|
|||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import kotlinx.coroutines.flow.toSet
|
||||||
import kotlinx.coroutines.flow.transformLatest
|
import kotlinx.coroutines.flow.transformLatest
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -697,9 +700,11 @@ class Account(
|
|||||||
LiveFollowList(authorsPlusMe = setOf(signer.pubKey))
|
LiveFollowList(authorsPlusMe = setOf(signer.pubKey))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val peopleList = noteState.note.event as? GeneralListEvent
|
val noteEvent = noteState.note.event
|
||||||
if (peopleList != null) {
|
if (noteEvent is GeneralListEvent) {
|
||||||
waitToDecrypt(peopleList) ?: LiveFollowList(authorsPlusMe = setOf(signer.pubKey))
|
waitToDecrypt(noteEvent) ?: LiveFollowList(authorsPlusMe = setOf(signer.pubKey))
|
||||||
|
} else if (noteEvent is FollowListEvent) {
|
||||||
|
LiveFollowList(authors = noteEvent.pubKeys().toSet(), authorsPlusMe = setOf(signer.pubKey) + noteEvent.pubKeys())
|
||||||
} else {
|
} else {
|
||||||
LiveFollowList(authorsPlusMe = setOf(signer.pubKey))
|
LiveFollowList(authorsPlusMe = setOf(signer.pubKey))
|
||||||
}
|
}
|
||||||
@@ -3622,10 +3627,15 @@ class Account(
|
|||||||
fun getAllPeopleLists(pubkey: HexKey): List<AddressableNote> =
|
fun getAllPeopleLists(pubkey: HexKey): List<AddressableNote> =
|
||||||
LocalCache.addressables
|
LocalCache.addressables
|
||||||
.filter { _, addressableNote ->
|
.filter { _, addressableNote ->
|
||||||
val event = (addressableNote.event as? PeopleListEvent)
|
val noteEvent = addressableNote.event
|
||||||
event != null &&
|
|
||||||
event.pubKey == pubkey &&
|
if (noteEvent is PeopleListEvent) {
|
||||||
(event.hasAnyTaggedUser() || event.cachedPrivateTags()?.isNotEmpty() == true)
|
noteEvent.pubKey == pubkey && (noteEvent.hasAnyTaggedUser() || noteEvent.cachedPrivateTags()?.isNotEmpty() == true)
|
||||||
|
} else if (noteEvent is FollowListEvent) {
|
||||||
|
noteEvent.pubKey == pubkey && noteEvent.hasAnyTaggedUser()
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun markAsRead(
|
fun markAsRead(
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentRequestEvent
|
|||||||
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
|
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
|
||||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||||
|
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||||
@@ -828,6 +829,13 @@ object LocalCache : ILocalCache {
|
|||||||
consumeBaseReplaceable(event, relay)
|
consumeBaseReplaceable(event, relay)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun consume(
|
||||||
|
event: FollowListEvent,
|
||||||
|
relay: Relay?,
|
||||||
|
) {
|
||||||
|
consumeBaseReplaceable(event, relay)
|
||||||
|
}
|
||||||
|
|
||||||
private fun consume(
|
private fun consume(
|
||||||
event: AdvertisedRelayListEvent,
|
event: AdvertisedRelayListEvent,
|
||||||
relay: Relay?,
|
relay: Relay?,
|
||||||
@@ -2622,6 +2630,7 @@ object LocalCache : ILocalCache {
|
|||||||
is FileServersEvent -> consume(event, relay)
|
is FileServersEvent -> consume(event, relay)
|
||||||
is FileStorageEvent -> consume(event, relay)
|
is FileStorageEvent -> consume(event, relay)
|
||||||
is FileStorageHeaderEvent -> consume(event, relay)
|
is FileStorageHeaderEvent -> consume(event, relay)
|
||||||
|
is FollowListEvent -> consume(event, relay)
|
||||||
is GiftWrapEvent -> consume(event, relay)
|
is GiftWrapEvent -> consume(event, relay)
|
||||||
is GitIssueEvent -> consume(event, relay)
|
is GitIssueEvent -> consume(event, relay)
|
||||||
is GitReplyEvent -> 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.nip47WalletConnect.LnZapPaymentResponseEvent
|
||||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||||
|
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.nip52Calendar.CalendarDateSlotEvent
|
import com.vitorpamplona.quartz.nip52Calendar.CalendarDateSlotEvent
|
||||||
@@ -135,6 +136,7 @@ class AccountFilterAssembler(
|
|||||||
kinds =
|
kinds =
|
||||||
listOf(
|
listOf(
|
||||||
PeopleListEvent.KIND,
|
PeopleListEvent.KIND,
|
||||||
|
FollowListEvent.KIND,
|
||||||
MuteListEvent.KIND,
|
MuteListEvent.KIND,
|
||||||
BadgeProfilesEvent.KIND,
|
BadgeProfilesEvent.KIND,
|
||||||
EmojiPackSelectionEvent.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.nip28PublicChat.admin.ChannelMetadataEvent
|
||||||
import com.vitorpamplona.quartz.nip30CustomEmoji.pack.EmojiPackEvent
|
import com.vitorpamplona.quartz.nip30CustomEmoji.pack.EmojiPackEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||||
|
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||||
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
|
||||||
@@ -226,6 +227,7 @@ class SearchFilterAssembler(
|
|||||||
listOf(
|
listOf(
|
||||||
InteractiveStoryPrologueEvent.KIND,
|
InteractiveStoryPrologueEvent.KIND,
|
||||||
InteractiveStorySceneEvent.KIND,
|
InteractiveStorySceneEvent.KIND,
|
||||||
|
FollowListEvent.KIND,
|
||||||
),
|
),
|
||||||
search = mySearchString,
|
search = mySearchString,
|
||||||
limit = 100,
|
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.Size20Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
|
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
@@ -252,7 +253,15 @@ fun RenderOption(option: Name) {
|
|||||||
) {
|
) {
|
||||||
val noteState by observeNote(option.note)
|
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)
|
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.elements.TimeAgo
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
|
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayDMRelayList
|
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.DisplayNIP65RelayList
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
|
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayRelaySet
|
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.nip35Torrents.TorrentEvent
|
||||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||||
|
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.RelaySetEvent
|
import com.vitorpamplona.quartz.nip51Lists.RelaySetEvent
|
||||||
@@ -624,6 +626,7 @@ private fun RenderNoteRow(
|
|||||||
is BadgeAwardEvent -> RenderBadgeAward(baseNote, backgroundColor, accountViewModel, nav)
|
is BadgeAwardEvent -> RenderBadgeAward(baseNote, backgroundColor, accountViewModel, nav)
|
||||||
is FhirResourceEvent -> RenderFhirResource(baseNote, accountViewModel, nav)
|
is FhirResourceEvent -> RenderFhirResource(baseNote, accountViewModel, nav)
|
||||||
is PeopleListEvent -> DisplayPeopleList(baseNote, backgroundColor, accountViewModel, nav)
|
is PeopleListEvent -> DisplayPeopleList(baseNote, backgroundColor, accountViewModel, nav)
|
||||||
|
is FollowListEvent -> DisplayFollowList(baseNote, backgroundColor, accountViewModel, nav)
|
||||||
is RelaySetEvent -> DisplayRelaySet(baseNote, backgroundColor, accountViewModel, nav)
|
is RelaySetEvent -> DisplayRelaySet(baseNote, backgroundColor, accountViewModel, nav)
|
||||||
is ChatMessageRelayListEvent -> DisplayDMRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
is ChatMessageRelayListEvent -> DisplayDMRelayList(baseNote, backgroundColor, accountViewModel, nav)
|
||||||
is AdvertisedRelayListEvent -> DisplayNIP65RelayList(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.GenericRepostEvent
|
||||||
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
|
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
|
||||||
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
||||||
|
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||||
@@ -135,6 +136,7 @@ class FollowListState(
|
|||||||
(
|
(
|
||||||
(
|
(
|
||||||
noteEvent is PeopleListEvent ||
|
noteEvent is PeopleListEvent ||
|
||||||
|
noteEvent is FollowListEvent ||
|
||||||
noteEvent is MuteListEvent ||
|
noteEvent is MuteListEvent ||
|
||||||
noteEvent is ContactListEvent
|
noteEvent is ContactListEvent
|
||||||
) ||
|
) ||
|
||||||
@@ -288,13 +290,22 @@ class ResourceName(
|
|||||||
class PeopleListName(
|
class PeopleListName(
|
||||||
val note: AddressableNote,
|
val note: AddressableNote,
|
||||||
) : Name() {
|
) : 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(
|
class CommunityName(
|
||||||
val note: AddressableNote,
|
val note: AddressableNote,
|
||||||
) : Name() {
|
) : Name() {
|
||||||
override fun name() = "/n/${(note.dTag() ?: "")}"
|
override fun name() = "/n/${(note.dTag())}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ open class DiscoverChatFeedFilter(
|
|||||||
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
||||||
|
|
||||||
fun buildFilterParams(account: Account): FilterByListParams =
|
fun buildFilterParams(account: Account): FilterByListParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
userHex = account.userProfile().pubkeyHex,
|
userHex = account.userProfile().pubkeyHex,
|
||||||
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
||||||
followLists = account.liveDiscoveryFollowLists.value,
|
followLists = account.liveDiscoveryFollowLists.value,
|
||||||
|
|||||||
+2
-2
@@ -44,7 +44,7 @@ open class DiscoverCommunityFeedFilter(
|
|||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val filterParams =
|
val filterParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
userHex = account.userProfile().pubkeyHex,
|
userHex = account.userProfile().pubkeyHex,
|
||||||
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
||||||
followLists = account.liveDiscoveryFollowLists.value,
|
followLists = account.liveDiscoveryFollowLists.value,
|
||||||
@@ -73,7 +73,7 @@ open class DiscoverCommunityFeedFilter(
|
|||||||
protected open fun innerApplyFilter(collection: Collection<Note>): Set<Note> {
|
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
|
// here, we need to look for CommunityDefinition in new collection AND new CommunityDefinition from Post Approvals
|
||||||
val filterParams =
|
val filterParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
userHex = account.userProfile().pubkeyHex,
|
userHex = account.userProfile().pubkeyHex,
|
||||||
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
||||||
followLists = account.liveDiscoveryFollowLists.value,
|
followLists = account.liveDiscoveryFollowLists.value,
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ open class DiscoverLiveFeedFilter(
|
|||||||
|
|
||||||
protected open fun innerApplyFilter(collection: Collection<Note>): Set<Note> {
|
protected open fun innerApplyFilter(collection: Collection<Note>): Set<Note> {
|
||||||
val filterParams =
|
val filterParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
userHex = account.userProfile().pubkeyHex,
|
userHex = account.userProfile().pubkeyHex,
|
||||||
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
selectedListName = account.settings.defaultDiscoveryFollowList.value,
|
||||||
followLists = account.liveDiscoveryFollowLists.value,
|
followLists = account.liveDiscoveryFollowLists.value,
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ open class DiscoverMarketplaceFeedFilter(
|
|||||||
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
||||||
|
|
||||||
fun buildFilterParams(account: Account): FilterByListParams =
|
fun buildFilterParams(account: Account): FilterByListParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
account.userProfile().pubkeyHex,
|
account.userProfile().pubkeyHex,
|
||||||
account.settings.defaultDiscoveryFollowList.value,
|
account.settings.defaultDiscoveryFollowList.value,
|
||||||
account.liveDiscoveryFollowLists.value,
|
account.liveDiscoveryFollowLists.value,
|
||||||
|
|||||||
+1
-1
@@ -56,7 +56,7 @@ open class DiscoverNIP89FeedFilter(
|
|||||||
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
||||||
|
|
||||||
fun buildFilterParams(account: Account): FilterByListParams =
|
fun buildFilterParams(account: Account): FilterByListParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
account.userProfile().pubkeyHex,
|
account.userProfile().pubkeyHex,
|
||||||
account.settings.defaultDiscoveryFollowList.value,
|
account.settings.defaultDiscoveryFollowList.value,
|
||||||
account.liveDiscoveryFollowLists.value,
|
account.liveDiscoveryFollowLists.value,
|
||||||
|
|||||||
+3
-3
@@ -43,8 +43,8 @@ open class NIP90ContentDiscoveryResponseFilter(
|
|||||||
open fun followList(): String = account.settings.defaultDiscoveryFollowList.value
|
open fun followList(): String = account.settings.defaultDiscoveryFollowList.value
|
||||||
|
|
||||||
override fun showHiddenKey(): Boolean =
|
override fun showHiddenKey(): Boolean =
|
||||||
followList() == PeopleListEvent.Companion.blockListFor(account.userProfile().pubkeyHex) ||
|
followList() == PeopleListEvent.blockListFor(account.userProfile().pubkeyHex) ||
|
||||||
followList() == MuteListEvent.Companion.blockListFor(account.userProfile().pubkeyHex)
|
followList() == MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
||||||
|
|
||||||
fun acceptableEvent(note: Note): Boolean {
|
fun acceptableEvent(note: Note): Boolean {
|
||||||
val noteEvent = note.event
|
val noteEvent = note.event
|
||||||
@@ -72,7 +72,7 @@ open class NIP90ContentDiscoveryResponseFilter(
|
|||||||
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
||||||
|
|
||||||
fun buildFilterParams(account: Account): FilterByListParams =
|
fun buildFilterParams(account: Account): FilterByListParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
account.userProfile().pubkeyHex,
|
account.userProfile().pubkeyHex,
|
||||||
account.settings.defaultDiscoveryFollowList.value,
|
account.settings.defaultDiscoveryFollowList.value,
|
||||||
account.liveDiscoveryFollowLists.value,
|
account.liveDiscoveryFollowLists.value,
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ class HomeConversationsFeedFilter(
|
|||||||
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
|
||||||
|
|
||||||
fun buildFilterParams(account: Account): FilterByListParams =
|
fun buildFilterParams(account: Account): FilterByListParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
userHex = account.userProfile().pubkeyHex,
|
userHex = account.userProfile().pubkeyHex,
|
||||||
selectedListName = account.settings.defaultHomeFollowList.value,
|
selectedListName = account.settings.defaultHomeFollowList.value,
|
||||||
followLists = account.liveHomeFollowLists.value,
|
followLists = account.liveHomeFollowLists.value,
|
||||||
|
|||||||
+1
-1
@@ -51,7 +51,7 @@ class HomeNewThreadFeedFilter(
|
|||||||
account.settings.defaultHomeFollowList.value == MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
account.settings.defaultHomeFollowList.value == MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
||||||
|
|
||||||
fun buildFilterParams(account: Account): FilterByListParams =
|
fun buildFilterParams(account: Account): FilterByListParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
userHex = account.userProfile().pubkeyHex,
|
userHex = account.userProfile().pubkeyHex,
|
||||||
selectedListName = account.settings.defaultHomeFollowList.value,
|
selectedListName = account.settings.defaultHomeFollowList.value,
|
||||||
followLists = account.liveHomeFollowLists.value,
|
followLists = account.liveHomeFollowLists.value,
|
||||||
|
|||||||
+3
-3
@@ -57,12 +57,12 @@ class NotificationFeedFilter(
|
|||||||
|
|
||||||
override fun showHiddenKey(): Boolean =
|
override fun showHiddenKey(): Boolean =
|
||||||
account.settings.defaultNotificationFollowList.value ==
|
account.settings.defaultNotificationFollowList.value ==
|
||||||
PeopleListEvent.Companion.blockListFor(account.userProfile().pubkeyHex) ||
|
PeopleListEvent.blockListFor(account.userProfile().pubkeyHex) ||
|
||||||
account.settings.defaultNotificationFollowList.value ==
|
account.settings.defaultNotificationFollowList.value ==
|
||||||
MuteListEvent.Companion.blockListFor(account.userProfile().pubkeyHex)
|
MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
||||||
|
|
||||||
fun buildFilterParams(account: Account): FilterByListParams =
|
fun buildFilterParams(account: Account): FilterByListParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
userHex = account.userProfile().pubkeyHex,
|
userHex = account.userProfile().pubkeyHex,
|
||||||
selectedListName = account.settings.defaultNotificationFollowList.value,
|
selectedListName = account.settings.defaultNotificationFollowList.value,
|
||||||
followLists = account.liveNotificationFollowLists.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.TorrentCommentEvent
|
||||||
import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
|
import com.vitorpamplona.quartz.nip35Torrents.TorrentEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||||
|
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||||
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
||||||
@@ -179,6 +180,7 @@ class UserProfileFilterAssembler(
|
|||||||
listOf(
|
listOf(
|
||||||
BookmarkListEvent.KIND,
|
BookmarkListEvent.KIND,
|
||||||
PeopleListEvent.KIND,
|
PeopleListEvent.KIND,
|
||||||
|
FollowListEvent.KIND,
|
||||||
AppRecommendationEvent.KIND,
|
AppRecommendationEvent.KIND,
|
||||||
),
|
),
|
||||||
authors = listOf(state.user.pubkeyHex),
|
authors = listOf(state.user.pubkeyHex),
|
||||||
|
|||||||
+3
-3
@@ -40,8 +40,8 @@ class UserProfileGalleryFeedFilter(
|
|||||||
override fun feedKey(): String = account.userProfile().pubkeyHex + "-" + "ProfileGallery"
|
override fun feedKey(): String = account.userProfile().pubkeyHex + "-" + "ProfileGallery"
|
||||||
|
|
||||||
override fun showHiddenKey(): Boolean =
|
override fun showHiddenKey(): Boolean =
|
||||||
account.settings.defaultStoriesFollowList.value == PeopleListEvent.Companion.blockListFor(account.userProfile().pubkeyHex) ||
|
account.settings.defaultStoriesFollowList.value == PeopleListEvent.blockListFor(account.userProfile().pubkeyHex) ||
|
||||||
account.settings.defaultStoriesFollowList.value == MuteListEvent.Companion.blockListFor(account.userProfile().pubkeyHex)
|
account.settings.defaultStoriesFollowList.value == MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val params = buildFilterParams(account)
|
val params = buildFilterParams(account)
|
||||||
@@ -77,7 +77,7 @@ class UserProfileGalleryFeedFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun buildFilterParams(account: Account): FilterByListParams =
|
fun buildFilterParams(account: Account): FilterByListParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
userHex = account.userProfile().pubkeyHex,
|
userHex = account.userProfile().pubkeyHex,
|
||||||
selectedListName = account.settings.defaultStoriesFollowList.value,
|
selectedListName = account.settings.defaultStoriesFollowList.value,
|
||||||
followLists = account.liveStoriesFollowLists.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.AudioTrackHeader
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
|
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayDMRelayList
|
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.DisplayNIP65RelayList
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
|
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.DisplayRelaySet
|
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.nip35Torrents.TorrentEvent
|
||||||
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent
|
||||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||||
|
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.RelaySetEvent
|
import com.vitorpamplona.quartz.nip51Lists.RelaySetEvent
|
||||||
@@ -531,6 +533,8 @@ private fun FullBleedNoteCompose(
|
|||||||
FileStorageHeaderDisplay(baseNote, roundedCorner = true, ContentScale.FillWidth, accountViewModel = accountViewModel)
|
FileStorageHeaderDisplay(baseNote, roundedCorner = true, ContentScale.FillWidth, accountViewModel = accountViewModel)
|
||||||
} else if (noteEvent is PeopleListEvent) {
|
} else if (noteEvent is PeopleListEvent) {
|
||||||
DisplayPeopleList(baseNote, backgroundColor, accountViewModel, nav)
|
DisplayPeopleList(baseNote, backgroundColor, accountViewModel, nav)
|
||||||
|
} else if (noteEvent is FollowListEvent) {
|
||||||
|
DisplayFollowList(baseNote, backgroundColor, accountViewModel, nav)
|
||||||
} else if (noteEvent is AudioTrackEvent) {
|
} else if (noteEvent is AudioTrackEvent) {
|
||||||
AudioTrackHeader(noteEvent, baseNote, ContentScale.FillWidth, accountViewModel, nav)
|
AudioTrackHeader(noteEvent, baseNote, ContentScale.FillWidth, accountViewModel, nav)
|
||||||
} else if (noteEvent is AudioHeaderEvent) {
|
} 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 feedKey(): String = account.userProfile().pubkeyHex + "-" + account.settings.defaultStoriesFollowList.value
|
||||||
|
|
||||||
override fun showHiddenKey(): Boolean =
|
override fun showHiddenKey(): Boolean =
|
||||||
account.settings.defaultStoriesFollowList.value == PeopleListEvent.Companion.blockListFor(account.userProfile().pubkeyHex) ||
|
account.settings.defaultStoriesFollowList.value == PeopleListEvent.blockListFor(account.userProfile().pubkeyHex) ||
|
||||||
account.settings.defaultStoriesFollowList.value == MuteListEvent.Companion.blockListFor(account.userProfile().pubkeyHex)
|
account.settings.defaultStoriesFollowList.value == MuteListEvent.blockListFor(account.userProfile().pubkeyHex)
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val params = buildFilterParams(account)
|
val params = buildFilterParams(account)
|
||||||
@@ -120,7 +120,7 @@ class VideoFeedFilter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun buildFilterParams(account: Account): FilterByListParams =
|
fun buildFilterParams(account: Account): FilterByListParams =
|
||||||
FilterByListParams.Companion.create(
|
FilterByListParams.create(
|
||||||
userHex = account.userProfile().pubkeyHex,
|
userHex = account.userProfile().pubkeyHex,
|
||||||
selectedListName = account.settings.defaultStoriesFollowList.value,
|
selectedListName = account.settings.defaultStoriesFollowList.value,
|
||||||
followLists = account.liveStoriesFollowLists.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.nip37Drafts.DraftEvent
|
||||||
import com.vitorpamplona.quartz.nip38UserStatus.StatusEvent
|
import com.vitorpamplona.quartz.nip38UserStatus.StatusEvent
|
||||||
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
|
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
|
||||||
|
import com.vitorpamplona.quartz.nip46RemoteSigner.NostrConnectEvent
|
||||||
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentRequestEvent
|
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentRequestEvent
|
||||||
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
|
import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent
|
||||||
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
import com.vitorpamplona.quartz.nip50Search.SearchRelayListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
import com.vitorpamplona.quartz.nip51Lists.BookmarkListEvent
|
||||||
|
import com.vitorpamplona.quartz.nip51Lists.FollowListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
import com.vitorpamplona.quartz.nip51Lists.MuteListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent
|
||||||
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
import com.vitorpamplona.quartz.nip51Lists.PinListEvent
|
||||||
@@ -197,6 +199,7 @@ class EventFactory {
|
|||||||
FileStorageEvent.KIND -> FileStorageEvent(id, pubKey, createdAt, tags, content, sig)
|
FileStorageEvent.KIND -> FileStorageEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
FileStorageHeaderEvent.KIND -> FileStorageHeaderEvent(id, pubKey, createdAt, tags, content, sig)
|
FileStorageHeaderEvent.KIND -> FileStorageHeaderEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
FhirResourceEvent.KIND -> FhirResourceEvent(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)
|
GenericRepostEvent.KIND -> GenericRepostEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
GiftWrapEvent.KIND -> GiftWrapEvent(id, pubKey, createdAt, tags, content, sig)
|
GiftWrapEvent.KIND -> GiftWrapEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
GitIssueEvent.KIND -> GitIssueEvent(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)
|
MetadataEvent.KIND -> MetadataEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
MuteListEvent.KIND -> MuteListEvent(id, pubKey, createdAt, tags, content, sig)
|
MuteListEvent.KIND -> MuteListEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
NNSEvent.KIND -> NNSEvent(id, pubKey, createdAt, tags, content, sig)
|
NNSEvent.KIND -> NNSEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
com.vitorpamplona.quartz.nip46RemoteSigner.NostrConnectEvent.KIND ->
|
NostrConnectEvent.KIND -> NostrConnectEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
com.vitorpamplona.quartz.nip46RemoteSigner
|
|
||||||
.NostrConnectEvent(id, pubKey, createdAt, tags, content, sig)
|
|
||||||
NIP90StatusEvent.KIND -> NIP90StatusEvent(id, pubKey, createdAt, tags, content, sig)
|
NIP90StatusEvent.KIND -> NIP90StatusEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
NIP90ContentDiscoveryRequestEvent.KIND -> NIP90ContentDiscoveryRequestEvent(id, pubKey, createdAt, tags, content, sig)
|
NIP90ContentDiscoveryRequestEvent.KIND -> NIP90ContentDiscoveryRequestEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
NIP90ContentDiscoveryResponseEvent.KIND -> NIP90ContentDiscoveryResponseEvent(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.geohash.geohashes
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.HashtagTag
|
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.HashtagTag
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
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.NameTag
|
||||||
import com.vitorpamplona.quartz.nip51Lists.tags.TitleTag
|
import com.vitorpamplona.quartz.nip51Lists.tags.TitleTag
|
||||||
import kotlinx.collections.immutable.ImmutableSet
|
import kotlinx.collections.immutable.ImmutableSet
|
||||||
@@ -63,6 +65,10 @@ abstract class GeneralListEvent(
|
|||||||
@Deprecated("NIP-51 has deprecated Title. Use name instead", ReplaceWith("name()"))
|
@Deprecated("NIP-51 has deprecated Title. Use name instead", ReplaceWith("name()"))
|
||||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||||
|
|
||||||
|
fun description() = tags.firstNotNullOfOrNull(DescriptionTag::parse)
|
||||||
|
|
||||||
|
fun image() = tags.firstNotNullOfOrNull(ImageTag::parse)
|
||||||
|
|
||||||
fun nameOrTitle() = name() ?: title()
|
fun nameOrTitle() = name() ?: title()
|
||||||
|
|
||||||
fun filterTagList(
|
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