Enabled citation via @ on chats

This commit is contained in:
Vitor Pamplona
2024-02-14 16:52:25 -05:00
parent bb7ec1ee4b
commit 9479e86b66
3 changed files with 104 additions and 41 deletions
@@ -50,8 +50,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.toggleable import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@@ -99,7 +97,6 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
@@ -158,9 +155,9 @@ import com.vitorpamplona.amethyst.ui.note.RegularPostIcon
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.MyTextField import com.vitorpamplona.amethyst.ui.screen.loggedIn.MyTextField
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ShowUserSuggestionList
import com.vitorpamplona.amethyst.ui.screen.loggedIn.TextSpinner import com.vitorpamplona.amethyst.ui.screen.loggedIn.TextSpinner
import com.vitorpamplona.amethyst.ui.screen.loggedIn.TitleExplainer import com.vitorpamplona.amethyst.ui.screen.loggedIn.TitleExplainer
import com.vitorpamplona.amethyst.ui.screen.loggedIn.UserLine
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
@@ -526,23 +523,11 @@ fun NewPostView(
} }
} }
val userSuggestions = postViewModel.userSuggestions ShowUserSuggestionList(
if (userSuggestions.isNotEmpty()) { postViewModel,
LazyColumn( accountViewModel,
contentPadding =
PaddingValues(
top = 10.dp,
),
modifier = Modifier.heightIn(0.dp, 300.dp), modifier = Modifier.heightIn(0.dp, 300.dp),
) { )
itemsIndexed(
userSuggestions,
key = { _, item -> item.pubkeyHex },
) { _, item ->
UserLine(item, accountViewModel) { postViewModel.autocompleteWithUser(item) }
}
}
}
BottomRowActions(postViewModel) BottomRowActions(postViewModel)
} }
@@ -649,7 +634,6 @@ private fun PollField(postViewModel: NewPostViewModel) {
} }
} }
@OptIn(ExperimentalComposeUiApi::class, ExperimentalMaterial3Api::class)
@Composable @Composable
private fun MessageField(postViewModel: NewPostViewModel) { private fun MessageField(postViewModel: NewPostViewModel) {
val focusRequester = remember { FocusRequester() } val focusRequester = remember { FocusRequester() }
@@ -38,10 +38,12 @@ import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.selection.LocalTextSelectionColors import androidx.compose.foundation.text.selection.LocalTextSelectionColors
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Cancel import androidx.compose.material.icons.filled.Cancel
import androidx.compose.material.icons.filled.EditNote import androidx.compose.material.icons.filled.EditNote
@@ -112,6 +114,7 @@ import com.vitorpamplona.amethyst.ui.actions.NewMessageTagger
import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel
import com.vitorpamplona.amethyst.ui.actions.ServerOption import com.vitorpamplona.amethyst.ui.actions.ServerOption
import com.vitorpamplona.amethyst.ui.actions.UploadFromGallery import com.vitorpamplona.amethyst.ui.actions.UploadFromGallery
import com.vitorpamplona.amethyst.ui.actions.UrlUserTagTransformation
import com.vitorpamplona.amethyst.ui.components.LoadNote import com.vitorpamplona.amethyst.ui.components.LoadNote
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
import com.vitorpamplona.amethyst.ui.components.SensitivityWarning import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
@@ -269,7 +272,13 @@ fun ChannelScreen(
val replyTo = remember { mutableStateOf<Note?>(null) } val replyTo = remember { mutableStateOf<Note?>(null) }
Column( Column(
modifier = remember { Modifier.fillMaxHeight().padding(vertical = 0.dp).weight(1f, true) }, modifier =
remember {
Modifier
.fillMaxHeight()
.padding(vertical = 0.dp)
.weight(1f, true)
},
) { ) {
if (channel is LiveActivitiesChannel) { if (channel is LiveActivitiesChannel) {
ShowVideoStreaming(channel, accountViewModel) ShowVideoStreaming(channel, accountViewModel)
@@ -340,7 +349,11 @@ fun DisplayReplyingToNote(
onCancel: () -> Unit, onCancel: () -> Unit,
) { ) {
Row( Row(
Modifier.padding(horizontal = 10.dp).animateContentSize(), Modifier
.padding(horizontal = 10.dp)
.heightIn(max = 100.dp)
.verticalScroll(rememberScrollState())
.animateContentSize(),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
if (replyingNote != null) { if (replyingNote != null) {
@@ -363,7 +376,10 @@ fun DisplayReplyingToNote(
Icon( Icon(
imageVector = Icons.Default.Cancel, imageVector = Icons.Default.Cancel,
null, null,
modifier = Modifier.padding(end = 5.dp).size(30.dp), modifier =
Modifier
.padding(end = 5.dp)
.size(30.dp),
tint = MaterialTheme.colorScheme.placeholderText, tint = MaterialTheme.colorScheme.placeholderText,
) )
} }
@@ -379,13 +395,13 @@ fun EditFieldRow(
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
onSendNewMessage: () -> Unit, onSendNewMessage: () -> Unit,
) { ) {
Row( Column(
modifier = EditFieldModifier, modifier = EditFieldModifier,
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) { ) {
val context = LocalContext.current val context = LocalContext.current
ShowUserSuggestionList(channelScreenModel, accountViewModel)
MyTextField( MyTextField(
value = channelScreenModel.message, value = channelScreenModel.message,
onValueChange = { channelScreenModel.updateMessage(it) }, onValueChange = { channelScreenModel.updateMessage(it) },
@@ -394,7 +410,7 @@ fun EditFieldRow(
capitalization = KeyboardCapitalization.Sentences, capitalization = KeyboardCapitalization.Sentences,
), ),
shape = EditFieldBorder, shape = EditFieldBorder,
modifier = Modifier.weight(1f, true), modifier = Modifier.fillMaxWidth(),
placeholder = { placeholder = {
Text( Text(
text = stringResource(R.string.reply_here), text = stringResource(R.string.reply_here),
@@ -431,6 +447,7 @@ fun EditFieldRow(
focusedIndicatorColor = Color.Transparent, focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent,
), ),
visualTransformation = UrlUserTagTransformation(MaterialTheme.colorScheme.primary),
) )
} }
} }
@@ -725,7 +742,11 @@ fun ShortChannelHeader(
} }
Column( Column(
modifier = Modifier.padding(start = 10.dp).height(35.dp).weight(1f), modifier =
Modifier
.padding(start = 10.dp)
.height(35.dp)
.weight(1f),
verticalArrangement = Arrangement.Center, verticalArrangement = Arrangement.Center,
) { ) {
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
@@ -738,7 +759,10 @@ fun ShortChannelHeader(
} }
Row( Row(
modifier = Modifier.height(Size35dp).padding(start = 5.dp), modifier =
Modifier
.height(Size35dp)
.padding(start = 5.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
if (channel is PublicChatChannel) { if (channel is PublicChatChannel) {
@@ -1028,7 +1052,12 @@ fun LiveFlag() {
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
fontSize = 16.sp, fontSize = 16.sp,
modifier = modifier =
remember { Modifier.clip(SmallBorder).background(Color.Red).padding(horizontal = 5.dp) }, remember {
Modifier
.clip(SmallBorder)
.background(Color.Red)
.padding(horizontal = 5.dp)
},
) )
} }
@@ -1039,7 +1068,12 @@ fun EndedFlag() {
color = Color.White, color = Color.White,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
modifier = modifier =
remember { Modifier.clip(SmallBorder).background(Color.Black).padding(horizontal = 5.dp) }, remember {
Modifier
.clip(SmallBorder)
.background(Color.Black)
.padding(horizontal = 5.dp)
},
) )
} }
@@ -1050,7 +1084,12 @@ fun OfflineFlag() {
color = Color.White, color = Color.White,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
modifier = modifier =
remember { Modifier.clip(SmallBorder).background(Color.Black).padding(horizontal = 5.dp) }, remember {
Modifier
.clip(SmallBorder)
.background(Color.Black)
.padding(horizontal = 5.dp)
},
) )
} }
@@ -1064,7 +1103,12 @@ fun ScheduledFlag(starts: Long?) {
color = Color.White, color = Color.White,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
modifier = modifier =
remember { Modifier.clip(SmallBorder).background(Color.Black).padding(horizontal = 5.dp) }, remember {
Modifier
.clip(SmallBorder)
.background(Color.Black)
.padding(horizontal = 5.dp)
},
) )
} }
@@ -1073,7 +1117,10 @@ private fun NoteCopyButton(note: Channel) {
var popupExpanded by remember { mutableStateOf(false) } var popupExpanded by remember { mutableStateOf(false) }
Button( Button(
modifier = Modifier.padding(horizontal = 3.dp).width(50.dp), modifier =
Modifier
.padding(horizontal = 3.dp)
.width(50.dp),
onClick = { popupExpanded = true }, onClick = { popupExpanded = true },
shape = ButtonBorder, shape = ButtonBorder,
colors = colors =
@@ -1116,7 +1163,10 @@ private fun EditButton(
} }
Button( Button(
modifier = Modifier.padding(horizontal = 3.dp).width(50.dp), modifier =
Modifier
.padding(horizontal = 3.dp)
.width(50.dp),
onClick = { wantsToPost = true }, onClick = { wantsToPost = true },
contentPadding = ZeroPadding, contentPadding = ZeroPadding,
) { ) {
@@ -25,11 +25,13 @@ import androidx.compose.animation.Crossfade
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
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.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
@@ -92,6 +94,7 @@ import com.vitorpamplona.amethyst.ui.actions.NewPostViewModel
import com.vitorpamplona.amethyst.ui.actions.PostButton import com.vitorpamplona.amethyst.ui.actions.PostButton
import com.vitorpamplona.amethyst.ui.actions.ServerOption import com.vitorpamplona.amethyst.ui.actions.ServerOption
import com.vitorpamplona.amethyst.ui.actions.UploadFromGallery import com.vitorpamplona.amethyst.ui.actions.UploadFromGallery
import com.vitorpamplona.amethyst.ui.actions.UrlUserTagTransformation
import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
import com.vitorpamplona.amethyst.ui.note.DisplayRoomSubject import com.vitorpamplona.amethyst.ui.note.DisplayRoomSubject
@@ -363,13 +366,13 @@ fun PrivateMessageEditFieldRow(
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
onSendNewMessage: () -> Unit, onSendNewMessage: () -> Unit,
) { ) {
Row( Column(
modifier = EditFieldModifier, modifier = EditFieldModifier,
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) { ) {
val context = LocalContext.current val context = LocalContext.current
ShowUserSuggestionList(channelScreenModel, accountViewModel)
MyTextField( MyTextField(
value = channelScreenModel.message, value = channelScreenModel.message,
onValueChange = { channelScreenModel.updateMessage(it) }, onValueChange = { channelScreenModel.updateMessage(it) },
@@ -378,7 +381,7 @@ fun PrivateMessageEditFieldRow(
capitalization = KeyboardCapitalization.Sentences, capitalization = KeyboardCapitalization.Sentences,
), ),
shape = EditFieldBorder, shape = EditFieldBorder,
modifier = Modifier.weight(1f, true), modifier = Modifier.fillMaxWidth(),
placeholder = { placeholder = {
Text( Text(
text = stringResource(R.string.reply_here), text = stringResource(R.string.reply_here),
@@ -461,10 +464,36 @@ fun PrivateMessageEditFieldRow(
focusedIndicatorColor = Color.Transparent, focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent,
), ),
visualTransformation = UrlUserTagTransformation(MaterialTheme.colorScheme.primary),
) )
} }
} }
@Composable
fun ShowUserSuggestionList(
channelScreenModel: NewPostViewModel,
accountViewModel: AccountViewModel,
modifier: Modifier = Modifier.heightIn(0.dp, 200.dp),
) {
val userSuggestions = channelScreenModel.userSuggestions
if (userSuggestions.isNotEmpty()) {
LazyColumn(
contentPadding =
PaddingValues(
top = 10.dp,
),
modifier = modifier,
) {
itemsIndexed(
userSuggestions,
key = { _, item -> item.pubkeyHex },
) { _, item ->
UserLine(item, accountViewModel) { channelScreenModel.autocompleteWithUser(item) }
}
}
}
}
@Composable @Composable
fun NewFeatureNIP24AlertDialog( fun NewFeatureNIP24AlertDialog(
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,