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