If the Share target intent opens with the new post screen already active, just updates the post instead of creating a new one.

This commit is contained in:
Vitor Pamplona
2024-10-17 13:59:52 -04:00
parent 44d8b8ff33
commit c0ba6f5b00
4 changed files with 58 additions and 9 deletions
@@ -981,6 +981,10 @@ open class NewPostViewModel : ViewModel() {
draftTextChanges.trySend("") draftTextChanges.trySend("")
} }
open fun addToMessage(it: String) {
updateMessage(TextFieldValue(message.text + " " + it))
}
open fun updateMessage(it: TextFieldValue) { open fun updateMessage(it: TextFieldValue) {
message = it message = it
urlPreview = findUrlInMessage() urlPreview = findUrlInMessage()
@@ -293,7 +293,7 @@ fun AppNavigation(
popEnterTransition = { scaleIn }, popEnterTransition = { scaleIn },
popExitTransition = { slideOutVerticallyToBottom }, popExitTransition = { slideOutVerticallyToBottom },
) { ) {
val draftMessage = it.message() val draftMessage = it.arguments?.getString("message")?.ifBlank { null }
val attachment = val attachment =
it.arguments?.getString("attachment")?.ifBlank { null }?.let { it.arguments?.getString("attachment")?.ifBlank { null }?.let {
Uri.parse(it) Uri.parse(it)
@@ -304,6 +304,7 @@ fun AppNavigation(
val version = it.arguments?.getString("version") val version = it.arguments?.getString("version")
val draft = it.arguments?.getString("draft") val draft = it.arguments?.getString("draft")
val enableMessageInterface = it.arguments?.getBoolean("enableMessageInterface") ?: false val enableMessageInterface = it.arguments?.getBoolean("enableMessageInterface") ?: false
NewPostScreen( NewPostScreen(
message = draftMessage, message = draftMessage,
attachment = attachment, attachment = attachment,
@@ -333,9 +334,12 @@ private fun NavigateIfIntentRequested(
accountStateViewModel: AccountStateViewModel, accountStateViewModel: AccountStateViewModel,
) { ) {
val activity = LocalContext.current.getActivity() val activity = LocalContext.current.getActivity()
var newAccount by remember { mutableStateOf<String?>(null) }
if (activity.intent.action == Intent.ACTION_SEND) { if (activity.intent.action == Intent.ACTION_SEND) {
// avoids restarting the new Post screen when the intent is for the screen.
// Microsoft's swift key sends Gifs as new actions
if (isBaseRoute(nav.controller, Route.NewPost.base)) return
// saves the intent to avoid processing again // saves the intent to avoid processing again
var message by remember { var message by remember {
mutableStateOf( mutableStateOf(
@@ -356,6 +360,8 @@ private fun NavigateIfIntentRequested(
media = null media = null
message = null message = null
} else { } else {
var newAccount by remember { mutableStateOf<String?>(null) }
var currentIntentNextPage by remember { var currentIntentNextPage by remember {
mutableStateOf( mutableStateOf(
activity.intent activity.intent
@@ -404,12 +410,16 @@ private fun NavigateIfIntentRequested(
val consumer = val consumer =
Consumer<Intent> { intent -> Consumer<Intent> { intent ->
if (intent.action == Intent.ACTION_SEND) { if (intent.action == Intent.ACTION_SEND) {
intent.getStringExtra(Intent.EXTRA_TEXT)?.let { // avoids restarting the new Post screen when the intent is for the screen.
nav.newStack(buildNewPostRoute(draftMessage = it)) // 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<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let { (intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let {
nav.newStack(buildNewPostRoute(attachment = it)) nav.newStack(buildNewPostRoute(attachment = it))
}
} }
} else { } else {
val uri = intent.data?.toString() val uri = intent.data?.toString()
@@ -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? { fun getRouteWithArguments(navController: NavHostController): String? {
val currentEntry = navController.currentBackStackEntry ?: return null val currentEntry = navController.currentBackStackEntry ?: return null
return getRouteWithArguments(currentEntry.destination, currentEntry.arguments) return getRouteWithArguments(currentEntry.destination, currentEntry.arguments)
@@ -21,9 +21,11 @@
package com.vitorpamplona.amethyst.ui.screen.loggedIn package com.vitorpamplona.amethyst.ui.screen.loggedIn
import android.Manifest import android.Manifest
import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Parcelable
import android.util.Log import android.util.Log
import android.util.Size import android.util.Size
import android.widget.Toast 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.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.core.util.Consumer
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.AsyncImage 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.LoadUrlPreview
import com.vitorpamplona.amethyst.ui.components.VideoView import com.vitorpamplona.amethyst.ui.components.VideoView
import com.vitorpamplona.amethyst.ui.components.ZapRaiserRequest 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.BaseUserPicture
import com.vitorpamplona.amethyst.ui.note.CancelIcon import com.vitorpamplona.amethyst.ui.note.CancelIcon
import com.vitorpamplona.amethyst.ui.note.CloseIcon import com.vitorpamplona.amethyst.ui.note.CloseIcon
@@ -203,12 +207,13 @@ fun NewPostScreen(
draft: Note? = null, draft: Note? = null,
enableMessageInterface: Boolean = false, enableMessageInterface: Boolean = false,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: INav, nav: Nav,
) { ) {
val postViewModel: NewPostViewModel = viewModel() val postViewModel: NewPostViewModel = viewModel()
postViewModel.wantsDirectMessage = enableMessageInterface postViewModel.wantsDirectMessage = enableMessageInterface
val context = LocalContext.current val context = LocalContext.current
val activity = context.getActivity()
val scrollState = rememberScrollState() val scrollState = rememberScrollState()
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
@@ -250,6 +255,27 @@ fun NewPostScreen(
NostrSearchEventOrUserDataSource.stop() NostrSearchEventOrUserDataSource.stop()
} }
} }
DisposableEffect(nav, activity) {
// Microsoft's swift key sends Gifs as new actions
val consumer =
Consumer<Intent> { intent ->
if (intent.action == Intent.ACTION_SEND) {
intent.getStringExtra(Intent.EXTRA_TEXT)?.ifBlank { null }?.let {
postViewModel.addToMessage(it)
}
(intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let {
postViewModel.selectImage(it)
}
}
}
activity.addOnNewIntentListener(consumer)
onDispose { activity.removeOnNewIntentListener(consumer) }
}
Scaffold( Scaffold(
topBar = { topBar = {
TopAppBar( TopAppBar(