Turn the Pay zaps via intent dialog into a full screen with route
This commit is contained in:
+28
-23
@@ -50,12 +50,14 @@ import com.vitorpamplona.amethyst.model.User
|
|||||||
import com.vitorpamplona.amethyst.service.ZapPaymentHandler
|
import com.vitorpamplona.amethyst.service.ZapPaymentHandler
|
||||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.UserFinderFilterAssemblerSubscription
|
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.UserFinderFilterAssemblerSubscription
|
||||||
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.toasts.multiline.UserBasedErrorMessage
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||||
import com.vitorpamplona.amethyst.ui.note.ObserveZapIcon
|
import com.vitorpamplona.amethyst.ui.note.ObserveZapIcon
|
||||||
import com.vitorpamplona.amethyst.ui.note.PayViaIntentDialog
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.ZapAmountChoicePopup
|
import com.vitorpamplona.amethyst.ui.note.ZapAmountChoicePopup
|
||||||
import com.vitorpamplona.amethyst.ui.note.ZapIcon
|
import com.vitorpamplona.amethyst.ui.note.ZapIcon
|
||||||
import com.vitorpamplona.amethyst.ui.note.ZappedIcon
|
import com.vitorpamplona.amethyst.ui.note.ZappedIcon
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.payViaIntent
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.ModifierWidth3dp
|
import com.vitorpamplona.amethyst.ui.theme.ModifierWidth3dp
|
||||||
@@ -64,11 +66,12 @@ import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
import com.vitorpamplona.amethyst.ui.theme.Size35dp
|
||||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlin.uuid.ExperimentalUuidApi
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration for zap button behavior and appearance
|
* Configuration for zap button behavior and appearance
|
||||||
@@ -91,6 +94,7 @@ data class ZapButtonCallbacks(
|
|||||||
val onZapComplete: ((Boolean) -> Unit)? = null,
|
val onZapComplete: ((Boolean) -> Unit)? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@OptIn(ExperimentalUuidApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ReusableZapButton(
|
fun ReusableZapButton(
|
||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
@@ -100,9 +104,6 @@ fun ReusableZapButton(
|
|||||||
callbacks: ZapButtonCallbacks = ZapButtonCallbacks(),
|
callbacks: ZapButtonCallbacks = ZapButtonCallbacks(),
|
||||||
) {
|
) {
|
||||||
var wantsToZap by remember { mutableStateOf<ImmutableList<Long>?>(null) }
|
var wantsToZap by remember { mutableStateOf<ImmutableList<Long>?>(null) }
|
||||||
var wantsToPay by remember(baseNote) {
|
|
||||||
mutableStateOf<ImmutableList<ZapPaymentHandler.Payable>>(persistentListOf())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Makes sure the user is loaded to get his ln address ahead of time (for DVM buttons)
|
// Makes sure the user is loaded to get his ln address ahead of time (for DVM buttons)
|
||||||
if (config.showUserFinderSubscription) {
|
if (config.showUserFinderSubscription) {
|
||||||
@@ -138,7 +139,19 @@ fun ReusableZapButton(
|
|||||||
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, message, toUser)
|
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, message, toUser)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onPayViaIntent = { wantsToPay = it },
|
onPayViaIntent = {
|
||||||
|
if (it.size == 1) {
|
||||||
|
val payable = it.first()
|
||||||
|
payViaIntent(payable.invoice, context, { }) {
|
||||||
|
zappingProgress = 0f
|
||||||
|
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, UserBasedErrorMessage(it, payable.info.user))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val uid = Uuid.random().toString()
|
||||||
|
accountViewModel.tempManualPaymentCache.put(uid, it)
|
||||||
|
nav.nav(Route.ManualZapSplitPayment(uid))
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
@@ -166,25 +179,17 @@ fun ReusableZapButton(
|
|||||||
onProgress = {
|
onProgress = {
|
||||||
scope.launch(Dispatchers.Main) { zappingProgress = it }
|
scope.launch(Dispatchers.Main) { zappingProgress = it }
|
||||||
},
|
},
|
||||||
onPayViaIntent = { wantsToPay = it },
|
onPayViaIntent = {
|
||||||
)
|
if (it.size == 1) {
|
||||||
}
|
val payable = it.first()
|
||||||
|
payViaIntent(payable.invoice, context, { }) {
|
||||||
if (wantsToPay.isNotEmpty()) {
|
|
||||||
PayViaIntentDialog(
|
|
||||||
payingInvoices = wantsToPay,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
onClose = { wantsToPay = persistentListOf() },
|
|
||||||
onError = {
|
|
||||||
wantsToPay = persistentListOf()
|
|
||||||
scope.launch {
|
|
||||||
zappingProgress = 0f
|
zappingProgress = 0f
|
||||||
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, it)
|
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, UserBasedErrorMessage(it, payable.info.user))
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
justShowError = {
|
val uid = Uuid.random().toString()
|
||||||
scope.launch {
|
accountViewModel.tempManualPaymentCache.put(uid, it)
|
||||||
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, it)
|
nav.nav(Route.ManualZapSplitPayment(uid))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
|||||||
import com.vitorpamplona.amethyst.ui.navigation.routes.getRouteWithArguments
|
import com.vitorpamplona.amethyst.ui.navigation.routes.getRouteWithArguments
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.routes.isBaseRoute
|
import com.vitorpamplona.amethyst.ui.navigation.routes.isBaseRoute
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.routes.isSameRoute
|
import com.vitorpamplona.amethyst.ui.navigation.routes.isSameRoute
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.PayViaIntentScreen
|
||||||
import com.vitorpamplona.amethyst.ui.note.nip22Comments.ReplyCommentPostScreen
|
import com.vitorpamplona.amethyst.ui.note.nip22Comments.ReplyCommentPostScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountSwitcherAndLeftDrawerLayout
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountSwitcherAndLeftDrawerLayout
|
||||||
@@ -137,6 +138,8 @@ fun AppNavigation(
|
|||||||
composableFromBottomArgs<Route.PeopleListMetadataEdit> { PeopleListMetadataScreen(it.dTag, accountViewModel, nav) }
|
composableFromBottomArgs<Route.PeopleListMetadataEdit> { PeopleListMetadataScreen(it.dTag, accountViewModel, nav) }
|
||||||
composableFromBottomArgs<Route.FollowPackMetadataEdit> { FollowPackMetadataScreen(it.dTag, accountViewModel, nav) }
|
composableFromBottomArgs<Route.FollowPackMetadataEdit> { FollowPackMetadataScreen(it.dTag, accountViewModel, nav) }
|
||||||
|
|
||||||
|
composableFromBottomArgs<Route.ManualZapSplitPayment> { PayViaIntentScreen(it.paymentId, accountViewModel, nav) }
|
||||||
|
|
||||||
composableFromBottomArgs<Route.EditProfile> { NewUserMetadataScreen(nav, accountViewModel) }
|
composableFromBottomArgs<Route.EditProfile> { NewUserMetadataScreen(nav, accountViewModel) }
|
||||||
composable<Route.Search> { SearchScreen(accountViewModel, nav) }
|
composable<Route.Search> { SearchScreen(accountViewModel, nav) }
|
||||||
|
|
||||||
|
|||||||
@@ -252,6 +252,11 @@ sealed class Route {
|
|||||||
val version: String? = null,
|
val version: String? = null,
|
||||||
val draft: String? = null,
|
val draft: String? = null,
|
||||||
) : Route()
|
) : Route()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class ManualZapSplitPayment(
|
||||||
|
val paymentId: String,
|
||||||
|
) : Route()
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : Route> isBaseRoute(navController: NavHostController): Boolean = navController.currentBackStackEntry?.destination?.hasRoute<T>() == true
|
inline fun <reified T : Route> isBaseRoute(navController: NavHostController): Boolean = navController.currentBackStackEntry?.destination?.hasRoute<T>() == true
|
||||||
@@ -310,6 +315,7 @@ fun getRouteWithArguments(navController: NavHostController): Route? {
|
|||||||
dest.hasRoute<Route.PeopleListManagement>() -> entry.toRoute<Route.PeopleListManagement>()
|
dest.hasRoute<Route.PeopleListManagement>() -> entry.toRoute<Route.PeopleListManagement>()
|
||||||
dest.hasRoute<Route.NewGroupDM>() -> entry.toRoute<Route.NewGroupDM>()
|
dest.hasRoute<Route.NewGroupDM>() -> entry.toRoute<Route.NewGroupDM>()
|
||||||
dest.hasRoute<Route.UserSettings>() -> entry.toRoute<Route.UserSettings>()
|
dest.hasRoute<Route.UserSettings>() -> entry.toRoute<Route.UserSettings>()
|
||||||
|
dest.hasRoute<Route.ManualZapSplitPayment>() -> entry.toRoute<Route.ManualZapSplitPayment>()
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
null
|
null
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ 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.mutableFloatStateOf
|
import androidx.compose.runtime.mutableFloatStateOf
|
||||||
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
|
||||||
@@ -81,6 +80,7 @@ import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
|||||||
import com.vitorpamplona.amethyst.ui.components.toasts.StringToastMsg
|
import com.vitorpamplona.amethyst.ui.components.toasts.StringToastMsg
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
|
import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.routes.routeToMessage
|
import com.vitorpamplona.amethyst.ui.navigation.routes.routeToMessage
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
|
||||||
@@ -102,14 +102,14 @@ import com.vitorpamplona.quartz.nip01Core.core.ImmutableListOfLists
|
|||||||
import com.vitorpamplona.quartz.nip01Core.core.toImmutableListOfLists
|
import com.vitorpamplona.quartz.nip01Core.core.toImmutableListOfLists
|
||||||
import com.vitorpamplona.quartz.nip31Alts.AltTag
|
import com.vitorpamplona.quartz.nip31Alts.AltTag
|
||||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
import kotlin.uuid.ExperimentalUuidApi
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
@@ -499,7 +499,7 @@ private fun RenderOptionBeforeVote(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class, ExperimentalUuidApi::class)
|
||||||
fun ZapVote(
|
fun ZapVote(
|
||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
poolOption: PollOption,
|
poolOption: PollOption,
|
||||||
@@ -513,14 +513,8 @@ fun ZapVote(
|
|||||||
val isLoggedUser by remember { derivedStateOf { accountViewModel.isLoggedUser(baseNote.author) } }
|
val isLoggedUser by remember { derivedStateOf { accountViewModel.isLoggedUser(baseNote.author) } }
|
||||||
|
|
||||||
var wantsToZap by remember { mutableStateOf(false) }
|
var wantsToZap by remember { mutableStateOf(false) }
|
||||||
var wantsToPay by remember {
|
|
||||||
mutableStateOf<ImmutableList<ZapPaymentHandler.Payable>>(
|
|
||||||
persistentListOf(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
var zappingProgress by remember { mutableFloatStateOf(0f) }
|
var zappingProgress by remember { mutableFloatStateOf(0f) }
|
||||||
var zapStartingTime by remember { mutableLongStateOf(0L) }
|
|
||||||
|
|
||||||
var showErrorMessageDialog by remember { mutableStateOf<StringToastMsg?>(null) }
|
var showErrorMessageDialog by remember { mutableStateOf<StringToastMsg?>(null) }
|
||||||
|
|
||||||
@@ -563,7 +557,6 @@ fun ZapVote(
|
|||||||
accountViewModel.zapAmountChoices().size == 1 &&
|
accountViewModel.zapAmountChoices().size == 1 &&
|
||||||
pollViewModel.isValidInputVoteAmount(accountViewModel.zapAmountChoices().first())
|
pollViewModel.isValidInputVoteAmount(accountViewModel.zapAmountChoices().first())
|
||||||
) {
|
) {
|
||||||
zapStartingTime = TimeUtils.now()
|
|
||||||
accountViewModel.zap(
|
accountViewModel.zap(
|
||||||
baseNote,
|
baseNote,
|
||||||
accountViewModel.zapAmountChoices().first() * 1000,
|
accountViewModel.zapAmountChoices().first() * 1000,
|
||||||
@@ -584,12 +577,13 @@ fun ZapVote(
|
|||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
if (wantsToZap) {
|
if (wantsToZap) {
|
||||||
|
val context = LocalContext.current
|
||||||
FilteredZapAmountChoicePopup(
|
FilteredZapAmountChoicePopup(
|
||||||
baseNote,
|
baseNote,
|
||||||
accountViewModel,
|
accountViewModel,
|
||||||
pollViewModel,
|
pollViewModel,
|
||||||
poolOption.option,
|
poolOption.option,
|
||||||
onZapStarts = { zapStartingTime = TimeUtils.now() },
|
onZapStarts = { },
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
wantsToZap = false
|
wantsToZap = false
|
||||||
zappingProgress = 0f
|
zappingProgress = 0f
|
||||||
@@ -600,33 +594,17 @@ fun ZapVote(
|
|||||||
zappingProgress = 0f
|
zappingProgress = 0f
|
||||||
},
|
},
|
||||||
onProgress = { scope.launch(Dispatchers.Main) { zappingProgress = it } },
|
onProgress = { scope.launch(Dispatchers.Main) { zappingProgress = it } },
|
||||||
onPayViaIntent = { wantsToPay = it },
|
onPayViaIntent = {
|
||||||
)
|
if (it.size == 1) {
|
||||||
}
|
val payable = it.first()
|
||||||
|
payViaIntent(payable.invoice, context, { }) { error ->
|
||||||
if (wantsToPay.isNotEmpty()) {
|
|
||||||
PayViaIntentDialog(
|
|
||||||
payingInvoices = wantsToPay,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
onClose = { wantsToPay = persistentListOf() },
|
|
||||||
onError = {
|
|
||||||
wantsToPay = persistentListOf()
|
|
||||||
scope.launch {
|
|
||||||
zappingProgress = 0f
|
zappingProgress = 0f
|
||||||
showErrorMessageDialog =
|
showErrorMessageDialog = StringToastMsg(stringRes(context, R.string.error_dialog_zap_error), error)
|
||||||
StringToastMsg(
|
|
||||||
stringRes(context, R.string.error_dialog_zap_error),
|
|
||||||
it.error,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
justShowError = {
|
val uid = Uuid.random().toString()
|
||||||
scope.launch {
|
accountViewModel.tempManualPaymentCache.put(uid, it)
|
||||||
showErrorMessageDialog =
|
nav.nav(Route.ManualZapSplitPayment(uid))
|
||||||
StringToastMsg(
|
|
||||||
stringRes(context, R.string.error_dialog_zap_error),
|
|
||||||
it.error,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ import com.vitorpamplona.amethyst.ui.components.AnimatedBorderTextCornerRadius
|
|||||||
import com.vitorpamplona.amethyst.ui.components.ClickableBox
|
import com.vitorpamplona.amethyst.ui.components.ClickableBox
|
||||||
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
|
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
|
||||||
import com.vitorpamplona.amethyst.ui.components.InLineIconRenderer
|
import com.vitorpamplona.amethyst.ui.components.InLineIconRenderer
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.toasts.multiline.UserBasedErrorMessage
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.routes.routeReplyTo
|
import com.vitorpamplona.amethyst.ui.navigation.routes.routeReplyTo
|
||||||
@@ -169,6 +170,8 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
import kotlin.uuid.ExperimentalUuidApi
|
||||||
|
import kotlin.uuid.Uuid
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReactionsRow(
|
fun ReactionsRow(
|
||||||
@@ -970,7 +973,7 @@ private fun likeClick(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class, ExperimentalUuidApi::class)
|
||||||
fun ZapReaction(
|
fun ZapReaction(
|
||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
grayTint: Color,
|
grayTint: Color,
|
||||||
@@ -983,12 +986,6 @@ fun ZapReaction(
|
|||||||
var wantsToZap by remember { mutableStateOf(false) }
|
var wantsToZap by remember { mutableStateOf(false) }
|
||||||
var wantsToChangeZapAmount by remember { mutableStateOf(false) }
|
var wantsToChangeZapAmount by remember { mutableStateOf(false) }
|
||||||
var wantsToSetCustomZap by remember { mutableStateOf(false) }
|
var wantsToSetCustomZap by remember { mutableStateOf(false) }
|
||||||
var wantsToPay by
|
|
||||||
remember(baseNote) {
|
|
||||||
mutableStateOf<ImmutableList<ZapPaymentHandler.Payable>>(
|
|
||||||
persistentListOf(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
@@ -1022,7 +1019,19 @@ fun ZapReaction(
|
|||||||
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, message, user)
|
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, message, user)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onPayViaIntent = { wantsToPay = it },
|
onPayViaIntent = {
|
||||||
|
if (it.size == 1) {
|
||||||
|
val payable = it.first()
|
||||||
|
payViaIntent(payable.invoice, context, { }) { error ->
|
||||||
|
zappingProgress = 0f
|
||||||
|
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, UserBasedErrorMessage(error, payable.info.user))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val uid = Uuid.random().toString()
|
||||||
|
accountViewModel.tempManualPaymentCache.put(uid, it)
|
||||||
|
nav.nav(Route.ManualZapSplitPayment(uid))
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1053,7 +1062,19 @@ fun ZapReaction(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onProgress = { scope.launch(Dispatchers.Main) { zappingProgress = it } },
|
onProgress = { scope.launch(Dispatchers.Main) { zappingProgress = it } },
|
||||||
onPayViaIntent = { wantsToPay = it },
|
onPayViaIntent = {
|
||||||
|
if (it.size == 1) {
|
||||||
|
val payable = it.first()
|
||||||
|
payViaIntent(payable.invoice, context, { }) { error ->
|
||||||
|
zappingProgress = 0f
|
||||||
|
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, UserBasedErrorMessage(error, payable.info.user))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val uid = Uuid.random().toString()
|
||||||
|
accountViewModel.tempManualPaymentCache.put(uid, it)
|
||||||
|
nav.nav(Route.ManualZapSplitPayment(uid))
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1064,26 +1085,6 @@ fun ZapReaction(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wantsToPay.isNotEmpty()) {
|
|
||||||
PayViaIntentDialog(
|
|
||||||
payingInvoices = wantsToPay,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
onClose = { wantsToPay = persistentListOf() },
|
|
||||||
onError = {
|
|
||||||
wantsToPay = persistentListOf()
|
|
||||||
scope.launch {
|
|
||||||
zappingProgress = 0f
|
|
||||||
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, it)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
justShowError = {
|
|
||||||
scope.launch {
|
|
||||||
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, it)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wantsToSetCustomZap) {
|
if (wantsToSetCustomZap) {
|
||||||
ZapCustomDialog(
|
ZapCustomDialog(
|
||||||
onZapStarts = { zapStartingTime = TimeUtils.now() },
|
onZapStarts = { zapStartingTime = TimeUtils.now() },
|
||||||
@@ -1095,7 +1096,19 @@ fun ZapReaction(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onProgress = { scope.launch(Dispatchers.Main) { zappingProgress = it } },
|
onProgress = { scope.launch(Dispatchers.Main) { zappingProgress = it } },
|
||||||
onPayViaIntent = { wantsToPay = it },
|
onPayViaIntent = {
|
||||||
|
if (it.size == 1) {
|
||||||
|
val payable = it.first()
|
||||||
|
payViaIntent(payable.invoice, context, { }) { error ->
|
||||||
|
zappingProgress = 0f
|
||||||
|
accountViewModel.toastManager.toast(R.string.error_dialog_zap_error, UserBasedErrorMessage(error, payable.info.user))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val uid = Uuid.random().toString()
|
||||||
|
accountViewModel.tempManualPaymentCache.put(uid, it)
|
||||||
|
nav.nav(Route.ManualZapSplitPayment(uid))
|
||||||
|
}
|
||||||
|
},
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
baseNote = baseNote,
|
baseNote = baseNote,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
@@ -67,10 +68,10 @@ import com.vitorpamplona.amethyst.model.Account
|
|||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.service.ZapPaymentHandler
|
import com.vitorpamplona.amethyst.service.ZapPaymentHandler
|
||||||
import com.vitorpamplona.amethyst.ui.components.SetDialogToEdgeToEdge
|
|
||||||
import com.vitorpamplona.amethyst.ui.components.TextSpinner
|
import com.vitorpamplona.amethyst.ui.components.TextSpinner
|
||||||
import com.vitorpamplona.amethyst.ui.components.TitleExplainer
|
import com.vitorpamplona.amethyst.ui.components.TitleExplainer
|
||||||
import com.vitorpamplona.amethyst.ui.components.toasts.multiline.UserBasedErrorMessage
|
import com.vitorpamplona.amethyst.ui.components.toasts.multiline.UserBasedErrorMessage
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
|
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
|
||||||
import com.vitorpamplona.amethyst.ui.note.buttons.CloseButton
|
import com.vitorpamplona.amethyst.ui.note.buttons.CloseButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
@@ -286,36 +287,27 @@ fun ZapButton(
|
|||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun PayViaIntentDialog(
|
fun PayViaIntentScreen(
|
||||||
payingInvoices: ImmutableList<ZapPaymentHandler.Payable>,
|
paymentId: String,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
onClose: () -> Unit,
|
nav: INav,
|
||||||
onError: (UserBasedErrorMessage) -> Unit,
|
|
||||||
justShowError: (UserBasedErrorMessage) -> Unit,
|
|
||||||
) {
|
) {
|
||||||
if (payingInvoices.size == 1) {
|
|
||||||
val context = LocalContext.current
|
|
||||||
val payable = payingInvoices.first()
|
|
||||||
payViaIntent(payable.invoice, context, onClose) {
|
|
||||||
onError(UserBasedErrorMessage(it, payable.info.user))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Dialog(
|
|
||||||
onDismissRequest = onClose,
|
|
||||||
properties =
|
|
||||||
DialogProperties(
|
|
||||||
dismissOnClickOutside = false,
|
|
||||||
usePlatformDefaultWidth = false,
|
|
||||||
decorFitsSystemWindows = false,
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
SetDialogToEdgeToEdge()
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
TopBarWithBackButton(stringRes(id = R.string.manual_zaps), onClose)
|
TopBarWithBackButton(stringRes(id = R.string.manual_zaps), nav::popBack)
|
||||||
},
|
},
|
||||||
) { pad ->
|
) { pad ->
|
||||||
|
val list = accountViewModel.tempManualPaymentCache.get(paymentId)
|
||||||
|
|
||||||
|
if (list == null) {
|
||||||
|
Column(
|
||||||
|
Modifier.fillMaxSize(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
) {
|
||||||
|
Text(stringRes(R.string.feed_is_empty))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
Modifier.padding(
|
Modifier.padding(
|
||||||
16.dp,
|
16.dp,
|
||||||
@@ -325,13 +317,12 @@ fun PayViaIntentDialog(
|
|||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
itemsIndexed(
|
itemsIndexed(
|
||||||
payingInvoices,
|
accountViewModel.tempManualPaymentCache.get(paymentId) ?: emptyList(),
|
||||||
key = { _: Int, invoice: ZapPaymentHandler.Payable ->
|
key = { _: Int, invoice: ZapPaymentHandler.Payable ->
|
||||||
invoice.invoice
|
invoice.invoice
|
||||||
},
|
},
|
||||||
) { index, payable ->
|
) { index, payable ->
|
||||||
DisplayPayable(index, payable, justShowError, accountViewModel)
|
DisplayPayable(index, payable, accountViewModel)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -342,7 +333,6 @@ fun PayViaIntentDialog(
|
|||||||
fun DisplayPayable(
|
fun DisplayPayable(
|
||||||
index: Int,
|
index: Int,
|
||||||
payable: ZapPaymentHandler.Payable,
|
payable: ZapPaymentHandler.Payable,
|
||||||
justShowError: (UserBasedErrorMessage) -> Unit,
|
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
) {
|
) {
|
||||||
val paid = rememberSaveable(payable) { mutableStateOf(false) }
|
val paid = rememberSaveable(payable) { mutableStateOf(false) }
|
||||||
@@ -395,7 +385,10 @@ fun DisplayPayable(
|
|||||||
|
|
||||||
PayButton(isActive = !paid.value) {
|
PayButton(isActive = !paid.value) {
|
||||||
payViaIntent(payable.invoice, context, { paid.value = true }) {
|
payViaIntent(payable.invoice, context, { paid.value = true }) {
|
||||||
justShowError(UserBasedErrorMessage(it, null))
|
accountViewModel.toastManager.toast(
|
||||||
|
R.string.error_dialog_zap_error,
|
||||||
|
UserBasedErrorMessage(it, payable.info.user),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -175,6 +175,8 @@ class AccountViewModel(
|
|||||||
val toastManager = ToastManager()
|
val toastManager = ToastManager()
|
||||||
val feedStates = AccountFeedContentStates(account, viewModelScope)
|
val feedStates = AccountFeedContentStates(account, viewModelScope)
|
||||||
|
|
||||||
|
val tempManualPaymentCache = LruCache<String, List<ZapPaymentHandler.Payable>>(5)
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
val notificationHasNewItems =
|
val notificationHasNewItems =
|
||||||
combineTransform(
|
combineTransform(
|
||||||
|
|||||||
Reference in New Issue
Block a user