From c0ba6f5b0071b59f06f63d0264ec9c4aaf2fcc79 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Thu, 17 Oct 2024 13:59:52 -0400 Subject: [PATCH] If the Share target intent opens with the new post screen already active, just updates the post instead of creating a new one. --- .../amethyst/ui/actions/NewPostViewModel.kt | 4 +++ .../amethyst/ui/navigation/AppNavigation.kt | 24 ++++++++++----- .../amethyst/ui/navigation/Routes.kt | 9 ++++++ .../ui/screen/loggedIn/NewPostScreen.kt | 30 +++++++++++++++++-- 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt index 51c20e8ae..997c3140d 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewPostViewModel.kt @@ -981,6 +981,10 @@ open class NewPostViewModel : ViewModel() { draftTextChanges.trySend("") } + open fun addToMessage(it: String) { + updateMessage(TextFieldValue(message.text + " " + it)) + } + open fun updateMessage(it: TextFieldValue) { message = it urlPreview = findUrlInMessage() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt index 50dd3e058..7d27bfc5f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt @@ -293,7 +293,7 @@ fun AppNavigation( popEnterTransition = { scaleIn }, popExitTransition = { slideOutVerticallyToBottom }, ) { - val draftMessage = it.message() + val draftMessage = it.arguments?.getString("message")?.ifBlank { null } val attachment = it.arguments?.getString("attachment")?.ifBlank { null }?.let { Uri.parse(it) @@ -304,6 +304,7 @@ fun AppNavigation( val version = it.arguments?.getString("version") val draft = it.arguments?.getString("draft") val enableMessageInterface = it.arguments?.getBoolean("enableMessageInterface") ?: false + NewPostScreen( message = draftMessage, attachment = attachment, @@ -333,9 +334,12 @@ private fun NavigateIfIntentRequested( accountStateViewModel: AccountStateViewModel, ) { val activity = LocalContext.current.getActivity() - var newAccount by remember { mutableStateOf(null) } if (activity.intent.action == Intent.ACTION_SEND) { + // avoids restarting the new Post screen when the intent is for the screen. + // Microsoft's swift key sends Gifs as new actions + if (isBaseRoute(nav.controller, Route.NewPost.base)) return + // saves the intent to avoid processing again var message by remember { mutableStateOf( @@ -356,6 +360,8 @@ private fun NavigateIfIntentRequested( media = null message = null } else { + var newAccount by remember { mutableStateOf(null) } + var currentIntentNextPage by remember { mutableStateOf( activity.intent @@ -404,12 +410,16 @@ private fun NavigateIfIntentRequested( val consumer = Consumer { intent -> if (intent.action == Intent.ACTION_SEND) { - intent.getStringExtra(Intent.EXTRA_TEXT)?.let { - nav.newStack(buildNewPostRoute(draftMessage = it)) - } + // avoids restarting the new Post screen when the intent is for the screen. + // Microsoft's swift key sends Gifs as new actions + if (!isBaseRoute(nav.controller, Route.NewPost.base)) { + intent.getStringExtra(Intent.EXTRA_TEXT)?.let { + nav.newStack(buildNewPostRoute(draftMessage = it)) + } - (intent.getParcelableExtra(Intent.EXTRA_STREAM) as? Uri)?.let { - nav.newStack(buildNewPostRoute(attachment = it)) + (intent.getParcelableExtra(Intent.EXTRA_STREAM) as? Uri)?.let { + nav.newStack(buildNewPostRoute(attachment = it)) + } } } else { val uri = intent.data?.toString() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt index c19d788ff..1a460faa0 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/navigation/Routes.kt @@ -241,6 +241,15 @@ sealed class Route( ) } +fun isBaseRoute( + navController: NavHostController, + startsWith: String, +): Boolean = + navController.currentBackStackEntry + ?.destination + ?.route + ?.startsWith(startsWith) ?: false + fun getRouteWithArguments(navController: NavHostController): String? { val currentEntry = navController.currentBackStackEntry ?: return null return getRouteWithArguments(currentEntry.destination, currentEntry.arguments) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NewPostScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NewPostScreen.kt index 9554e2e25..7dff3251e 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NewPostScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NewPostScreen.kt @@ -21,9 +21,11 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn import android.Manifest +import android.content.Intent import android.graphics.Bitmap import android.net.Uri import android.os.Build +import android.os.Parcelable import android.util.Log import android.util.Size import android.widget.Toast @@ -119,6 +121,7 @@ import androidx.compose.ui.text.style.TextDirection import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.core.util.Consumer import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import coil.compose.AsyncImage @@ -146,7 +149,8 @@ import com.vitorpamplona.amethyst.ui.components.InvoiceRequest import com.vitorpamplona.amethyst.ui.components.LoadUrlPreview import com.vitorpamplona.amethyst.ui.components.VideoView import com.vitorpamplona.amethyst.ui.components.ZapRaiserRequest -import com.vitorpamplona.amethyst.ui.navigation.INav +import com.vitorpamplona.amethyst.ui.navigation.Nav +import com.vitorpamplona.amethyst.ui.navigation.getActivity import com.vitorpamplona.amethyst.ui.note.BaseUserPicture import com.vitorpamplona.amethyst.ui.note.CancelIcon import com.vitorpamplona.amethyst.ui.note.CloseIcon @@ -203,12 +207,13 @@ fun NewPostScreen( draft: Note? = null, enableMessageInterface: Boolean = false, accountViewModel: AccountViewModel, - nav: INav, + nav: Nav, ) { val postViewModel: NewPostViewModel = viewModel() postViewModel.wantsDirectMessage = enableMessageInterface val context = LocalContext.current + val activity = context.getActivity() val scrollState = rememberScrollState() val scope = rememberCoroutineScope() @@ -250,6 +255,27 @@ fun NewPostScreen( NostrSearchEventOrUserDataSource.stop() } } + + DisposableEffect(nav, activity) { + // Microsoft's swift key sends Gifs as new actions + + val consumer = + Consumer { intent -> + if (intent.action == Intent.ACTION_SEND) { + intent.getStringExtra(Intent.EXTRA_TEXT)?.ifBlank { null }?.let { + postViewModel.addToMessage(it) + } + + (intent.getParcelableExtra(Intent.EXTRA_STREAM) as? Uri)?.let { + postViewModel.selectImage(it) + } + } + } + + activity.addOnNewIntentListener(consumer) + onDispose { activity.removeOnNewIntentListener(consumer) } + } + Scaffold( topBar = { TopAppBar(