diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt index 61e8d3d17..6adb42fd7 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/lnurl/LightningAddressResolver.kt @@ -57,7 +57,7 @@ class LightningAddressResolver() { if (it.isSuccessful) { onSuccess(it.body.string()) } else { - onError("Could not resolve $lnaddress. Error: ${it.code}. Check if the server up and if the lightning address $lnaddress is correct") + onError("The receiver's lightning service at $url is not available. It was calculated from the lightning address \"${lnaddress}\". Error: ${it.code}. Check if the server up and if the lightning address is correct") } } } catch (e: Exception) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt index 6775b9562..df4b33aca 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt @@ -215,6 +215,7 @@ fun AppNavigation( composable(route.route, route.arguments, content = { ChatroomScreen( roomId = it.arguments?.getString("id"), + draftMessage = it.arguments?.getString("message"), accountViewModel = accountViewModel, nav = nav ) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt index 9e4ff9981..f242c3815 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt @@ -120,9 +120,12 @@ sealed class Route( ) object Room : Route( - route = "Room/{id}", + route = "Room/{id}?message={message}", icon = R.drawable.ic_moments, - arguments = listOf(navArgument("id") { type = NavType.StringType }).toImmutableList() + arguments = listOf( + navArgument("id") { type = NavType.StringType }, + navArgument("message") { type = NavType.StringType; nullable = true; defaultValue = null } + ).toImmutableList() ) object RoomByAuthor : Route( diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChannelCardCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChannelCardCompose.kt index 5df050bf0..9c45a6a04 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChannelCardCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChannelCardCompose.kt @@ -625,7 +625,7 @@ fun RenderCommunitiesThumb(baseNote: Note, accountViewModel: AccountViewModel, n Spacer(modifier = StdHorzSpacer) LikeReaction(baseNote = baseNote, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel, nav) Spacer(modifier = StdHorzSpacer) - ZapReaction(baseNote = baseNote, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel) + ZapReaction(baseNote = baseNote, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel, nav = nav) } description?.let { @@ -739,7 +739,7 @@ fun RenderChannelThumb(baseNote: Note, channel: Channel, accountViewModel: Accou Spacer(modifier = StdHorzSpacer) LikeReaction(baseNote = baseNote, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel, nav) Spacer(modifier = StdHorzSpacer) - ZapReaction(baseNote = baseNote, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel) + ZapReaction(baseNote = baseNote, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel, nav = nav) } description?.let { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt index ab7081152..dceec11dd 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt @@ -566,7 +566,7 @@ private fun StatusRow( Row(verticalAlignment = Alignment.CenterVertically, modifier = ReactionRowHeightChat) { LikeReaction(baseNote, MaterialTheme.colors.placeholderText, accountViewModel, nav) Spacer(modifier = StdHorzSpacer) - ZapReaction(baseNote, MaterialTheme.colors.placeholderText, accountViewModel) + ZapReaction(baseNote, MaterialTheme.colors.placeholderText, accountViewModel, nav = nav) Spacer(modifier = DoubleHorzSpacer) ReplyReaction( baseNote = baseNote, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index f0efd1b96..56128b091 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -165,6 +165,7 @@ import com.vitorpamplona.quartz.events.BaseTextNoteEvent import com.vitorpamplona.quartz.events.ChannelCreateEvent import com.vitorpamplona.quartz.events.ChannelMessageEvent import com.vitorpamplona.quartz.events.ChannelMetadataEvent +import com.vitorpamplona.quartz.events.ChatroomKey import com.vitorpamplona.quartz.events.ChatroomKeyable import com.vitorpamplona.quartz.events.ClassifiedsEvent import com.vitorpamplona.quartz.events.CommunityDefinitionEvent @@ -782,9 +783,9 @@ private fun ShortCommunityActionOptions( nav: (String) -> Unit ) { Spacer(modifier = StdHorzSpacer) - LikeReaction(baseNote = note, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel, nav) + LikeReaction(baseNote = note, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel, nav = nav) Spacer(modifier = StdHorzSpacer) - ZapReaction(baseNote = note, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel) + ZapReaction(baseNote = note, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel, nav = nav) WatchAddressableNoteFollows(note, accountViewModel) { isFollowing -> if (!isFollowing) { @@ -1236,6 +1237,16 @@ fun routeFor(note: Note, loggedIn: User): String? { return null } +fun routeToMessage(user: User, draftMessage: String?, accountViewModel: AccountViewModel): String { + val withKey = ChatroomKey(persistentSetOf(user.pubkeyHex)) + accountViewModel.account.userProfile().createChatroom(withKey) + return if (draftMessage != null) { + "Room/${withKey.hashCode()}?message=$draftMessage" + } else { + "Room/${withKey.hashCode()}" + } +} + fun routeFor(note: Channel): String { return "Channel/${note.idHex}" } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/PollNote.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/PollNote.kt index c78a3bd83..13253cfb2 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/PollNote.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/PollNote.kt @@ -130,8 +130,7 @@ private fun OptionNote( ZapVote( baseNote, poolOption, - accountViewModel, - pollViewModel, + pollViewModel = pollViewModel, nonClickablePrepend = { RenderOptionAfterVote( poolOption.descriptor, @@ -145,18 +144,21 @@ private fun OptionNote( ) }, clickablePrepend = { - } + }, + accountViewModel = accountViewModel, + nav = nav ) } else { ZapVote( baseNote, poolOption, - accountViewModel, - pollViewModel, + pollViewModel = pollViewModel, nonClickablePrepend = {}, clickablePrepend = { RenderOptionBeforeVote(poolOption.descriptor, canPreview, tags, backgroundColor, accountViewModel, nav) - } + }, + accountViewModel = accountViewModel, + nav = nav ) } } @@ -267,11 +269,12 @@ private fun RenderOptionBeforeVote( fun ZapVote( baseNote: Note, poolOption: PollOption, - accountViewModel: AccountViewModel, - pollViewModel: PollNoteViewModel, modifier: Modifier = Modifier, + pollViewModel: PollNoteViewModel, nonClickablePrepend: @Composable () -> Unit, - clickablePrepend: @Composable () -> Unit + clickablePrepend: @Composable () -> Unit, + accountViewModel: AccountViewModel, + nav: (String) -> Unit ) { val isLoggedUser by remember { derivedStateOf { @@ -281,6 +284,7 @@ fun ZapVote( var wantsToZap by remember { mutableStateOf(false) } var zappingProgress by remember { mutableStateOf(0f) } + var showErrorMessageDialog by remember { mutableStateOf(null) } val context = LocalContext.current val scope = rememberCoroutineScope() @@ -382,7 +386,7 @@ fun ZapVote( onError = { scope.launch { zappingProgress = 0f - Toast.makeText(context, it, Toast.LENGTH_SHORT).show() + showErrorMessageDialog = it } }, onProgress = { @@ -393,6 +397,19 @@ fun ZapVote( ) } + if (showErrorMessageDialog != null) { + ErrorMessageDialog( + title = stringResource(id = R.string.error_dialog_zap_error), + textContent = showErrorMessageDialog ?: "", + onClickStartMessage = { + baseNote.author?.let { + nav(routeToMessage(it, showErrorMessageDialog, accountViewModel)) + } + }, + onDismiss = { showErrorMessageDialog = null } + ) + } + clickablePrepend() if (poolOption.zappedByLoggedIn) { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index ff7d3bc46..a7fbccffc 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -211,7 +211,7 @@ private fun InnerReactionRow( ) { val (value, elapsed) = measureTimedValue { Row(verticalAlignment = CenterVertically) { - ZapReaction(baseNote, MaterialTheme.colors.placeholderText, accountViewModel) + ZapReaction(baseNote, MaterialTheme.colors.placeholderText, accountViewModel, nav = nav) } } Log.d("Rendering Metrics", "Reaction Zaps: ${baseNote.event?.content()?.split("\n")?.getOrNull(0)?.take(15)}.. $elapsed") @@ -909,11 +909,13 @@ fun ZapReaction( grayTint: Color, accountViewModel: AccountViewModel, iconSize: Dp = 20.dp, - animationSize: Dp = 14.dp + animationSize: Dp = 14.dp, + nav: (String) -> Unit ) { var wantsToZap by remember { mutableStateOf(false) } var wantsToChangeZapAmount by remember { mutableStateOf(false) } var wantsToSetCustomZap by remember { mutableStateOf(false) } + var showErrorMessageDialog by remember { mutableStateOf(null) } val context = LocalContext.current val scope = rememberCoroutineScope() @@ -965,7 +967,7 @@ fun ZapReaction( onError = { scope.launch { zappingProgress = 0f - Toast.makeText(context, it, Toast.LENGTH_SHORT).show() + showErrorMessageDialog = it } }, onProgress = { @@ -976,6 +978,19 @@ fun ZapReaction( ) } + if (showErrorMessageDialog != null) { + ErrorMessageDialog( + title = stringResource(id = R.string.error_dialog_zap_error), + textContent = showErrorMessageDialog ?: "", + onClickStartMessage = { + baseNote.author?.let { + nav(routeToMessage(it, showErrorMessageDialog, accountViewModel)) + } + }, + onDismiss = { showErrorMessageDialog = null } + ) + } + if (wantsToChangeZapAmount) { UpdateZapAmountDialog({ wantsToChangeZapAmount = false }, accountViewModel = accountViewModel) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt index 80cbd63da..591553867 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ZapCustomDialog.kt @@ -4,11 +4,14 @@ import android.widget.Toast import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Done import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardType @@ -111,8 +114,7 @@ fun ZapCustomDialog(onClose: () -> Unit, accountViewModel: AccountViewModel, bas onError = { zappingProgress = 0f scope.launch { - Toast - .makeText(context, it, Toast.LENGTH_SHORT).show() + Toast.makeText(context, it, Toast.LENGTH_SHORT).show() } }, onProgress = { @@ -225,3 +227,51 @@ fun ZapButton(isActive: Boolean, onPost: () -> Unit) { Text(text = "⚡Zap ", color = Color.White) } } + +@Composable +fun ErrorMessageDialog( + title: String, + textContent: String, + buttonColors: ButtonColors = ButtonDefaults.buttonColors(), + onClickStartMessage: () -> Unit, + onDismiss: () -> Unit +) { + AlertDialog( + onDismissRequest = onDismiss, + title = { + Text(title) + }, + text = { + Text(textContent) + }, + buttons = { + Row( + modifier = Modifier + .padding(all = 8.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + TextButton(onClick = onClickStartMessage) { + Icon( + painter = painterResource(R.drawable.ic_dm), + contentDescription = null + ) + Spacer(Modifier.width(8.dp)) + Text(stringResource(R.string.error_dialog_talk_to_user)) + } + Button(onClick = onDismiss, colors = buttonColors) { + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = Icons.Outlined.Done, + contentDescription = null + ) + Spacer(Modifier.width(8.dp)) + Text(stringResource(R.string.error_dialog_button_ok)) + } + } + } + } + ) +} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt index 724c1d574..46fe8e705 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt @@ -893,7 +893,7 @@ private fun ShortChannelActionOptions( Spacer(modifier = StdHorzSpacer) LikeReaction(baseNote = it, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel, nav) Spacer(modifier = StdHorzSpacer) - ZapReaction(baseNote = it, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel) + ZapReaction(baseNote = it, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel, nav = nav) Spacer(modifier = StdHorzSpacer) } } @@ -968,7 +968,7 @@ private fun LiveChannelActionOptions( LikeReaction(baseNote = it, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel, nav) Spacer(modifier = StdHorzSpacer) - ZapReaction(baseNote = it, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel) + ZapReaction(baseNote = it, grayTint = MaterialTheme.colors.onSurface, accountViewModel = accountViewModel, nav = nav) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt index eed164283..6b51062c5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt @@ -101,6 +101,7 @@ import kotlinx.coroutines.withContext @Composable fun ChatroomScreen( roomId: String?, + draftMessage: String? = null, accountViewModel: AccountViewModel, nav: (String) -> Unit ) { @@ -110,6 +111,7 @@ fun ChatroomScreen( it?.let { PrepareChatroomViewModels( room = it, + draftMessage = draftMessage, accountViewModel = accountViewModel, nav = nav ) @@ -120,6 +122,7 @@ fun ChatroomScreen( @Composable fun ChatroomScreenByAuthor( authorPubKeyHex: String?, + draftMessage: String? = null, accountViewModel: AccountViewModel, nav: (String) -> Unit ) { @@ -129,6 +132,7 @@ fun ChatroomScreenByAuthor( it?.let { PrepareChatroomViewModels( room = it, + draftMessage = draftMessage, accountViewModel = accountViewModel, nav = nav ) @@ -166,7 +170,12 @@ fun LoadRoomByAuthor(authorPubKeyHex: String, accountViewModel: AccountViewModel } @Composable -fun PrepareChatroomViewModels(room: ChatroomKey, accountViewModel: AccountViewModel, nav: (String) -> Unit) { +fun PrepareChatroomViewModels( + room: ChatroomKey, + draftMessage: String?, + accountViewModel: AccountViewModel, + nav: (String) -> Unit +) { val feedViewModel: NostrChatroomFeedViewModel = viewModel( key = room.hashCode().toString() + "ChatroomViewModels", factory = NostrChatroomFeedViewModel.Factory( @@ -193,6 +202,12 @@ fun PrepareChatroomViewModels(room: ChatroomKey, accountViewModel: AccountViewMo } } + if (draftMessage != null) { + LaunchedEffect(key1 = draftMessage) { + newPostModel.message = TextFieldValue(draftMessage) + } + } + ChatroomScreen( room = room, feedViewModel = feedViewModel, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt index 1ce0efd78..e42350ae1 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/VideoScreen.kt @@ -467,7 +467,7 @@ fun ReactionsColumn(baseNote: Note, accountViewModel: AccountViewModel, nav: (St wantsToQuote = baseNote } LikeReaction(baseNote, grayTint = MaterialTheme.colors.onBackground, accountViewModel, nav, iconSize = 40.dp, heartSize = Size35dp, 28.sp) - ZapReaction(baseNote, grayTint = MaterialTheme.colors.onBackground, accountViewModel, iconSize = 40.dp, animationSize = Size35dp) + ZapReaction(baseNote, grayTint = MaterialTheme.colors.onBackground, accountViewModel, iconSize = 40.dp, animationSize = Size35dp, nav = nav) ViewCountReaction(baseNote, grayTint = MaterialTheme.colors.onBackground, barChartSize = 39.dp, viewCountColorFilter = MaterialTheme.colors.onBackgroundColorFilter) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e1ecc33a2..567000a05 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -554,4 +554,8 @@ Error parsing error message Votes are weighted by the zap amount. You can set a minimum amount to avoid spammers and a maximum amount to avoid a large zappers taking over the poll. Use the same amount in both fields to make sure every vote is valued the same amount. Leave it empty to accept any amount. + + Unable to send zap + Message the User + Ok