Finishes the routing for note edits for live, public and ephemeral chats as well as public messages.

This commit is contained in:
Vitor Pamplona
2025-08-19 18:21:27 -04:00
parent f56d927f72
commit 5662eda54c
18 changed files with 163 additions and 47 deletions
@@ -146,11 +146,32 @@ fun AppNavigation(
composableFromEndArgs<Route.Room> { ChatroomScreen(it.toKey(), it.message, it.replyId, it.draftId, accountViewModel, nav) } composableFromEndArgs<Route.Room> { ChatroomScreen(it.toKey(), it.message, it.replyId, it.draftId, accountViewModel, nav) }
composableFromEndArgs<Route.RoomByAuthor> { ChatroomByAuthorScreen(it.id, null, accountViewModel, nav) } composableFromEndArgs<Route.RoomByAuthor> { ChatroomByAuthorScreen(it.id, null, accountViewModel, nav) }
composableFromEndArgs<Route.PublicChatChannel> { PublicChatChannelScreen(it.id, accountViewModel, nav) } composableFromEndArgs<Route.PublicChatChannel> {
composableFromEndArgs<Route.LiveActivityChannel> { LiveActivityChannelScreen(Address(it.kind, it.pubKeyHex, it.dTag), accountViewModel, nav) } PublicChatChannelScreen(
it.id,
it.draftId?.let { hex -> accountViewModel.getNoteIfExists(hex) },
accountViewModel,
nav,
)
}
composableFromEndArgs<Route.LiveActivityChannel> {
LiveActivityChannelScreen(
Address(it.kind, it.pubKeyHex, it.dTag),
draft = it.draftId?.let { hex -> accountViewModel.getNoteIfExists(hex) },
accountViewModel,
nav,
)
}
composableFromEndArgs<Route.EphemeralChat> { composableFromEndArgs<Route.EphemeralChat> {
RelayUrlNormalizer.normalizeOrNull(it.relayUrl)?.let { relay -> RelayUrlNormalizer.normalizeOrNull(it.relayUrl)?.let { relay ->
EphemeralChatScreen(RoomId(it.id, relay), accountViewModel, nav) EphemeralChatScreen(
channelId = RoomId(it.id, relay),
draft = it.draftId?.let { hex -> accountViewModel.getNoteIfExists(hex) },
accountViewModel = accountViewModel,
nav = nav,
)
} }
} }
@@ -177,6 +198,7 @@ fun AppNavigation(
NewPublicMessageScreen( NewPublicMessageScreen(
to = it.toKey(), to = it.toKey(),
reply = it.replyId?.let { hex -> accountViewModel.getNoteIfExists(hex) }, reply = it.replyId?.let { hex -> accountViewModel.getNoteIfExists(hex) },
draft = it.draftId?.let { hex -> accountViewModel.getNoteIfExists(hex) },
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
nav = nav, nav = nav,
) )
@@ -218,7 +240,7 @@ fun AppNavigation(
) )
} }
composableFromBottomArgs<Route.NewPost> { composableFromBottomArgs<Route.NewShortNote> {
ShortNotePostScreen( ShortNotePostScreen(
message = it.message, message = it.message,
attachment = it.attachment?.ifBlank { null }?.toUri(), attachment = it.attachment?.ifBlank { null }?.toUri(),
@@ -259,7 +281,7 @@ private fun NavigateIfIntentRequested(
if (activity.intent.action == Intent.ACTION_SEND) { if (activity.intent.action == Intent.ACTION_SEND) {
// avoids restarting the new Post screen when the intent is for the screen. // avoids restarting the new Post screen when the intent is for the screen.
// Microsoft's swift key sends Gifs as new actions // Microsoft's swift key sends Gifs as new actions
if (isBaseRoute<Route.NewPost>(nav.controller)) return if (isBaseRoute<Route.NewShortNote>(nav.controller)) return
// saves the intent to avoid processing again // saves the intent to avoid processing again
var message by remember { var message by remember {
@@ -276,7 +298,7 @@ private fun NavigateIfIntentRequested(
) )
} }
nav.newStack(Route.NewPost(message = message, attachment = media.toString())) nav.newStack(Route.NewShortNote(message = message, attachment = media.toString()))
} else { } else {
var newAccount by remember { mutableStateOf<String?>(null) } var newAccount by remember { mutableStateOf<String?>(null) }
@@ -335,13 +357,13 @@ private fun NavigateIfIntentRequested(
if (intent.action == Intent.ACTION_SEND) { if (intent.action == Intent.ACTION_SEND) {
// avoids restarting the new Post screen when the intent is for the screen. // avoids restarting the new Post screen when the intent is for the screen.
// Microsoft's swift key sends Gifs as new actions // Microsoft's swift key sends Gifs as new actions
if (!isBaseRoute<Route.NewPost>(nav.controller)) { if (!isBaseRoute<Route.NewShortNote>(nav.controller)) {
intent.getStringExtra(Intent.EXTRA_TEXT)?.let { intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
nav.newStack(Route.NewPost(message = it)) nav.newStack(Route.NewShortNote(message = it))
} }
(intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let { (intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let {
nav.newStack(Route.NewPost(attachment = it.toString())) nav.newStack(Route.NewShortNote(attachment = it.toString()))
} }
} }
} else { } else {
@@ -28,6 +28,7 @@ import com.vitorpamplona.amethyst.model.emphChat.EphemeralChatChannel
import com.vitorpamplona.amethyst.model.nip28PublicChats.PublicChatChannel import com.vitorpamplona.amethyst.model.nip28PublicChats.PublicChatChannel
import com.vitorpamplona.amethyst.model.nip53LiveActivities.LiveActivitiesChannel import com.vitorpamplona.amethyst.model.nip53LiveActivities.LiveActivitiesChannel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.quartz.experimental.ephemChat.chat.EphemeralChatEvent
import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId
import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent import com.vitorpamplona.quartz.experimental.publicMessages.PublicMessageEvent
import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent import com.vitorpamplona.quartz.nip01Core.core.AddressableEvent
@@ -40,6 +41,7 @@ import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
import com.vitorpamplona.quartz.nip22Comments.CommentEvent import com.vitorpamplona.quartz.nip22Comments.CommentEvent
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
import com.vitorpamplona.quartz.nip28PublicChat.base.IsInPublicChatChannel import com.vitorpamplona.quartz.nip28PublicChat.base.IsInPublicChatChannel
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent
import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent
@@ -49,6 +51,7 @@ import com.vitorpamplona.quartz.nip72ModCommunities.definition.CommunityDefiniti
import com.vitorpamplona.quartz.nip73ExternalIds.location.isGeohashedScoped import com.vitorpamplona.quartz.nip73ExternalIds.location.isGeohashedScoped
import com.vitorpamplona.quartz.nip73ExternalIds.topics.isHashtagScoped import com.vitorpamplona.quartz.nip73ExternalIds.topics.isHashtagScoped
import com.vitorpamplona.quartz.nip89AppHandlers.definition.AppDefinitionEvent import com.vitorpamplona.quartz.nip89AppHandlers.definition.AppDefinitionEvent
import com.vitorpamplona.quartz.nip99Classifieds.ClassifiedsEvent
fun routeFor( fun routeFor(
note: Note, note: Note,
@@ -78,6 +81,10 @@ fun routeFor(
innerEvent.activityAddress()?.let { innerEvent.activityAddress()?.let {
return Route.LiveActivityChannel(it.kind, it.pubKeyHex, it.dTag) return Route.LiveActivityChannel(it.kind, it.pubKeyHex, it.dTag)
} }
} else if (innerEvent is EphemeralChatEvent) {
innerEvent.roomId()?.let {
return Route.EphemeralChat(it.id, it.relayUrl.url)
}
} else if (innerEvent is ChatroomKeyable) { } else if (innerEvent is ChatroomKeyable) {
val room = innerEvent.chatroomKey(loggedIn.userProfile().pubkeyHex) val room = innerEvent.chatroomKey(loggedIn.userProfile().pubkeyHex)
loggedIn.chatroomList.getOrCreatePrivateChatroom(room) loggedIn.chatroomList.getOrCreatePrivateChatroom(room)
@@ -206,7 +213,7 @@ fun routeReplyTo(
users = noteEvent.groupKeySet() - account.userProfile().pubkeyHex, users = noteEvent.groupKeySet() - account.userProfile().pubkeyHex,
parentId = noteEvent.id, parentId = noteEvent.id,
) )
is TextNoteEvent -> Route.NewPost(baseReplyTo = note.idHex) is TextNoteEvent -> Route.NewShortNote(baseReplyTo = note.idHex)
is PrivateDmEvent -> is PrivateDmEvent ->
routeToMessage( routeToMessage(
room = noteEvent.chatroomKey(account.userProfile().pubkeyHex), room = noteEvent.chatroomKey(account.userProfile().pubkeyHex),
@@ -236,3 +243,49 @@ fun routeReplyTo(
else -> Route.GenericCommentPost(replyTo = note.idHex) else -> Route.GenericCommentPost(replyTo = note.idHex)
} }
} }
suspend fun routeEditDraftTo(
note: Note,
account: Account,
): Route? {
val noteEvent = note.event as DraftWrapEvent
val draft = account.draftsDecryptionCache.cachedDraft(noteEvent)
return when (draft) {
is ChannelMessageEvent -> draft.channelId()?.let { Route.PublicChatChannel(it, draftId = note.idHex) }
is LiveActivitiesChatMessageEvent -> {
draft.activityAddress()?.let { Route.LiveActivityChannel(it.kind, it.pubKeyHex, it.dTag, draftId = note.idHex) }
}
is EphemeralChatEvent -> {
draft.roomId()?.let { Route.EphemeralChat(it.id, it.relayUrl.url, draftId = note.idHex) }
}
is ChatroomKeyable -> {
val room = draft.chatroomKey(account.userProfile().pubkeyHex)
account.chatroomList.getOrCreatePrivateChatroom(room)
return Route.Room(room, draftId = note.idHex)
}
is TextNoteEvent -> Route.NewShortNote(draft = note.idHex)
is ClassifiedsEvent -> Route.NewProduct(draft = note.idHex)
is PublicMessageEvent ->
Route.NewPublicMessage(
users = draft.groupKeySet() - account.userProfile().pubkeyHex,
parentId = noteEvent.id,
draftId = note.idHex,
)
is CommentEvent -> {
if (draft.isGeohashedScoped()) {
Route.GeoPost(draft = note.idHex)
} else if (draft.isHashtagScoped()) {
Route.HashtagPost(draft = note.idHex)
} else {
Route.GenericCommentPost(draft = note.idHex)
}
}
else -> null
}
}
@@ -90,16 +90,14 @@ sealed class Route {
@Serializable data class PublicChatChannel( @Serializable data class PublicChatChannel(
val id: String, val id: String,
val draftId: HexKey? = null,
) : Route() ) : Route()
@Serializable data class LiveActivityChannel( @Serializable data class LiveActivityChannel(
val kind: Int, val kind: Int,
val pubKeyHex: HexKey, val pubKeyHex: HexKey,
val dTag: String, val dTag: String,
) : Route() val draftId: HexKey? = null,
@Serializable data class EphemeralChatChannel(
val id: String,
) : Route() ) : Route()
@Serializable data class RelayInfo( @Serializable data class RelayInfo(
@@ -109,6 +107,7 @@ sealed class Route {
@Serializable data class EphemeralChat( @Serializable data class EphemeralChat(
val id: String, val id: String,
val relayUrl: String, val relayUrl: String,
val draftId: HexKey? = null,
) : Route() ) : Route()
@Serializable object NewEphemeralChat : Route() @Serializable object NewEphemeralChat : Route()
@@ -141,10 +140,12 @@ sealed class Route {
@Serializable data class NewPublicMessage( @Serializable data class NewPublicMessage(
val to: String, val to: String,
val replyId: HexKey? = null, val replyId: HexKey? = null,
val draftId: HexKey? = null,
) : Route() { ) : Route() {
constructor(users: Set<HexKey>, parentId: HexKey) : this( constructor(users: Set<HexKey>, parentId: HexKey, draftId: HexKey? = null) : this(
to = users.joinToString(","), to = users.joinToString(","),
replyId = parentId, replyId = parentId,
draftId = draftId,
) )
fun toKey(): Set<HexKey> = to.split(",").toSet() fun toKey(): Set<HexKey> = to.split(",").toSet()
@@ -196,7 +197,7 @@ sealed class Route {
) : Route() ) : Route()
@Serializable @Serializable
data class NewPost( data class NewShortNote(
val message: String? = null, val message: String? = null,
val attachment: String? = null, val attachment: String? = null,
val baseReplyTo: String? = null, val baseReplyTo: String? = null,
@@ -248,7 +249,7 @@ fun getRouteWithArguments(navController: NavHostController): Route? {
dest.hasRoute<Route.EditMediaServers>() -> entry.toRoute<Route.EditMediaServers>() dest.hasRoute<Route.EditMediaServers>() -> entry.toRoute<Route.EditMediaServers>()
dest.hasRoute<Route.Nip47NWCSetup>() -> entry.toRoute<Route.Nip47NWCSetup>() dest.hasRoute<Route.Nip47NWCSetup>() -> entry.toRoute<Route.Nip47NWCSetup>()
dest.hasRoute<Route.Room>() -> entry.toRoute<Route.Room>() dest.hasRoute<Route.Room>() -> entry.toRoute<Route.Room>()
dest.hasRoute<Route.NewPost>() -> entry.toRoute<Route.NewPost>() dest.hasRoute<Route.NewShortNote>() -> entry.toRoute<Route.NewShortNote>()
dest.hasRoute<Route.NewProduct>() -> entry.toRoute<Route.NewProduct>() dest.hasRoute<Route.NewProduct>() -> entry.toRoute<Route.NewProduct>()
dest.hasRoute<Route.GeoPost>() -> entry.toRoute<Route.GeoPost>() dest.hasRoute<Route.GeoPost>() -> entry.toRoute<Route.GeoPost>()
dest.hasRoute<Route.HashtagPost>() -> entry.toRoute<Route.HashtagPost>() dest.hasRoute<Route.HashtagPost>() -> entry.toRoute<Route.HashtagPost>()
@@ -84,7 +84,7 @@ import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.routes.routeEditDraftTo
import com.vitorpamplona.amethyst.ui.painterRes import com.vitorpamplona.amethyst.ui.painterRes
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.report.ReportNoteDialog import com.vitorpamplona.amethyst.ui.screen.loggedIn.report.ReportNoteDialog
@@ -169,11 +169,9 @@ fun NoteQuickActionMenu(
note = note, note = note,
onDismiss = onDismiss, onDismiss = onDismiss,
onWantsToEditDraft = { onWantsToEditDraft = {
nav.nav( nav.nav {
Route.NewPost( routeEditDraftTo(note, accountViewModel.account)
draft = note.idHex, }
),
)
}, },
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
nav = nav, nav = nav,
@@ -48,7 +48,6 @@ import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
@@ -155,7 +154,6 @@ import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.amethyst.ui.theme.reactionBox import com.vitorpamplona.amethyst.ui.theme.reactionBox
import com.vitorpamplona.amethyst.ui.theme.ripple24dp import com.vitorpamplona.amethyst.ui.theme.ripple24dp
import com.vitorpamplona.amethyst.ui.theme.selectedReactionBoxModifier import com.vitorpamplona.amethyst.ui.theme.selectedReactionBoxModifier
import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.EmptyClientListener.onError
import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
import com.vitorpamplona.quartz.nip30CustomEmoji.CustomEmoji import com.vitorpamplona.quartz.nip30CustomEmoji.CustomEmoji
@@ -541,7 +539,7 @@ private fun BoostWithDialog(
accountViewModel, accountViewModel,
onQuotePress = { onQuotePress = {
nav.nav { nav.nav {
Route.NewPost( Route.NewShortNote(
quote = baseNote.idHex, quote = baseNote.idHex,
version = version =
(editState.value as? GenericLoadable.Loaded) (editState.value as? GenericLoadable.Loaded)
@@ -562,7 +560,7 @@ private fun BoostWithDialog(
null null
} }
Route.NewPost( Route.NewShortNote(
baseReplyTo = replyTo?.idHex, baseReplyTo = replyTo?.idHex,
fork = baseNote.idHex, fork = baseNote.idHex,
version = version =
@@ -47,7 +47,7 @@ import com.vitorpamplona.amethyst.ui.actions.EditPostView
import com.vitorpamplona.amethyst.ui.components.ClickableBox import com.vitorpamplona.amethyst.ui.components.ClickableBox
import com.vitorpamplona.amethyst.ui.components.GenericLoadable import com.vitorpamplona.amethyst.ui.components.GenericLoadable
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.routes.routeEditDraftTo
import com.vitorpamplona.amethyst.ui.note.VerticalDotsIcon import com.vitorpamplona.amethyst.ui.note.VerticalDotsIcon
import com.vitorpamplona.amethyst.ui.note.externalLinkForNote import com.vitorpamplona.amethyst.ui.note.externalLinkForNote
import com.vitorpamplona.amethyst.ui.note.types.EditState import com.vitorpamplona.amethyst.ui.note.types.EditState
@@ -240,11 +240,9 @@ fun NoteDropDownMenu(
DropdownMenuItem( DropdownMenuItem(
text = { Text(stringRes(R.string.edit_draft)) }, text = { Text(stringRes(R.string.edit_draft)) },
onClick = { onClick = {
val route = nav.nav {
Route.NewPost( routeEditDraftTo(note, accountViewModel.account)
draft = note.idHex, }
)
nav.nav(route)
}, },
) )
} }
@@ -1691,7 +1691,7 @@ class AccountViewModel(
class CachedDraftNotes( class CachedDraftNotes(
val accountViewModel: AccountViewModel, val accountViewModel: AccountViewModel,
) : GenericBaseCacheAsync<DraftWrapEvent, Note>(20) { ) : GenericBaseCacheAsync<DraftWrapEvent, Note>(100) {
override suspend fun compute(key: DraftWrapEvent): Note? = override suspend fun compute(key: DraftWrapEvent): Note? =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val decrypted = accountViewModel.account.draftsDecryptionCache.cachedDraft(key) val decrypted = accountViewModel.account.draftsDecryptionCache.cachedDraft(key)
@@ -25,10 +25,12 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
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 com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.emphChat.EphemeralChatChannel import com.vitorpamplona.amethyst.model.emphChat.EphemeralChatChannel
import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -44,6 +46,7 @@ import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId
@Composable @Composable
fun EphemeralChatChannelView( fun EphemeralChatChannelView(
channelId: RoomId?, channelId: RoomId?,
draft: Note? = null,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
@@ -52,6 +55,7 @@ fun EphemeralChatChannelView(
LoadEphemeralChatChannel(channelId, accountViewModel) { ephem -> LoadEphemeralChatChannel(channelId, accountViewModel) { ephem ->
PrepareChannelViewModels( PrepareChannelViewModels(
baseChannel = ephem, baseChannel = ephem,
draft = draft,
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
nav = nav, nav = nav,
) )
@@ -61,6 +65,7 @@ fun EphemeralChatChannelView(
@Composable @Composable
private fun PrepareChannelViewModels( private fun PrepareChannelViewModels(
baseChannel: EphemeralChatChannel, baseChannel: EphemeralChatChannel,
draft: Note? = null,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
@@ -78,6 +83,12 @@ private fun PrepareChannelViewModels(
channelScreenModel.init(accountViewModel) channelScreenModel.init(accountViewModel)
channelScreenModel.load(baseChannel) channelScreenModel.load(baseChannel)
if (draft != null) {
LaunchedEffect(draft, channelScreenModel, accountViewModel) {
channelScreenModel.editFromDraft(draft)
}
}
ChannelView( ChannelView(
channel = baseChannel, channel = baseChannel,
feedViewModel = feedViewModel, feedViewModel = feedViewModel,
@@ -22,8 +22,10 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.ephem
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -33,6 +35,7 @@ import com.vitorpamplona.quartz.experimental.ephemChat.chat.RoomId
@Composable @Composable
fun EphemeralChatScreen( fun EphemeralChatScreen(
channelId: RoomId, channelId: RoomId,
draft: Note? = null,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
@@ -45,8 +48,8 @@ fun EphemeralChatScreen(
}, },
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
) { ) {
Column(Modifier.padding(it)) { Column(Modifier.padding(it).statusBarsPadding()) {
EphemeralChatChannelView(channelId, accountViewModel, nav) EphemeralChatChannelView(channelId, draft, accountViewModel, nav)
} }
} }
} }
@@ -25,10 +25,12 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
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 com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.nip28PublicChats.PublicChatChannel import com.vitorpamplona.amethyst.model.nip28PublicChats.PublicChatChannel
import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -44,6 +46,7 @@ import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
@Composable @Composable
fun PublicChatChannelView( fun PublicChatChannelView(
channelId: String?, channelId: String?,
draft: Note? = null,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
@@ -52,6 +55,7 @@ fun PublicChatChannelView(
LoadPublicChatChannel(channelId, accountViewModel) { LoadPublicChatChannel(channelId, accountViewModel) {
PrepareChannelViewModels( PrepareChannelViewModels(
baseChannel = it, baseChannel = it,
draft = draft,
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
nav = nav, nav = nav,
) )
@@ -61,6 +65,7 @@ fun PublicChatChannelView(
@Composable @Composable
fun PrepareChannelViewModels( fun PrepareChannelViewModels(
baseChannel: PublicChatChannel, baseChannel: PublicChatChannel,
draft: Note? = null,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
@@ -78,6 +83,12 @@ fun PrepareChannelViewModels(
channelScreenModel.init(accountViewModel) channelScreenModel.init(accountViewModel)
channelScreenModel.load(baseChannel) channelScreenModel.load(baseChannel)
if (draft != null) {
LaunchedEffect(draft, channelScreenModel, accountViewModel) {
channelScreenModel.editFromDraft(draft)
}
}
ChannelView( ChannelView(
channel = baseChannel, channel = baseChannel,
feedViewModel = feedViewModel, feedViewModel = feedViewModel,
@@ -22,8 +22,10 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.nip28
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.note.LoadPublicChatChannel import com.vitorpamplona.amethyst.ui.note.LoadPublicChatChannel
@@ -34,6 +36,7 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey
@Composable @Composable
fun PublicChatChannelScreen( fun PublicChatChannelScreen(
channelId: HexKey?, channelId: HexKey?,
draft: Note?,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
@@ -48,8 +51,8 @@ fun PublicChatChannelScreen(
}, },
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
) { ) {
Column(Modifier.padding(it)) { Column(Modifier.padding(it).statusBarsPadding()) {
PublicChatChannelView(channelId, accountViewModel, nav) PublicChatChannelView(channelId, draft, accountViewModel, nav)
} }
} }
} }
@@ -25,10 +25,12 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
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 com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.nip53LiveActivities.LiveActivitiesChannel import com.vitorpamplona.amethyst.model.nip53LiveActivities.LiveActivitiesChannel
import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel import com.vitorpamplona.amethyst.ui.feeds.WatchLifecycleAndUpdateModel
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
@@ -45,6 +47,7 @@ import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
@Composable @Composable
fun LiveActivityChannelView( fun LiveActivityChannelView(
channelId: Address?, channelId: Address?,
draft: Note? = null,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
@@ -53,6 +56,7 @@ fun LiveActivityChannelView(
LoadLiveActivityChannel(channelId, accountViewModel) { LoadLiveActivityChannel(channelId, accountViewModel) {
PrepareChannelViewModels( PrepareChannelViewModels(
baseChannel = it, baseChannel = it,
draft = draft,
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
nav = nav, nav = nav,
) )
@@ -62,6 +66,7 @@ fun LiveActivityChannelView(
@Composable @Composable
fun PrepareChannelViewModels( fun PrepareChannelViewModels(
baseChannel: LiveActivitiesChannel, baseChannel: LiveActivitiesChannel,
draft: Note? = null,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
@@ -79,6 +84,12 @@ fun PrepareChannelViewModels(
channelScreenModel.init(accountViewModel) channelScreenModel.init(accountViewModel)
channelScreenModel.load(baseChannel) channelScreenModel.load(baseChannel)
if (draft != null) {
LaunchedEffect(draft, channelScreenModel, accountViewModel) {
channelScreenModel.editFromDraft(draft)
}
}
LiveActivityChannelView( LiveActivityChannelView(
channel = baseChannel, channel = baseChannel,
feedViewModel = feedViewModel, feedViewModel = feedViewModel,
@@ -22,8 +22,10 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.nip53
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.note.LoadLiveActivityChannel import com.vitorpamplona.amethyst.ui.note.LoadLiveActivityChannel
@@ -34,6 +36,7 @@ import com.vitorpamplona.quartz.nip01Core.tags.addressables.Address
@Composable @Composable
fun LiveActivityChannelScreen( fun LiveActivityChannelScreen(
channelId: Address?, channelId: Address?,
draft: Note? = null,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: INav,
) { ) {
@@ -48,8 +51,8 @@ fun LiveActivityChannelScreen(
}, },
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
) { ) {
Column(Modifier.padding(it)) { Column(Modifier.padding(it).statusBarsPadding()) {
LiveActivityChannelView(channelId, accountViewModel, nav) LiveActivityChannelView(channelId, draft, accountViewModel, nav)
} }
} }
} }
@@ -207,10 +207,10 @@ open class ChannelNewMessageViewModel :
private fun loadFromDraft(draft: Note) { private fun loadFromDraft(draft: Note) {
val draftEvent = draft.event ?: return val draftEvent = draft.event ?: return
val localfowardZapTo = draftEvent.tags.zapSplitSetup() val localForwardZapTo = draftEvent.tags.zapSplitSetup()
val totalWeight = localfowardZapTo.sumOf { it.weight } val totalWeight = localForwardZapTo.sumOf { it.weight }
forwardZapTo = SplitBuilder() forwardZapTo = SplitBuilder()
localfowardZapTo.forEach { localForwardZapTo.forEach {
if (it is ZapSplitSetup) { if (it is ZapSplitSetup) {
val user = LocalCache.getOrCreateUser(it.pubKeyHex) val user = LocalCache.getOrCreateUser(it.pubKeyHex)
forwardZapTo.addItem(user, (it.weight / totalWeight).toFloat()) forwardZapTo.addItem(user, (it.weight / totalWeight).toFloat())
@@ -218,7 +218,7 @@ open class ChannelNewMessageViewModel :
// don't support edditing old-style splits. // don't support edditing old-style splits.
} }
forwardZapToEditting = TextFieldValue("") forwardZapToEditting = TextFieldValue("")
wantsForwardZapTo = localfowardZapTo.isNotEmpty() wantsForwardZapTo = localForwardZapTo.isNotEmpty()
wantsToMarkAsSensitive = draftEvent.isSensitive() wantsToMarkAsSensitive = draftEvent.isSensitive()
@@ -57,7 +57,7 @@ fun NewCommunityNoteButton(
FloatingActionButton( FloatingActionButton(
onClick = { onClick = {
val route = val route =
Route.NewPost( Route.NewShortNote(
baseReplyTo = note.idHex, baseReplyTo = note.idHex,
) )
nav.nav(route) nav.nav(route)
@@ -38,7 +38,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size55Modifier
fun NewNoteButton(nav: INav) { fun NewNoteButton(nav: INav) {
FloatingActionButton( FloatingActionButton(
onClick = { onClick = {
nav.nav(Route.NewPost()) nav.nav(Route.NewShortNote())
}, },
modifier = Size55Modifier, modifier = Size55Modifier,
shape = CircleShape, shape = CircleShape,
@@ -105,6 +105,7 @@ import kotlinx.coroutines.withContext
fun NewPublicMessageScreen( fun NewPublicMessageScreen(
to: Set<HexKey>? = null, to: Set<HexKey>? = null,
reply: Note? = null, reply: Note? = null,
draft: Note? = null,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: Nav, nav: Nav,
) { ) {
@@ -119,6 +120,9 @@ fun NewPublicMessageScreen(
reply?.let { reply?.let {
postViewModel.reply(it) postViewModel.reply(it)
} }
draft?.let {
postViewModel.editFromDraft(it)
}
} }
} }
@@ -431,7 +431,7 @@ fun ReactionsColumn(
iconSize = Size40dp, iconSize = Size40dp,
onQuotePress = { onQuotePress = {
nav.nav( nav.nav(
Route.NewPost( Route.NewShortNote(
quote = baseNote.idHex, quote = baseNote.idHex,
), ),
) )