NoteCompose refactoring
This commit is contained in:
@@ -31,6 +31,11 @@ class PrivateDmEvent(
|
|||||||
*/
|
*/
|
||||||
fun replyTo() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1)
|
fun replyTo() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.get(1)
|
||||||
|
|
||||||
|
fun with(pubkeyHex: String): Boolean {
|
||||||
|
return pubkeyHex == pubKey ||
|
||||||
|
tags.firstOrNull { it.size > 1 && it[0] == "p" }?.getOrNull(1) == pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
fun plainContent(privKey: ByteArray, pubKey: ByteArray): String? {
|
fun plainContent(privKey: ByteArray, pubKey: ByteArray): String? {
|
||||||
return try {
|
return try {
|
||||||
val sharedSecret = Utils.getSharedSecret(privKey, pubKey)
|
val sharedSecret = Utils.getSharedSecret(privKey, pubKey)
|
||||||
|
|||||||
@@ -359,9 +359,9 @@ fun BechLink(word: String, canPreview: Boolean, backgroundColor: Color, accountV
|
|||||||
LocalCache.checkGetOrCreateNote(it.hex)?.let { note ->
|
LocalCache.checkGetOrCreateNote(it.hex)?.let { note ->
|
||||||
baseNotePair = Pair(note, it.additionalChars)
|
baseNotePair = Pair(note, it.additionalChars)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
nip19Route = it
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nip19Route = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.vitorpamplona.amethyst.NotificationCache
|
import com.vitorpamplona.amethyst.NotificationCache
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.BadgeCard
|
import com.vitorpamplona.amethyst.ui.screen.BadgeCard
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -48,7 +47,6 @@ fun BadgeCompose(likeSetCard: BadgeCard, isInnerNote: Boolean = false, routeForL
|
|||||||
|
|
||||||
val context = LocalContext.current.applicationContext
|
val context = LocalContext.current.applicationContext
|
||||||
|
|
||||||
val noteEvent = note?.event
|
|
||||||
var popupExpanded by remember { mutableStateOf(false) }
|
var popupExpanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
if (note == null) {
|
if (note == null) {
|
||||||
@@ -73,15 +71,7 @@ fun BadgeCompose(likeSetCard: BadgeCard, isInnerNote: Boolean = false, routeForL
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.background(backgroundColor).combinedClickable(
|
modifier = Modifier.background(backgroundColor).combinedClickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (noteEvent !is ChannelMessageEvent) {
|
routeFor(note, accountViewModel.userProfile())?.let { navController.navigate(it) }
|
||||||
navController.navigate("Note/${note.idHex}") {
|
|
||||||
launchSingleTop = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
note.channel()?.let {
|
|
||||||
navController.navigate("Channel/${it.idHex}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onLongClick = { popupExpanded = true }
|
onLongClick = { popupExpanded = true }
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ fun HiddenNote(reports: Set<Note>, loggedIn: User, modifier: Modifier = Modifier
|
|||||||
FlowRow(modifier = Modifier.padding(top = 10.dp)) {
|
FlowRow(modifier = Modifier.padding(top = 10.dp)) {
|
||||||
reports.forEach {
|
reports.forEach {
|
||||||
NoteAuthorPicture(
|
NoteAuthorPicture(
|
||||||
note = it,
|
baseNote = it,
|
||||||
navController = navController,
|
navController = navController,
|
||||||
userAccount = loggedIn,
|
userAccount = loggedIn,
|
||||||
size = 35.dp
|
size = 35.dp
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import androidx.navigation.NavController
|
|||||||
import com.google.accompanist.flowlayout.FlowRow
|
import com.google.accompanist.flowlayout.FlowRow
|
||||||
import com.vitorpamplona.amethyst.NotificationCache
|
import com.vitorpamplona.amethyst.NotificationCache
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.BoostSetCard
|
import com.vitorpamplona.amethyst.ui.screen.BoostSetCard
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -68,15 +67,7 @@ fun BoostSetCompose(boostSetCard: BoostSetCard, isInnerNote: Boolean = false, ro
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.background(backgroundColor).combinedClickable(
|
modifier = Modifier.background(backgroundColor).combinedClickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (noteEvent !is ChannelMessageEvent) {
|
routeFor(note, account.userProfile())?.let { navController.navigate(it) }
|
||||||
navController.navigate("Note/${note.idHex}") {
|
|
||||||
launchSingleTop = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
note.channel()?.let {
|
|
||||||
navController.navigate("Channel/${it.idHex}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onLongClick = { popupExpanded = true }
|
onLongClick = { popupExpanded = true }
|
||||||
)
|
)
|
||||||
@@ -109,7 +100,7 @@ fun BoostSetCompose(boostSetCard: BoostSetCard, isInnerNote: Boolean = false, ro
|
|||||||
FlowRow() {
|
FlowRow() {
|
||||||
boostSetCard.boostEvents.forEach {
|
boostSetCard.boostEvents.forEach {
|
||||||
NoteAuthorPicture(
|
NoteAuthorPicture(
|
||||||
note = it,
|
baseNote = it,
|
||||||
navController = navController,
|
navController = navController,
|
||||||
userAccount = account.userProfile(),
|
userAccount = account.userProfile(),
|
||||||
size = 35.dp
|
size = 35.dp
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import androidx.navigation.NavController
|
|||||||
import com.google.accompanist.flowlayout.FlowRow
|
import com.google.accompanist.flowlayout.FlowRow
|
||||||
import com.vitorpamplona.amethyst.NotificationCache
|
import com.vitorpamplona.amethyst.NotificationCache
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.LikeSetCard
|
import com.vitorpamplona.amethyst.ui.screen.LikeSetCard
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -68,15 +67,7 @@ fun LikeSetCompose(likeSetCard: LikeSetCard, isInnerNote: Boolean = false, route
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.background(backgroundColor).combinedClickable(
|
modifier = Modifier.background(backgroundColor).combinedClickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (noteEvent !is ChannelMessageEvent) {
|
routeFor(note, account.userProfile())?.let { navController.navigate(it) }
|
||||||
navController.navigate("Note/${note.idHex}") {
|
|
||||||
launchSingleTop = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
note.channel()?.let {
|
|
||||||
navController.navigate("Channel/${it.idHex}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onLongClick = { popupExpanded = true }
|
onLongClick = { popupExpanded = true }
|
||||||
)
|
)
|
||||||
@@ -109,7 +100,7 @@ fun LikeSetCompose(likeSetCard: LikeSetCard, isInnerNote: Boolean = false, route
|
|||||||
FlowRow() {
|
FlowRow() {
|
||||||
likeSetCard.likeEvents.forEach {
|
likeSetCard.likeEvents.forEach {
|
||||||
NoteAuthorPicture(
|
NoteAuthorPicture(
|
||||||
note = it,
|
baseNote = it,
|
||||||
navController = navController,
|
navController = navController,
|
||||||
userAccount = account.userProfile(),
|
userAccount = account.userProfile(),
|
||||||
size = 35.dp
|
size = 35.dp
|
||||||
|
|||||||
@@ -26,9 +26,6 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.vitorpamplona.amethyst.NotificationCache
|
import com.vitorpamplona.amethyst.NotificationCache
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
|
||||||
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
|
||||||
import com.vitorpamplona.amethyst.service.model.PrivateDmEvent
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.MessageSetCard
|
import com.vitorpamplona.amethyst.ui.screen.MessageSetCard
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -66,30 +63,7 @@ fun MessageSetCompose(messageSetCard: MessageSetCard, isInnerNote: Boolean = fal
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.background(backgroundColor).combinedClickable(
|
modifier = Modifier.background(backgroundColor).combinedClickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (noteEvent is ChannelMessageEvent) {
|
routeFor(note, accountViewModel.userProfile())?.let { navController.navigate(it) }
|
||||||
note.channel()?.let {
|
|
||||||
navController.navigate("Channel/${it.idHex}")
|
|
||||||
}
|
|
||||||
} else if (noteEvent is PrivateDmEvent) {
|
|
||||||
val replyAuthorBase =
|
|
||||||
(note.event as? PrivateDmEvent)
|
|
||||||
?.recipientPubKey()
|
|
||||||
?.let { LocalCache.getOrCreateUser(it) }
|
|
||||||
|
|
||||||
var userToComposeOn = note.author!!
|
|
||||||
|
|
||||||
if (replyAuthorBase != null) {
|
|
||||||
if (note.author == accountViewModel.userProfile()) {
|
|
||||||
userToComposeOn = replyAuthorBase
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
navController.navigate("Room/${userToComposeOn.pubkeyHex}")
|
|
||||||
} else {
|
|
||||||
navController.navigate("Note/${note.idHex}") {
|
|
||||||
launchSingleTop = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onLongClick = { popupExpanded = true }
|
onLongClick = { popupExpanded = true }
|
||||||
)
|
)
|
||||||
@@ -120,7 +94,7 @@ fun MessageSetCompose(messageSetCard: MessageSetCard, isInnerNote: Boolean = fal
|
|||||||
|
|
||||||
Column(modifier = Modifier.padding(start = if (!isInnerNote) 10.dp else 0.dp)) {
|
Column(modifier = Modifier.padding(start = if (!isInnerNote) 10.dp else 0.dp)) {
|
||||||
NoteCompose(
|
NoteCompose(
|
||||||
baseNote = note,
|
baseNote = messageSetCard.note,
|
||||||
routeForLastRead = null,
|
routeForLastRead = null,
|
||||||
isBoostedNote = true,
|
isBoostedNote = true,
|
||||||
addMarginTop = false,
|
addMarginTop = false,
|
||||||
|
|||||||
@@ -37,9 +37,7 @@ import com.vitorpamplona.amethyst.model.Account
|
|||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
|
||||||
import com.vitorpamplona.amethyst.service.model.LnZapRequestEvent
|
import com.vitorpamplona.amethyst.service.model.LnZapRequestEvent
|
||||||
import com.vitorpamplona.amethyst.service.model.PrivateDmEvent
|
|
||||||
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
||||||
import com.vitorpamplona.amethyst.ui.screen.MultiSetCard
|
import com.vitorpamplona.amethyst.ui.screen.MultiSetCard
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
@@ -83,32 +81,7 @@ fun MultiSetCompose(multiSetCard: MultiSetCard, routeForLastRead: String, accoun
|
|||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
.combinedClickable(
|
.combinedClickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (noteEvent is ChannelMessageEvent) {
|
routeFor(note, account.userProfile())?.let { navController.navigate(it) }
|
||||||
note
|
|
||||||
.channel()
|
|
||||||
?.let {
|
|
||||||
navController.navigate("Channel/${it.idHex}")
|
|
||||||
}
|
|
||||||
} else if (noteEvent is PrivateDmEvent) {
|
|
||||||
val replyAuthorBase =
|
|
||||||
(note.event as? PrivateDmEvent)
|
|
||||||
?.recipientPubKey()
|
|
||||||
?.let { LocalCache.getOrCreateUser(it) }
|
|
||||||
|
|
||||||
var userToComposeOn = note.author!!
|
|
||||||
|
|
||||||
if (replyAuthorBase != null) {
|
|
||||||
if (note.author == accountViewModel.userProfile()) {
|
|
||||||
userToComposeOn = replyAuthorBase
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
navController.navigate("Room/${userToComposeOn.pubkeyHex}")
|
|
||||||
} else {
|
|
||||||
navController.navigate("Note/${note.idHex}") {
|
|
||||||
launchSingleTop = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onLongClick = { popupExpanded = true }
|
onLongClick = { popupExpanded = true }
|
||||||
)
|
)
|
||||||
@@ -195,7 +168,7 @@ fun MultiSetCompose(multiSetCard: MultiSetCard, routeForLastRead: String, accoun
|
|||||||
}
|
}
|
||||||
|
|
||||||
NoteCompose(
|
NoteCompose(
|
||||||
baseNote = note,
|
baseNote = multiSetCard.note,
|
||||||
routeForLastRead = null,
|
routeForLastRead = null,
|
||||||
modifier = Modifier.padding(top = 5.dp),
|
modifier = Modifier.padding(top = 5.dp),
|
||||||
isBoostedNote = true,
|
isBoostedNote = true,
|
||||||
@@ -225,7 +198,7 @@ fun AuthorGalleryZaps(
|
|||||||
Column(modifier = Modifier.padding(start = 10.dp)) {
|
Column(modifier = Modifier.padding(start = 10.dp)) {
|
||||||
FlowRow() {
|
FlowRow() {
|
||||||
authorNotes.forEach {
|
authorNotes.forEach {
|
||||||
AuthorPictureAndComment(it.key, it.value, navController, accountUser, accountViewModel)
|
AuthorPictureAndComment(it.key, navController, accountUser, accountViewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,7 +207,6 @@ fun AuthorGalleryZaps(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun AuthorPictureAndComment(
|
private fun AuthorPictureAndComment(
|
||||||
zapRequest: Note,
|
zapRequest: Note,
|
||||||
zapEvent: Note,
|
|
||||||
navController: NavController,
|
navController: NavController,
|
||||||
accountUser: User,
|
accountUser: User,
|
||||||
accountViewModel: AccountViewModel
|
accountViewModel: AccountViewModel
|
||||||
|
|||||||
@@ -127,10 +127,6 @@ fun NoteComposeInner(
|
|||||||
var popupExpanded by remember { mutableStateOf(false) }
|
var popupExpanded by remember { mutableStateOf(false) }
|
||||||
var showHiddenNote by remember { mutableStateOf(false) }
|
var showHiddenNote by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
val context = LocalContext.current.applicationContext
|
|
||||||
|
|
||||||
var moreActionsExpanded by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
var isAcceptable by remember { mutableStateOf(true) }
|
var isAcceptable by remember { mutableStateOf(true) }
|
||||||
var canPreview by remember { mutableStateOf(true) }
|
var canPreview by remember { mutableStateOf(true) }
|
||||||
|
|
||||||
@@ -205,28 +201,7 @@ fun NoteComposeInner(
|
|||||||
Column(
|
Column(
|
||||||
modifier = modifier.combinedClickable(
|
modifier = modifier.combinedClickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (noteEvent is ChannelMessageEvent) {
|
routeFor(note, loggedIn)?.let { navController.navigate(it) }
|
||||||
baseChannel?.let {
|
|
||||||
navController.navigate("Channel/${it.idHex}")
|
|
||||||
}
|
|
||||||
} else if (noteEvent is PrivateDmEvent) {
|
|
||||||
val replyAuthorBase =
|
|
||||||
(note.event as? PrivateDmEvent)
|
|
||||||
?.recipientPubKey()
|
|
||||||
?.let { LocalCache.getOrCreateUser(it) }
|
|
||||||
|
|
||||||
var userToComposeOn = note.author!!
|
|
||||||
|
|
||||||
if (replyAuthorBase != null) {
|
|
||||||
if (note.author == accountViewModel.userProfile()) {
|
|
||||||
userToComposeOn = replyAuthorBase
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
navController.navigate("Room/${userToComposeOn.pubkeyHex}")
|
|
||||||
} else {
|
|
||||||
navController.navigate("Note/${note.idHex}")
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onLongClick = { popupExpanded = true }
|
onLongClick = { popupExpanded = true }
|
||||||
).background(backgroundColor)
|
).background(backgroundColor)
|
||||||
@@ -244,155 +219,331 @@ fun NoteComposeInner(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(start = if (!isBoostedNote && !isQuotedNote) 10.dp else 0.dp)
|
modifier = Modifier
|
||||||
|
.padding(start = if (!isBoostedNote && !isQuotedNote) 10.dp else 0.dp)
|
||||||
) {
|
) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
FirstUserInfoRow(
|
||||||
if (isQuotedNote) {
|
baseNote = baseNote,
|
||||||
NoteAuthorPicture(note, navController, loggedIn, 25.dp)
|
showAuthorPicture = isQuotedNote,
|
||||||
Spacer(Modifier.padding(horizontal = 5.dp))
|
account = account,
|
||||||
NoteUsernameDisplay(note, Modifier.weight(1f))
|
accountViewModel = accountViewModel,
|
||||||
} else {
|
navController = navController
|
||||||
NoteUsernameDisplay(note, Modifier.weight(1f))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noteEvent is RepostEvent) {
|
|
||||||
Text(
|
|
||||||
" ${stringResource(id = R.string.boosted)}",
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
DisplayFollowingHashtagsInPost(noteEvent, account, navController)
|
|
||||||
}
|
|
||||||
|
|
||||||
Text(
|
|
||||||
timeAgo(note.createdAt(), context = context),
|
|
||||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
|
||||||
maxLines = 1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
IconButton(
|
if (noteEvent !is RepostEvent && !makeItShort && !isQuotedNote) {
|
||||||
modifier = Modifier.size(24.dp),
|
SecondUserInfoRow(
|
||||||
onClick = { moreActionsExpanded = true }
|
note,
|
||||||
) {
|
account,
|
||||||
Icon(
|
navController
|
||||||
imageVector = Icons.Default.MoreVert,
|
|
||||||
null,
|
|
||||||
modifier = Modifier.size(15.dp),
|
|
||||||
tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
NoteDropDownMenu(baseNote, moreActionsExpanded, { moreActionsExpanded = false }, accountViewModel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noteEvent !is RepostEvent && note.author != null && !makeItShort && !isQuotedNote) {
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
ObserveDisplayNip05Status(note.author!!, Modifier.weight(1f))
|
|
||||||
|
|
||||||
val baseReward = noteEvent.getReward()
|
|
||||||
if (baseReward != null) {
|
|
||||||
DisplayReward(baseReward, baseNote, account, navController)
|
|
||||||
}
|
|
||||||
|
|
||||||
val pow = noteEvent.getPoWRank()
|
|
||||||
if (pow > 20) {
|
|
||||||
DisplayPoW(pow)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(2.dp))
|
Spacer(modifier = Modifier.height(2.dp))
|
||||||
|
|
||||||
if (!makeItShort && noteEvent is TextNoteEvent && (note.replyTo != null || noteEvent.mentions().isNotEmpty())) {
|
if (!makeItShort) {
|
||||||
val replyingDirectlyTo = note.replyTo?.lastOrNull()
|
ReplyRow(
|
||||||
if (replyingDirectlyTo != null && unPackReply) {
|
note,
|
||||||
NoteCompose(
|
unPackReply,
|
||||||
baseNote = replyingDirectlyTo,
|
backgroundColor,
|
||||||
isQuotedNote = true,
|
account,
|
||||||
modifier = Modifier
|
accountViewModel,
|
||||||
.padding(top = 5.dp)
|
navController
|
||||||
.fillMaxWidth()
|
)
|
||||||
.clip(shape = RoundedCornerShape(15.dp))
|
}
|
||||||
.border(
|
|
||||||
1.dp,
|
when (noteEvent) {
|
||||||
MaterialTheme.colors.onSurface.copy(alpha = 0.12f),
|
is ReactionEvent -> {
|
||||||
RoundedCornerShape(15.dp)
|
RenderReaction(note, backgroundColor, accountViewModel, navController)
|
||||||
),
|
}
|
||||||
unPackReply = false,
|
|
||||||
makeItShort = true,
|
is RepostEvent -> {
|
||||||
parentBackgroundColor = MaterialTheme.colors.onSurface.copy(alpha = 0.05f).compositeOver(backgroundColor),
|
RenderRepost(note, backgroundColor, accountViewModel, navController)
|
||||||
accountViewModel = accountViewModel,
|
}
|
||||||
navController = navController
|
|
||||||
|
is ReportEvent -> {
|
||||||
|
RenderReport(note)
|
||||||
|
}
|
||||||
|
|
||||||
|
is LongTextNoteEvent -> {
|
||||||
|
RenderLongFormContent(note, loggedIn, accountViewModel, navController)
|
||||||
|
}
|
||||||
|
|
||||||
|
is BadgeAwardEvent -> {
|
||||||
|
RenderBadgeAward(note, backgroundColor, accountViewModel, navController)
|
||||||
|
}
|
||||||
|
|
||||||
|
is PrivateDmEvent -> {
|
||||||
|
RenderPrivateMessage(note, makeItShort, canPreview, backgroundColor, accountViewModel, navController)
|
||||||
|
}
|
||||||
|
|
||||||
|
is HighlightEvent -> {
|
||||||
|
RenderHighlight(note, makeItShort, canPreview, backgroundColor, accountViewModel, navController)
|
||||||
|
}
|
||||||
|
|
||||||
|
is PollNoteEvent -> {
|
||||||
|
RenderPoll(
|
||||||
|
note,
|
||||||
|
makeItShort,
|
||||||
|
canPreview,
|
||||||
|
backgroundColor,
|
||||||
|
accountViewModel,
|
||||||
|
navController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
RenderTextEvent(
|
||||||
|
note,
|
||||||
|
makeItShort,
|
||||||
|
canPreview,
|
||||||
|
backgroundColor,
|
||||||
|
accountViewModel,
|
||||||
|
navController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NoteQuickActionMenu(note, popupExpanded, { popupExpanded = false }, accountViewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun routeFor(note: Note, loggedIn: User): String? {
|
||||||
|
val noteEvent = note.event
|
||||||
|
|
||||||
|
if (noteEvent is ChannelMessageEvent || noteEvent is ChannelCreateEvent || noteEvent is ChannelMetadataEvent) {
|
||||||
|
note.channel()?.let {
|
||||||
|
return "Channel/${it.idHex}"
|
||||||
|
}
|
||||||
|
} else if (noteEvent is PrivateDmEvent) {
|
||||||
|
val replyAuthorBase =
|
||||||
|
(note.event as? PrivateDmEvent)
|
||||||
|
?.recipientPubKey()
|
||||||
|
?.let { LocalCache.getOrCreateUser(it) }
|
||||||
|
|
||||||
|
var userToComposeOn = note.author!!
|
||||||
|
|
||||||
|
if (replyAuthorBase != null) {
|
||||||
|
if (note.author == loggedIn) {
|
||||||
|
userToComposeOn = replyAuthorBase
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Room/${userToComposeOn.pubkeyHex}"
|
||||||
|
} else {
|
||||||
|
return "Note/${note.idHex}"
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RenderTextEvent(
|
||||||
|
note: Note,
|
||||||
|
makeItShort: Boolean,
|
||||||
|
canPreview: Boolean,
|
||||||
|
backgroundColor: Color,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
val noteEvent = note.event ?: return
|
||||||
|
|
||||||
|
val eventContent = accountViewModel.decrypt(note)
|
||||||
|
|
||||||
|
if (eventContent != null) {
|
||||||
|
if (makeItShort && accountViewModel.isLoggedUser(note.author)) {
|
||||||
|
Text(
|
||||||
|
text = eventContent,
|
||||||
|
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||||
|
maxLines = 2,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
ReplyInformation(note.replyTo, noteEvent.mentions(), account, navController)
|
TranslatableRichTextViewer(
|
||||||
}
|
content = eventContent,
|
||||||
Spacer(modifier = Modifier.height(5.dp))
|
canPreview = canPreview && !makeItShort,
|
||||||
} else if (!makeItShort && noteEvent is ChannelMessageEvent && (note.replyTo != null || noteEvent.mentions().isNotEmpty())) {
|
modifier = Modifier.fillMaxWidth(),
|
||||||
val sortedMentions = noteEvent.mentions()
|
tags = noteEvent.tags(),
|
||||||
.mapNotNull { LocalCache.checkGetOrCreateUser(it) }
|
backgroundColor = backgroundColor,
|
||||||
.toSet()
|
|
||||||
.sortedBy { loggedIn.isFollowingCached(it) }
|
|
||||||
|
|
||||||
note.channel()?.let {
|
|
||||||
ReplyInformationChannel(note.replyTo, sortedMentions, it, navController)
|
|
||||||
}
|
|
||||||
Spacer(modifier = Modifier.height(5.dp))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noteEvent is ReactionEvent || noteEvent is RepostEvent) {
|
|
||||||
note.replyTo?.lastOrNull()?.let {
|
|
||||||
NoteCompose(
|
|
||||||
it,
|
|
||||||
modifier = Modifier,
|
|
||||||
isBoostedNote = true,
|
|
||||||
unPackReply = false,
|
|
||||||
parentBackgroundColor = backgroundColor,
|
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
navController = navController
|
navController = navController
|
||||||
)
|
)
|
||||||
|
|
||||||
|
DisplayUncitedHashtags(noteEvent.hashtags(), eventContent, navController)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reposts have trash in their contents.
|
if (!makeItShort) {
|
||||||
if (noteEvent is ReactionEvent) {
|
|
||||||
val refactorReactionText =
|
|
||||||
if (noteEvent.content == "+") "❤" else noteEvent.content
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = refactorReactionText
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else if (noteEvent is ReportEvent) {
|
|
||||||
val reportType = (noteEvent.reportedPost() + noteEvent.reportedAuthor()).map {
|
|
||||||
when (it.reportType) {
|
|
||||||
ReportEvent.ReportType.EXPLICIT -> stringResource(R.string.explicit_content)
|
|
||||||
ReportEvent.ReportType.NUDITY -> stringResource(R.string.nudity)
|
|
||||||
ReportEvent.ReportType.PROFANITY -> stringResource(R.string.profanity_hateful_speech)
|
|
||||||
ReportEvent.ReportType.SPAM -> stringResource(R.string.spam)
|
|
||||||
ReportEvent.ReportType.IMPERSONATION -> stringResource(R.string.impersonation)
|
|
||||||
ReportEvent.ReportType.ILLEGAL -> stringResource(R.string.illegal_behavior)
|
|
||||||
}
|
|
||||||
}.toSet().joinToString(", ")
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = reportType
|
|
||||||
)
|
|
||||||
|
|
||||||
Divider(
|
|
||||||
modifier = Modifier.padding(top = 40.dp),
|
|
||||||
thickness = 0.25.dp
|
|
||||||
)
|
|
||||||
} else if (noteEvent is LongTextNoteEvent) {
|
|
||||||
LongFormHeader(noteEvent, note, loggedIn)
|
|
||||||
|
|
||||||
ReactionsRow(note, accountViewModel, navController)
|
ReactionsRow(note, accountViewModel, navController)
|
||||||
|
}
|
||||||
|
|
||||||
Divider(
|
Divider(
|
||||||
modifier = Modifier.padding(top = 10.dp),
|
modifier = Modifier.padding(top = 10.dp),
|
||||||
thickness = 0.25.dp
|
thickness = 0.25.dp
|
||||||
)
|
)
|
||||||
} else if (noteEvent is BadgeAwardEvent && !note.replyTo.isNullOrEmpty()) {
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RenderPoll(
|
||||||
|
note: Note,
|
||||||
|
makeItShort: Boolean,
|
||||||
|
canPreview: Boolean,
|
||||||
|
backgroundColor: Color,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
val noteEvent = note.event as? PollNoteEvent ?: return
|
||||||
|
val eventContent = noteEvent.content()
|
||||||
|
|
||||||
|
if (makeItShort && accountViewModel.isLoggedUser(note.author)) {
|
||||||
|
Text(
|
||||||
|
text = eventContent,
|
||||||
|
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||||
|
maxLines = 2,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
TranslatableRichTextViewer(
|
||||||
|
eventContent,
|
||||||
|
canPreview = canPreview && !makeItShort,
|
||||||
|
Modifier.fillMaxWidth(),
|
||||||
|
noteEvent.tags(),
|
||||||
|
backgroundColor,
|
||||||
|
accountViewModel,
|
||||||
|
navController
|
||||||
|
)
|
||||||
|
|
||||||
|
DisplayUncitedHashtags(noteEvent.hashtags(), eventContent, navController)
|
||||||
|
|
||||||
|
PollNote(
|
||||||
|
note,
|
||||||
|
canPreview = canPreview && !makeItShort,
|
||||||
|
backgroundColor,
|
||||||
|
accountViewModel,
|
||||||
|
navController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!makeItShort) {
|
||||||
|
ReactionsRow(note, accountViewModel, navController)
|
||||||
|
}
|
||||||
|
|
||||||
|
Divider(
|
||||||
|
modifier = Modifier.padding(top = 10.dp),
|
||||||
|
thickness = 0.25.dp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RenderHighlight(
|
||||||
|
note: Note,
|
||||||
|
makeItShort: Boolean,
|
||||||
|
canPreview: Boolean,
|
||||||
|
backgroundColor: Color,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
val noteEvent = note.event as? HighlightEvent ?: return
|
||||||
|
|
||||||
|
DisplayHighlight(
|
||||||
|
noteEvent.quote(),
|
||||||
|
noteEvent.author(),
|
||||||
|
noteEvent.inUrl(),
|
||||||
|
makeItShort,
|
||||||
|
canPreview,
|
||||||
|
backgroundColor,
|
||||||
|
accountViewModel,
|
||||||
|
navController
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!makeItShort) {
|
||||||
|
ReactionsRow(note, accountViewModel, navController)
|
||||||
|
}
|
||||||
|
|
||||||
|
Divider(
|
||||||
|
modifier = Modifier.padding(top = 10.dp),
|
||||||
|
thickness = 0.25.dp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RenderPrivateMessage(
|
||||||
|
note: Note,
|
||||||
|
makeItShort: Boolean,
|
||||||
|
canPreview: Boolean,
|
||||||
|
backgroundColor: Color,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
val noteEvent = note.event as? PrivateDmEvent ?: return
|
||||||
|
val withMe = noteEvent.with(accountViewModel.userProfile().pubkeyHex)
|
||||||
|
|
||||||
|
if (withMe) {
|
||||||
|
val eventContent = accountViewModel.decrypt(note)
|
||||||
|
|
||||||
|
if (eventContent != null) {
|
||||||
|
if (makeItShort && accountViewModel.isLoggedUser(note.author)) {
|
||||||
|
Text(
|
||||||
|
text = eventContent,
|
||||||
|
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||||
|
maxLines = 2,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
TranslatableRichTextViewer(
|
||||||
|
content = eventContent,
|
||||||
|
canPreview = canPreview && !makeItShort,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
tags = noteEvent.tags(),
|
||||||
|
backgroundColor = backgroundColor,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
navController = navController
|
||||||
|
)
|
||||||
|
|
||||||
|
DisplayUncitedHashtags(noteEvent.hashtags(), eventContent, navController)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val recipient = noteEvent.recipientPubKey()?.let { LocalCache.checkGetOrCreateUser(it) }
|
||||||
|
|
||||||
|
TranslatableRichTextViewer(
|
||||||
|
stringResource(
|
||||||
|
id = R.string.private_conversation_notification,
|
||||||
|
"@${note.author?.pubkeyNpub()}",
|
||||||
|
"@${recipient?.pubkeyNpub()}"
|
||||||
|
),
|
||||||
|
canPreview = !makeItShort,
|
||||||
|
Modifier.fillMaxWidth(),
|
||||||
|
noteEvent.tags(),
|
||||||
|
backgroundColor,
|
||||||
|
accountViewModel,
|
||||||
|
navController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!makeItShort) {
|
||||||
|
ReactionsRow(note, accountViewModel, navController)
|
||||||
|
}
|
||||||
|
|
||||||
|
Divider(
|
||||||
|
modifier = Modifier.padding(top = 10.dp),
|
||||||
|
thickness = 0.25.dp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun RenderBadgeAward(
|
||||||
|
note: Note,
|
||||||
|
backgroundColor: Color,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
if (note.replyTo.isNullOrEmpty()) return
|
||||||
|
|
||||||
|
val noteEvent = note.event as? BadgeAwardEvent ?: return
|
||||||
|
|
||||||
Text(text = stringResource(R.string.award_granted_to))
|
Text(text = stringResource(R.string.award_granted_to))
|
||||||
|
|
||||||
FlowRow(modifier = Modifier.padding(top = 5.dp)) {
|
FlowRow(modifier = Modifier.padding(top = 5.dp)) {
|
||||||
@@ -402,7 +553,7 @@ fun NoteComposeInner(
|
|||||||
UserPicture(
|
UserPicture(
|
||||||
user = it,
|
user = it,
|
||||||
navController = navController,
|
navController = navController,
|
||||||
userAccount = loggedIn,
|
userAccount = accountViewModel.userProfile(),
|
||||||
size = 35.dp
|
size = 35.dp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -427,93 +578,68 @@ fun NoteComposeInner(
|
|||||||
modifier = Modifier.padding(top = 10.dp),
|
modifier = Modifier.padding(top = 10.dp),
|
||||||
thickness = 0.25.dp
|
thickness = 0.25.dp
|
||||||
)
|
)
|
||||||
} else if (noteEvent is PrivateDmEvent &&
|
}
|
||||||
noteEvent.recipientPubKey() != loggedIn.pubkeyHex &&
|
|
||||||
note.author !== loggedIn
|
@Composable
|
||||||
|
private fun RenderReaction(
|
||||||
|
note: Note,
|
||||||
|
backgroundColor: Color,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
navController: NavController
|
||||||
) {
|
) {
|
||||||
val recipient = noteEvent.recipientPubKey()?.let { LocalCache.checkGetOrCreateUser(it) }
|
note.replyTo?.lastOrNull()?.let {
|
||||||
|
NoteCompose(
|
||||||
TranslatableRichTextViewer(
|
it,
|
||||||
stringResource(
|
modifier = Modifier,
|
||||||
id = R.string.private_conversation_notification,
|
isBoostedNote = true,
|
||||||
"@${note.author?.pubkeyNpub()}",
|
unPackReply = false,
|
||||||
"@${recipient?.pubkeyNpub()}"
|
parentBackgroundColor = backgroundColor,
|
||||||
),
|
accountViewModel = accountViewModel,
|
||||||
canPreview = !makeItShort,
|
navController = navController
|
||||||
Modifier.fillMaxWidth(),
|
|
||||||
noteEvent.tags(),
|
|
||||||
backgroundColor,
|
|
||||||
accountViewModel,
|
|
||||||
navController
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!makeItShort) {
|
|
||||||
ReactionsRow(note, accountViewModel, navController)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Divider(
|
// Reposts have trash in their contents.
|
||||||
modifier = Modifier.padding(top = 10.dp),
|
val refactorReactionText =
|
||||||
thickness = 0.25.dp
|
if (note.event?.content() == "+") "❤" else note.event?.content() ?: ""
|
||||||
)
|
|
||||||
} else if (noteEvent is HighlightEvent) {
|
|
||||||
DisplayHighlight(
|
|
||||||
noteEvent.quote(),
|
|
||||||
noteEvent.author(),
|
|
||||||
noteEvent.inUrl(),
|
|
||||||
makeItShort,
|
|
||||||
canPreview,
|
|
||||||
backgroundColor,
|
|
||||||
accountViewModel,
|
|
||||||
navController
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!makeItShort) {
|
|
||||||
ReactionsRow(note, accountViewModel, navController)
|
|
||||||
}
|
|
||||||
|
|
||||||
Divider(
|
|
||||||
modifier = Modifier.padding(top = 10.dp),
|
|
||||||
thickness = 0.25.dp
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
val eventContent = accountViewModel.decrypt(note)
|
|
||||||
|
|
||||||
if (eventContent != null) {
|
|
||||||
if (makeItShort && note.author == loggedIn) {
|
|
||||||
Text(
|
Text(
|
||||||
text = eventContent,
|
text = refactorReactionText
|
||||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
|
||||||
maxLines = 2,
|
|
||||||
overflow = TextOverflow.Ellipsis
|
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
TranslatableRichTextViewer(
|
|
||||||
eventContent,
|
|
||||||
canPreview = canPreview && !makeItShort,
|
|
||||||
Modifier.fillMaxWidth(),
|
|
||||||
noteEvent.tags(),
|
|
||||||
backgroundColor,
|
|
||||||
accountViewModel,
|
|
||||||
navController
|
|
||||||
)
|
|
||||||
|
|
||||||
DisplayUncitedHashtags(noteEvent.hashtags(), eventContent, navController)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noteEvent is PollNoteEvent) {
|
@Composable
|
||||||
PollNote(
|
private fun RenderRepost(
|
||||||
note,
|
note: Note,
|
||||||
canPreview = canPreview && !makeItShort,
|
backgroundColor: Color,
|
||||||
backgroundColor,
|
accountViewModel: AccountViewModel,
|
||||||
accountViewModel,
|
navController: NavController
|
||||||
navController
|
) {
|
||||||
|
note.replyTo?.lastOrNull()?.let {
|
||||||
|
NoteCompose(
|
||||||
|
it,
|
||||||
|
modifier = Modifier,
|
||||||
|
isBoostedNote = true,
|
||||||
|
unPackReply = false,
|
||||||
|
parentBackgroundColor = backgroundColor,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
navController = navController
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!makeItShort) {
|
@Composable
|
||||||
|
private fun RenderLongFormContent(
|
||||||
|
note: Note,
|
||||||
|
loggedIn: User,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
val noteEvent = note.event as? LongTextNoteEvent ?: return
|
||||||
|
|
||||||
|
LongFormHeader(noteEvent, note, loggedIn)
|
||||||
|
|
||||||
ReactionsRow(note, accountViewModel, navController)
|
ReactionsRow(note, accountViewModel, navController)
|
||||||
}
|
|
||||||
|
|
||||||
Divider(
|
Divider(
|
||||||
modifier = Modifier.padding(top = 10.dp),
|
modifier = Modifier.padding(top = 10.dp),
|
||||||
@@ -521,9 +647,167 @@ fun NoteComposeInner(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
NoteQuickActionMenu(note, popupExpanded, { popupExpanded = false }, accountViewModel)
|
@Composable
|
||||||
|
private fun RenderReport(note: Note) {
|
||||||
|
val noteEvent = note.event as? ReportEvent ?: return
|
||||||
|
|
||||||
|
val reportType = (noteEvent.reportedPost() + noteEvent.reportedAuthor()).map {
|
||||||
|
when (it.reportType) {
|
||||||
|
ReportEvent.ReportType.EXPLICIT -> stringResource(R.string.explicit_content)
|
||||||
|
ReportEvent.ReportType.NUDITY -> stringResource(R.string.nudity)
|
||||||
|
ReportEvent.ReportType.PROFANITY -> stringResource(R.string.profanity_hateful_speech)
|
||||||
|
ReportEvent.ReportType.SPAM -> stringResource(R.string.spam)
|
||||||
|
ReportEvent.ReportType.IMPERSONATION -> stringResource(R.string.impersonation)
|
||||||
|
ReportEvent.ReportType.ILLEGAL -> stringResource(R.string.illegal_behavior)
|
||||||
|
}
|
||||||
|
}.toSet().joinToString(", ")
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = reportType
|
||||||
|
)
|
||||||
|
|
||||||
|
Divider(
|
||||||
|
modifier = Modifier.padding(top = 40.dp),
|
||||||
|
thickness = 0.25.dp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ReplyRow(
|
||||||
|
note: Note,
|
||||||
|
unPackReply: Boolean,
|
||||||
|
backgroundColor: Color,
|
||||||
|
account: Account,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
val noteEvent = note.event
|
||||||
|
|
||||||
|
if (noteEvent is TextNoteEvent &&
|
||||||
|
(note.replyTo != null || noteEvent.mentions().isNotEmpty())
|
||||||
|
) {
|
||||||
|
val replyingDirectlyTo = note.replyTo?.lastOrNull()
|
||||||
|
if (replyingDirectlyTo != null && unPackReply) {
|
||||||
|
NoteCompose(
|
||||||
|
baseNote = replyingDirectlyTo,
|
||||||
|
isQuotedNote = true,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 5.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clip(shape = RoundedCornerShape(15.dp))
|
||||||
|
.border(
|
||||||
|
1.dp,
|
||||||
|
MaterialTheme.colors.onSurface.copy(alpha = 0.12f),
|
||||||
|
RoundedCornerShape(15.dp)
|
||||||
|
),
|
||||||
|
unPackReply = false,
|
||||||
|
makeItShort = true,
|
||||||
|
parentBackgroundColor = MaterialTheme.colors.onSurface.copy(alpha = 0.05f)
|
||||||
|
.compositeOver(backgroundColor),
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
navController = navController
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ReplyInformation(note.replyTo, noteEvent.mentions(), account, navController)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(5.dp))
|
||||||
|
} else if (
|
||||||
|
noteEvent is ChannelMessageEvent &&
|
||||||
|
(note.replyTo != null || noteEvent.mentions().isNotEmpty())
|
||||||
|
) {
|
||||||
|
val sortedMentions = noteEvent.mentions()
|
||||||
|
.mapNotNull { LocalCache.checkGetOrCreateUser(it) }
|
||||||
|
.toSet()
|
||||||
|
.sortedBy { account.isFollowing(it) }
|
||||||
|
|
||||||
|
note.channel()?.let {
|
||||||
|
ReplyInformationChannel(note.replyTo, sortedMentions, it, navController)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(5.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun SecondUserInfoRow(
|
||||||
|
note: Note,
|
||||||
|
account: Account,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
val noteEvent = note.event ?: return
|
||||||
|
val noteAuthor = note.author ?: return
|
||||||
|
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
ObserveDisplayNip05Status(noteAuthor, Modifier.weight(1f))
|
||||||
|
|
||||||
|
val baseReward = noteEvent.getReward()
|
||||||
|
if (baseReward != null) {
|
||||||
|
DisplayReward(baseReward, note, account, navController)
|
||||||
|
}
|
||||||
|
|
||||||
|
val pow = noteEvent.getPoWRank()
|
||||||
|
if (pow > 20) {
|
||||||
|
DisplayPoW(pow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun FirstUserInfoRow(
|
||||||
|
baseNote: Note,
|
||||||
|
showAuthorPicture: Boolean,
|
||||||
|
account: Account,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
var moreActionsExpanded by remember { mutableStateOf(false) }
|
||||||
|
val context = LocalContext.current.applicationContext
|
||||||
|
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
if (showAuthorPicture) {
|
||||||
|
NoteAuthorPicture(baseNote, navController, account.userProfile(), 25.dp)
|
||||||
|
Spacer(Modifier.padding(horizontal = 5.dp))
|
||||||
|
NoteUsernameDisplay(baseNote, Modifier.weight(1f))
|
||||||
|
} else {
|
||||||
|
NoteUsernameDisplay(baseNote, Modifier.weight(1f))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseNote.event is RepostEvent) {
|
||||||
|
Text(
|
||||||
|
" ${stringResource(id = R.string.boosted)}",
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
baseNote.event?.let {
|
||||||
|
DisplayFollowingHashtagsInPost(it, account, navController)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
timeAgo(baseNote.createdAt(), context = context),
|
||||||
|
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||||
|
maxLines = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
IconButton(
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
onClick = { moreActionsExpanded = true }
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.MoreVert,
|
||||||
|
null,
|
||||||
|
modifier = Modifier.size(15.dp),
|
||||||
|
tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
||||||
|
)
|
||||||
|
|
||||||
|
NoteDropDownMenu(
|
||||||
|
baseNote,
|
||||||
|
moreActionsExpanded,
|
||||||
|
{ moreActionsExpanded = false },
|
||||||
|
accountViewModel
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -626,7 +910,6 @@ fun DisplayHighlight(
|
|||||||
) {
|
) {
|
||||||
val quote = highlight.split("\n").map { "> *${it.removeSuffix(" ")}*" }.joinToString("\n")
|
val quote = highlight.split("\n").map { "> *${it.removeSuffix(" ")}*" }.joinToString("\n")
|
||||||
|
|
||||||
if (quote != null) {
|
|
||||||
TranslatableRichTextViewer(
|
TranslatableRichTextViewer(
|
||||||
quote,
|
quote,
|
||||||
canPreview = canPreview && !makeItShort,
|
canPreview = canPreview && !makeItShort,
|
||||||
@@ -636,7 +919,6 @@ fun DisplayHighlight(
|
|||||||
accountViewModel,
|
accountViewModel,
|
||||||
navController
|
navController
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
FlowRow() {
|
FlowRow() {
|
||||||
authorHex?.let { authorHex ->
|
authorHex?.let { authorHex ->
|
||||||
@@ -1158,13 +1440,13 @@ private fun ShowMoreRelaysButton(onClick: () -> Unit) {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NoteAuthorPicture(
|
fun NoteAuthorPicture(
|
||||||
note: Note,
|
baseNote: Note,
|
||||||
navController: NavController,
|
navController: NavController,
|
||||||
userAccount: User,
|
userAccount: User,
|
||||||
size: Dp,
|
size: Dp,
|
||||||
pictureModifier: Modifier = Modifier
|
pictureModifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
NoteAuthorPicture(note, userAccount, size, pictureModifier) {
|
NoteAuthorPicture(baseNote, userAccount, size, pictureModifier) {
|
||||||
navController.navigate("User/${it.pubkeyHex}")
|
navController.navigate("User/${it.pubkeyHex}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import androidx.navigation.NavController
|
|||||||
import com.google.accompanist.flowlayout.FlowRow
|
import com.google.accompanist.flowlayout.FlowRow
|
||||||
import com.vitorpamplona.amethyst.NotificationCache
|
import com.vitorpamplona.amethyst.NotificationCache
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.ZapSetCard
|
import com.vitorpamplona.amethyst.ui.screen.ZapSetCard
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
|
||||||
@@ -70,15 +69,7 @@ fun ZapSetCompose(zapSetCard: ZapSetCard, isInnerNote: Boolean = false, routeFor
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.background(backgroundColor).combinedClickable(
|
modifier = Modifier.background(backgroundColor).combinedClickable(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (noteEvent !is ChannelMessageEvent) {
|
routeFor(note, account.userProfile())?.let { navController.navigate(it) }
|
||||||
navController.navigate("Note/${note.idHex}") {
|
|
||||||
launchSingleTop = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
note.channel()?.let {
|
|
||||||
navController.navigate("Channel/${it.idHex}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onLongClick = { popupExpanded = true }
|
onLongClick = { popupExpanded = true }
|
||||||
)
|
)
|
||||||
@@ -113,7 +104,7 @@ fun ZapSetCompose(zapSetCard: ZapSetCard, isInnerNote: Boolean = false, routeFor
|
|||||||
FlowRow() {
|
FlowRow() {
|
||||||
zapSetCard.zapEvents.forEach {
|
zapSetCard.zapEvents.forEach {
|
||||||
NoteAuthorPicture(
|
NoteAuthorPicture(
|
||||||
note = it.key,
|
baseNote = it.key,
|
||||||
navController = navController,
|
navController = navController,
|
||||||
userAccount = account.userProfile(),
|
userAccount = account.userProfile(),
|
||||||
size = 35.dp
|
size = 35.dp
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ fun ZapUserSetCompose(zapSetCard: ZapUserSetCard, isInnerNote: Boolean = false,
|
|||||||
FlowRow() {
|
FlowRow() {
|
||||||
zapSetCard.zapEvents.forEach {
|
zapSetCard.zapEvents.forEach {
|
||||||
NoteAuthorPicture(
|
NoteAuthorPicture(
|
||||||
note = it.key,
|
baseNote = it.key,
|
||||||
navController = navController,
|
navController = navController,
|
||||||
userAccount = account.userProfile(),
|
userAccount = account.userProfile(),
|
||||||
size = 35.dp
|
size = 35.dp
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.screen
|
package com.vitorpamplona.amethyst.ui.screen
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@@ -32,6 +33,8 @@ import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
|||||||
import com.vitorpamplona.amethyst.ui.note.ZapSetCompose
|
import com.vitorpamplona.amethyst.ui.note.ZapSetCompose
|
||||||
import com.vitorpamplona.amethyst.ui.note.ZapUserSetCompose
|
import com.vitorpamplona.amethyst.ui.note.ZapUserSetCompose
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import kotlin.time.ExperimentalTime
|
||||||
|
import kotlin.time.measureTimedValue
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -85,6 +88,7 @@ fun CardFeedView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalTime::class)
|
||||||
@Composable
|
@Composable
|
||||||
private fun FeedLoaded(
|
private fun FeedLoaded(
|
||||||
state: CardFeedState.Loaded,
|
state: CardFeedState.Loaded,
|
||||||
@@ -114,6 +118,7 @@ private fun FeedLoaded(
|
|||||||
state = listState
|
state = listState
|
||||||
) {
|
) {
|
||||||
itemsIndexed(state.feed.value, key = { _, item -> item.id() }) { _, item ->
|
itemsIndexed(state.feed.value, key = { _, item -> item.id() }) { _, item ->
|
||||||
|
val (value, elapsed) = measureTimedValue {
|
||||||
when (item) {
|
when (item) {
|
||||||
is NoteCard -> NoteCompose(
|
is NoteCard -> NoteCompose(
|
||||||
item.note,
|
item.note,
|
||||||
@@ -170,5 +175,7 @@ private fun FeedLoaded(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Log.d("Time", "${item.javaClass.simpleName} Feed in $elapsed")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ fun NoteMaster(
|
|||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
NoteAuthorPicture(
|
NoteAuthorPicture(
|
||||||
note = baseNote,
|
baseNote = baseNote,
|
||||||
navController = navController,
|
navController = navController,
|
||||||
userAccount = account.userProfile(),
|
userAccount = account.userProfile(),
|
||||||
size = 55.dp
|
size = 55.dp
|
||||||
|
|||||||
Reference in New Issue
Block a user