mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-27 22:46:22 +02:00
Activates NIP-22 reply for everything but kind 1s.
This commit is contained in:
@@ -50,6 +50,7 @@ import com.vitorpamplona.amethyst.service.relayClient.notifyCommand.compose.Disp
|
|||||||
import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataScreen
|
import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataScreen
|
||||||
import com.vitorpamplona.amethyst.ui.components.getActivity
|
import com.vitorpamplona.amethyst.ui.components.getActivity
|
||||||
import com.vitorpamplona.amethyst.ui.components.toasts.DisplayErrorMessages
|
import com.vitorpamplona.amethyst.ui.components.toasts.DisplayErrorMessages
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.nip22Comments.ReplyCommentPostScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.SharedPreferencesViewModel
|
import com.vitorpamplona.amethyst.ui.screen.SharedPreferencesViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountSwitcherAndLeftDrawerLayout
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountSwitcherAndLeftDrawerLayout
|
||||||
@@ -168,6 +169,18 @@ fun AppNavigation(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
composableFromBottomArgs<Route.GenericCommentPost> {
|
||||||
|
ReplyCommentPostScreen(
|
||||||
|
reply = it.replyTo?.let { hex -> accountViewModel.getNoteIfExists(hex) },
|
||||||
|
message = it.message,
|
||||||
|
attachment = it.attachment?.ifBlank { null }?.toUri(),
|
||||||
|
quote = it.quote?.let { hex -> accountViewModel.getNoteIfExists(hex) },
|
||||||
|
draft = it.draft?.let { hex -> accountViewModel.getNoteIfExists(hex) },
|
||||||
|
accountViewModel,
|
||||||
|
nav,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
composableFromBottomArgs<Route.NewProduct> {
|
composableFromBottomArgs<Route.NewProduct> {
|
||||||
NewProductScreen(
|
NewProductScreen(
|
||||||
message = it.message,
|
message = it.message,
|
||||||
|
@@ -211,39 +211,10 @@ fun routeReplyTo(
|
|||||||
} else if (noteEvent.isHashtagScoped()) {
|
} else if (noteEvent.isHashtagScoped()) {
|
||||||
Route.HashtagPost(replyTo = note.idHex)
|
Route.HashtagPost(replyTo = note.idHex)
|
||||||
} else {
|
} else {
|
||||||
null
|
Route.GenericCommentPost(replyTo = note.idHex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> null
|
else -> Route.GenericCommentPost(replyTo = note.idHex)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun routeQuote(
|
|
||||||
note: Note,
|
|
||||||
asUser: User,
|
|
||||||
): Route? {
|
|
||||||
val noteEvent = note.event
|
|
||||||
return when (noteEvent) {
|
|
||||||
is TextNoteEvent -> Route.NewPost(baseReplyTo = note.idHex)
|
|
||||||
is PrivateDmEvent ->
|
|
||||||
routeToMessage(
|
|
||||||
room = noteEvent.chatroomKey(asUser.pubkeyHex),
|
|
||||||
draftMessage = null,
|
|
||||||
replyId = noteEvent.id,
|
|
||||||
draftId = null,
|
|
||||||
fromUser = asUser,
|
|
||||||
)
|
|
||||||
is ChatroomKeyable ->
|
|
||||||
routeToMessage(
|
|
||||||
room = noteEvent.chatroomKey(asUser.pubkeyHex),
|
|
||||||
draftMessage = null,
|
|
||||||
replyId = noteEvent.id,
|
|
||||||
draftId = null,
|
|
||||||
fromUser = asUser,
|
|
||||||
)
|
|
||||||
is CommentEvent -> Route.GeoPost(replyTo = note.idHex)
|
|
||||||
|
|
||||||
else -> null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -159,6 +159,15 @@ sealed class Route {
|
|||||||
val draft: String? = null,
|
val draft: String? = null,
|
||||||
) : Route()
|
) : Route()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GenericCommentPost(
|
||||||
|
val message: String? = null,
|
||||||
|
val attachment: String? = null,
|
||||||
|
val replyTo: String? = null,
|
||||||
|
val quote: String? = null,
|
||||||
|
val draft: String? = null,
|
||||||
|
) : Route()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class NewPost(
|
data class NewPost(
|
||||||
val message: String? = null,
|
val message: String? = null,
|
||||||
@@ -212,6 +221,7 @@ fun getRouteWithArguments(navController: NavHostController): Route? {
|
|||||||
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>()
|
||||||
|
dest.hasRoute<Route.GenericCommentPost>() -> entry.toRoute<Route.GenericCommentPost>()
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
null
|
null
|
||||||
|
@@ -221,12 +221,8 @@ open class CommentPostViewModel :
|
|||||||
}
|
}
|
||||||
|
|
||||||
open fun reply(post: Note) {
|
open fun reply(post: Note) {
|
||||||
val accountViewModel = accountViewModel ?: return
|
|
||||||
val noteEvent = post.event as? CommentEvent ?: return
|
|
||||||
val scope = noteEvent.scope() ?: return
|
|
||||||
|
|
||||||
this.replyingTo = post
|
this.replyingTo = post
|
||||||
this.externalIdentity = scope
|
this.externalIdentity = (post.event as? CommentEvent)?.scope()
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun quote(quote: Note) {
|
open fun quote(quote: Note) {
|
||||||
|
@@ -0,0 +1,471 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.note.nip22Comments
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.compose.foundation.horizontalScroll
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
|
import androidx.compose.foundation.layout.imePadding
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.RelaySelectionDialogEasy
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.Nav
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.BaseUserPicture
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.contentWarning.ContentSensitivityExplainer
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.contentWarning.MarkAsSensitiveButton
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.emojiSuggestions.ShowEmojiSuggestionList
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.emojiSuggestions.WatchAndLoadMyEmojiList
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.invoice.AddLnInvoiceButton
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.invoice.InvoiceRequest
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.location.AddGeoHashButton
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.location.LocationAsHash
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.messagefield.MessageField
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.previews.DisplayPreviews
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.secretEmoji.AddSecretEmojiButton
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.secretEmoji.SecretEmojiRequest
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.uploads.ImageVideoDescription
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.ShowUserSuggestionList
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.AddZapraiserButton
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.ZapRaiserRequest
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapTo
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapToButton
|
||||||
|
import com.vitorpamplona.amethyst.ui.painterRes
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CloseButton
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.Notifying
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.PostButton
|
||||||
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ReplyCommentPostScreen(
|
||||||
|
reply: Note? = null,
|
||||||
|
message: String? = null,
|
||||||
|
attachment: Uri? = null,
|
||||||
|
quote: Note? = null,
|
||||||
|
draft: Note? = null,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: Nav,
|
||||||
|
) {
|
||||||
|
val postViewModel: CommentPostViewModel = viewModel()
|
||||||
|
postViewModel.init(accountViewModel)
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
postViewModel.reloadRelaySet()
|
||||||
|
reply?.let {
|
||||||
|
postViewModel.reply(it)
|
||||||
|
}
|
||||||
|
draft?.let {
|
||||||
|
postViewModel.editFromDraft(it)
|
||||||
|
}
|
||||||
|
quote?.let {
|
||||||
|
postViewModel.quote(it)
|
||||||
|
}
|
||||||
|
message?.ifBlank { null }?.let {
|
||||||
|
postViewModel.updateMessage(TextFieldValue(it))
|
||||||
|
}
|
||||||
|
attachment?.let {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val mediaType = context.contentResolver.getType(it)
|
||||||
|
postViewModel.selectImage(persistentListOf(SelectedMedia(it, mediaType)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericCommentPostScreen(postViewModel, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun GenericCommentPostScreen(
|
||||||
|
postViewModel: CommentPostViewModel,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: Nav,
|
||||||
|
) {
|
||||||
|
WatchAndLoadMyEmojiList(accountViewModel)
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
title = {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = CenterVertically,
|
||||||
|
) {
|
||||||
|
Spacer(modifier = StdHorzSpacer)
|
||||||
|
|
||||||
|
Box {
|
||||||
|
IconButton(
|
||||||
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
onClick = { postViewModel.showRelaysDialog = true },
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterRes(R.drawable.relays),
|
||||||
|
contentDescription = stringRes(id = R.string.relay_list_selector),
|
||||||
|
modifier = Modifier.height(25.dp),
|
||||||
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PostButton(
|
||||||
|
onPost = {
|
||||||
|
// uses the accountViewModel scope to avoid cancelling this
|
||||||
|
// function when the postViewModel is released
|
||||||
|
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
postViewModel.sendPostSync()
|
||||||
|
nav.popBack()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isActive = postViewModel.canPost(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
Row {
|
||||||
|
Spacer(modifier = StdHorzSpacer)
|
||||||
|
CloseButton(
|
||||||
|
onPress = {
|
||||||
|
// uses the accountViewModel scope to avoid cancelling this
|
||||||
|
// function when the postViewModel is released
|
||||||
|
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
postViewModel.sendDraftSync()
|
||||||
|
nav.popBack()
|
||||||
|
postViewModel.cancel()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
colors =
|
||||||
|
TopAppBarDefaults.topAppBarColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) { pad ->
|
||||||
|
if (postViewModel.showRelaysDialog) {
|
||||||
|
RelaySelectionDialogEasy(
|
||||||
|
preSelectedList = postViewModel.relayList ?: persistentListOf(),
|
||||||
|
onClose = { postViewModel.showRelaysDialog = false },
|
||||||
|
onPost = { postViewModel.relayList = it.map { it.url }.toImmutableList() },
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Surface(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.padding(pad)
|
||||||
|
.consumeWindowInsets(pad)
|
||||||
|
.imePadding(),
|
||||||
|
) {
|
||||||
|
GenericCommentPostBody(
|
||||||
|
postViewModel,
|
||||||
|
accountViewModel,
|
||||||
|
nav,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun GenericCommentPostBody(
|
||||||
|
postViewModel: CommentPostViewModel,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: Nav,
|
||||||
|
) {
|
||||||
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
|
Column(Modifier.fillMaxSize()) {
|
||||||
|
Row(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(
|
||||||
|
start = Size10dp,
|
||||||
|
end = Size10dp,
|
||||||
|
).weight(1f),
|
||||||
|
) {
|
||||||
|
Column(Modifier.fillMaxWidth().verticalScroll(scrollState)) {
|
||||||
|
postViewModel.externalIdentity?.let {
|
||||||
|
Row {
|
||||||
|
DisplayExternalId(it, nav)
|
||||||
|
Spacer(modifier = StdVertSpacer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
postViewModel.replyingTo?.let {
|
||||||
|
Row {
|
||||||
|
NoteCompose(
|
||||||
|
baseNote = it,
|
||||||
|
modifier = MaterialTheme.colorScheme.replyModifier,
|
||||||
|
isQuotedNote = true,
|
||||||
|
unPackReply = false,
|
||||||
|
makeItShort = true,
|
||||||
|
quotesLeft = 1,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav,
|
||||||
|
)
|
||||||
|
Spacer(modifier = StdVertSpacer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
Notifying(postViewModel.notifying?.toImmutableList(), accountViewModel) {
|
||||||
|
postViewModel.removeFromReplyList(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.padding(vertical = Size10dp),
|
||||||
|
) {
|
||||||
|
BaseUserPicture(
|
||||||
|
accountViewModel.userProfile(),
|
||||||
|
Size35dp,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
)
|
||||||
|
MessageField(
|
||||||
|
R.string.what_s_on_your_mind,
|
||||||
|
postViewModel,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplayPreviews(postViewModel.urlPreviews, accountViewModel, nav)
|
||||||
|
|
||||||
|
if (postViewModel.wantsToMarkAsSensitive) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = CenterVertically,
|
||||||
|
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
||||||
|
) {
|
||||||
|
ContentSensitivityExplainer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (postViewModel.wantsToAddGeoHash) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = CenterVertically,
|
||||||
|
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
||||||
|
) {
|
||||||
|
LocationAsHash(postViewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (postViewModel.wantsForwardZapTo) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = CenterVertically,
|
||||||
|
modifier = Modifier.padding(top = Size5dp, bottom = Size5dp, start = Size10dp),
|
||||||
|
) {
|
||||||
|
ForwardZapTo(postViewModel, accountViewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
postViewModel.multiOrchestrator?.let {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = CenterVertically,
|
||||||
|
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
ImageVideoDescription(
|
||||||
|
it,
|
||||||
|
accountViewModel.account.settings.defaultFileServer,
|
||||||
|
onAdd = { alt, server, sensitiveContent, mediaQuality ->
|
||||||
|
postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context)
|
||||||
|
if (server.type != ServerType.NIP95) {
|
||||||
|
accountViewModel.account.settings.changeDefaultFileServer(server)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDelete = postViewModel::deleteMediaToUpload,
|
||||||
|
onCancel = { postViewModel.multiOrchestrator = null },
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (postViewModel.wantsInvoice) {
|
||||||
|
postViewModel.lnAddress()?.let { lud16 ->
|
||||||
|
InvoiceRequest(
|
||||||
|
lud16,
|
||||||
|
accountViewModel.account.userProfile().pubkeyHex,
|
||||||
|
accountViewModel,
|
||||||
|
stringRes(id = R.string.lightning_invoice),
|
||||||
|
stringRes(id = R.string.lightning_create_and_add_invoice),
|
||||||
|
onSuccess = {
|
||||||
|
postViewModel.insertAtCursor(it)
|
||||||
|
postViewModel.wantsInvoice = false
|
||||||
|
},
|
||||||
|
onError = { title, message -> accountViewModel.toastManager.toast(title, message) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (postViewModel.wantsSecretEmoji) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = CenterVertically,
|
||||||
|
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
||||||
|
) {
|
||||||
|
Column(Modifier.fillMaxWidth()) {
|
||||||
|
SecretEmojiRequest {
|
||||||
|
postViewModel.insertAtCursor(it)
|
||||||
|
postViewModel.wantsSecretEmoji = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (postViewModel.wantsZapraiser && postViewModel.hasLnAddress()) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = CenterVertically,
|
||||||
|
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
||||||
|
) {
|
||||||
|
ZapRaiserRequest(
|
||||||
|
stringRes(id = R.string.zapraiser),
|
||||||
|
postViewModel,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
postViewModel.userSuggestions?.let {
|
||||||
|
ShowUserSuggestionList(
|
||||||
|
it,
|
||||||
|
postViewModel::autocompleteWithUser,
|
||||||
|
accountViewModel,
|
||||||
|
modifier = Modifier.heightIn(0.dp, 300.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
postViewModel.emojiSuggestions?.let {
|
||||||
|
ShowEmojiSuggestionList(
|
||||||
|
it,
|
||||||
|
postViewModel::autocompleteWithEmoji,
|
||||||
|
postViewModel::autocompleteWithEmojiUrl,
|
||||||
|
accountViewModel,
|
||||||
|
modifier = Modifier.heightIn(0.dp, 300.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
BottomRowActions(postViewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun BottomRowActions(postViewModel: CommentPostViewModel) {
|
||||||
|
val scrollState = rememberScrollState()
|
||||||
|
Row(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.horizontalScroll(scrollState)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(50.dp),
|
||||||
|
verticalAlignment = CenterVertically,
|
||||||
|
) {
|
||||||
|
SelectFromGallery(
|
||||||
|
isUploading = postViewModel.isUploadingImage,
|
||||||
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
|
modifier = Modifier,
|
||||||
|
) {
|
||||||
|
postViewModel.selectImage(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
TakePictureButton(
|
||||||
|
onPictureTaken = {
|
||||||
|
postViewModel.selectImage(it)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
ForwardZapToButton(postViewModel.wantsForwardZapTo) {
|
||||||
|
postViewModel.wantsForwardZapTo = !postViewModel.wantsForwardZapTo
|
||||||
|
}
|
||||||
|
|
||||||
|
if (postViewModel.canAddZapRaiser) {
|
||||||
|
AddZapraiserButton(postViewModel.wantsZapraiser) {
|
||||||
|
postViewModel.wantsZapraiser = !postViewModel.wantsZapraiser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkAsSensitiveButton(postViewModel.wantsToMarkAsSensitive) {
|
||||||
|
postViewModel.toggleMarkAsSensitive()
|
||||||
|
}
|
||||||
|
|
||||||
|
AddGeoHashButton(postViewModel.wantsToAddGeoHash) {
|
||||||
|
postViewModel.wantsToAddGeoHash = !postViewModel.wantsToAddGeoHash
|
||||||
|
}
|
||||||
|
|
||||||
|
AddSecretEmojiButton(postViewModel.wantsSecretEmoji) {
|
||||||
|
postViewModel.wantsSecretEmoji = !postViewModel.wantsSecretEmoji
|
||||||
|
}
|
||||||
|
|
||||||
|
if (postViewModel.canAddInvoice && postViewModel.hasLnAddress()) {
|
||||||
|
AddLnInvoiceButton(postViewModel.wantsInvoice) {
|
||||||
|
postViewModel.wantsInvoice = !postViewModel.wantsInvoice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -21,85 +21,21 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.geohash
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.geohash
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.foundation.horizontalScroll
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.heightIn
|
|
||||||
import androidx.compose.foundation.layout.imePadding
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Surface
|
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
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.getValue
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.vitorpamplona.amethyst.R
|
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.ui.actions.RelaySelectionDialogEasy
|
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
|
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.Nav
|
import com.vitorpamplona.amethyst.ui.navigation.Nav
|
||||||
import com.vitorpamplona.amethyst.ui.note.BaseUserPicture
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.contentWarning.ContentSensitivityExplainer
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.contentWarning.MarkAsSensitiveButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.emojiSuggestions.ShowEmojiSuggestionList
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.emojiSuggestions.WatchAndLoadMyEmojiList
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.invoice.AddLnInvoiceButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.invoice.InvoiceRequest
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.messagefield.MessageField
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.previews.DisplayPreviews
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.secretEmoji.AddSecretEmojiButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.secretEmoji.SecretEmojiRequest
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.uploads.ImageVideoDescription
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.ShowUserSuggestionList
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.AddZapraiserButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.ZapRaiserRequest
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapTo
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapToButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.nip22Comments.CommentPostViewModel
|
import com.vitorpamplona.amethyst.ui.note.nip22Comments.CommentPostViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.note.nip22Comments.DisplayExternalId
|
import com.vitorpamplona.amethyst.ui.note.nip22Comments.GenericCommentPostScreen
|
||||||
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.CloseButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.Notifying
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.PostButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
|
||||||
import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId
|
import com.vitorpamplona.quartz.nip73ExternalIds.location.GeohashId
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -143,322 +79,5 @@ fun GeoHashPostScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NewGeoPostScreenInner(postViewModel, accountViewModel, nav)
|
GenericCommentPostScreen(postViewModel, accountViewModel, nav)
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun NewGeoPostScreenInner(
|
|
||||||
postViewModel: CommentPostViewModel,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: Nav,
|
|
||||||
) {
|
|
||||||
WatchAndLoadMyEmojiList(accountViewModel)
|
|
||||||
|
|
||||||
Scaffold(
|
|
||||||
topBar = {
|
|
||||||
TopAppBar(
|
|
||||||
title = {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
) {
|
|
||||||
Spacer(modifier = StdHorzSpacer)
|
|
||||||
|
|
||||||
Box {
|
|
||||||
IconButton(
|
|
||||||
modifier = Modifier.align(Alignment.Center),
|
|
||||||
onClick = { postViewModel.showRelaysDialog = true },
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterRes(R.drawable.relays),
|
|
||||||
contentDescription = stringRes(id = R.string.relay_list_selector),
|
|
||||||
modifier = Modifier.height(25.dp),
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PostButton(
|
|
||||||
onPost = {
|
|
||||||
// uses the accountViewModel scope to avoid cancelling this
|
|
||||||
// function when the postViewModel is released
|
|
||||||
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
postViewModel.sendPostSync()
|
|
||||||
nav.popBack()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isActive = postViewModel.canPost(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
navigationIcon = {
|
|
||||||
Row {
|
|
||||||
Spacer(modifier = StdHorzSpacer)
|
|
||||||
CloseButton(
|
|
||||||
onPress = {
|
|
||||||
// uses the accountViewModel scope to avoid cancelling this
|
|
||||||
// function when the postViewModel is released
|
|
||||||
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
postViewModel.sendDraftSync()
|
|
||||||
nav.popBack()
|
|
||||||
postViewModel.cancel()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors =
|
|
||||||
TopAppBarDefaults.topAppBarColors(
|
|
||||||
containerColor = MaterialTheme.colorScheme.surface,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
) { pad ->
|
|
||||||
if (postViewModel.showRelaysDialog) {
|
|
||||||
RelaySelectionDialogEasy(
|
|
||||||
preSelectedList = postViewModel.relayList ?: persistentListOf(),
|
|
||||||
onClose = { postViewModel.showRelaysDialog = false },
|
|
||||||
onPost = { postViewModel.relayList = it.map { it.url }.toImmutableList() },
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Surface(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.padding(pad)
|
|
||||||
.consumeWindowInsets(pad)
|
|
||||||
.imePadding(),
|
|
||||||
) {
|
|
||||||
NewGeoPostBody(
|
|
||||||
postViewModel,
|
|
||||||
accountViewModel,
|
|
||||||
nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun NewGeoPostBody(
|
|
||||||
postViewModel: CommentPostViewModel,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: Nav,
|
|
||||||
) {
|
|
||||||
val scrollState = rememberScrollState()
|
|
||||||
|
|
||||||
Column(Modifier.fillMaxSize()) {
|
|
||||||
Row(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(
|
|
||||||
start = Size10dp,
|
|
||||||
end = Size10dp,
|
|
||||||
).weight(1f),
|
|
||||||
) {
|
|
||||||
Column(Modifier.fillMaxWidth().verticalScroll(scrollState)) {
|
|
||||||
postViewModel.externalIdentity?.let {
|
|
||||||
Row {
|
|
||||||
DisplayExternalId(it, nav)
|
|
||||||
Spacer(modifier = StdVertSpacer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
postViewModel.replyingTo?.let {
|
|
||||||
Row {
|
|
||||||
NoteCompose(
|
|
||||||
baseNote = it,
|
|
||||||
modifier = MaterialTheme.colorScheme.replyModifier,
|
|
||||||
isQuotedNote = true,
|
|
||||||
unPackReply = false,
|
|
||||||
makeItShort = true,
|
|
||||||
quotesLeft = 1,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
Spacer(modifier = StdVertSpacer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
Notifying(postViewModel.notifying?.toImmutableList(), accountViewModel) {
|
|
||||||
postViewModel.removeFromReplyList(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.padding(vertical = Size10dp),
|
|
||||||
) {
|
|
||||||
BaseUserPicture(
|
|
||||||
accountViewModel.userProfile(),
|
|
||||||
Size35dp,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
)
|
|
||||||
MessageField(
|
|
||||||
R.string.what_s_on_your_mind,
|
|
||||||
postViewModel,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplayPreviews(postViewModel.urlPreviews, accountViewModel, nav)
|
|
||||||
|
|
||||||
if (postViewModel.wantsToMarkAsSensitive) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
|
||||||
) {
|
|
||||||
ContentSensitivityExplainer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.wantsForwardZapTo) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
modifier = Modifier.padding(top = Size5dp, bottom = Size5dp, start = Size10dp),
|
|
||||||
) {
|
|
||||||
ForwardZapTo(postViewModel, accountViewModel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
postViewModel.multiOrchestrator?.let {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
|
||||||
ImageVideoDescription(
|
|
||||||
it,
|
|
||||||
accountViewModel.account.settings.defaultFileServer,
|
|
||||||
onAdd = { alt, server, sensitiveContent, mediaQuality ->
|
|
||||||
postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context)
|
|
||||||
if (server.type != ServerType.NIP95) {
|
|
||||||
accountViewModel.account.settings.changeDefaultFileServer(server)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onDelete = postViewModel::deleteMediaToUpload,
|
|
||||||
onCancel = { postViewModel.multiOrchestrator = null },
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.wantsInvoice) {
|
|
||||||
postViewModel.lnAddress()?.let { lud16 ->
|
|
||||||
InvoiceRequest(
|
|
||||||
lud16,
|
|
||||||
accountViewModel.account.userProfile().pubkeyHex,
|
|
||||||
accountViewModel,
|
|
||||||
stringRes(id = R.string.lightning_invoice),
|
|
||||||
stringRes(id = R.string.lightning_create_and_add_invoice),
|
|
||||||
onSuccess = {
|
|
||||||
postViewModel.insertAtCursor(it)
|
|
||||||
postViewModel.wantsInvoice = false
|
|
||||||
},
|
|
||||||
onError = { title, message -> accountViewModel.toastManager.toast(title, message) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.wantsSecretEmoji) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
|
||||||
) {
|
|
||||||
Column(Modifier.fillMaxWidth()) {
|
|
||||||
SecretEmojiRequest {
|
|
||||||
postViewModel.insertAtCursor(it)
|
|
||||||
postViewModel.wantsSecretEmoji = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.wantsZapraiser && postViewModel.hasLnAddress()) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
|
||||||
) {
|
|
||||||
ZapRaiserRequest(
|
|
||||||
stringRes(id = R.string.zapraiser),
|
|
||||||
postViewModel,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
postViewModel.userSuggestions?.let {
|
|
||||||
ShowUserSuggestionList(
|
|
||||||
it,
|
|
||||||
postViewModel::autocompleteWithUser,
|
|
||||||
accountViewModel,
|
|
||||||
modifier = Modifier.heightIn(0.dp, 300.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
postViewModel.emojiSuggestions?.let {
|
|
||||||
ShowEmojiSuggestionList(
|
|
||||||
it,
|
|
||||||
postViewModel::autocompleteWithEmoji,
|
|
||||||
postViewModel::autocompleteWithEmojiUrl,
|
|
||||||
accountViewModel,
|
|
||||||
modifier = Modifier.heightIn(0.dp, 300.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
BottomRowActions(postViewModel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun BottomRowActions(postViewModel: CommentPostViewModel) {
|
|
||||||
val scrollState = rememberScrollState()
|
|
||||||
Row(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.horizontalScroll(scrollState)
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(50.dp),
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
) {
|
|
||||||
SelectFromGallery(
|
|
||||||
isUploading = postViewModel.isUploadingImage,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
modifier = Modifier,
|
|
||||||
) {
|
|
||||||
postViewModel.selectImage(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
TakePictureButton(
|
|
||||||
onPictureTaken = {
|
|
||||||
postViewModel.selectImage(it)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
ForwardZapToButton(postViewModel.wantsForwardZapTo) {
|
|
||||||
postViewModel.wantsForwardZapTo = !postViewModel.wantsForwardZapTo
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.canAddZapRaiser) {
|
|
||||||
AddZapraiserButton(postViewModel.wantsZapraiser) {
|
|
||||||
postViewModel.wantsZapraiser = !postViewModel.wantsZapraiser
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MarkAsSensitiveButton(postViewModel.wantsToMarkAsSensitive) {
|
|
||||||
postViewModel.toggleMarkAsSensitive()
|
|
||||||
}
|
|
||||||
|
|
||||||
AddSecretEmojiButton(postViewModel.wantsSecretEmoji) {
|
|
||||||
postViewModel.wantsSecretEmoji = !postViewModel.wantsSecretEmoji
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.canAddInvoice && postViewModel.hasLnAddress()) {
|
|
||||||
AddLnInvoiceButton(postViewModel.wantsInvoice) {
|
|
||||||
postViewModel.wantsInvoice = !postViewModel.wantsInvoice
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -21,87 +21,21 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.hashtag
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.hashtag
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.foundation.horizontalScroll
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.heightIn
|
|
||||||
import androidx.compose.foundation.layout.imePadding
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Surface
|
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
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.getValue
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.vitorpamplona.amethyst.R
|
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.ui.actions.RelaySelectionDialogEasy
|
|
||||||
import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
|
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
|
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.Nav
|
import com.vitorpamplona.amethyst.ui.navigation.Nav
|
||||||
import com.vitorpamplona.amethyst.ui.note.BaseUserPicture
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.contentWarning.ContentSensitivityExplainer
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.contentWarning.MarkAsSensitiveButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.emojiSuggestions.ShowEmojiSuggestionList
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.emojiSuggestions.WatchAndLoadMyEmojiList
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.invoice.AddLnInvoiceButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.invoice.InvoiceRequest
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.location.AddGeoHashButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.location.LocationAsHash
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.messagefield.MessageField
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.previews.DisplayPreviews
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.secretEmoji.AddSecretEmojiButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.secretEmoji.SecretEmojiRequest
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.uploads.ImageVideoDescription
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.userSuggestions.ShowUserSuggestionList
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.AddZapraiserButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapraiser.ZapRaiserRequest
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapTo
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.creators.zapsplits.ForwardZapToButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.nip22Comments.CommentPostViewModel
|
import com.vitorpamplona.amethyst.ui.note.nip22Comments.CommentPostViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.note.nip22Comments.DisplayExternalId
|
import com.vitorpamplona.amethyst.ui.note.nip22Comments.GenericCommentPostScreen
|
||||||
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.CloseButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.Notifying
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.PostButton
|
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
|
||||||
import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId
|
import com.vitorpamplona.quartz.nip73ExternalIds.topics.HashtagId
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -145,335 +79,5 @@ fun HashtagPostScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HashtagPostScreenInner(postViewModel, accountViewModel, nav)
|
GenericCommentPostScreen(postViewModel, accountViewModel, nav)
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun HashtagPostScreenInner(
|
|
||||||
postViewModel: CommentPostViewModel,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: Nav,
|
|
||||||
) {
|
|
||||||
WatchAndLoadMyEmojiList(accountViewModel)
|
|
||||||
|
|
||||||
Scaffold(
|
|
||||||
topBar = {
|
|
||||||
TopAppBar(
|
|
||||||
title = {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
) {
|
|
||||||
Spacer(modifier = StdHorzSpacer)
|
|
||||||
|
|
||||||
Box {
|
|
||||||
IconButton(
|
|
||||||
modifier = Modifier.align(Alignment.Center),
|
|
||||||
onClick = { postViewModel.showRelaysDialog = true },
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
painter = painterRes(R.drawable.relays),
|
|
||||||
contentDescription = stringRes(id = R.string.relay_list_selector),
|
|
||||||
modifier = Modifier.height(25.dp),
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PostButton(
|
|
||||||
onPost = {
|
|
||||||
// uses the accountViewModel scope to avoid cancelling this
|
|
||||||
// function when the postViewModel is released
|
|
||||||
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
postViewModel.sendPostSync()
|
|
||||||
nav.popBack()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isActive = postViewModel.canPost(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
navigationIcon = {
|
|
||||||
Row {
|
|
||||||
Spacer(modifier = StdHorzSpacer)
|
|
||||||
CloseButton(
|
|
||||||
onPress = {
|
|
||||||
// uses the accountViewModel scope to avoid cancelling this
|
|
||||||
// function when the postViewModel is released
|
|
||||||
accountViewModel.viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
postViewModel.sendDraftSync()
|
|
||||||
nav.popBack()
|
|
||||||
postViewModel.cancel()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors =
|
|
||||||
TopAppBarDefaults.topAppBarColors(
|
|
||||||
containerColor = MaterialTheme.colorScheme.surface,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
) { pad ->
|
|
||||||
if (postViewModel.showRelaysDialog) {
|
|
||||||
RelaySelectionDialogEasy(
|
|
||||||
preSelectedList = postViewModel.relayList ?: persistentListOf(),
|
|
||||||
onClose = { postViewModel.showRelaysDialog = false },
|
|
||||||
onPost = { postViewModel.relayList = it.map { it.url }.toImmutableList() },
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Surface(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.padding(pad)
|
|
||||||
.consumeWindowInsets(pad)
|
|
||||||
.imePadding(),
|
|
||||||
) {
|
|
||||||
HashtagPostBody(
|
|
||||||
postViewModel,
|
|
||||||
accountViewModel,
|
|
||||||
nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun HashtagPostBody(
|
|
||||||
postViewModel: CommentPostViewModel,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: Nav,
|
|
||||||
) {
|
|
||||||
val scrollState = rememberScrollState()
|
|
||||||
|
|
||||||
Column(Modifier.fillMaxSize()) {
|
|
||||||
Row(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(
|
|
||||||
start = Size10dp,
|
|
||||||
end = Size10dp,
|
|
||||||
).weight(1f),
|
|
||||||
) {
|
|
||||||
Column(Modifier.fillMaxWidth().verticalScroll(scrollState)) {
|
|
||||||
postViewModel.externalIdentity?.let {
|
|
||||||
Row {
|
|
||||||
DisplayExternalId(it, nav)
|
|
||||||
Spacer(modifier = StdVertSpacer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
postViewModel.replyingTo?.let {
|
|
||||||
Row {
|
|
||||||
NoteCompose(
|
|
||||||
baseNote = it,
|
|
||||||
modifier = MaterialTheme.colorScheme.replyModifier,
|
|
||||||
isQuotedNote = true,
|
|
||||||
unPackReply = false,
|
|
||||||
makeItShort = true,
|
|
||||||
quotesLeft = 1,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
Spacer(modifier = StdVertSpacer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row {
|
|
||||||
Notifying(postViewModel.notifying?.toImmutableList(), accountViewModel) {
|
|
||||||
postViewModel.removeFromReplyList(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.padding(vertical = Size10dp),
|
|
||||||
) {
|
|
||||||
BaseUserPicture(
|
|
||||||
accountViewModel.userProfile(),
|
|
||||||
Size35dp,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
)
|
|
||||||
MessageField(
|
|
||||||
R.string.what_s_on_your_mind,
|
|
||||||
postViewModel,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplayPreviews(postViewModel.urlPreviews, accountViewModel, nav)
|
|
||||||
|
|
||||||
if (postViewModel.wantsToMarkAsSensitive) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
|
||||||
) {
|
|
||||||
ContentSensitivityExplainer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.wantsToAddGeoHash) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
|
||||||
) {
|
|
||||||
LocationAsHash(postViewModel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.wantsForwardZapTo) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
modifier = Modifier.padding(top = Size5dp, bottom = Size5dp, start = Size10dp),
|
|
||||||
) {
|
|
||||||
ForwardZapTo(postViewModel, accountViewModel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
postViewModel.multiOrchestrator?.let {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
|
||||||
) {
|
|
||||||
val context = LocalContext.current
|
|
||||||
ImageVideoDescription(
|
|
||||||
it,
|
|
||||||
accountViewModel.account.settings.defaultFileServer,
|
|
||||||
onAdd = { alt, server, sensitiveContent, mediaQuality ->
|
|
||||||
postViewModel.upload(alt, if (sensitiveContent) "" else null, mediaQuality, server, accountViewModel.toastManager::toast, context)
|
|
||||||
if (server.type != ServerType.NIP95) {
|
|
||||||
accountViewModel.account.settings.changeDefaultFileServer(server)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onDelete = postViewModel::deleteMediaToUpload,
|
|
||||||
onCancel = { postViewModel.multiOrchestrator = null },
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.wantsInvoice) {
|
|
||||||
postViewModel.lnAddress()?.let { lud16 ->
|
|
||||||
InvoiceRequest(
|
|
||||||
lud16,
|
|
||||||
accountViewModel.account.userProfile().pubkeyHex,
|
|
||||||
accountViewModel,
|
|
||||||
stringRes(id = R.string.lightning_invoice),
|
|
||||||
stringRes(id = R.string.lightning_create_and_add_invoice),
|
|
||||||
onSuccess = {
|
|
||||||
postViewModel.insertAtCursor(it)
|
|
||||||
postViewModel.wantsInvoice = false
|
|
||||||
},
|
|
||||||
onError = { title, message -> accountViewModel.toastManager.toast(title, message) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.wantsSecretEmoji) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
|
||||||
) {
|
|
||||||
Column(Modifier.fillMaxWidth()) {
|
|
||||||
SecretEmojiRequest {
|
|
||||||
postViewModel.insertAtCursor(it)
|
|
||||||
postViewModel.wantsSecretEmoji = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.wantsZapraiser && postViewModel.hasLnAddress()) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
modifier = Modifier.padding(vertical = Size5dp, horizontal = Size10dp),
|
|
||||||
) {
|
|
||||||
ZapRaiserRequest(
|
|
||||||
stringRes(id = R.string.zapraiser),
|
|
||||||
postViewModel,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
postViewModel.userSuggestions?.let {
|
|
||||||
ShowUserSuggestionList(
|
|
||||||
it,
|
|
||||||
postViewModel::autocompleteWithUser,
|
|
||||||
accountViewModel,
|
|
||||||
modifier = Modifier.heightIn(0.dp, 300.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
postViewModel.emojiSuggestions?.let {
|
|
||||||
ShowEmojiSuggestionList(
|
|
||||||
it,
|
|
||||||
postViewModel::autocompleteWithEmoji,
|
|
||||||
postViewModel::autocompleteWithEmojiUrl,
|
|
||||||
accountViewModel,
|
|
||||||
modifier = Modifier.heightIn(0.dp, 300.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
BottomRowActions(postViewModel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun BottomRowActions(postViewModel: CommentPostViewModel) {
|
|
||||||
val scrollState = rememberScrollState()
|
|
||||||
Row(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.horizontalScroll(scrollState)
|
|
||||||
.fillMaxWidth()
|
|
||||||
.height(50.dp),
|
|
||||||
verticalAlignment = CenterVertically,
|
|
||||||
) {
|
|
||||||
SelectFromGallery(
|
|
||||||
isUploading = postViewModel.isUploadingImage,
|
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
|
||||||
modifier = Modifier,
|
|
||||||
) {
|
|
||||||
postViewModel.selectImage(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
TakePictureButton(
|
|
||||||
onPictureTaken = {
|
|
||||||
postViewModel.selectImage(it)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
ForwardZapToButton(postViewModel.wantsForwardZapTo) {
|
|
||||||
postViewModel.wantsForwardZapTo = !postViewModel.wantsForwardZapTo
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.canAddZapRaiser) {
|
|
||||||
AddZapraiserButton(postViewModel.wantsZapraiser) {
|
|
||||||
postViewModel.wantsZapraiser = !postViewModel.wantsZapraiser
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MarkAsSensitiveButton(postViewModel.wantsToMarkAsSensitive) {
|
|
||||||
postViewModel.toggleMarkAsSensitive()
|
|
||||||
}
|
|
||||||
|
|
||||||
AddGeoHashButton(postViewModel.wantsToAddGeoHash) {
|
|
||||||
postViewModel.wantsToAddGeoHash = !postViewModel.wantsToAddGeoHash
|
|
||||||
}
|
|
||||||
|
|
||||||
AddSecretEmojiButton(postViewModel.wantsSecretEmoji) {
|
|
||||||
postViewModel.wantsSecretEmoji = !postViewModel.wantsSecretEmoji
|
|
||||||
}
|
|
||||||
|
|
||||||
if (postViewModel.canAddInvoice && postViewModel.hasLnAddress()) {
|
|
||||||
AddLnInvoiceButton(postViewModel.wantsInvoice) {
|
|
||||||
postViewModel.wantsInvoice = !postViewModel.wantsInvoice
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user