Adds support for NipTexts on Amethyst
This commit is contained in:
@@ -46,6 +46,7 @@ import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStory
|
|||||||
import com.vitorpamplona.quartz.experimental.medical.FhirResourceEvent
|
import com.vitorpamplona.quartz.experimental.medical.FhirResourceEvent
|
||||||
import com.vitorpamplona.quartz.experimental.nip95.data.FileStorageEvent
|
import com.vitorpamplona.quartz.experimental.nip95.data.FileStorageEvent
|
||||||
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.nns.NNSEvent
|
import com.vitorpamplona.quartz.experimental.nns.NNSEvent
|
||||||
import com.vitorpamplona.quartz.experimental.profileGallery.ProfileGalleryEntryEvent
|
import com.vitorpamplona.quartz.experimental.profileGallery.ProfileGalleryEntryEvent
|
||||||
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
||||||
@@ -665,6 +666,51 @@ object LocalCache : ILocalCache {
|
|||||||
wasVerified: Boolean,
|
wasVerified: Boolean,
|
||||||
) = consumeRegularEvent(event, relay, wasVerified)
|
) = consumeRegularEvent(event, relay, wasVerified)
|
||||||
|
|
||||||
|
fun consume(
|
||||||
|
event: NipTextEvent,
|
||||||
|
relay: NormalizedRelayUrl?,
|
||||||
|
wasVerified: Boolean,
|
||||||
|
): Boolean {
|
||||||
|
val version = getOrCreateNote(event.id)
|
||||||
|
val note = getOrCreateAddressableNote(event.address())
|
||||||
|
val author = getOrCreateUser(event.pubKey)
|
||||||
|
|
||||||
|
val isVerified =
|
||||||
|
if (version.event == null && (wasVerified || justVerify(event))) {
|
||||||
|
version.loadEvent(event, author, emptyList())
|
||||||
|
version.moveAllReferencesTo(note)
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
wasVerified
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relay != null) {
|
||||||
|
author.addRelayBeingUsed(relay, event.createdAt)
|
||||||
|
note.addRelay(relay)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Already processed this event.
|
||||||
|
if (note.event?.id == event.id) return wasVerified
|
||||||
|
|
||||||
|
if (antiSpam.isSpam(event, relay)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVerified || justVerify(event)) {
|
||||||
|
val replyTo = computeReplyTo(event)
|
||||||
|
|
||||||
|
if (event.createdAt > (note.createdAt() ?: 0L)) {
|
||||||
|
note.loadEvent(event, author, replyTo)
|
||||||
|
|
||||||
|
refreshNewNoteObservers(note)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
fun consume(
|
fun consume(
|
||||||
event: LongTextNoteEvent,
|
event: LongTextNoteEvent,
|
||||||
relay: NormalizedRelayUrl?,
|
relay: NormalizedRelayUrl?,
|
||||||
@@ -2852,6 +2898,7 @@ object LocalCache : ILocalCache {
|
|||||||
is MetadataEvent -> consume(event, relay, wasVerified)
|
is MetadataEvent -> consume(event, relay, wasVerified)
|
||||||
is MuteListEvent -> consume(event, relay, wasVerified)
|
is MuteListEvent -> consume(event, relay, wasVerified)
|
||||||
is NNSEvent -> consume(event, relay, wasVerified)
|
is NNSEvent -> consume(event, relay, wasVerified)
|
||||||
|
is NipTextEvent -> consume(event, relay, wasVerified)
|
||||||
is OtsEvent -> consume(event, relay, wasVerified)
|
is OtsEvent -> consume(event, relay, wasVerified)
|
||||||
is PictureEvent -> consume(event, relay, wasVerified)
|
is PictureEvent -> consume(event, relay, wasVerified)
|
||||||
is PrivateDmEvent -> consume(event, relay, wasVerified)
|
is PrivateDmEvent -> consume(event, relay, wasVerified)
|
||||||
|
|||||||
+2
@@ -24,6 +24,7 @@ import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
|||||||
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStorySceneEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStorySceneEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.nns.NNSEvent
|
import com.vitorpamplona.quartz.experimental.nns.NNSEvent
|
||||||
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
||||||
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
||||||
@@ -81,6 +82,7 @@ val SearchPostsByTextKinds3 =
|
|||||||
InteractiveStoryPrologueEvent.KIND,
|
InteractiveStoryPrologueEvent.KIND,
|
||||||
InteractiveStorySceneEvent.KIND,
|
InteractiveStorySceneEvent.KIND,
|
||||||
FollowListEvent.KIND,
|
FollowListEvent.KIND,
|
||||||
|
NipTextEvent.KIND,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun searchPostsByText(
|
fun searchPostsByText(
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderLiveActivityEvent
|
|||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderLongFormContent
|
import com.vitorpamplona.amethyst.ui.note.types.RenderLongFormContent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderNIP90ContentDiscoveryResponse
|
import com.vitorpamplona.amethyst.ui.note.types.RenderNIP90ContentDiscoveryResponse
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderNIP90Status
|
import com.vitorpamplona.amethyst.ui.note.types.RenderNIP90Status
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.types.RenderNipContent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderPinListEvent
|
import com.vitorpamplona.amethyst.ui.note.types.RenderPinListEvent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderPoll
|
import com.vitorpamplona.amethyst.ui.note.types.RenderPoll
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderPostApproval
|
import com.vitorpamplona.amethyst.ui.note.types.RenderPostApproval
|
||||||
@@ -167,6 +168,7 @@ import com.vitorpamplona.quartz.experimental.forks.isAFork
|
|||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryBaseEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryBaseEvent
|
||||||
import com.vitorpamplona.quartz.experimental.medical.FhirResourceEvent
|
import com.vitorpamplona.quartz.experimental.medical.FhirResourceEvent
|
||||||
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
||||||
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geoHashOrScope
|
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geoHashOrScope
|
||||||
@@ -727,6 +729,7 @@ private fun RenderNoteRow(
|
|||||||
is ReportEvent -> RenderReport(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
is ReportEvent -> RenderReport(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
|
||||||
is LongTextNoteEvent -> RenderLongFormContent(baseNote, accountViewModel, nav)
|
is LongTextNoteEvent -> RenderLongFormContent(baseNote, accountViewModel, nav)
|
||||||
is WikiNoteEvent -> RenderWikiContent(baseNote, accountViewModel, nav)
|
is WikiNoteEvent -> RenderWikiContent(baseNote, accountViewModel, nav)
|
||||||
|
is NipTextEvent -> RenderNipContent(baseNote, accountViewModel, nav)
|
||||||
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)
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ fun ForkInformationRowLightColor(
|
|||||||
nav: INav,
|
nav: INav,
|
||||||
) {
|
) {
|
||||||
val noteState by observeNote(originalVersion, accountViewModel)
|
val noteState by observeNote(originalVersion, accountViewModel)
|
||||||
val note = noteState?.note ?: return
|
val note = noteState.note
|
||||||
val author = note.author ?: return
|
val author = note.author ?: return
|
||||||
val route = remember(note) { routeFor(note, accountViewModel.account) }
|
val route = remember(note) { routeFor(note, accountViewModel.account) }
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ fun ForkInformationRow(
|
|||||||
nav: INav,
|
nav: INav,
|
||||||
) {
|
) {
|
||||||
val noteState by observeNote(originalVersion, accountViewModel)
|
val noteState by observeNote(originalVersion, accountViewModel)
|
||||||
val note = noteState?.note ?: return
|
val note = noteState.note
|
||||||
val route = remember(note) { routeFor(note, accountViewModel.account) }
|
val route = remember(note) { routeFor(note, accountViewModel.account) }
|
||||||
|
|
||||||
if (route != null) {
|
if (route != null) {
|
||||||
|
|||||||
@@ -0,0 +1,196 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 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 android.R.attr.label
|
||||||
|
import android.R.attr.maxLines
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.FlowRow
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.SpacedBy5dp
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.kinds.kinds
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RenderNipContent(
|
||||||
|
note: Note,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
val noteEvent = note.event as? NipTextEvent ?: return
|
||||||
|
|
||||||
|
NipNoteHeader(noteEvent, note, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun NipNoteHeader(
|
||||||
|
noteEvent: NipTextEvent,
|
||||||
|
note: Note,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
val title = remember(noteEvent) { noteEvent.title() }
|
||||||
|
val kinds = remember(noteEvent) { noteEvent.kinds() }
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.padding(top = Size5dp)
|
||||||
|
.clip(shape = QuoteBorder)
|
||||||
|
.border(
|
||||||
|
1.dp,
|
||||||
|
MaterialTheme.colorScheme.subtleBorder,
|
||||||
|
QuoteBorder,
|
||||||
|
),
|
||||||
|
verticalArrangement = SpacedBy5dp,
|
||||||
|
) {
|
||||||
|
title?.let {
|
||||||
|
Text(
|
||||||
|
text = it,
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 10.dp, end = 10.dp, top = 10.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = remember(noteEvent) { noteEvent.summary() ?: noteEvent.content },
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 10.dp, end = 10.dp, bottom = 10.dp),
|
||||||
|
color = Color.Gray,
|
||||||
|
maxLines = 3,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
if (kinds.isNotEmpty()) {
|
||||||
|
FlowRow(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 10.dp, end = 10.dp, bottom = 10.dp),
|
||||||
|
horizontalArrangement = SpacedBy5dp,
|
||||||
|
verticalArrangement = SpacedBy5dp,
|
||||||
|
itemVerticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.kinds),
|
||||||
|
)
|
||||||
|
kinds.forEach {
|
||||||
|
NoPaddingSuggestionChip(
|
||||||
|
label = it.toString(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun NipNoteHeaderPreview() {
|
||||||
|
val event =
|
||||||
|
NipTextEvent(
|
||||||
|
id = "eb2b05394ff0014bb6a79c2eacfd1c80696821592f4dbf86c950c4bf16614aa0",
|
||||||
|
pubKey = "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c",
|
||||||
|
createdAt = 1767978398,
|
||||||
|
content = "Trusted Translations\n--------------------\n\n`draft` `optional`\n\nThis NIP allows anyone to post a translation for any event on a `kind:76`.\n\n```js\n{\n \"kind\": 76,\n \"tags\": [\n [\"e\", \"\u003coriginal_event_id\u003e\", \"\u003crelay\u003e\"]\n [\"k\", \"\u003coriginal_event_kind\u003e\"]\n [\"l\", \"\u003ctranslated_to_language_country\u003e\"], // ISO 639-1: \"en\", \"es\", ...\n [\"l\", \"\u003ctranslated_to_language_code\u003e\"], // ISO 639-1: \"en-us\", \"en-br\"\n [\"s\", \"title\", \"translated title tag\"]\n [\"s\", \"summary\", \"translated summary tag\"]\n ],\n \"content\": \"this is a translated version of the original content\",\n // ...other fields\n}\n```\n\n`e` tag points to the event being translated, `k` tag points to the kind of that event.\n\n`l` tags define the language this was translated to in lowercase codes as defined by ISO 639-1. \n\n`s` tags are the translations for tags in the original event. \n\n`.content` contains the translation of the original `.content`\n\nClients SHOULD request translations by `e` and `l` tags spoken by their user. For every tag being rendered, Clients SHOULD look for their translated versions.\n\nProviders SHOULD use the event id in the filter to know which events need translations.\n\nProviders MAY store their translations behind a paid relay with NIP-42 auth.\n\n## Declaring Translation Providers\n\nKind `10041` lists the user's authorized translation providers. Each `p` tag is followed by the `pubkey` of the service publishing kind 76s, and the relay translations can be found. Users can specify these publicly or privately by JSON-stringifying and encrypting the tag list in the `.content` using NIP-44. \n\n```js\n{\n \"kind\": 10041,\n \"tags\": [\n [\"p\", \"4fd5e210530e4f6b2cb083795834bfe5108324f1ed9f00ab73b9e8fcfe5f12fe\", \"wss://translations.nostr.com\"],\n [\"l\", \"\u003ctranslated_to_language_country\u003e\"], // ISO 639-1: \"en\", \"es\", ...\n [\"l\", \"\u003ctranslated_to_language_code\u003e\"], // ISO 639-1: \"en-us\", \"en-br\"\n //...\n}\n```\n\n`l` tags in this event are the languages the user understands and wants translations to.\n\nProviders SHOULD create the `10041` event and post to the user's outbox relay.",
|
||||||
|
sig = "7fa9f1d49c41c7bfbdad6d089d1c6685777c86de8fbda7662a630888658839f0444cb1398385f759461c09191b287fa222eec0ffe22b3fa8cf740f71aab9dc21",
|
||||||
|
tags =
|
||||||
|
arrayOf(
|
||||||
|
arrayOf("d", "trusted-translations"),
|
||||||
|
arrayOf("title", "Trusted Translations"),
|
||||||
|
arrayOf("k", "1011"),
|
||||||
|
arrayOf("k", "10041"),
|
||||||
|
arrayOf("k", "1011"),
|
||||||
|
arrayOf("k", "10041"),
|
||||||
|
arrayOf("k", "1011"),
|
||||||
|
arrayOf("k", "10041"),
|
||||||
|
arrayOf("k", "1011"),
|
||||||
|
arrayOf("k", "10041"),
|
||||||
|
arrayOf("client", "nostrhub.io"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
LocalCache.justConsume(event, null, true)
|
||||||
|
val note = LocalCache.getOrCreateNote(event.id)
|
||||||
|
|
||||||
|
ThemeComparisonColumn(
|
||||||
|
toPreview = {
|
||||||
|
NipNoteHeader(
|
||||||
|
noteEvent = event,
|
||||||
|
note = note,
|
||||||
|
accountViewModel = mockAccountViewModel(),
|
||||||
|
nav = EmptyNav(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun NoPaddingSuggestionChip(
|
||||||
|
label: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
Surface(
|
||||||
|
shape = MaterialTheme.shapes.extraSmall, // Use a small shape for chip look
|
||||||
|
color = MaterialTheme.colorScheme.secondaryContainer, // Default chip color
|
||||||
|
modifier = modifier,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
// Apply desired internal padding to the Text itself
|
||||||
|
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp),
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@ import com.vitorpamplona.amethyst.ui.stringRes
|
|||||||
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
||||||
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||||
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||||
@@ -392,6 +393,7 @@ val DEFAULT_FEED_KINDS =
|
|||||||
LiveActivitiesChatMessageEvent.KIND,
|
LiveActivitiesChatMessageEvent.KIND,
|
||||||
LiveActivitiesEvent.KIND,
|
LiveActivitiesEvent.KIND,
|
||||||
WikiNoteEvent.KIND,
|
WikiNoteEvent.KIND,
|
||||||
|
NipTextEvent.KIND,
|
||||||
InteractiveStoryPrologueEvent.KIND,
|
InteractiveStoryPrologueEvent.KIND,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -406,6 +408,7 @@ val DEFAULT_COMMUNITY_FEEDS =
|
|||||||
AudioTrackEvent.KIND,
|
AudioTrackEvent.KIND,
|
||||||
PinListEvent.KIND,
|
PinListEvent.KIND,
|
||||||
WikiNoteEvent.KIND,
|
WikiNoteEvent.KIND,
|
||||||
|
NipTextEvent.KIND,
|
||||||
CommunityPostApprovalEvent.KIND,
|
CommunityPostApprovalEvent.KIND,
|
||||||
InteractiveStoryPrologueEvent.KIND,
|
InteractiveStoryPrologueEvent.KIND,
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-1
@@ -33,6 +33,7 @@ import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
|||||||
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
||||||
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
|
import com.vitorpamplona.quartz.nip18Reposts.GenericRepostEvent
|
||||||
@@ -49,12 +50,13 @@ class FollowPackFeedNewThreadFeedFilter(
|
|||||||
val followPackNote: AddressableNote,
|
val followPackNote: AddressableNote,
|
||||||
val account: Account,
|
val account: Account,
|
||||||
) : AdditiveFeedFilter<Note>() {
|
) : AdditiveFeedFilter<Note>() {
|
||||||
companion object Companion {
|
companion object {
|
||||||
val ADDRESSABLE_KINDS =
|
val ADDRESSABLE_KINDS =
|
||||||
listOf(
|
listOf(
|
||||||
AudioTrackEvent.KIND,
|
AudioTrackEvent.KIND,
|
||||||
InteractiveStoryPrologueEvent.KIND,
|
InteractiveStoryPrologueEvent.KIND,
|
||||||
WikiNoteEvent.KIND,
|
WikiNoteEvent.KIND,
|
||||||
|
NipTextEvent.KIND,
|
||||||
ClassifiedsEvent.KIND,
|
ClassifiedsEvent.KIND,
|
||||||
LongTextNoteEvent.KIND,
|
LongTextNoteEvent.KIND,
|
||||||
)
|
)
|
||||||
|
|||||||
+2
@@ -25,6 +25,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.nip22Commen
|
|||||||
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
||||||
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStorySceneEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStorySceneEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||||
@@ -58,6 +59,7 @@ val PostsByHashtagKinds2 =
|
|||||||
InteractiveStorySceneEvent.KIND,
|
InteractiveStorySceneEvent.KIND,
|
||||||
AudioTrackEvent.KIND,
|
AudioTrackEvent.KIND,
|
||||||
AudioHeaderEvent.KIND,
|
AudioHeaderEvent.KIND,
|
||||||
|
NipTextEvent.KIND,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun filterPostsByHashtags(
|
fun filterPostsByHashtags(
|
||||||
|
|||||||
+2
@@ -25,6 +25,7 @@ import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.nip22Comments.filterHomePostsByScopes
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.nip22Comments.filterHomePostsByScopes
|
||||||
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||||
@@ -52,6 +53,7 @@ val HomePostsBuHashtagsKinds =
|
|||||||
InteractiveStoryPrologueEvent.KIND,
|
InteractiveStoryPrologueEvent.KIND,
|
||||||
CommentEvent.KIND,
|
CommentEvent.KIND,
|
||||||
WikiNoteEvent.KIND,
|
WikiNoteEvent.KIND,
|
||||||
|
NipTextEvent.KIND,
|
||||||
VoiceEvent.KIND,
|
VoiceEvent.KIND,
|
||||||
VoiceReplyEvent.KIND,
|
VoiceReplyEvent.KIND,
|
||||||
)
|
)
|
||||||
|
|||||||
+2
@@ -25,6 +25,7 @@ import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.muted.MutedAuthors
|
|||||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||||
import com.vitorpamplona.quartz.experimental.ephemChat.chat.EphemeralChatEvent
|
import com.vitorpamplona.quartz.experimental.ephemChat.chat.EphemeralChatEvent
|
||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||||
@@ -53,6 +54,7 @@ val HomePostsNewThreadKinds =
|
|||||||
LongTextNoteEvent.KIND,
|
LongTextNoteEvent.KIND,
|
||||||
HighlightEvent.KIND,
|
HighlightEvent.KIND,
|
||||||
WikiNoteEvent.KIND,
|
WikiNoteEvent.KIND,
|
||||||
|
NipTextEvent.KIND,
|
||||||
PollNoteEvent.KIND,
|
PollNoteEvent.KIND,
|
||||||
InteractiveStoryPrologueEvent.KIND,
|
InteractiveStoryPrologueEvent.KIND,
|
||||||
)
|
)
|
||||||
|
|||||||
+3
@@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.home.datasource.nip72Commu
|
|||||||
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
import com.vitorpamplona.amethyst.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet
|
||||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||||
@@ -41,6 +42,7 @@ val HomePostsFromCommunityKinds =
|
|||||||
ClassifiedsEvent.KIND,
|
ClassifiedsEvent.KIND,
|
||||||
HighlightEvent.KIND,
|
HighlightEvent.KIND,
|
||||||
WikiNoteEvent.KIND,
|
WikiNoteEvent.KIND,
|
||||||
|
NipTextEvent.KIND,
|
||||||
CommunityPostApprovalEvent.KIND,
|
CommunityPostApprovalEvent.KIND,
|
||||||
CommentEvent.KIND,
|
CommentEvent.KIND,
|
||||||
InteractiveStoryPrologueEvent.KIND,
|
InteractiveStoryPrologueEvent.KIND,
|
||||||
@@ -53,6 +55,7 @@ val HomePostsFromCommunityKindsStr =
|
|||||||
ClassifiedsEvent.KIND.toString(),
|
ClassifiedsEvent.KIND.toString(),
|
||||||
HighlightEvent.KIND.toString(),
|
HighlightEvent.KIND.toString(),
|
||||||
WikiNoteEvent.KIND.toString(),
|
WikiNoteEvent.KIND.toString(),
|
||||||
|
NipTextEvent.KIND.toString(),
|
||||||
CommunityPostApprovalEvent.KIND.toString(),
|
CommunityPostApprovalEvent.KIND.toString(),
|
||||||
CommentEvent.KIND.toString(),
|
CommentEvent.KIND.toString(),
|
||||||
InteractiveStoryPrologueEvent.KIND.toString(),
|
InteractiveStoryPrologueEvent.KIND.toString(),
|
||||||
|
|||||||
+2
@@ -31,6 +31,7 @@ import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
|
|||||||
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
||||||
import com.vitorpamplona.quartz.experimental.forks.forkFromVersion
|
import com.vitorpamplona.quartz.experimental.forks.forkFromVersion
|
||||||
import com.vitorpamplona.quartz.experimental.forks.isForkFromAddressWithPubkey
|
import com.vitorpamplona.quartz.experimental.forks.isForkFromAddressWithPubkey
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser
|
import com.vitorpamplona.quartz.nip01Core.tags.people.isTaggedUser
|
||||||
@@ -77,6 +78,7 @@ class NotificationFeedFilter(
|
|||||||
listOf(
|
listOf(
|
||||||
AudioTrackEvent.KIND,
|
AudioTrackEvent.KIND,
|
||||||
WikiNoteEvent.KIND,
|
WikiNoteEvent.KIND,
|
||||||
|
NipTextEvent.KIND,
|
||||||
ClassifiedsEvent.KIND,
|
ClassifiedsEvent.KIND,
|
||||||
LongTextNoteEvent.KIND,
|
LongTextNoteEvent.KIND,
|
||||||
CalendarTimeSlotEvent.KIND,
|
CalendarTimeSlotEvent.KIND,
|
||||||
|
|||||||
+2
@@ -24,6 +24,7 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
|||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap
|
||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
||||||
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||||
@@ -58,6 +59,7 @@ val UserProfilePostKinds2 =
|
|||||||
listOf(
|
listOf(
|
||||||
TorrentEvent.KIND,
|
TorrentEvent.KIND,
|
||||||
TorrentCommentEvent.KIND,
|
TorrentCommentEvent.KIND,
|
||||||
|
NipTextEvent.KIND,
|
||||||
InteractiveStoryPrologueEvent.KIND,
|
InteractiveStoryPrologueEvent.KIND,
|
||||||
CommentEvent.KIND,
|
CommentEvent.KIND,
|
||||||
VoiceReplyEvent.KIND,
|
VoiceReplyEvent.KIND,
|
||||||
|
|||||||
+2
@@ -30,6 +30,7 @@ import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
|||||||
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
||||||
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
||||||
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||||
@@ -76,6 +77,7 @@ class UserProfileMutualFeedFilter(
|
|||||||
it.event is GenericRepostEvent ||
|
it.event is GenericRepostEvent ||
|
||||||
it.event is LongTextNoteEvent ||
|
it.event is LongTextNoteEvent ||
|
||||||
it.event is WikiNoteEvent ||
|
it.event is WikiNoteEvent ||
|
||||||
|
it.event is NipTextEvent ||
|
||||||
it.event is PollNoteEvent ||
|
it.event is PollNoteEvent ||
|
||||||
it.event is HighlightEvent ||
|
it.event is HighlightEvent ||
|
||||||
it.event is InteractiveStoryPrologueEvent ||
|
it.event is InteractiveStoryPrologueEvent ||
|
||||||
|
|||||||
+2
@@ -30,6 +30,7 @@ import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
|||||||
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
import com.vitorpamplona.quartz.experimental.audio.header.AudioHeaderEvent
|
||||||
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
import com.vitorpamplona.quartz.experimental.audio.track.AudioTrackEvent
|
||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryPrologueEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||||
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||||
@@ -77,6 +78,7 @@ class UserProfileNewThreadFeedFilter(
|
|||||||
it.event is GenericRepostEvent ||
|
it.event is GenericRepostEvent ||
|
||||||
it.event is LongTextNoteEvent ||
|
it.event is LongTextNoteEvent ||
|
||||||
it.event is WikiNoteEvent ||
|
it.event is WikiNoteEvent ||
|
||||||
|
it.event is NipTextEvent ||
|
||||||
it.event is PollNoteEvent ||
|
it.event is PollNoteEvent ||
|
||||||
it.event is HighlightEvent ||
|
it.event is HighlightEvent ||
|
||||||
it.event is InteractiveStoryPrologueEvent ||
|
it.event is InteractiveStoryPrologueEvent ||
|
||||||
|
|||||||
+23
@@ -191,6 +191,7 @@ import com.vitorpamplona.quartz.experimental.forks.forkFromAddress
|
|||||||
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryBaseEvent
|
import com.vitorpamplona.quartz.experimental.interactiveStories.InteractiveStoryBaseEvent
|
||||||
import com.vitorpamplona.quartz.experimental.medical.FhirResourceEvent
|
import com.vitorpamplona.quartz.experimental.medical.FhirResourceEvent
|
||||||
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
||||||
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
import com.vitorpamplona.quartz.experimental.zapPolls.PollNoteEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||||
@@ -545,6 +546,7 @@ private fun FullBleedNoteCompose(
|
|||||||
is BadgeDefinitionEvent -> BadgeDisplay(baseNote = baseNote, accountViewModel)
|
is BadgeDefinitionEvent -> BadgeDisplay(baseNote = baseNote, accountViewModel)
|
||||||
is LongTextNoteEvent -> RenderLongFormHeaderForThread(noteEvent, baseNote, accountViewModel)
|
is LongTextNoteEvent -> RenderLongFormHeaderForThread(noteEvent, baseNote, accountViewModel)
|
||||||
is WikiNoteEvent -> RenderWikiHeaderForThread(noteEvent, accountViewModel, nav)
|
is WikiNoteEvent -> RenderWikiHeaderForThread(noteEvent, accountViewModel, nav)
|
||||||
|
is NipTextEvent -> RenderNipHeaderForThread(noteEvent, accountViewModel, nav)
|
||||||
is ClassifiedsEvent -> RenderClassifiedsReaderForThread(noteEvent, baseNote, accountViewModel, nav)
|
is ClassifiedsEvent -> RenderClassifiedsReaderForThread(noteEvent, baseNote, accountViewModel, nav)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1157,3 +1159,24 @@ private fun RenderWikiHeaderForThread(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RenderNipHeaderForThread(
|
||||||
|
noteEvent: NipTextEvent,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
val forkedAddress = remember(noteEvent) { noteEvent.forkFromAddress() }
|
||||||
|
|
||||||
|
Row(modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 12.dp)) {
|
||||||
|
Column {
|
||||||
|
forkedAddress?.let {
|
||||||
|
LoadAddressableNote(it, accountViewModel) { originalVersion ->
|
||||||
|
if (originalVersion != null) {
|
||||||
|
ForkInformationRow(originalVersion, Modifier.fillMaxWidth(), accountViewModel, nav)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1465,4 +1465,5 @@
|
|||||||
|
|
||||||
<string name="follow_set_delete">Delete List</string>
|
<string name="follow_set_delete">Delete List</string>
|
||||||
<string name="follow_pack_delete">Delete Pack</string>
|
<string name="follow_pack_delete">Delete Pack</string>
|
||||||
|
<string name="kinds">Kinds</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package com.vitorpamplona.quartz.experimental.forks
|
||||||
|
|
||||||
|
class IForkableEvent {
|
||||||
|
}
|
||||||
+151
@@ -0,0 +1,151 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 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.experimental.nipsOnNostr
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import com.vitorpamplona.quartz.experimental.forks.parseFork
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.tags.ForkTag
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.Address
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.hints.AddressHintProvider
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.hints.EventHintProvider
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.hints.types.EventIdHint
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.dTag.dTag
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.kinds.kinds
|
||||||
|
import com.vitorpamplona.quartz.nip10Notes.BaseNoteEvent
|
||||||
|
import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag
|
||||||
|
import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag
|
||||||
|
import com.vitorpamplona.quartz.nip19Bech32.addressHints
|
||||||
|
import com.vitorpamplona.quartz.nip19Bech32.addressIds
|
||||||
|
import com.vitorpamplona.quartz.nip19Bech32.eventHints
|
||||||
|
import com.vitorpamplona.quartz.nip19Bech32.eventIds
|
||||||
|
import com.vitorpamplona.quartz.nip22Comments.RootScope
|
||||||
|
import com.vitorpamplona.quartz.nip23LongContent.tags.TitleTag
|
||||||
|
import com.vitorpamplona.quartz.nip31Alts.alt
|
||||||
|
import com.vitorpamplona.quartz.nip50Search.SearchableEvent
|
||||||
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
|
import kotlin.uuid.ExperimentalUuidApi
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
class NipTextEvent(
|
||||||
|
id: HexKey,
|
||||||
|
pubKey: HexKey,
|
||||||
|
createdAt: Long,
|
||||||
|
tags: Array<Array<String>>,
|
||||||
|
content: String,
|
||||||
|
sig: HexKey,
|
||||||
|
) : BaseNoteEvent(id, pubKey, createdAt, KIND, tags, content, sig),
|
||||||
|
AddressableEvent,
|
||||||
|
RootScope,
|
||||||
|
EventHintProvider,
|
||||||
|
AddressHintProvider,
|
||||||
|
SearchableEvent {
|
||||||
|
override fun indexableContent() = "title: " + title() + "\n" + content
|
||||||
|
|
||||||
|
override fun dTag() = tags.dTag()
|
||||||
|
|
||||||
|
override fun aTag(relayHint: NormalizedRelayUrl?) = ATag(kind, pubKey, dTag(), relayHint)
|
||||||
|
|
||||||
|
override fun address() = Address(kind, pubKey, dTag())
|
||||||
|
|
||||||
|
override fun addressTag() = Address.assemble(kind, pubKey, dTag())
|
||||||
|
|
||||||
|
override fun eventHints(): List<EventIdHint> {
|
||||||
|
val qHints = tags.mapNotNull(QTag::parseEventAsHint)
|
||||||
|
val nip19Hints = citedNIP19().eventHints()
|
||||||
|
|
||||||
|
return qHints + nip19Hints
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun linkedEventIds(): List<HexKey> {
|
||||||
|
val qHints = tags.mapNotNull(QTag::parseEventId)
|
||||||
|
val nip19Hints = citedNIP19().eventIds()
|
||||||
|
|
||||||
|
return qHints + nip19Hints
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addressHints(): List<AddressHint> {
|
||||||
|
val aHints = tags.mapNotNull(ATag::parseAsHint)
|
||||||
|
val qHints = tags.mapNotNull(QTag::parseAddressAsHint)
|
||||||
|
val nip19Hints = citedNIP19().addressHints()
|
||||||
|
|
||||||
|
return aHints + qHints + nip19Hints
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun linkedAddressIds(): List<String> {
|
||||||
|
val aHints = tags.mapNotNull(ATag::parseAddressId)
|
||||||
|
val qHints = tags.mapNotNull(QTag::parseAddressId)
|
||||||
|
val nip19Hints = citedNIP19().addressIds()
|
||||||
|
|
||||||
|
return aHints + qHints + nip19Hints
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isAFork() = tags.any { it.size > 3 && (it[0] == "a" || it[0] == "e") && it[3] == "fork" }
|
||||||
|
|
||||||
|
fun forkFromAddress() = tags.firstNotNullOfOrNull(ForkTag::parseAddress)
|
||||||
|
|
||||||
|
fun forkFromVersion() = tags.firstNotNullOfOrNull(MarkedETag::parseFork)
|
||||||
|
|
||||||
|
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||||
|
|
||||||
|
fun summary() =
|
||||||
|
content.lineSequence().drop(1).firstNotNullOfOrNull {
|
||||||
|
if (it.isBlank() ||
|
||||||
|
it.startsWith("---") ||
|
||||||
|
it.startsWith("`draft") ||
|
||||||
|
it.startsWith("#")
|
||||||
|
) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KIND = 30817
|
||||||
|
const val KIND_STR = "30817"
|
||||||
|
|
||||||
|
@OptIn(ExperimentalUuidApi::class)
|
||||||
|
fun build(
|
||||||
|
description: String,
|
||||||
|
title: String,
|
||||||
|
kinds: List<Int>,
|
||||||
|
dTag: String = Uuid.random().toString(),
|
||||||
|
createdAt: Long = TimeUtils.now(),
|
||||||
|
initializer: TagArrayBuilder<NipTextEvent>.() -> Unit = {},
|
||||||
|
) = eventTemplate(KIND, description, createdAt) {
|
||||||
|
dTag(dTag)
|
||||||
|
alt("NIP: $title")
|
||||||
|
|
||||||
|
title(title)
|
||||||
|
kinds(kinds)
|
||||||
|
|
||||||
|
initializer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 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.experimental.nipsOnNostr
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.tags.kinds.KindTag
|
||||||
|
import com.vitorpamplona.quartz.nip23LongContent.tags.TitleTag
|
||||||
|
|
||||||
|
fun TagArrayBuilder<NipTextEvent>.title(title: String) = addUnique(TitleTag.assemble(title))
|
||||||
|
|
||||||
|
fun TagArrayBuilder<NipTextEvent>.kinds(kinds: List<Int>) = addAll(KindTag.assemble(kinds))
|
||||||
+145
@@ -0,0 +1,145 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 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.experimental.nipsOnNostr.tags
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.Address
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.hints.types.AddressHint
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
|
||||||
|
import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefinitionEvent
|
||||||
|
import com.vitorpamplona.quartz.utils.arrayOfNotNull
|
||||||
|
import com.vitorpamplona.quartz.utils.ensure
|
||||||
|
|
||||||
|
class ForkTag(
|
||||||
|
val address: Address,
|
||||||
|
val relayHint: NormalizedRelayUrl? = null,
|
||||||
|
) {
|
||||||
|
fun toTag() = Address.assemble(address.kind, address.pubKeyHex, address.dTag)
|
||||||
|
|
||||||
|
fun toTagArray() = assemble(address, relayHint)
|
||||||
|
|
||||||
|
fun toTagIdOnly() = assemble(address, null)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG_NAME = "a"
|
||||||
|
|
||||||
|
fun isTagged(tag: Array<String>) = tag.has(1) && tag[0] == TAG_NAME && Address.isOfKind(tag[1], NipTextEvent.KIND_STR)
|
||||||
|
|
||||||
|
fun isTagged(
|
||||||
|
tag: Array<String>,
|
||||||
|
addressId: String,
|
||||||
|
) = tag.has(1) && tag[0] == TAG_NAME && tag[1] == addressId
|
||||||
|
|
||||||
|
fun isTagged(
|
||||||
|
tag: Array<String>,
|
||||||
|
address: ForkTag,
|
||||||
|
) = tag.has(1) && tag[0] == TAG_NAME && tag[1] == address.toTag()
|
||||||
|
|
||||||
|
fun isIn(
|
||||||
|
tag: Array<String>,
|
||||||
|
addressIds: Set<String>,
|
||||||
|
) = tag.has(1) && tag[0] == TAG_NAME && tag[1] in addressIds
|
||||||
|
|
||||||
|
fun parse(tag: Array<String>): ForkTag? {
|
||||||
|
ensure(tag.has(1)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(
|
||||||
|
Address.Companion.isOfKind(
|
||||||
|
tag[1],
|
||||||
|
CommunityDefinitionEvent.Companion.KIND_STR,
|
||||||
|
),
|
||||||
|
) { return null }
|
||||||
|
|
||||||
|
val address = Address.Companion.parse(tag[1]) ?: return null
|
||||||
|
val relayHint = tag.getOrNull(2)?.let { RelayUrlNormalizer.Companion.normalizeOrNull(it) }
|
||||||
|
return ForkTag(address, relayHint)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseValidAddress(tag: Array<String>): String? {
|
||||||
|
ensure(tag.has(1)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(
|
||||||
|
Address.Companion.isOfKind(
|
||||||
|
tag[1],
|
||||||
|
CommunityDefinitionEvent.Companion.KIND_STR,
|
||||||
|
),
|
||||||
|
) { return null }
|
||||||
|
return Address.Companion.parse(tag[1])?.toValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseAddress(tag: Array<String>): Address? {
|
||||||
|
ensure(tag.has(1)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(tag[1].isNotEmpty()) { return null }
|
||||||
|
val address = Address.parse(tag[1]) ?: return null
|
||||||
|
ensure(address.kind == NipTextEvent.KIND) { return null }
|
||||||
|
return address
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseAddressId(tag: Array<String>): String? {
|
||||||
|
ensure(tag.has(1)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(
|
||||||
|
Address.isOfKind(
|
||||||
|
tag[1],
|
||||||
|
NipTextEvent.KIND_STR,
|
||||||
|
),
|
||||||
|
) { return null }
|
||||||
|
return tag[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseAsHint(tag: Array<String>): AddressHint? {
|
||||||
|
ensure(tag.has(2)) { return null }
|
||||||
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
|
ensure(
|
||||||
|
Address.isOfKind(
|
||||||
|
tag[1],
|
||||||
|
NipTextEvent.KIND_STR,
|
||||||
|
),
|
||||||
|
) { return null }
|
||||||
|
ensure(tag[2].isNotEmpty()) { return null }
|
||||||
|
|
||||||
|
val relayHint = RelayUrlNormalizer.normalizeOrNull(tag[2])
|
||||||
|
ensure(relayHint != null) { return null }
|
||||||
|
|
||||||
|
return AddressHint(tag[1], relayHint)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assemble(
|
||||||
|
aTagId: String,
|
||||||
|
relay: NormalizedRelayUrl?,
|
||||||
|
) = arrayOfNotNull(TAG_NAME, aTagId, relay?.url, "fork")
|
||||||
|
|
||||||
|
fun assemble(
|
||||||
|
address: Address,
|
||||||
|
relay: NormalizedRelayUrl?,
|
||||||
|
) = assemble(address.toValue(), relay)
|
||||||
|
|
||||||
|
fun assemble(
|
||||||
|
kind: Int,
|
||||||
|
pubKey: String,
|
||||||
|
dTag: String,
|
||||||
|
relay: NormalizedRelayUrl?,
|
||||||
|
) = assemble(Address.assemble(kind, pubKey, dTag), relay)
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
-14
@@ -18,21 +18,22 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* 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.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.experimental.forks
|
package com.vitorpamplona.quartz.experimental.nipsOnNostr.tags
|
||||||
|
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.Address
|
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
import com.vitorpamplona.quartz.utils.ensure
|
||||||
import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent
|
|
||||||
import com.vitorpamplona.quartz.nip10Notes.tags.MarkedETag
|
|
||||||
|
|
||||||
fun BaseThreadedEvent.isAFork() = tags.any { it.size > 3 && (it[0] == "a" || it[0] == "e") && it[3] == "fork" }
|
class TitleTag {
|
||||||
|
companion object {
|
||||||
|
const val TAG_NAME = "title"
|
||||||
|
|
||||||
fun BaseThreadedEvent.forkFromAddress() =
|
fun parse(tag: Array<String>): String? {
|
||||||
tags.firstOrNull { it.size > 3 && it[0] == "a" && it[3] == "fork" }?.let {
|
ensure(tag.has(1)) { return null }
|
||||||
val aTagValue = it[1]
|
ensure(tag[0] == TAG_NAME) { return null }
|
||||||
Address.parse(aTagValue)
|
ensure(tag[1].isNotEmpty()) { return null }
|
||||||
|
return tag[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assemble(title: String) = arrayOf(TAG_NAME, title)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fun BaseThreadedEvent.forkFromVersion() = tags.firstNotNullOfOrNull(MarkedETag::parseFork)
|
|
||||||
|
|
||||||
fun BaseThreadedEvent.isForkFromAddressWithPubkey(authorHex: HexKey) = tags.any { it.size > 3 && it[0] == "a" && it[3] == "fork" && it[1].contains(authorHex) }
|
|
||||||
+2
-1
@@ -21,6 +21,7 @@
|
|||||||
package com.vitorpamplona.quartz.nip10Notes
|
package com.vitorpamplona.quartz.nip10Notes
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.aTag.taggedATags
|
import com.vitorpamplona.quartz.nip01Core.tags.aTag.taggedATags
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
|
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
|
||||||
@@ -79,7 +80,7 @@ open class BaseThreadedEvent(
|
|||||||
val tagAddresses =
|
val tagAddresses =
|
||||||
taggedATags()
|
taggedATags()
|
||||||
.filter { aTag ->
|
.filter { aTag ->
|
||||||
aTag.kind != CommunityDefinitionEvent.KIND && (kind != WikiNoteEvent.KIND || aTag.kind != WikiNoteEvent.KIND)
|
aTag.kind != CommunityDefinitionEvent.KIND && (kind != WikiNoteEvent.KIND || aTag.kind != WikiNoteEvent.KIND) && (kind != NipTextEvent.KIND || aTag.kind != NipTextEvent.KIND)
|
||||||
// removes forks from itself.
|
// removes forks from itself.
|
||||||
}.map {
|
}.map {
|
||||||
it.toTag()
|
it.toTag()
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.vitorpamplona.quartz.nip54Wiki
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||||
|
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
||||||
|
import com.vitorpamplona.quartz.nip23LongContent.tags.PublishedAtTag
|
||||||
|
|
||||||
|
fun TagArrayBuilder<LongTextNoteEvent>.title(title: String) = addUnique(TitleTag.assemble(title))
|
||||||
|
|
||||||
|
fun TagArrayBuilder<LongTextNoteEvent>.summary(summary: String) = addUnique(SummaryTag.assemble(summary))
|
||||||
|
|
||||||
|
fun TagArrayBuilder<LongTextNoteEvent>.image(imageUrl: String) = addUnique(ImageTag.assemble(imageUrl))
|
||||||
|
|
||||||
|
fun TagArrayBuilder<LongTextNoteEvent>.publishedAt(publishedAt: Long) = addUnique(PublishedAtTag.assemble(publishedAt))
|
||||||
@@ -131,9 +131,7 @@ class WikiNoteEvent(
|
|||||||
fun image() = tags.firstOrNull { it.size > 1 && it[0] == "image" }?.get(1)
|
fun image() = tags.firstOrNull { it.size > 1 && it[0] == "image" }?.get(1)
|
||||||
|
|
||||||
override fun publishedAt(): Long? {
|
override fun publishedAt(): Long? {
|
||||||
val publishedAt = tags.firstNotNullOfOrNull(PublishedAtTag::parse)
|
val publishedAt = tags.firstNotNullOfOrNull(PublishedAtTag::parse) ?: return null
|
||||||
|
|
||||||
if (publishedAt == null) return null
|
|
||||||
|
|
||||||
// removes posts in the future.
|
// removes posts in the future.
|
||||||
return if (publishedAt <= createdAt) {
|
return if (publishedAt <= createdAt) {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import com.vitorpamplona.quartz.experimental.medical.FhirResourceEvent
|
|||||||
import com.vitorpamplona.quartz.experimental.nip95.data.FileStorageEvent
|
import com.vitorpamplona.quartz.experimental.nip95.data.FileStorageEvent
|
||||||
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
import com.vitorpamplona.quartz.experimental.nip95.header.FileStorageHeaderEvent
|
||||||
import com.vitorpamplona.quartz.experimental.nipA3.PaymentTargetsEvent
|
import com.vitorpamplona.quartz.experimental.nipA3.PaymentTargetsEvent
|
||||||
|
import com.vitorpamplona.quartz.experimental.nipsOnNostr.NipTextEvent
|
||||||
import com.vitorpamplona.quartz.experimental.nns.NNSEvent
|
import com.vitorpamplona.quartz.experimental.nns.NNSEvent
|
||||||
import com.vitorpamplona.quartz.experimental.profileGallery.ProfileGalleryEntryEvent
|
import com.vitorpamplona.quartz.experimental.profileGallery.ProfileGalleryEntryEvent
|
||||||
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
|
||||||
@@ -266,6 +267,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)
|
||||||
|
NipTextEvent.KIND -> NipTextEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
NostrConnectEvent.KIND -> 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)
|
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user