Improve note rendering

This commit is contained in:
Kgothatso Ngako committed 2026-05-03 19:03:50 +02:00
1 parent 3fef7bdabc
commit e7db6598d0
9 files changed
+483 -201

No files matched your search

@@ -7,21 +7,24 @@ import ac.cord.auxiliary.compose.database.model.QuotedRelation
import ac.cord.auxiliary.compose.extensions.toFormattedTimeAndDateString import ac.cord.auxiliary.compose.extensions.toFormattedTimeAndDateString
import ac.cord.auxiliary.compose.ui.composable.widgets.content.RichContent import ac.cord.auxiliary.compose.ui.composable.widgets.content.RichContent
import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileAvatar import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileAvatar
import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileColor
import ac.cord.auxiliary.compose.ui.theme.AuxTheme
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.room3.Embedded import androidx.room3.Embedded
import androidx.room3.Relation import androidx.room3.Relation
import com.vitorpamplona.quartz.nip01Core.core.HexKey
data class LocalQuotedNostrEvent( data class LocalQuotedNostrEvent(
@Embedded val quotedRelation: QuotedRelation, @Embedded val quotedRelation: QuotedRelation,
@@ -46,37 +49,43 @@ data class LocalQuotedNostrEvent(
val mentionedProfiles: List<LocalMention> = emptyList(), val mentionedProfiles: List<LocalMention> = emptyList(),
) { ) {
@Composable @Composable
fun RenderNotePreview() { fun RenderNotePreview(
onNavigateToEvent: (HexKey) -> Unit
) {
Column { Column {
Row( Row(
modifier = Modifier.fillMaxWidth().padding(12.dp), modifier = Modifier.fillMaxWidth().padding(10.dp)
horizontalArrangement = Arrangement.spacedBy(4.dp), // .clickable(
// onClick = {
// onNavigateToEvent.invoke(profile.nostrEventId)
// }
// )
,
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.Start),
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
val profile = profile
ProfileAvatar( ProfileAvatar(
profile = profile, publicKey = nostrEvent.pubKey,
publicKey = nostrEvent.pubKey profile = profile
) )
Column( Column(
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f)
) { ){
Text( Text(
text = profile?.displayName ?: profile?.userName ?: nostrEvent.pubKey, text = profile?.humanReadableNameOrPubkey() ?: nostrEvent.pubKey,
style = MaterialTheme.typography.labelLarge style = MaterialTheme.typography.bodyMedium
) )
profile?.nip05?.let { profile?.staticIdentifier()?.let { staticIdentifier ->
Text( Text(
text = profile.nip05 ?: "", text = staticIdentifier,
style = MaterialTheme.typography.labelMedium style = MaterialTheme.typography.bodySmall,
color = ProfileColor.fromProfile(profile)
) )
} }
} }
} }
Column( Column(
modifier = Modifier.fillMaxWidth().padding( modifier = Modifier.fillMaxWidth().padding(
horizontal = 10.dp horizontal = 10.dp
@@ -86,6 +95,7 @@ data class LocalQuotedNostrEvent(
nostrEvent = nostrEvent, nostrEvent = nostrEvent,
localQuotedNostrEvent = null, localQuotedNostrEvent = null,
mentionedProfiles = mentionedProfiles, mentionedProfiles = mentionedProfiles,
onNavigateToEvent = onNavigateToEvent
) )
} }
@@ -101,3 +111,36 @@ data class LocalQuotedNostrEvent(
} }
} }
} }
@Preview
@Composable
private fun LocalQuotedNostrEventPreview() {
AuxTheme {
Surface(
modifier = Modifier.padding(20.dp)
) {
LocalQuotedNostrEvent(
nostrEvent = NostrEvent(
id = "1c7213118d4e17c6bad5c6b11125f005619bc3e43374affb9cd6483f665fd5e6",
content = "God is not in the habit of coming down from heaven to solve people’s problems on earth.",
pubKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
kind = 0,
sig = "hexsig",
tags = emptyArray()
),
quotedRelation = QuotedRelation(
quotingNostrEventId = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a520",
quotedProfilePublicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
quotedNostrEventId = "1c7213118d4e17c6bad5c6b11125f005619bc3e43374affb9cd6483f665fd5e6"
),
profile = Profile(
publicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
nostrEventId = "referenced",
displayName = "Steve Biko"
),
).RenderNotePreview(
onNavigateToEvent = {}
)
}
}
}
@@ -78,7 +78,7 @@ fun NostrEventDetailScreen(
feedListUIState.localNostrEvent, feedListUIState.localNostrEvent,
onNavigateBack = onNavigateBack, onNavigateBack = onNavigateBack,
onNavigateToWriteAReply = onNavigateToWriteAReply, onNavigateToWriteAReply = onNavigateToWriteAReply,
onNavigateToQuoteNostrEvent = onNavigateToQuoteNostrEvent onNavigateToNostrEvent = onNavigateToQuoteNostrEvent
) )
} }
RepostEvent.KIND -> { RepostEvent.KIND -> {
@@ -47,11 +47,7 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextField import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.SpanStyle
@@ -60,7 +56,6 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import co.touchlab.kermit.Logger
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
import kotlin.time.Clock import kotlin.time.Clock
@@ -368,6 +363,7 @@ fun WriteNewNoteScreen(
) )
}, },
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
onNavigateToEvent = {}
// TODO: Add TextAlign.Center // TODO: Add TextAlign.Center
) )
@@ -1,6 +1,5 @@
package ac.cord.auxiliary.compose.ui.composable.widgets.content package ac.cord.auxiliary.compose.ui.composable.widgets.content
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalNostrEvent
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalQuotedNostrEvent import ac.cord.auxiliary.compose.database.model.intermdiate.LocalQuotedNostrEvent
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@@ -28,7 +27,7 @@ internal fun QuotedAddressableNote(
dTag: String, dTag: String,
author: String, author: String,
relayHints: List<String>, relayHints: List<String>,
onNoteClick: ((String) -> Unit)?, onNoteClick: (String) -> Unit,
onProfileClick: ((String) -> Unit)?, onProfileClick: ((String) -> Unit)?,
noteActions: NoteActions?, noteActions: NoteActions?,
style: TextStyle style: TextStyle
@@ -39,7 +38,7 @@ internal fun QuotedAddressableNote(
if (localQuotedNostrEvent != null) { if (localQuotedNostrEvent != null) {
QuotedNote( QuotedNote(
localQuotedNostrEvent = localQuotedNostrEvent, localQuotedNostrEvent = localQuotedNostrEvent,
onNoteClick = onNoteClick, onNavigateToEvent = onNoteClick,
noteActions = noteActions noteActions = noteActions
) )
} else { } else {
@@ -1,8 +1,10 @@
package ac.cord.auxiliary.compose.ui.composable.widgets.content package ac.cord.auxiliary.compose.ui.composable.widgets.content
import ac.cord.auxiliary.compose.database.model.NostrEvent
import ac.cord.auxiliary.compose.database.model.Profile import ac.cord.auxiliary.compose.database.model.Profile
import ac.cord.auxiliary.compose.database.model.QuotedRelation import ac.cord.auxiliary.compose.database.model.QuotedRelation
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalQuotedNostrEvent import ac.cord.auxiliary.compose.database.model.intermdiate.LocalQuotedNostrEvent
import ac.cord.auxiliary.compose.ui.theme.AuxTheme
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@@ -19,12 +21,14 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.quartz.nip01Core.core.HexKey
@Composable @Composable
fun QuotedNote( fun QuotedNote(
localQuotedNostrEvent: LocalQuotedNostrEvent? = null, localQuotedNostrEvent: LocalQuotedNostrEvent? = null,
onNoteClick: ((String) -> Unit)? = null, onNavigateToEvent:(HexKey) -> Unit,
noteActions: NoteActions? = null noteActions: NoteActions? = null
) { ) {
// Observe versions so we recompose when data arrives from relays // Observe versions so we recompose when data arrives from relays
@@ -36,7 +40,7 @@ fun QuotedNote(
// } // }
// } // }
val effectiveNoteClick = noteActions?.onNoteClick ?: onNoteClick val effectiveNoteClick = noteActions?.onNoteClick ?: onNavigateToEvent
// Fetch poll votes when quoted event is a poll // Fetch poll votes when quoted event is a poll
// LaunchedEffect(event?.id, event?.kind) { // LaunchedEffect(event?.id, event?.kind) {
@@ -59,7 +63,9 @@ fun QuotedNote(
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 6.dp) .padding(vertical = 6.dp)
) { ) {
localQuotedNostrEvent.RenderNotePreview() localQuotedNostrEvent.RenderNotePreview(
onNavigateToEvent = onNavigateToEvent
)
// quotedNostrEvent.RenderNotePreview() // quotedNostrEvent.RenderNotePreview()
} }
} else if (localQuotedNostrEvent != null) { } else if (localQuotedNostrEvent != null) {
@@ -70,13 +76,13 @@ fun QuotedNote(
color = MaterialTheme.colorScheme.surface, color = MaterialTheme.colorScheme.surface,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 6.dp)
.then( .then(
if (effectiveNoteClick != null) Modifier.clickable { effectiveNoteClick(localQuotedNostrEvent.nostrEvent.id) } Modifier.clickable { effectiveNoteClick(localQuotedNostrEvent.nostrEvent.id) }
else Modifier
) )
) { ) {
localQuotedNostrEvent.RenderNotePreview() localQuotedNostrEvent.RenderNotePreview(
onNavigateToEvent = onNavigateToEvent
)
} }
} else { } else {
// Loading state // Loading state
@@ -109,3 +115,40 @@ fun QuotedNote(
} }
} }
} }
@Preview
@Composable
private fun QuotedNotePreview() {
AuxTheme {
Surface(
modifier = Modifier.padding(20.dp)
) {
QuotedNote(
localQuotedNostrEvent = LocalQuotedNostrEvent(
nostrEvent = NostrEvent(
id = "1c7213118d4e17c6bad5c6b11125f005619bc3e43374affb9cd6483f665fd5e6",
content = "God is not in the habit of coming down from heaven to solve people’s problems on earth.",
pubKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
kind = 0,
sig = "hexsig",
tags = emptyArray()
),
quotedRelation = QuotedRelation(
quotingNostrEventId = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a520",
quotedProfilePublicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
quotedNostrEventId = "1c7213118d4e17c6bad5c6b11125f005619bc3e43374affb9cd6483f665fd5e6"
),
profile = Profile(
publicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
nostrEventId = "referenced",
displayName = "Steve Biko"
),
),
onNavigateToEvent = { },
noteActions = null
)
}
}
}
@@ -5,14 +5,14 @@ import ac.cord.auxiliary.compose.database.model.NostrEvent
import ac.cord.auxiliary.compose.database.model.Profile import ac.cord.auxiliary.compose.database.model.Profile
import ac.cord.auxiliary.compose.database.model.QuotedRelation import ac.cord.auxiliary.compose.database.model.QuotedRelation
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalMention import ac.cord.auxiliary.compose.database.model.intermdiate.LocalMention
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalNostrEvent
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalQuotedNostrEvent import ac.cord.auxiliary.compose.database.model.intermdiate.LocalQuotedNostrEvent
import ac.cord.auxiliary.compose.ui.composable.widgets.content.Constants.INLINE_CONTENT_TAG import ac.cord.auxiliary.compose.ui.composable.widgets.content.Constants.INLINE_CONTENT_TAG
import ac.cord.auxiliary.compose.ui.composable.widgets.feed.ListView
import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileColor import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileColor
import ac.cord.auxiliary.compose.ui.theme.AuxTheme import ac.cord.auxiliary.compose.ui.theme.AuxTheme
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.InlineTextContent import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.text.selection.SelectionContainer
@@ -41,6 +41,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import coil3.compose.AsyncImage import coil3.compose.AsyncImage
import com.vitorpamplona.quartz.nip01Core.core.HexKey
@Composable @Composable
fun RichContent( fun RichContent(
@@ -54,7 +55,7 @@ fun RichContent(
imetaMap: Map<String, MediaMeta> = emptyMap(), imetaMap: Map<String, MediaMeta> = emptyMap(),
plainLinks: Boolean = false, plainLinks: Boolean = false,
onProfileClick: ((String) -> Unit)? = null, onProfileClick: ((String) -> Unit)? = null,
onNoteClick: ((String) -> Unit)? = null, onNavigateToEvent: (HexKey) -> Unit,
onHashtagClick: ((String) -> Unit)? = null, onHashtagClick: ((String) -> Unit)? = null,
onLiveStreamClick: ((String, String, String?) -> Unit)? = null, onLiveStreamClick: ((String, String, String?) -> Unit)? = null,
noteActions: NoteActions? = null, noteActions: NoteActions? = null,
@@ -294,7 +295,7 @@ fun RichContent(
if (localQuotedNostrEvent != null) { if (localQuotedNostrEvent != null) {
QuotedNote( QuotedNote(
localQuotedNostrEvent = localQuotedNostrEvent, localQuotedNostrEvent = localQuotedNostrEvent,
onNoteClick = onNoteClick, onNavigateToEvent = onNavigateToEvent,
noteActions = noteActions noteActions = noteActions
) )
} else { } else {
@@ -316,7 +317,7 @@ fun RichContent(
dTag = segment.dTag, dTag = segment.dTag,
author = segment.author, author = segment.author,
relayHints = segment.relays, relayHints = segment.relays,
onNoteClick = onNoteClick, onNoteClick = onNavigateToEvent,
onProfileClick = onProfileClick, onProfileClick = onProfileClick,
noteActions = noteActions, noteActions = noteActions,
style = style style = style
@@ -423,7 +424,7 @@ private fun RichContentPreview() {
modifier = Modifier.padding(10.dp), modifier = Modifier.padding(10.dp),
nostrEvent = NostrEvent( nostrEvent = NostrEvent(
id = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a520", id = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a520",
content = "Something something something nostr:npub1uh366qnj68a7atvwgwdy4569xd6v5jtferftapqztwjwlzh9553q47pqsx\nnostr:note1uh366qnj68a7atvwgwdy4569xd6v5jtferftapqztwjwlzh955s53z8ee", content = "Something something something nostr:npub1uh366qnj68a7atvwgwdy4569xd6v5jtferftapqztwjwlzh9553q47pqsx\nhttps://www.brainyquote.com/authors/steven-biko-quotes\nnostr:nevent1qqspcusnzxx5u97xht2udvg3yhcq2cvmc0jrxa90lwwdvjplve0atespzpmhxue69uhkummnw3ezuamfdejsyg8h5g639qhuv803hzwexfwhyud6t6suxfu364anddqvrmn9j4cahvxksr8q",
pubKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522", pubKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
kind = 0, kind = 0,
sig = "hexsig", sig = "hexsig",
@@ -431,8 +432,8 @@ private fun RichContentPreview() {
), ),
localQuotedNostrEvent = LocalQuotedNostrEvent( localQuotedNostrEvent = LocalQuotedNostrEvent(
nostrEvent = NostrEvent( nostrEvent = NostrEvent(
id = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a521", id = "1c7213118d4e17c6bad5c6b11125f005619bc3e43374affb9cd6483f665fd5e6",
content = "Quote me on this!", content = "God is not in the habit of coming down from heaven to solve people’s problems on earth.",
pubKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522", pubKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
kind = 0, kind = 0,
sig = "hexsig", sig = "hexsig",
@@ -441,12 +442,12 @@ private fun RichContentPreview() {
quotedRelation = QuotedRelation( quotedRelation = QuotedRelation(
quotingNostrEventId = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a520", quotingNostrEventId = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a520",
quotedProfilePublicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522", quotedProfilePublicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
quotedNostrEventId = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a521" quotedNostrEventId = "1c7213118d4e17c6bad5c6b11125f005619bc3e43374affb9cd6483f665fd5e6"
), ),
profile = Profile( profile = Profile(
publicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522", publicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
nostrEventId = "referenced", nostrEventId = "referenced",
displayName = "Frank Talk" displayName = "Steve Biko"
), ),
), ),
mentionedProfiles = listOf( mentionedProfiles = listOf(
@@ -462,6 +463,7 @@ private fun RichContentPreview() {
), ),
) )
), ),
onNavigateToEvent = {}
) )
} }
@@ -4,13 +4,10 @@ import ac.cord.auxiliary.compose.database.model.NostrEvent
import ac.cord.auxiliary.compose.database.model.Profile import ac.cord.auxiliary.compose.database.model.Profile
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalNostrEvent import ac.cord.auxiliary.compose.database.model.intermdiate.LocalNostrEvent
import ac.cord.auxiliary.compose.extensions.toFormattedTimeAndDateString import ac.cord.auxiliary.compose.extensions.toFormattedTimeAndDateString
import ac.cord.auxiliary.compose.ui.composable.widgets.content.ContentParser
import ac.cord.auxiliary.compose.ui.composable.widgets.content.ContentSegment
import ac.cord.auxiliary.compose.ui.composable.widgets.content.RichContent import ac.cord.auxiliary.compose.ui.composable.widgets.content.RichContent
import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileAvatar import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileAvatar
import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileColor import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileColor
import ac.cord.auxiliary.compose.ui.theme.AuxTheme import ac.cord.auxiliary.compose.ui.theme.AuxTheme
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -21,14 +18,8 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CornerBasedShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.input.InputTransformation
import androidx.compose.foundation.text.input.OutputTransformation
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AddReaction import androidx.compose.material.icons.filled.AddReaction
import androidx.compose.material.icons.filled.ArrowBackIosNew import androidx.compose.material.icons.filled.ArrowBackIosNew
@@ -37,36 +28,25 @@ import androidx.compose.material.icons.filled.CurrencyBitcoin
import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.filled.Repeat import androidx.compose.material.icons.filled.Repeat
import androidx.compose.material.icons.filled.Reply
import androidx.compose.material.icons.filled.Send
import androidx.compose.material3.BottomAppBar import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FlexibleBottomAppBar import androidx.compose.material3.FlexibleBottomAppBar
import androidx.compose.material3.FloatingToolbarDefaults
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.HorizontalFloatingToolbar
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Shapes
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.graphics.shapes.CornerRounding import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
@@ -75,7 +55,7 @@ fun TextNoteEventDetail(
localNostrEvent: LocalNostrEvent, localNostrEvent: LocalNostrEvent,
onNavigateBack: () -> Unit, onNavigateBack: () -> Unit,
onNavigateToWriteAReply: (String) -> Unit, onNavigateToWriteAReply: (String) -> Unit,
onNavigateToQuoteNostrEvent: (String) -> Unit, onNavigateToNostrEvent: (HexKey) -> Unit,
) { ) {
Scaffold( Scaffold(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
@@ -259,7 +239,8 @@ fun TextNoteEventDetail(
), ),
nostrEvent = localNostrEvent.nostrEvent, nostrEvent = localNostrEvent.nostrEvent,
localQuotedNostrEvent = localNostrEvent.localQuotedNostrEvent, localQuotedNostrEvent = localNostrEvent.localQuotedNostrEvent,
mentionedProfiles = localNostrEvent.mentionedProfiles mentionedProfiles = localNostrEvent.mentionedProfiles,
onNavigateToEvent = onNavigateToNostrEvent
) )
Row( Row(
@@ -302,7 +283,7 @@ fun TextNoteEventDetail(
IconButton( IconButton(
onClick = { onClick = {
onNavigateToQuoteNostrEvent.invoke( onNavigateToNostrEvent.invoke(
localNostrEvent.nostrEvent.id localNostrEvent.nostrEvent.id
) )
} }
@@ -373,7 +354,7 @@ It has survived not only five centuries, but also the leap into electronic types
), ),
onNavigateBack = {}, onNavigateBack = {},
onNavigateToWriteAReply = {}, onNavigateToWriteAReply = {},
onNavigateToQuoteNostrEvent = {} onNavigateToNostrEvent = {}
) )
} }
} }
@@ -1,8 +1,12 @@
package ac.cord.auxiliary.compose.ui.composable.widgets.feed package ac.cord.auxiliary.compose.ui.composable.widgets.feed
import ac.cord.auxiliary.compose.database.model.InReplyToRelation
import ac.cord.auxiliary.compose.database.model.NostrEvent import ac.cord.auxiliary.compose.database.model.NostrEvent
import ac.cord.auxiliary.compose.database.model.Profile import ac.cord.auxiliary.compose.database.model.Profile
import ac.cord.auxiliary.compose.database.model.RepostedRelation
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalInReplyToNostrEvent
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalNostrEvent import ac.cord.auxiliary.compose.database.model.intermdiate.LocalNostrEvent
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalRepostedNostrEvent
import ac.cord.auxiliary.compose.extensions.toFormattedTimeAndDateString import ac.cord.auxiliary.compose.extensions.toFormattedTimeAndDateString
import ac.cord.auxiliary.compose.ui.composable.widgets.content.RichContent import ac.cord.auxiliary.compose.ui.composable.widgets.content.RichContent
import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileAvatar import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileAvatar
@@ -36,6 +40,7 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
import kotlin.time.Instant import kotlin.time.Instant
@@ -135,7 +140,7 @@ fun LocalNostrEvent.ListView(
@Preview @Preview
@Composable @Composable
private fun EventListViewPreview() { private fun EventListViewRepostedPreview() {
AuxTheme { AuxTheme {
Surface( Surface(
modifier = Modifier.padding(20.dp) modifier = Modifier.padding(20.dp)
@@ -143,17 +148,92 @@ private fun EventListViewPreview() {
LocalNostrEvent( LocalNostrEvent(
nostrEvent = NostrEvent( nostrEvent = NostrEvent(
id = "hex", id = "hex",
content = "Something something seomthing", content = "Reposting",
pubKey = "hexpubkeypubkeypubkeypubkey", pubKey = "hexpubkeypubkeypubkeypubkey",
kind = 0, kind = RepostEvent.KIND,
sig = "hexsig", sig = "hexsig",
tags = emptyArray() tags = emptyArray()
), ),
localRepostedNostrEvent = LocalRepostedNostrEvent(
repostedRelation = RepostedRelation(
repostingNostrEventId = "hex",
repostedNostrEventId = "repostedhex",
repostedProfilePublicKey = "reposterHex"
),
nostrEvent = NostrEvent(
id = "hex",
content = "Something something something",
pubKey = "hexpubkeypubkeypubkeypubkey",
kind = 0,
sig = "hexsig",
tags = emptyArray()
),
profile = Profile(
publicKey = "hesd",
nostrEventId = "referenced",
displayName = "Frank Talk",
nip05 = "frank@talk.at"
),
mentionedProfiles = emptyList()
),
profile = Profile( profile = Profile(
publicKey = "", publicKey = "",
nostrEventId = "referenced", nostrEventId = "referenced",
displayName = "Frank Talk", displayName = "Steve Biko",
nip05 = "frank@talk.at" nip05 = "steve@bck.co.za"
),
).ListView(
onNavigateToEvent = {}
)
}
}
}
@Preview
@Composable
private fun EventListViewInReplyPreview() {
AuxTheme {
Surface(
modifier = Modifier.padding(20.dp)
) {
LocalNostrEvent(
nostrEvent = NostrEvent(
id = "hex",
content = "Reposting",
pubKey = "hexpubkeypubkeypubkeypubkey",
kind = TextNoteEvent.KIND,
sig = "hexsig",
tags = emptyArray()
),
localInReplyToNostrEvent = LocalInReplyToNostrEvent(
inReplyToRelation = InReplyToRelation(
inReplyToNostrEventId = "nostrEvent",
inReplyToRootNostrEventId = "rootId",
inReplyToProfilePublicKey = "inReplyToProfileKey",
inReplyToRootProfilePublicKey = "rootPubKey",
replyingNostrEventId = "hex"
),
nostrEvent = NostrEvent(
id = "hex",
content = "Something something something",
pubKey = "hexpubkeypubkeypubkeypubkey",
kind = 0,
sig = "hexsig",
tags = emptyArray()
),
profile = Profile(
publicKey = "hesd",
nostrEventId = "referenced",
displayName = "Frank Talk",
nip05 = "frank@talk.at"
),
mentionedProfiles = emptyList()
),
profile = Profile(
publicKey = "",
nostrEventId = "referenced",
displayName = "Steve Biko",
nip05 = "steve@bck.co.za"
), ),
).ListView( ).ListView(
onNavigateToEvent = {} onNavigateToEvent = {}
@@ -1,10 +1,12 @@
package ac.cord.auxiliary.compose.ui.composable.widgets.feed package ac.cord.auxiliary.compose.ui.composable.widgets.feed
import ac.cord.auxiliary.compose.database.model.InReplyToRelation
import ac.cord.auxiliary.compose.database.model.Mention
import ac.cord.auxiliary.compose.database.model.NostrEvent import ac.cord.auxiliary.compose.database.model.NostrEvent
import ac.cord.auxiliary.compose.database.model.Profile import ac.cord.auxiliary.compose.database.model.Profile
import ac.cord.auxiliary.compose.database.model.QuotedRelation
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalInReplyToNostrEvent import ac.cord.auxiliary.compose.database.model.intermdiate.LocalInReplyToNostrEvent
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalMention import ac.cord.auxiliary.compose.database.model.intermdiate.LocalMention
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalNostrEvent
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalQuotedNostrEvent import ac.cord.auxiliary.compose.database.model.intermdiate.LocalQuotedNostrEvent
import ac.cord.auxiliary.compose.extensions.toFormattedTimeAndDateString import ac.cord.auxiliary.compose.extensions.toFormattedTimeAndDateString
import ac.cord.auxiliary.compose.ui.composable.widgets.content.RichContent import ac.cord.auxiliary.compose.ui.composable.widgets.content.RichContent
@@ -27,6 +29,7 @@ import androidx.compose.material3.SuggestionChip
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
@@ -44,156 +47,150 @@ internal fun TextNoteFeedItem(
mentionedProfiles: List<LocalMention>, mentionedProfiles: List<LocalMention>,
onNavigateToEvent: (HexKey) -> Unit onNavigateToEvent: (HexKey) -> Unit
) { ) {
if (localInReplyToNostrEvent != null) { val expended = mutableStateOf(false)
Row(
modifier = Modifier.fillMaxWidth().padding(
horizontal = 20.dp
),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically
) {
Text(
"In reply to ",
style = MaterialTheme.typography.labelSmall
)
Text( Column {
modifier = Modifier.clickable(
onClick = { if (localInReplyToNostrEvent != null) {
onNavigateToEvent.invoke(localInReplyToNostrEvent.inReplyToRelation.inReplyToNostrEventId) Row(
} modifier = Modifier.fillMaxWidth().padding(
horizontal = 20.dp
), ),
style = MaterialTheme.typography.labelLargeEmphasized, horizontalArrangement = Arrangement.End,
text = localInReplyToNostrEvent.profile?.humanReadableNameOrPubkey() ?: "loading information..." verticalAlignment = Alignment.CenterVertically
) ) {
} Text(
} "In reply to ",
style = MaterialTheme.typography.labelSmall
)
ElevatedCard( Text(
modifier = Modifier.padding( modifier = Modifier.clickable(
horizontal = 10.dp
),
onClick = {
onNavigateToEvent.invoke(nostrEvent.id)
}
) {
Column(
modifier = Modifier.padding(10.dp).fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(10.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
if (profile != null) {
Row(
modifier = Modifier.fillMaxWidth().clickable(
onClick = { onClick = {
onNavigateToEvent.invoke(profile.nostrEventId) onNavigateToEvent.invoke(localInReplyToNostrEvent.inReplyToRelation.inReplyToNostrEventId)
} }
), ),
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.Start), style = MaterialTheme.typography.labelLargeEmphasized,
verticalAlignment = Alignment.CenterVertically color = ProfileColor.fromPublicKey(localInReplyToNostrEvent.nostrEvent.pubKey),
) { text = localInReplyToNostrEvent.profile?.humanReadableNameOrPubkey() ?: "loading information..."
ProfileAvatar( )
publicKey = nostrEvent.pubKey, }
profile = profile }
)
Column( ElevatedCard(
modifier = Modifier.weight(1f) modifier = Modifier.padding(
){ horizontal = 10.dp
Text( ),
text = profile.humanReadableNameOrPubkey(), onClick = {
style = MaterialTheme.typography.bodyMedium onNavigateToEvent.invoke(nostrEvent.id)
}
) {
Column(
modifier = Modifier.padding(10.dp).fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(10.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
if (profile != null) {
Row(
modifier = Modifier.fillMaxWidth().clickable(
onClick = {
onNavigateToEvent.invoke(profile.nostrEventId)
}
),
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.Start),
verticalAlignment = Alignment.CenterVertically
) {
ProfileAvatar(
publicKey = nostrEvent.pubKey,
profile = profile
) )
profile.staticIdentifier()?.let { staticIdentifier -> Column(
modifier = Modifier.weight(1f)
){
Text( Text(
text = staticIdentifier, text = profile.humanReadableNameOrPubkey(),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodyMedium
color = ProfileColor.fromProfile(profile) )
profile.staticIdentifier()?.let { staticIdentifier ->
Text(
text = staticIdentifier,
style = MaterialTheme.typography.bodySmall,
color = ProfileColor.fromProfile(profile)
)
}
}
}
} else {
Text(
text = "Loading author information"
)
}
RichContent(
modifier = Modifier.fillMaxWidth(),
nostrEvent = nostrEvent,
localQuotedNostrEvent = localQuotedNostrEvent,
mentionedProfiles = mentionedProfiles,
onNavigateToEvent = onNavigateToEvent
)
if (expended.value) {
LazyRow(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(
10.dp,
alignment = Alignment.Start
)
) {
item {
AssistChip(
label = {
Text(
text = nostrEvent.kind.toString() // TODO: Kind by name...
)
},
onClick = {
}
)
}
items(
items = nostrEvent.tags,
) { tag ->
SuggestionChip(
label = {
Text(
text = tag.joinToString(":"),
maxLines = 1
)
},
onClick = {
}
) )
} }
} }
} }
} else {
Text( Text(
text = "Loading author information" modifier = Modifier.fillMaxWidth(),
style = MaterialTheme.typography.labelLarge,
textAlign = TextAlign.End,
text = nostrEvent.createdAt.toFormattedTimeAndDateString()
) )
} }
RichContent(
modifier = Modifier.fillMaxWidth(),
nostrEvent = nostrEvent,
localQuotedNostrEvent = localQuotedNostrEvent,
mentionedProfiles = mentionedProfiles
)
LazyRow(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(
10.dp,
alignment = Alignment.Start
)
) {
item {
AssistChip(
label = {
Text(
text = nostrEvent.kind.toString() // TODO: Kind by name...
)
},
onClick = {
}
)
}
// item {
// SuggestionChip(
// label = {
// Text(
// text = if (localNostrEvent.mentionedProfiles.isNotEmpty()) {
// localNostrEvent.mentionedProfiles.joinToString(",") { it?.profile?.humanReadableNameOrPubkey() ?: "Find user information" }
// } else {
// ":-("
// }
// )
// },
// onClick = {
//
// }
// )
// }
items(
items = nostrEvent.tags,
) { tag ->
SuggestionChip(
label = {
Text(
text = tag.joinToString(":"),
maxLines = 1
)
},
onClick = {
}
)
}
}
Text(
modifier = Modifier.fillMaxWidth(),
style = MaterialTheme.typography.labelLarge,
textAlign = TextAlign.End,
text = nostrEvent.createdAt.toFormattedTimeAndDateString()
)
} }
} }
} }
@Preview @Preview
@Composable @Composable
private fun EventListViewPreview() { private fun TextNoteFeedItemPreview() {
AuxTheme { AuxTheme {
Surface( Surface(
modifier = Modifier.padding(20.dp) modifier = Modifier.padding(20.dp)
@@ -201,7 +198,7 @@ private fun EventListViewPreview() {
TextNoteFeedItem( TextNoteFeedItem(
nostrEvent = NostrEvent( nostrEvent = NostrEvent(
id = "hex", id = "hex",
content = "Something something something", content = "You are either alive and proud or you are dead, and when you are dead, you can't care anyway. https://www.brainyquote.com/authors/steven-biko-quotes",
pubKey = "hexpubkeypubkeypubkeypubkey", pubKey = "hexpubkeypubkeypubkeypubkey",
kind = 0, kind = 0,
sig = "hexsig", sig = "hexsig",
@@ -221,3 +218,144 @@ private fun EventListViewPreview() {
} }
} }
} }
@Preview
@Composable
private fun TextNoteFeedItemInReplyToPreview() {
AuxTheme {
Surface(
modifier = Modifier.padding(20.dp)
) {
TextNoteFeedItem(
nostrEvent = NostrEvent(
id = "hex",
content = "It is better to die for an idea that will live, than to live for an idea that will die",
pubKey = "hexpubkeypubkeypubkeypubkey",
kind = 0,
sig = "hexsig",
tags = emptyArray()
),
profile = Profile(
publicKey = "",
nostrEventId = "referenced",
displayName = "Frank Talk",
nip05 = "frank@talk.at"
),
localQuotedNostrEvent = null,
localInReplyToNostrEvent = LocalInReplyToNostrEvent(
inReplyToRelation = InReplyToRelation(
inReplyToNostrEventId = "nostrEvent",
inReplyToRootNostrEventId = "rootId",
inReplyToProfilePublicKey = "inReplyToProfileKey",
inReplyToRootProfilePublicKey = "rootPubKey",
replyingNostrEventId = "hex"
),
nostrEvent = NostrEvent(
id = "hex",
content = "Something something something",
pubKey = "hexie",
kind = 0,
sig = "hexsig",
tags = emptyArray()
),
profile = Profile(
publicKey = "hesd",
nostrEventId = "referenced",
displayName = "Steve Biko",
nip05 = "steve@bcm.co.za"
),
mentionedProfiles = emptyList()
),
mentionedProfiles = emptyList(),
onNavigateToEvent = {}
)
}
}
}
@Preview
@Composable
private fun TextNoteFeedItemQuoteNostrEventPreview() {
AuxTheme {
Surface(
modifier = Modifier.padding(20.dp)
) {
TextNoteFeedItem(
nostrEvent = NostrEvent(
id = "hex",
content = "The revolutionary sees his task as liberation not only of the oppressed but also of the oppressor. Happiness can never truly exist in a state of tension.\n" +
"Read more at nostr:npub1uh366qnj68a7atvwgwdy4569xd6v5jtferftapqztwjwlzh9553q47pqsx\nnostr:nevent1qqspcusnzxx5u97xht2udvg3yhcq2cvmc0jrxa90lwwdvjplve0atespzpmhxue69uhkummnw3ezuamfdejsyg8h5g639qhuv803hzwexfwhyud6t6suxfu364anddqvrmn9j4cahvxksr8q",
pubKey = "hexpubkeypubkeypubkeypubkey",
kind = 0,
sig = "hexsig",
tags = emptyArray()
),
profile = Profile(
publicKey = "",
nostrEventId = "referenced",
displayName = "Frank Talk",
nip05 = "frank@talk.at"
),
localQuotedNostrEvent = LocalQuotedNostrEvent(
nostrEvent = NostrEvent(
id = "1c7213118d4e17c6bad5c6b11125f005619bc3e43374affb9cd6483f665fd5e6",
content = "God is not in the habit of coming down from heaven to solve people’s problems on earth.",
pubKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
kind = 0,
sig = "hexsig",
tags = emptyArray()
),
quotedRelation = QuotedRelation(
quotingNostrEventId = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a520",
quotedProfilePublicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
quotedNostrEventId = "1c7213118d4e17c6bad5c6b11125f005619bc3e43374affb9cd6483f665fd5e6"
),
profile = Profile(
publicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
nostrEventId = "referenced",
displayName = "Steve Biko"
),
),
localInReplyToNostrEvent = LocalInReplyToNostrEvent(
inReplyToRelation = InReplyToRelation(
inReplyToNostrEventId = "nostrEvent",
inReplyToRootNostrEventId = "rootId",
inReplyToProfilePublicKey = "inReplyToProfileKey",
inReplyToRootProfilePublicKey = "rootPubKey",
replyingNostrEventId = "hex"
),
nostrEvent = NostrEvent(
id = "hex",
content = "Something something something",
pubKey = "hexie",
kind = 0,
sig = "hexsig",
tags = emptyArray()
),
profile = Profile(
publicKey = "hesd",
nostrEventId = "referenced",
displayName = "Steve Biko",
nip05 = "steve@bcm.co.za"
),
mentionedProfiles = emptyList()
),
mentionedProfiles = listOf(
LocalMention(
mention = Mention(
mentioningNostrEventId = "000067b3f15cac88ba066b28c370083a4fc80dacc054e554ab1dc0def974c89c",
mentionedPublicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522"
),
profile = Profile(
publicKey = "e5e3ad0272d1fbeead8e439a4ad3453374ca4969c8d2be84025ba4ef8ae5a522",
nostrEventId = "referenced",
displayName = "Steve Biko",
nip05 = "steve@bcm.co.za"
),
)
),
onNavigateToEvent = {}
)
}
}
}