Improve note rendering
This commit is contained in:
1 parent
3fef7bdabc
commit
e7db6598d0
9 files changed
+483
-201
No files matched your search
+59
-16
@@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,4 +110,37 @@ 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 = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -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 -> {
|
||||||
|
|||||||
+1
-5
@@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -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 {
|
||||||
|
|||||||
+50
-7
@@ -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
|
||||||
@@ -108,4 +114,41 @@ 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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+12
-10
@@ -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 = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-25
@@ -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 = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+85
-5
@@ -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 = {}
|
||||||
|
|||||||
+267
-129
@@ -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",
|
||||||
@@ -220,4 +217,145 @@ 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 = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user