mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-03-26 17:52:29 +01:00
Visual support for Kind1 forks.
This commit is contained in:
parent
782926fbea
commit
3c36f52baf
@ -1325,6 +1325,7 @@ class Account(
|
||||
replyingTo: String?,
|
||||
root: String?,
|
||||
directMentions: Set<HexKey>,
|
||||
forkedFrom: Event?,
|
||||
relayList: List<Relay>? = null,
|
||||
geohash: String? = null,
|
||||
nip94attachments: List<FileHeaderEvent>? = null,
|
||||
@ -1349,6 +1350,7 @@ class Account(
|
||||
directMentions = directMentions,
|
||||
geohash = geohash,
|
||||
nip94attachments = nip94attachments,
|
||||
forkedFrom = forkedFrom,
|
||||
signer = signer,
|
||||
) {
|
||||
Client.send(it, relayList = relayList)
|
||||
|
@ -186,6 +186,7 @@ fun NewPostView(
|
||||
onClose: () -> Unit,
|
||||
baseReplyTo: Note? = null,
|
||||
quote: Note? = null,
|
||||
fork: Note? = null,
|
||||
enableMessageInterface: Boolean = false,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
@ -201,7 +202,7 @@ fun NewPostView(
|
||||
var relayList = remember { accountViewModel.account.activeWriteRelays().toImmutableList() }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
postViewModel.load(accountViewModel, baseReplyTo, quote)
|
||||
postViewModel.load(accountViewModel, baseReplyTo, quote, fork)
|
||||
|
||||
launch(Dispatchers.IO) {
|
||||
postViewModel.imageUploadingError.collect { error ->
|
||||
|
@ -55,6 +55,7 @@ import com.vitorpamplona.quartz.events.BaseTextNoteEvent
|
||||
import com.vitorpamplona.quartz.events.ChatMessageEvent
|
||||
import com.vitorpamplona.quartz.events.ClassifiedsEvent
|
||||
import com.vitorpamplona.quartz.events.CommunityDefinitionEvent
|
||||
import com.vitorpamplona.quartz.events.Event
|
||||
import com.vitorpamplona.quartz.events.FileHeaderEvent
|
||||
import com.vitorpamplona.quartz.events.FileStorageEvent
|
||||
import com.vitorpamplona.quartz.events.FileStorageHeaderEvent
|
||||
@ -85,10 +86,10 @@ open class NewPostViewModel() : ViewModel() {
|
||||
var requiresNIP24: Boolean = false
|
||||
|
||||
var originalNote: Note? = null
|
||||
var forkedFromNote: Note? = null
|
||||
|
||||
var pTags by mutableStateOf<List<User>?>(null)
|
||||
var eTags by mutableStateOf<List<Note>?>(null)
|
||||
var imetaTags = mutableStateListOf<Array<String>>()
|
||||
|
||||
var nip94attachments by mutableStateOf<List<FileHeaderEvent>>(emptyList())
|
||||
var nip95attachments by
|
||||
@ -166,6 +167,7 @@ open class NewPostViewModel() : ViewModel() {
|
||||
accountViewModel: AccountViewModel,
|
||||
replyingTo: Note?,
|
||||
quote: Note?,
|
||||
fork: Note?,
|
||||
) {
|
||||
this.accountViewModel = accountViewModel
|
||||
this.account = accountViewModel.account
|
||||
@ -214,6 +216,37 @@ open class NewPostViewModel() : ViewModel() {
|
||||
zapRaiserAmount = null
|
||||
forwardZapTo = Split()
|
||||
forwardZapToEditting = TextFieldValue("")
|
||||
|
||||
fork?.let {
|
||||
message = TextFieldValue(it.event?.content() ?: "")
|
||||
urlPreview = findUrlInMessage()
|
||||
|
||||
it.event?.isSensitive()?.let {
|
||||
if (it) wantsToMarkAsSensitive = true
|
||||
}
|
||||
|
||||
it.event?.zapraiserAmount()?.let {
|
||||
zapRaiserAmount = it
|
||||
}
|
||||
|
||||
it.event?.zapSplitSetup()?.let {
|
||||
val totalWeight = it.sumOf { if (it.isLnAddress) 0.0 else it.weight }
|
||||
|
||||
it.forEach {
|
||||
if (!it.isLnAddress) {
|
||||
forwardZapTo.addItem(LocalCache.getOrCreateUser(it.lnAddressOrPubKeyHex), (it.weight / totalWeight).toFloat())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it.author?.let {
|
||||
if (this.pTags?.contains(it) != true) {
|
||||
this.pTags = listOf(it) + (this.pTags ?: emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
forkedFromNote = it
|
||||
}
|
||||
}
|
||||
|
||||
fun sendPost(relayList: List<Relay>? = null) {
|
||||
@ -404,9 +437,16 @@ open class NewPostViewModel() : ViewModel() {
|
||||
|
||||
val replyId = originalNote?.idHex
|
||||
|
||||
val replyToSet =
|
||||
if (forkedFromNote != null) {
|
||||
(listOfNotNull(forkedFromNote) + (tagger.eTags ?: emptyList())).ifEmpty { null }
|
||||
} else {
|
||||
tagger.eTags
|
||||
}
|
||||
|
||||
account?.sendPost(
|
||||
message = tagger.message,
|
||||
replyTo = tagger.eTags,
|
||||
replyTo = replyToSet,
|
||||
mentions = tagger.pTags,
|
||||
tags = null,
|
||||
zapReceiver = zapReceiver,
|
||||
@ -415,6 +455,7 @@ open class NewPostViewModel() : ViewModel() {
|
||||
replyingTo = replyId,
|
||||
root = rootId,
|
||||
directMentions = tagger.directMentions,
|
||||
forkedFrom = forkedFromNote?.event as? Event,
|
||||
relayList = relayList,
|
||||
geohash = geoHash,
|
||||
nip94attachments = usedAttachments,
|
||||
@ -504,7 +545,6 @@ open class NewPostViewModel() : ViewModel() {
|
||||
urlPreview = null
|
||||
isUploadingImage = false
|
||||
pTags = null
|
||||
imetaTags.clear()
|
||||
|
||||
wantsDirectMessage = false
|
||||
|
||||
|
@ -65,7 +65,7 @@ fun ChannelFabColumn(
|
||||
|
||||
if (wantsToSendNewMessage) {
|
||||
NewPostView(
|
||||
{ wantsToSendNewMessage = false },
|
||||
onClose = { wantsToSendNewMessage = false },
|
||||
enableMessageInterface = true,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
|
@ -294,6 +294,7 @@ fun CreateClickableText(
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
overrideColor: Color? = null,
|
||||
fontWeight: FontWeight? = null,
|
||||
fontSize: TextUnit = TextUnit.Unspecified,
|
||||
route: String,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
@ -304,12 +305,14 @@ fun CreateClickableText(
|
||||
remember(clickablePart, suffix) {
|
||||
val clickablePartStyle =
|
||||
SpanStyle(
|
||||
fontSize = fontSize,
|
||||
color = overrideColor ?: primaryColor,
|
||||
fontWeight = fontWeight,
|
||||
)
|
||||
|
||||
val nonClickablePartStyle =
|
||||
SpanStyle(
|
||||
fontSize = fontSize,
|
||||
color = overrideColor ?: onBackgroundColor,
|
||||
fontWeight = fontWeight,
|
||||
)
|
||||
@ -562,6 +565,7 @@ fun CreateClickableTextWithEmoji(
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
overrideColor: Color? = null,
|
||||
fontWeight: FontWeight = FontWeight.Normal,
|
||||
fontSize: TextUnit = TextUnit.Unspecified,
|
||||
route: String,
|
||||
nav: (String) -> Unit,
|
||||
tags: ImmutableListOfLists<String>?,
|
||||
@ -570,11 +574,12 @@ fun CreateClickableTextWithEmoji(
|
||||
text = clickablePart,
|
||||
tags = tags,
|
||||
onRegularText = {
|
||||
CreateClickableText(it, null, maxLines, overrideColor, fontWeight, route, nav)
|
||||
CreateClickableText(it, null, maxLines, overrideColor, fontWeight, fontSize, route, nav)
|
||||
},
|
||||
onEmojiText = {
|
||||
val clickablePartStyle =
|
||||
SpanStyle(
|
||||
fontSize = fontSize,
|
||||
color = overrideColor ?: MaterialTheme.colorScheme.primary,
|
||||
fontWeight = fontWeight,
|
||||
)
|
||||
|
@ -32,6 +32,15 @@ class SplitItem<T>(val key: T) {
|
||||
class Split<T>() {
|
||||
var items: List<SplitItem<T>> by mutableStateOf(emptyList())
|
||||
|
||||
fun addItem(
|
||||
key: T,
|
||||
percentage: Float,
|
||||
) {
|
||||
val newItem = SplitItem(key)
|
||||
newItem.percentage = percentage
|
||||
this.items = items.plus(newItem)
|
||||
}
|
||||
|
||||
fun addItem(key: T): Int {
|
||||
val wasEqualSplit = isEqualSplit()
|
||||
val newItem = SplitItem(key)
|
||||
|
@ -184,6 +184,7 @@ class AddBountyAmountViewModel : ViewModel() {
|
||||
replyingTo = null,
|
||||
root = null,
|
||||
directMentions = setOf(),
|
||||
forkedFrom = null,
|
||||
)
|
||||
|
||||
nextAmount = TextFieldValue("")
|
||||
|
@ -80,6 +80,7 @@ import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
@ -178,6 +179,7 @@ import com.vitorpamplona.amethyst.ui.theme.grayText
|
||||
import com.vitorpamplona.amethyst.ui.theme.imageModifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
|
||||
import com.vitorpamplona.amethyst.ui.theme.newItemBackgroundColor
|
||||
import com.vitorpamplona.amethyst.ui.theme.nip05
|
||||
import com.vitorpamplona.amethyst.ui.theme.normalNoteModifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.normalWithTopMarginNoteModifier
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
@ -2512,28 +2514,32 @@ fun SecondUserInfoRow(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val noteEvent = remember { note.event } ?: return
|
||||
val noteAuthor = remember { note.author } ?: return
|
||||
val noteEvent = note.event ?: return
|
||||
val noteAuthor = note.author ?: return
|
||||
|
||||
Row(
|
||||
verticalAlignment = CenterVertically,
|
||||
modifier = UserNameMaxRowHeight,
|
||||
) {
|
||||
ObserveDisplayNip05Status(noteAuthor, remember { Modifier.weight(1f) }, accountViewModel, nav)
|
||||
if (noteEvent is BaseTextNoteEvent && noteEvent.isAFork()) {
|
||||
ShowForkInformation(noteEvent, remember(noteEvent) { Modifier.weight(1f) }, accountViewModel, nav)
|
||||
} else {
|
||||
ObserveDisplayNip05Status(noteAuthor, remember(noteEvent) { Modifier.weight(1f) }, accountViewModel, nav)
|
||||
}
|
||||
|
||||
val geo = remember { noteEvent.getGeoHash() }
|
||||
val geo = remember(noteEvent) { noteEvent.getGeoHash() }
|
||||
if (geo != null) {
|
||||
Spacer(StdHorzSpacer)
|
||||
DisplayLocation(geo, nav)
|
||||
}
|
||||
|
||||
val baseReward = remember { noteEvent.getReward()?.let { Reward(it) } }
|
||||
val baseReward = remember(noteEvent) { noteEvent.getReward()?.let { Reward(it) } }
|
||||
if (baseReward != null) {
|
||||
Spacer(StdHorzSpacer)
|
||||
DisplayReward(baseReward, note, accountViewModel, nav)
|
||||
}
|
||||
|
||||
val pow = remember { noteEvent.getPoWRank() }
|
||||
val pow = remember(noteEvent) { noteEvent.getPoWRank() }
|
||||
if (pow > 20) {
|
||||
Spacer(StdHorzSpacer)
|
||||
DisplayPoW(pow)
|
||||
@ -2541,6 +2547,76 @@ fun SecondUserInfoRow(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ShowForkInformation(
|
||||
noteEvent: BaseTextNoteEvent,
|
||||
modifier: Modifier,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val forkedAddress = remember(noteEvent) { noteEvent.forkFromAddress() }
|
||||
val forkedEvent = remember(noteEvent) { noteEvent.forkFromVersion() }
|
||||
if (forkedAddress != null) {
|
||||
LoadAddressableNote(aTag = forkedAddress, accountViewModel = accountViewModel) { addressableNote ->
|
||||
if (addressableNote != null) {
|
||||
ForkInformationRowLightColor(addressableNote, modifier, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
} else if (forkedEvent != null) {
|
||||
LoadNote(forkedEvent, accountViewModel = accountViewModel) { event ->
|
||||
if (event != null) {
|
||||
ForkInformationRowLightColor(event, modifier, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ForkInformationRowLightColor(
|
||||
originalVersion: Note,
|
||||
modifier: Modifier = Modifier,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val noteState by originalVersion.live().metadata.observeAsState()
|
||||
val note = noteState?.note ?: return
|
||||
val author = note.author ?: return
|
||||
val route = remember(note) { routeFor(note, accountViewModel.userProfile()) }
|
||||
|
||||
if (route != null) {
|
||||
Row(modifier) {
|
||||
ClickableText(
|
||||
text =
|
||||
buildAnnotatedString {
|
||||
append(stringResource(id = R.string.forked_from))
|
||||
append(" ")
|
||||
},
|
||||
onClick = { nav(route) },
|
||||
style = LocalTextStyle.current.copy(color = MaterialTheme.colorScheme.nip05, fontSize = Font14SP),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Visible,
|
||||
)
|
||||
|
||||
val userState by author.live().metadata.observeAsState()
|
||||
val userDisplayName = remember(userState) { userState?.user?.toBestDisplayName() }
|
||||
val userTags =
|
||||
remember(userState) { userState?.user?.info?.latestMetadata?.tags?.toImmutableListOfLists() }
|
||||
|
||||
if (userDisplayName != null) {
|
||||
CreateClickableTextWithEmoji(
|
||||
clickablePart = userDisplayName,
|
||||
maxLines = 1,
|
||||
route = route,
|
||||
overrideColor = MaterialTheme.colorScheme.nip05,
|
||||
fontSize = Font14SP,
|
||||
nav = nav,
|
||||
tags = userTags,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LoadStatuses(
|
||||
user: User,
|
||||
@ -3928,7 +4004,6 @@ private fun WikiNoteHeader(
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val title = remember(noteEvent) { noteEvent.title() }
|
||||
val forkedAddress = remember(noteEvent) { noteEvent.forkFromAddress() }
|
||||
val summary =
|
||||
remember(noteEvent) {
|
||||
noteEvent.summary()?.ifBlank { null } ?: noteEvent.content.take(200).ifBlank { null }
|
||||
|
@ -127,6 +127,7 @@ import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||
import com.vitorpamplona.amethyst.ui.theme.placeholderTextColorFilter
|
||||
import com.vitorpamplona.quartz.encoders.Nip30CustomEmoji
|
||||
import com.vitorpamplona.quartz.events.BaseTextNoteEvent
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.ImmutableSet
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
@ -499,6 +500,7 @@ private fun BoostWithDialog(
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
var wantsToQuote by remember { mutableStateOf<Note?>(null) }
|
||||
var wantsToFork by remember { mutableStateOf<Note?>(null) }
|
||||
|
||||
if (wantsToQuote != null) {
|
||||
NewPostView(
|
||||
@ -510,7 +512,34 @@ private fun BoostWithDialog(
|
||||
)
|
||||
}
|
||||
|
||||
BoostReaction(baseNote, grayTint, accountViewModel) { wantsToQuote = baseNote }
|
||||
if (wantsToFork != null) {
|
||||
val replyTo =
|
||||
remember(wantsToFork) {
|
||||
val forkEvent = wantsToFork?.event
|
||||
if (forkEvent is BaseTextNoteEvent) {
|
||||
val hex = forkEvent.replyingTo()
|
||||
wantsToFork?.replyTo?.filter { it.event?.id() == hex }?.firstOrNull()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
NewPostView(
|
||||
onClose = { wantsToFork = null },
|
||||
baseReplyTo = replyTo,
|
||||
fork = wantsToFork,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
)
|
||||
}
|
||||
|
||||
BoostReaction(
|
||||
baseNote,
|
||||
grayTint,
|
||||
accountViewModel,
|
||||
onQuotePress = { wantsToQuote = baseNote },
|
||||
onForkPress = { wantsToFork = baseNote },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@ -650,6 +679,7 @@ fun BoostReaction(
|
||||
iconSizeModifier: Modifier = Size20Modifier,
|
||||
iconSize: Dp = Size20dp,
|
||||
onQuotePress: () -> Unit,
|
||||
onForkPress: () -> Unit,
|
||||
) {
|
||||
var wantsToBoost by remember { mutableStateOf(false) }
|
||||
|
||||
@ -671,7 +701,13 @@ fun BoostReaction(
|
||||
wantsToBoost = false
|
||||
onQuotePress()
|
||||
},
|
||||
onRepost = { accountViewModel.boost(baseNote) },
|
||||
onRepost = {
|
||||
accountViewModel.boost(baseNote)
|
||||
},
|
||||
onFork = {
|
||||
wantsToBoost = false
|
||||
onForkPress()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1149,6 +1185,7 @@ private fun BoostTypeChoicePopup(
|
||||
onDismiss: () -> Unit,
|
||||
onQuote: () -> Unit,
|
||||
onRepost: () -> Unit,
|
||||
onFork: () -> Unit,
|
||||
) {
|
||||
val iconSizePx = with(LocalDensity.current) { -iconSize.toPx().toInt() }
|
||||
|
||||
@ -1189,6 +1226,18 @@ private fun BoostTypeChoicePopup(
|
||||
) {
|
||||
Text(stringResource(R.string.quote), color = Color.White, textAlign = TextAlign.Center)
|
||||
}
|
||||
|
||||
Button(
|
||||
modifier = Modifier.padding(horizontal = 3.dp),
|
||||
onClick = onFork,
|
||||
shape = ButtonBorder,
|
||||
colors =
|
||||
ButtonDefaults.buttonColors(
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
),
|
||||
) {
|
||||
Text(stringResource(R.string.fork), color = Color.White, textAlign = TextAlign.Center)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,6 @@ import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil.compose.AsyncImage
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.components.InlineCarrousel
|
||||
@ -913,7 +912,7 @@ private fun RenderWikiHeaderForThread(
|
||||
forkedAddress?.let {
|
||||
LoadAddressableNote(aTag = it, accountViewModel = accountViewModel) { originalVersion ->
|
||||
if (originalVersion != null) {
|
||||
ShowForkInformation(originalVersion, Modifier.fillMaxWidth(), accountViewModel, nav)
|
||||
ForkInformationRow(originalVersion, Modifier.fillMaxWidth(), accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -934,8 +933,8 @@ private fun RenderWikiHeaderForThread(
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ShowForkInformation(
|
||||
originalVersion: AddressableNote,
|
||||
fun ForkInformationRow(
|
||||
originalVersion: Note,
|
||||
modifier: Modifier = Modifier,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
|
@ -476,9 +476,12 @@ fun ReactionsColumn(
|
||||
accountViewModel = accountViewModel,
|
||||
iconSizeModifier = Size40Modifier,
|
||||
iconSize = Size40dp,
|
||||
) {
|
||||
wantsToQuote = baseNote
|
||||
}
|
||||
onQuotePress = {
|
||||
wantsToQuote = baseNote
|
||||
},
|
||||
onForkPress = {
|
||||
},
|
||||
)
|
||||
LikeReaction(
|
||||
baseNote = baseNote,
|
||||
grayTint = MaterialTheme.colorScheme.onBackground,
|
||||
|
@ -47,6 +47,7 @@
|
||||
<string name="boost">Boost</string>
|
||||
<string name="boosted">boosted</string>
|
||||
<string name="quote">Quote</string>
|
||||
<string name="fork">Fork</string>
|
||||
<string name="new_amount_in_sats">New Amount in Sats</string>
|
||||
<string name="add">Add</string>
|
||||
<string name="replying_to">"replying to "</string>
|
||||
@ -777,6 +778,7 @@
|
||||
<string name="max_limit">Max Limit</string>
|
||||
<string name="restricted_writes">Restricted Writes</string>
|
||||
<string name="forked_from">Forked from</string>
|
||||
<string name="forked_tag">FORK</string>
|
||||
<string name="git_repository">Git Repository: %1$s</string>
|
||||
<string name="git_web_address">Web:</string>
|
||||
<string name="git_clone_address">Clone:</string>
|
||||
|
@ -22,6 +22,7 @@ package com.vitorpamplona.quartz.events
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.encoders.ATag
|
||||
import com.vitorpamplona.quartz.encoders.HexKey
|
||||
import com.vitorpamplona.quartz.encoders.Nip19Bech32
|
||||
import com.vitorpamplona.quartz.encoders.Nip19Bech32.nip19regex
|
||||
@ -42,6 +43,18 @@ open class BaseTextNoteEvent(
|
||||
) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
|
||||
fun mentions() = taggedUsers()
|
||||
|
||||
fun isAFork() = tags.any { it.size > 3 && (it[0] == "a" || it[0] == "e") && it[3] == "fork" }
|
||||
|
||||
fun forkFromAddress() =
|
||||
tags.firstOrNull { it.size > 3 && it[0] == "a" && it[3] == "fork" }?.let {
|
||||
val aTagValue = it[1]
|
||||
val relay = it.getOrNull(2)
|
||||
|
||||
ATag.parse(aTagValue, relay)
|
||||
}
|
||||
|
||||
fun forkFromVersion() = tags.firstOrNull { it.size > 3 && it[0] == "e" && it[3] == "fork" }?.get(1)
|
||||
|
||||
open fun replyTos(): List<HexKey> {
|
||||
val oldStylePositional = tags.filter { it.size > 1 && it.size <= 3 && it[0] == "e" }.map { it[1] }
|
||||
val newStyleReply = tags.lastOrNull { it.size > 3 && it[0] == "e" && it[3] == "reply" }?.get(1)
|
||||
|
@ -57,6 +57,7 @@ class TextNoteEvent(
|
||||
directMentions: Set<HexKey> = emptySet(),
|
||||
geohash: String? = null,
|
||||
nip94attachments: List<FileHeaderEvent>? = null,
|
||||
forkedFrom: Event? = null,
|
||||
signer: NostrSigner,
|
||||
createdAt: Long = TimeUtils.now(),
|
||||
onReady: (TextNoteEvent) -> Unit,
|
||||
@ -69,6 +70,7 @@ class TextNoteEvent(
|
||||
root = root,
|
||||
replyingTo = replyingTo,
|
||||
directMentions = directMentions,
|
||||
forkedFrom = forkedFrom?.id,
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -93,6 +95,7 @@ class TextNoteEvent(
|
||||
root = root,
|
||||
replyingTo = replyingTo,
|
||||
directMentions = directMentions,
|
||||
forkedFrom = (forkedFrom as? AddressableEvent)?.address()?.toTag(),
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -136,6 +139,7 @@ class TextNoteEvent(
|
||||
root: String?,
|
||||
replyingTo: String?,
|
||||
directMentions: Set<HexKey>,
|
||||
forkedFrom: String?,
|
||||
) = sortedWith { o1, o2 ->
|
||||
when {
|
||||
o1 == o2 -> 0
|
||||
@ -150,6 +154,7 @@ class TextNoteEvent(
|
||||
when (it) {
|
||||
root -> arrayOf(tagName, it, "", "root")
|
||||
replyingTo -> arrayOf(tagName, it, "", "reply")
|
||||
forkedFrom -> arrayOf(tagName, it, "", "fork")
|
||||
in directMentions -> arrayOf(tagName, it, "", "mention")
|
||||
else -> arrayOf(tagName, it)
|
||||
}
|
||||
|
@ -41,16 +41,6 @@ class WikiNoteEvent(
|
||||
|
||||
fun topics() = hashtags()
|
||||
|
||||
fun forkFromAddress() =
|
||||
tags.firstOrNull { it.size > 3 && it[0] == "a" && it[3] == "fork" }?.let {
|
||||
val aTagValue = it[1]
|
||||
val relay = it.getOrNull(2)
|
||||
|
||||
ATag.parse(aTagValue, relay)
|
||||
}
|
||||
|
||||
fun forkFromVersion() = tags.firstOrNull { it.size > 3 && it[0] == "e" && it[3] == "fork" }?.get(1)
|
||||
|
||||
fun title() = tags.firstOrNull { it.size > 1 && it[0] == "title" }?.get(1)
|
||||
|
||||
fun summary() = tags.firstOrNull { it.size > 1 && it[0] == "summary" }?.get(1)
|
||||
|
Loading…
x
Reference in New Issue
Block a user