diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt index 992072871..8e5c609b3 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/Account.kt @@ -405,17 +405,13 @@ class Account( val emojiUrl = EmojiUrl.decode(reaction) if (emojiUrl != null) { note.event?.let { - var event = ReactionEvent.create(emojiUrl, it, keyPair) + val event = ReactionEvent.create(emojiUrl, it, keyPair) if (loginWithAmber) { - AmberUtils.openAmber(event) - if (AmberUtils.content.isBlank()) { - return - } - event = ReactionEvent.create(event, AmberUtils.content) + AmberUtils.signEvent(event) + } else { + Client.send(event) + LocalCache.consume(event) } - - Client.send(event) - LocalCache.consume(event) } return @@ -423,16 +419,13 @@ class Account( } note.event?.let { - var event = ReactionEvent.create(reaction, it, keyPair) + val event = ReactionEvent.create(reaction, it, keyPair) if (loginWithAmber) { - AmberUtils.openAmber(event) - if (AmberUtils.content.isBlank()) { - return - } - event = ReactionEvent.create(event, AmberUtils.content) + AmberUtils.signEvent(event) + } else { + Client.send(event) + LocalCache.consume(event) } - Client.send(event) - LocalCache.consume(event) } } } @@ -453,7 +446,7 @@ class Account( ) } LnZapEvent.ZapType.PUBLIC -> { - val unsignedEvent = LnZapRequestEvent.createPublic( + return LnZapRequestEvent.createPublic( event, userProfile().latestContactList?.relays()?.keys?.ifEmpty { null } ?: localRelays.map { it.url }.toSet(), @@ -461,21 +454,10 @@ class Account( pollOption, message ) - AmberUtils.content = "" - AmberUtils.openAmber(unsignedEvent) - if (AmberUtils.content.isBlank()) return null - return LnZapRequestEvent( - unsignedEvent.id, - unsignedEvent.pubKey, - unsignedEvent.createdAt, - unsignedEvent.tags, - unsignedEvent.content, - AmberUtils.content - ) } LnZapEvent.ZapType.PRIVATE -> { - val unsignedEvent = LnZapRequestEvent.createPrivateZap( + return LnZapRequestEvent.createPrivateZap( event, userProfile().latestContactList?.relays()?.keys?.ifEmpty { null } ?: localRelays.map { it.url }.toSet(), @@ -483,10 +465,6 @@ class Account( pollOption, message ) - AmberUtils.content = "" - AmberUtils.openAmber(unsignedEvent) - if (AmberUtils.content.isBlank()) return null - return Event.fromJson(AmberUtils.content) as LnZapRequestEvent } else -> null } @@ -674,16 +652,13 @@ class Account( val myNotes = notes.filter { it.author == userProfile() }.map { it.idHex } if (myNotes.isNotEmpty()) { - var event = DeletionEvent.create(myNotes, keyPair) + val event = DeletionEvent.create(myNotes, keyPair) if (loginWithAmber) { - AmberUtils.openAmber(event) - if (AmberUtils.content.isBlank()) { - return - } - event = DeletionEvent.create(event, AmberUtils.content) + AmberUtils.signEvent(event) + } else { + Client.send(event) + LocalCache.consume(event) } - Client.send(event) - LocalCache.consume(event) } } @@ -711,27 +686,21 @@ class Account( note.event?.let { if (it.kind() == 1) { - var event = RepostEvent.create(it, keyPair) + val event = RepostEvent.create(it, keyPair) if (loginWithAmber) { - AmberUtils.openAmber(event) - if (AmberUtils.content.isBlank()) { - return - } - event = RepostEvent.create(event, AmberUtils.content) + AmberUtils.signEvent(event) + } else { + Client.send(event) + LocalCache.consume(event) } - Client.send(event) - LocalCache.consume(event) } else { - var event = GenericRepostEvent.create(it, keyPair) + val event = GenericRepostEvent.create(it, keyPair) if (loginWithAmber) { - AmberUtils.openAmber(event) - if (AmberUtils.content.isBlank()) { - return - } - event = GenericRepostEvent.create(event, AmberUtils.content) + AmberUtils.signEvent(event) + } else { + Client.send(event) + LocalCache.consume(event) } - Client.send(event) - LocalCache.consume(event) } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/AmberUtils.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/AmberUtils.kt index 175919044..c8ea573a7 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/AmberUtils.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/AmberUtils.kt @@ -7,6 +7,7 @@ import com.vitorpamplona.amethyst.ServiceManager import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.ui.actions.SignerType import com.vitorpamplona.quartz.encoders.HexKey +import com.vitorpamplona.quartz.encoders.toHexKey import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.EventInterface import com.vitorpamplona.quartz.events.LnZapRequestEvent @@ -54,18 +55,20 @@ object AmberUtils { event.id() ) while (isActivityRunning) { - Thread.sleep(100) + // do nothing } } - fun loginWithAmber() { + fun signEvent(event: EventInterface) { checkNotInMainThread() + ServiceManager.shouldPauseService = false + isActivityRunning = true openAmber( - "", - SignerType.GET_PUBLIC_KEY, - IntentUtils.activityResultLauncher, - "", - "" + event.toJson(), + SignerType.SIGN_EVENT, + IntentUtils.signEventResultLauncher, + account.keyPair.pubKey.toHexKey(), + event.id() ) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/IntentUtils.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/IntentUtils.kt index 5962943b2..2047e4ed1 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/IntentUtils.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/IntentUtils.kt @@ -9,6 +9,7 @@ import androidx.activity.result.contract.ActivityResultContracts import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.ServiceManager import com.vitorpamplona.amethyst.model.LocalCache +import com.vitorpamplona.amethyst.service.relays.Client import com.vitorpamplona.amethyst.ui.MainActivity import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.GiftWrapEvent @@ -22,6 +23,7 @@ object IntentUtils { lateinit var activityResultLauncher: ActivityResultLauncher lateinit var decryptGossipResultLauncher: ActivityResultLauncher lateinit var blockListResultLauncher: ActivityResultLauncher + lateinit var signEventResultLauncher: ActivityResultLauncher val eventCache = LruCache(100) @OptIn(DelicateCoroutinesApi::class) @@ -63,6 +65,31 @@ object IntentUtils { @OptIn(DelicateCoroutinesApi::class) fun start(activity: MainActivity) { + signEventResultLauncher = activity.registerForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) { + if (it.resultCode != Activity.RESULT_OK) { + GlobalScope.launch(Dispatchers.Main) { + Toast.makeText( + Amethyst.instance, + "Sign request rejected", + Toast.LENGTH_SHORT + ).show() + } + } else { + val json = it.data?.getStringExtra("event") ?: "" + GlobalScope.launch(Dispatchers.IO) { + val signedEvent = Event.fromJson(json) + if (signedEvent.hasValidSignature()) { + Client.send(signedEvent) + LocalCache.verifyAndConsume(signedEvent, null) + } + } + } + AmberUtils.isActivityRunning = false + ServiceManager.shouldPauseService = true + } + activityResultLauncher = activity.registerForActivityResult( ActivityResultContracts.StartActivityForResult() ) { 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 13253cfb2..6abbddadc 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 @@ -1,6 +1,9 @@ package com.vitorpamplona.amethyst.ui.note +import android.app.Activity import android.widget.Toast +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.material.* @@ -22,8 +25,12 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import androidx.lifecycle.viewmodel.compose.viewModel +import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.ServiceManager import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.service.AmberUtils +import com.vitorpamplona.amethyst.ui.actions.SignerType import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange @@ -32,8 +39,10 @@ import com.vitorpamplona.amethyst.ui.theme.Font14SP import com.vitorpamplona.amethyst.ui.theme.QuoteBorder import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink import com.vitorpamplona.amethyst.ui.theme.placeholderText +import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.ImmutableListOfLists import com.vitorpamplona.quartz.events.LnZapEvent +import com.vitorpamplona.quartz.events.LnZapRequestEvent import com.vitorpamplona.quartz.events.toImmutableListOfLists import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -291,6 +300,60 @@ fun ZapVote( nonClickablePrepend() + val event = remember { mutableStateOf(null) } + val activityResult = rememberLauncherForActivityResult( + contract = ActivityResultContracts.StartActivityForResult(), + onResult = { + if (it.resultCode != Activity.RESULT_OK) { + scope.launch(Dispatchers.Main) { + Toast.makeText( + Amethyst.instance, + "Sign request rejected", + Toast.LENGTH_SHORT + ).show() + } + } else { + val json = it.data?.getStringExtra("event") ?: "" + val signedEvent = Event.fromJson(json) as LnZapRequestEvent + if (signedEvent.hasValidSignature()) { + accountViewModel.zap( + baseNote, + accountViewModel.account.zapAmountChoices.first() * 1000, + null, + "", + context, + { + scope.launch { + zappingProgress = 0f + showErrorMessageDialog = it + } + }, + { progress: Float -> + zappingProgress = progress + }, + accountViewModel.account.defaultZapType, + null + ) + } + } + AmberUtils.isActivityRunning = false + ServiceManager.shouldPauseService = true + event.value = null + } + ) + + LaunchedEffect(event.value) { + if (event.value != null) { + AmberUtils.openAmber( + event.value!!.toJson(), + SignerType.SIGN_EVENT, + activityResult, + "", + event.value!!.id() + ) + } + } + Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.combinedClickable( @@ -362,7 +425,8 @@ fun ZapVote( zappingProgress = it } }, - zapType = accountViewModel.account.defaultZapType + zapType = accountViewModel.account.defaultZapType, + null ) } else { wantsToZap = true @@ -502,7 +566,8 @@ fun FilteredZapAmountChoicePopup( context, onError, onProgress, - defaultZapType + defaultZapType, + null ) onDismiss() }, @@ -526,7 +591,8 @@ fun FilteredZapAmountChoicePopup( context, onError, onProgress, - defaultZapType + defaultZapType, + null ) onDismiss() }, 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 b7b0ebc02..70e2fd643 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 @@ -1,8 +1,11 @@ package com.vitorpamplona.amethyst.ui.note +import android.app.Activity import android.content.Context import android.util.Log import android.widget.Toast +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContentTransitionScope import androidx.compose.animation.ContentTransform @@ -46,6 +49,7 @@ import androidx.compose.runtime.MutableState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableLongStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -76,9 +80,13 @@ import androidx.lifecycle.map import coil.compose.AsyncImage import coil.request.CachePolicy import coil.request.ImageRequest +import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.ServiceManager import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.service.AmberUtils import com.vitorpamplona.amethyst.ui.actions.NewPostView +import com.vitorpamplona.amethyst.ui.actions.SignerType import com.vitorpamplona.amethyst.ui.components.ImageUrlType import com.vitorpamplona.amethyst.ui.components.InLineIconRenderer import com.vitorpamplona.amethyst.ui.components.TextType @@ -107,6 +115,9 @@ import com.vitorpamplona.amethyst.ui.theme.TinyBorders import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.amethyst.ui.theme.placeholderTextColorFilter +import com.vitorpamplona.quartz.events.Event +import com.vitorpamplona.quartz.events.LnZapEvent +import com.vitorpamplona.quartz.events.LnZapRequestEvent import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableMap import kotlinx.coroutines.CoroutineScope @@ -951,6 +962,63 @@ fun ZapReaction( var zappingProgress by remember { mutableStateOf(0f) } + val event = remember { mutableStateOf(null) } + val activityResult = rememberLauncherForActivityResult( + contract = ActivityResultContracts.StartActivityForResult(), + onResult = { + if (it.resultCode != Activity.RESULT_OK) { + wantsToZap = false + zappingProgress = 0f + scope.launch(Dispatchers.Main) { + Toast.makeText( + Amethyst.instance, + "Sign request rejected", + Toast.LENGTH_SHORT + ).show() + } + } else { + val json = it.data?.getStringExtra("event") ?: "" + val signedEvent = Event.fromJson(json) as LnZapRequestEvent + if (signedEvent.hasValidSignature()) { + accountViewModel.zap( + baseNote, + accountViewModel.account.zapAmountChoices.first() * 1000, + null, + "", + context, + { + scope.launch { + zappingProgress = 0f + showErrorMessageDialog = it + } + }, + { progress: Float -> + zappingProgress = progress + }, + accountViewModel.account.defaultZapType, + signedEvent + ) + } + } + AmberUtils.isActivityRunning = false + ServiceManager.shouldPauseService = true + event.value = null + wantsToZap = false + } + ) + + LaunchedEffect(event.value) { + if (event.value != null) { + AmberUtils.openAmber( + event.value!!.toJson(), + SignerType.SIGN_EVENT, + activityResult, + "", + event.value!!.id() + ) + } + } + Row( verticalAlignment = CenterVertically, modifier = Modifier @@ -976,7 +1044,8 @@ fun ZapReaction( zappingProgress = 0f showErrorMessageDialog = it } - } + }, + event ) }, onLongClick = { @@ -1083,7 +1152,8 @@ private fun zapClick( context: Context, onZappingProgress: (Float) -> Unit, onMultipleChoices: () -> Unit, - onError: (String) -> Unit + onError: (String) -> Unit, + event: MutableState ) { if (accountViewModel.account.zapAmountChoices.isEmpty()) { scope.launch { @@ -1098,20 +1168,30 @@ private fun zapClick( } else if (!accountViewModel.isWriteable()) { if (accountViewModel.loggedInWithAmber()) { if (accountViewModel.account.zapAmountChoices.size == 1) { - accountViewModel.zap( - baseNote, - accountViewModel.account.zapAmountChoices.first() * 1000, - null, - "", - context, - onError = onError, - onProgress = { - scope.launch(Dispatchers.Main) { - onZappingProgress(it) - } - }, - zapType = accountViewModel.account.defaultZapType - ) + if (accountViewModel.account.defaultZapType != LnZapEvent.ZapType.ANONYMOUS && accountViewModel.account.defaultZapType != LnZapEvent.ZapType.NONZAP) { + event.value = accountViewModel.account.createZapRequestFor( + baseNote, + null, + "", + accountViewModel.account.defaultZapType + ) + } else { + accountViewModel.zap( + baseNote, + accountViewModel.account.zapAmountChoices.first() * 1000, + null, + "", + context, + onError = onError, + onProgress = { + scope.launch(Dispatchers.Main) { + onZappingProgress(it) + } + }, + zapType = accountViewModel.account.defaultZapType, + null + ) + } } else if (accountViewModel.account.zapAmountChoices.size > 1) { onMultipleChoices() } @@ -1139,7 +1219,8 @@ private fun zapClick( onZappingProgress(it) } }, - zapType = accountViewModel.account.defaultZapType + zapType = accountViewModel.account.defaultZapType, + null ) } else if (accountViewModel.account.zapAmountChoices.size > 1) { onMultipleChoices() @@ -1458,10 +1539,58 @@ fun ZapAmountChoicePopup( onProgress: (percent: Float) -> Unit ) { val context = LocalContext.current - + val scope = rememberCoroutineScope() val accountState by accountViewModel.accountLiveData.observeAsState() val account = accountState?.account ?: return val zapMessage = "" + var event by remember { mutableStateOf(null) } + var amount by remember { mutableLongStateOf(0L) } + val activityResult = rememberLauncherForActivityResult( + contract = ActivityResultContracts.StartActivityForResult(), + onResult = { + if (it.resultCode != Activity.RESULT_OK) { + scope.launch(Dispatchers.Main) { + Toast.makeText( + Amethyst.instance, + "Sign request rejected", + Toast.LENGTH_SHORT + ).show() + } + } else { + val json = it.data?.getStringExtra("event") ?: "" + val signedEvent = Event.fromJson(json) as LnZapRequestEvent + if (signedEvent.hasValidSignature()) { + accountViewModel.zap( + baseNote, + amount, + null, + zapMessage, + context, + onError, + onProgress, + account.defaultZapType, + signedEvent + ) + amount = 0 + } + } + AmberUtils.isActivityRunning = false + ServiceManager.shouldPauseService = true + event = null + } + ) + + LaunchedEffect(event) { + if (event != null) { + AmberUtils.openAmber( + event!!.toJson(), + SignerType.SIGN_EVENT, + activityResult, + "", + event!!.id() + ) + } + } Popup( alignment = Alignment.BottomCenter, @@ -1473,17 +1602,23 @@ fun ZapAmountChoicePopup( Button( modifier = Modifier.padding(horizontal = 3.dp), onClick = { - accountViewModel.zap( - baseNote, - amountInSats * 1000, - null, - zapMessage, - context, - onError, - onProgress, - account.defaultZapType - ) - onDismiss() + if (accountViewModel.loggedInWithAmber() && account.defaultZapType != LnZapEvent.ZapType.NONZAP && account.defaultZapType != LnZapEvent.ZapType.ANONYMOUS) { + amount = amountInSats * 1000 + event = account.createZapRequestFor(baseNote, null, zapMessage, account.defaultZapType) + } else { + accountViewModel.zap( + baseNote, + amountInSats * 1000, + null, + zapMessage, + context, + onError, + onProgress, + account.defaultZapType, + null + ) + onDismiss() + } }, shape = ButtonBorder, colors = ButtonDefaults @@ -1497,17 +1632,23 @@ fun ZapAmountChoicePopup( textAlign = TextAlign.Center, modifier = Modifier.combinedClickable( onClick = { - accountViewModel.zap( - baseNote, - amountInSats * 1000, - null, - zapMessage, - context, - onError, - onProgress, - account.defaultZapType - ) - onDismiss() + if (accountViewModel.loggedInWithAmber() && account.defaultZapType != LnZapEvent.ZapType.NONZAP && account.defaultZapType != LnZapEvent.ZapType.ANONYMOUS) { + amount = amountInSats * 1000 + event = account.createZapRequestFor(baseNote, null, zapMessage, account.defaultZapType) + } else { + accountViewModel.zap( + baseNote, + amountInSats * 1000, + null, + zapMessage, + context, + onError, + onProgress, + account.defaultZapType, + null + ) + onDismiss() + } }, onLongClick = { onChangeAmount() 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 828182dac..07031b7fc 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 @@ -1,5 +1,9 @@ package com.vitorpamplona.amethyst.ui.note +import android.app.Activity +import android.widget.Toast +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.* @@ -19,17 +23,26 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewmodel.compose.viewModel +import com.vitorpamplona.amethyst.Amethyst import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.ServiceManager import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.service.AmberUtils import com.vitorpamplona.amethyst.ui.actions.CloseButton +import com.vitorpamplona.amethyst.ui.actions.SignerType import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.TextSpinner import com.vitorpamplona.amethyst.ui.theme.ButtonBorder import com.vitorpamplona.amethyst.ui.theme.placeholderText +import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.LnZapEvent +import com.vitorpamplona.quartz.events.LnZapRequestEvent import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch class ZapOptionstViewModel : ViewModel() { private var account: Account? = null @@ -83,6 +96,55 @@ fun ZapCustomDialog( val zapOptionExplainers = remember { zapTypes.map { it.third }.toImmutableList() } var selectedZapType by remember(accountViewModel) { mutableStateOf(accountViewModel.account.defaultZapType) } + val event = remember { mutableStateOf(null) } + val activityResult = rememberLauncherForActivityResult( + contract = ActivityResultContracts.StartActivityForResult(), + onResult = { + if (it.resultCode != Activity.RESULT_OK) { + postViewModel.viewModelScope.launch(Dispatchers.Main) { + Toast.makeText( + Amethyst.instance, + "Sign request rejected", + Toast.LENGTH_SHORT + ).show() + } + event.value = null + } else { + val json = it.data?.getStringExtra("event") ?: "" + val signedEvent = Event.fromJson(json) as LnZapRequestEvent + if (signedEvent.hasValidSignature()) { + accountViewModel.zap( + baseNote, + postViewModel.value()!! * 1000L, + null, + postViewModel.customMessage.text, + context, + onError, + onProgress, + selectedZapType, + signedEvent + ) + event.value = null + onClose() + } + } + AmberUtils.isActivityRunning = false + ServiceManager.shouldPauseService = true + } + ) + + LaunchedEffect(event.value) { + if (event.value != null) { + AmberUtils.openAmber( + event.value!!.toJson(), + SignerType.SIGN_EVENT, + activityResult, + "", + event.value!!.id() + ) + } + } + Dialog( onDismissRequest = { onClose() }, properties = DialogProperties( @@ -105,17 +167,22 @@ fun ZapCustomDialog( ZapButton( isActive = postViewModel.canSend() ) { - accountViewModel.zap( - baseNote, - postViewModel.value()!! * 1000L, - null, - postViewModel.customMessage.text, - context, - onError = onError, - onProgress = onProgress, - zapType = selectedZapType - ) - onClose() + if (accountViewModel.loggedInWithAmber() && selectedZapType != LnZapEvent.ZapType.ANONYMOUS && selectedZapType != LnZapEvent.ZapType.PUBLIC) { + event.value = accountViewModel.account.createZapRequestFor(baseNote, null, postViewModel.customMessage.text, selectedZapType) + } else { + accountViewModel.zap( + baseNote, + postViewModel.value()!! * 1000L, + null, + postViewModel.customMessage.text, + context, + onError = onError, + onProgress = onProgress, + zapType = selectedZapType, + null + ) + onClose() + } } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index def0e15de..59a20221e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -217,13 +217,33 @@ class AccountViewModel(val account: Account) : ViewModel() { return null } - fun zap(note: Note, amount: Long, pollOption: Int?, message: String, context: Context, onError: (String) -> Unit, onProgress: (percent: Float) -> Unit, zapType: LnZapEvent.ZapType) { + fun zap( + note: Note, + amount: Long, + pollOption: Int?, + message: String, + context: Context, + onError: (String) -> Unit, + onProgress: (percent: Float) -> Unit, + zapType: LnZapEvent.ZapType, + zapRequest: LnZapRequestEvent? + ) { viewModelScope.launch(Dispatchers.IO) { - innerZap(note, amount, pollOption, message, context, onError, onProgress, zapType) + innerZap(note, amount, pollOption, message, context, onError, onProgress, zapType, zapRequest) } } - private suspend fun innerZap(note: Note, amount: Long, pollOption: Int?, message: String, context: Context, onError: (String) -> Unit, onProgress: (percent: Float) -> Unit, zapType: LnZapEvent.ZapType) { + private suspend fun innerZap( + note: Note, + amount: Long, + pollOption: Int?, + message: String, + context: Context, + onError: (String) -> Unit, + onProgress: (percent: Float) -> Unit, + zapType: LnZapEvent.ZapType, + zapRequest: LnZapRequestEvent? + ) { val lud16 = note.event?.zapAddress() ?: note.author?.info?.lud16?.trim() ?: note.author?.info?.lud06?.trim() if (lud16.isNullOrBlank()) { @@ -232,11 +252,14 @@ class AccountViewModel(val account: Account) : ViewModel() { } var zapRequestJson = "" - if (zapType != LnZapEvent.ZapType.NONZAP) { - val zapRequest = account.createZapRequestFor(note, pollOption, message, zapType) if (zapRequest != null) { zapRequestJson = zapRequest.toJson() + } else { + val localZapRequest = account.createZapRequestFor(note, pollOption, message, zapType) + if (localZapRequest != null) { + zapRequestJson = localZapRequest.toJson() + } } }