From affa4bd4aba4b38f2824ecd4e1ea73be5904e3cf Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Fri, 7 Feb 2025 10:49:55 -0500 Subject: [PATCH 01/11] chore(fc): adjust layout for hostable avatar some more for clip prevention Signed-off-by: Brandon McAnsh --- .../com/getcode/ui/components/chat/HostableAvatar.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/HostableAvatar.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/HostableAvatar.kt index 7d3a4155f..be681746c 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/HostableAvatar.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/HostableAvatar.kt @@ -13,6 +13,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.CompositingStrategy +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.layout.Layout import androidx.compose.ui.layout.MeasureScope @@ -59,7 +61,7 @@ fun HostableAvatar( } ) { Layout( - modifier = modifier, + modifier = modifier.graphicsLayer { clip = false }, content = { UserAvatar( modifier = Modifier @@ -73,6 +75,7 @@ fun HostableAvatar( if (isHost) { Image( modifier = imageModifier + .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen } .layoutId("crown") .size(getBadgeSize(size)) .background(color = Color(0xFFE9C432), shape = CircleShape) @@ -88,6 +91,7 @@ fun HostableAvatar( is AvatarEndAction.Icon -> { Image( modifier = imageModifier + .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen } .layoutId("badge") .size(getBadgeSize(size)) .background(color = endAction.backgroundColor, shape = CircleShape) @@ -160,13 +164,13 @@ private fun MeasureScope.placeBadgeOnAvatarPerimeter( val badgeRadius = widthOrZero(placeable) / 2f - val distanceBetweenCenters = avatarRadius + badgeRadius - 16.dp.toPx() + val distanceBetweenCenters = avatarRadius + badgeRadius - (avatarRadius * 0.30f) val badgeCenterX = centerX + distanceBetweenCenters * cos(angle) val badgeCenterY = centerY + distanceBetweenCenters * sin(angle) val offsetX = badgeCenterX - badgeRadius - val offsetY = badgeCenterY - badgeRadius + val offsetY = badgeCenterY - badgeRadius + 2.dp.toPx() return IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) } \ No newline at end of file From e7e5b05c8ca675756ba6513cc9796017735127fe Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Fri, 7 Feb 2025 11:23:07 -0500 Subject: [PATCH 02/11] fix(fc): handle read pointers while sitting at bottom of chat Signed-off-by: Brandon McAnsh --- .../getcode/ui/components/chat/MessageList.kt | 24 +++++++++++++------ .../chat/utils/HandleMessageChanges.kt | 2 +- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/MessageList.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/MessageList.kt index 464190ef8..f3cc1d570 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/MessageList.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/MessageList.kt @@ -28,16 +28,20 @@ import androidx.paging.compose.itemKey import com.getcode.model.ID import com.getcode.model.chat.MessageContent import com.getcode.model.chat.MessageStatus +import com.getcode.model.uuid import com.getcode.theme.CodeTheme import com.getcode.ui.components.chat.messagecontents.MessageControlAction import com.getcode.ui.components.chat.utils.ChatItem import com.getcode.ui.components.chat.utils.MessageTip import com.getcode.ui.components.text.markup.Markup import com.getcode.util.formatDateRelatively +import com.getcode.utils.timestamp import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterNot +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach sealed interface MessageListEvent { data class AdvancePointer(val messageId: ID) : MessageListEvent @@ -275,12 +279,18 @@ private fun HandleMessageReads( }.distinctUntilChanged(), snapshotFlow { listState.isScrollInProgress }, snapshotFlow { listState.firstVisibleItemIndex }, - ) { loadState, isScrolling, firstVisibleIndex -> - Triple(loadState, isScrolling, firstVisibleIndex) - }.filter { (loadStateIsNotLoading, isScrolling, _) -> - // Wait until scrolling stops, messages are not loading, and we are at the bottom - loadStateIsNotLoading && !isScrolling && messages.itemCount > 0 && hasSetAtUnread - }.collect { (_, _, firstVisibleIndex) -> + snapshotFlow { messages.itemCount }, + ) { loadState, isScrolling, firstVisibleIndex, itemCount -> + Triple(loadState, isScrolling, firstVisibleIndex) to itemCount + }.filter { (state, itemCount) -> + val (loadStateIsNotLoading, isScrolling, firstVisibleIndex) = state + // Ensure we react to new messages while at the bottom + loadStateIsNotLoading && !isScrolling && hasSetAtUnread && + (firstVisibleIndex == 0 || firstVisibleIndex == itemCount - 1) && itemCount > 0 + }.onEach { (state, _) -> + + val (_, _, firstVisibleIndex) = state + val closestChatMessage = messages[firstVisibleIndex]?.let { it as? ChatItem.Message } @@ -298,7 +308,7 @@ private fun HandleMessageReads( } } } - } + }.launchIn(this) } } diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/utils/HandleMessageChanges.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/utils/HandleMessageChanges.kt index 8c4fa919b..1108ffbdf 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/utils/HandleMessageChanges.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/utils/HandleMessageChanges.kt @@ -38,7 +38,7 @@ fun HandleMessageChanges( .filter { it.refresh is LoadState.NotLoading } .mapNotNull { items.itemSnapshotList.firstOrNull() } .filterIsInstance() - .distinctUntilChangedBy { it.date } + .distinctUntilChangedBy { it.chatMessageId } .collect { newMessage -> if (newMessage.status.isOutgoing()) { if (newMessage.date.toEpochMilliseconds() > lastMessageSent) { From a98cdfc9c88be47e904c9ff571c5aba93d8e6ef0 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Fri, 7 Feb 2025 12:14:35 -0500 Subject: [PATCH 03/11] chore(fc): update copy around message fee Signed-off-by: Brandon McAnsh --- flipchatApp/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flipchatApp/src/main/res/values/strings.xml b/flipchatApp/src/main/res/values/strings.xml index 377a58fbb..ebdd43c85 100644 --- a/flipchatApp/src/main/res/values/strings.xml +++ b/flipchatApp/src/main/res/values/strings.xml @@ -114,7 +114,7 @@ Join %1$s Join Room: ⬢ %1$s Pay to Chat: ⬢ %1$s - Audience Messages: ⬢ %1$s + Audience Message: ⬢ %1$s Leave Flipchat? You will need to pay to get back in, but we won\’t tell people you left @@ -227,7 +227,7 @@ Finalize Account Creation Accounts on Flipchat must be purchased for %1$s to reduce spam Change Cover Charge - Change Listener Message Fee + Change Audience Message Fee Add Flipchat Name Edit Flipchat Name Change Flipchat Name From 0745180f953275088717fa570f149f73d2b17605 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Mon, 10 Feb 2025 10:34:31 -0500 Subject: [PATCH 04/11] fix(fc): observe balance directly on tip confirmation Signed-off-by: Brandon McAnsh --- .../kotlin/xyz/flipchat/app/MainActivity.kt | 6 ++++++ .../payments/MessageTipPaymentConfirmation.kt | 8 ++++++- .../app/features/payments/PaymentScaffold.kt | 2 +- .../kotlin/com/getcode/models/BillState.kt | 1 - .../com/getcode/network/BalanceController.kt | 5 ++++- .../flipchat/services/PaymentController.kt | 21 ++----------------- 6 files changed, 20 insertions(+), 23 deletions(-) diff --git a/flipchatApp/src/main/kotlin/xyz/flipchat/app/MainActivity.kt b/flipchatApp/src/main/kotlin/xyz/flipchat/app/MainActivity.kt index f6808c3ff..06802c0ec 100644 --- a/flipchatApp/src/main/kotlin/xyz/flipchat/app/MainActivity.kt +++ b/flipchatApp/src/main/kotlin/xyz/flipchat/app/MainActivity.kt @@ -11,6 +11,8 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.fragment.app.FragmentActivity import com.getcode.libs.opengraph.LocalOpenGraphParser import com.getcode.libs.opengraph.OpenGraphParser +import com.getcode.network.BalanceController +import com.getcode.network.LocalBalanceController import com.getcode.network.client.Client import com.getcode.network.exchange.ExchangeNull import com.getcode.network.exchange.LocalExchange @@ -73,6 +75,9 @@ class MainActivity : FragmentActivity() { @Inject lateinit var openGraphParser: OpenGraphParser + @Inject + lateinit var balanceController: BalanceController + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) handleUncaughtException() @@ -90,6 +95,7 @@ class MainActivity : FragmentActivity() { LocalLabs provides betaFeatures, LocalBillingClient provides iapController, LocalOpenGraphParser provides openGraphParser, + LocalBalanceController provides balanceController, ) { Rinku { App(tipsEngine = tipsEngine) diff --git a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/MessageTipPaymentConfirmation.kt b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/MessageTipPaymentConfirmation.kt index 0263e91b2..d65aa47b7 100644 --- a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/MessageTipPaymentConfirmation.kt +++ b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/MessageTipPaymentConfirmation.kt @@ -4,18 +4,21 @@ import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.res.stringResource +import cafe.adriel.voyager.navigator.currentOrThrow import com.getcode.model.Currency import com.getcode.model.KinAmount import com.getcode.model.Rate import com.getcode.model.kin import com.getcode.models.ConfirmationState import com.getcode.models.MessageTipPaymentConfirmation +import com.getcode.network.LocalBalanceController import com.getcode.theme.CodeTheme import com.getcode.ui.components.Modal import com.getcode.ui.components.SlideToConfirm @@ -58,11 +61,14 @@ internal fun MessageTipPaymentConfirmation( ) } + val balanceController = LocalBalanceController.currentOrThrow + val currentBalance by balanceController.formattedBalance.collectAsState() + Modal(modifier) { if (state != null) { MessageTipConfirmationContent( pickerState = pickerState, - balance = confirmation?.balance, + balance = currentBalance?.formattedValue, isSending = isSending, state = state, onApproved = { diff --git a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PaymentScaffold.kt b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PaymentScaffold.kt index f8017f9f2..c0543c333 100644 --- a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PaymentScaffold.kt +++ b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PaymentScaffold.kt @@ -73,7 +73,7 @@ fun PaymentScaffold(content: @Composable () -> Unit) { AnimatedContent( modifier = Modifier.align(BottomCenter), - targetState = state.billState.messageTipPaymentConfirmation?.balance, + targetState = state.billState.messageTipPaymentConfirmation?.metadata, transitionSpec = AnimationUtils.modalAnimationSpec(speed = ModalAnimationSpeed.Fast), label = "message tip payments", ) { diff --git a/libs/requests/src/main/kotlin/com/getcode/models/BillState.kt b/libs/requests/src/main/kotlin/com/getcode/models/BillState.kt index 7555a2e1d..ce002e531 100644 --- a/libs/requests/src/main/kotlin/com/getcode/models/BillState.kt +++ b/libs/requests/src/main/kotlin/com/getcode/models/BillState.kt @@ -233,7 +233,6 @@ data class MessageTipPaymentConfirmation( override val state: ConfirmationState, val destination: PublicKey, val metadata: ExtendedMetadata, - val balance: String?, override val showScrim: Boolean = true, override val cancellable: Boolean = true, ): Confirmation(showScrim, state) diff --git a/services/flipchat/payments/src/main/kotlin/com/getcode/network/BalanceController.kt b/services/flipchat/payments/src/main/kotlin/com/getcode/network/BalanceController.kt index 1012bfe4a..1efc181de 100644 --- a/services/flipchat/payments/src/main/kotlin/com/getcode/network/BalanceController.kt +++ b/services/flipchat/payments/src/main/kotlin/com/getcode/network/BalanceController.kt @@ -1,6 +1,6 @@ package com.getcode.network -import com.codeinc.gen.user.v1.user +import androidx.compose.runtime.staticCompositionLocalOf import com.getcode.model.Currency import com.getcode.model.CurrencyCode import com.getcode.model.Rate @@ -32,6 +32,7 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine import timber.log.Timber +import xyz.flipchat.services.PaymentController import xyz.flipchat.services.user.AuthState import xyz.flipchat.services.user.UserManager import java.util.Locale @@ -243,3 +244,5 @@ open class BalanceController @Inject constructor( } } } + +val LocalBalanceController = staticCompositionLocalOf { null } diff --git a/services/flipchat/payments/src/main/kotlin/xyz/flipchat/services/PaymentController.kt b/services/flipchat/payments/src/main/kotlin/xyz/flipchat/services/PaymentController.kt index d5320d258..76d1c1849 100644 --- a/services/flipchat/payments/src/main/kotlin/xyz/flipchat/services/PaymentController.kt +++ b/services/flipchat/payments/src/main/kotlin/xyz/flipchat/services/PaymentController.kt @@ -3,23 +3,17 @@ package xyz.flipchat.services import androidx.compose.runtime.staticCompositionLocalOf import com.getcode.domain.BillController import com.getcode.manager.TopBarManager -import com.getcode.model.Currency import com.getcode.model.ID import com.getcode.model.KinAmount import com.getcode.models.BillState import com.getcode.models.ConfirmationState import com.getcode.models.MessageTipPaymentConfirmation import com.getcode.models.PublicPaymentConfirmation -import com.getcode.network.BalanceController import com.getcode.network.repository.PaymentError import com.getcode.network.repository.PaymentRepository import com.getcode.services.model.ExtendedMetadata import com.getcode.solana.keys.PublicKey import com.getcode.util.resources.ResourceHelper -import com.getcode.utils.CurrencyUtils -import com.getcode.utils.Kin -import com.getcode.utils.flagResId -import com.getcode.utils.formatAmountString import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -58,16 +52,14 @@ open class PaymentController @Inject constructor( private val paymentRepository: PaymentRepository, private val resources: ResourceHelper, private val billController: BillController, - private val balanceController: BalanceController, - private val currencyUtils: CurrencyUtils, ) { - protected val scope = CoroutineScope(Dispatchers.IO) + private val scope = CoroutineScope(Dispatchers.IO) val state = billController.state.map { PaymentState(it) }.stateIn(scope, started = SharingStarted.Eagerly, initialValue = PaymentState()) - protected val _eventFlow: MutableSharedFlow = MutableSharedFlow() + private val _eventFlow: MutableSharedFlow = MutableSharedFlow() val eventFlow: SharedFlow = _eventFlow.asSharedFlow() fun presentPublicPaymentConfirmation( @@ -156,21 +148,12 @@ open class PaymentController @Inject constructor( } fun presentMessageTipConfirmation(metadata: ExtendedMetadata, destination: PublicKey) { - val rawBalance = balanceController.rawBalance - val balance = formatAmountString( - resources, - Currency.Kin, - rawBalance, - suffix = resources.getKinSuffix() - ) - billController.update { it.copy( messageTipPaymentConfirmation = MessageTipPaymentConfirmation( state = ConfirmationState.AwaitingConfirmation, metadata = metadata, destination = destination, - balance = balance, ) ) } From 844fc77c9692aa60dc3f4aec11fe34dd7e6d3cb9 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Mon, 10 Feb 2025 11:16:37 -0500 Subject: [PATCH 05/11] chore(fc): update copy aroud message fee Signed-off-by: Brandon McAnsh --- flipchatApp/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flipchatApp/src/main/res/values/strings.xml b/flipchatApp/src/main/res/values/strings.xml index ebdd43c85..4926dd741 100644 --- a/flipchatApp/src/main/res/values/strings.xml +++ b/flipchatApp/src/main/res/values/strings.xml @@ -114,7 +114,7 @@ Join %1$s Join Room: ⬢ %1$s Pay to Chat: ⬢ %1$s - Audience Message: ⬢ %1$s + Listener Message: ⬢ %1$s Leave Flipchat? You will need to pay to get back in, but we won\’t tell people you left @@ -227,7 +227,7 @@ Finalize Account Creation Accounts on Flipchat must be purchased for %1$s to reduce spam Change Cover Charge - Change Audience Message Fee + Change Listener Message Fee Add Flipchat Name Edit Flipchat Name Change Flipchat Name From 063af7023b7aec3773348ecf4eef7a81052f596d Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Mon, 10 Feb 2025 12:11:42 -0500 Subject: [PATCH 06/11] chore(fc): set context sheets to themed for all Signed-off-by: Brandon McAnsh --- .../xyz/flipchat/app/features/chat/info/RoomInfoScreen.kt | 3 +-- .../main/kotlin/com/getcode/navigation/screens/ContextSheet.kt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/chat/info/RoomInfoScreen.kt b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/chat/info/RoomInfoScreen.kt index a322b09ab..7a2c8cd3c 100644 --- a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/chat/info/RoomInfoScreen.kt +++ b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/chat/info/RoomInfoScreen.kt @@ -197,8 +197,7 @@ class RoomInfoScreen( buildActions( state, viewModel::dispatchEvent - ), - ContextMenuStyle.Themed + ) ) ) } diff --git a/ui/navigation/src/main/kotlin/com/getcode/navigation/screens/ContextSheet.kt b/ui/navigation/src/main/kotlin/com/getcode/navigation/screens/ContextSheet.kt index 2eed89eb1..5b636894e 100644 --- a/ui/navigation/src/main/kotlin/com/getcode/navigation/screens/ContextSheet.kt +++ b/ui/navigation/src/main/kotlin/com/getcode/navigation/screens/ContextSheet.kt @@ -44,7 +44,7 @@ sealed interface ContextMenuStyle { class ContextSheet( private val actions: List, - private val style: ContextMenuStyle = ContextMenuStyle.Default + private val style: ContextMenuStyle = ContextMenuStyle.Themed ) : Screen { @Composable From 1499ff6ee653620b1944084dac5a9237a44b9109 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Mon, 10 Feb 2025 12:33:53 -0500 Subject: [PATCH 07/11] chore(fc): handle back presses when payment modals are up Signed-off-by: Brandon McAnsh --- .../app/features/payments/MessageTipPaymentConfirmation.kt | 5 +++++ .../xyz/flipchat/app/features/payments/PaymentScaffold.kt | 3 +-- .../app/features/payments/PublicPaymentConfirmation.kt | 6 ++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/MessageTipPaymentConfirmation.kt b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/MessageTipPaymentConfirmation.kt index d65aa47b7..c59bd261c 100644 --- a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/MessageTipPaymentConfirmation.kt +++ b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/MessageTipPaymentConfirmation.kt @@ -1,5 +1,6 @@ package xyz.flipchat.app.features.payments +import androidx.activity.compose.BackHandler import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.Text @@ -64,6 +65,10 @@ internal fun MessageTipPaymentConfirmation( val balanceController = LocalBalanceController.currentOrThrow val currentBalance by balanceController.formattedBalance.collectAsState() + BackHandler { + onCancel() + } + Modal(modifier) { if (state != null) { MessageTipConfirmationContent( diff --git a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PaymentScaffold.kt b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PaymentScaffold.kt index c0543c333..2dd752e89 100644 --- a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PaymentScaffold.kt +++ b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PaymentScaffold.kt @@ -17,7 +17,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import com.getcode.models.BillState import com.getcode.theme.Black40 -import com.getcode.ui.modals.TipConfirmation import com.getcode.ui.utils.AnimationUtils import com.getcode.ui.utils.ModalAnimationSpeed import com.getcode.ui.utils.rememberedClickable @@ -45,7 +44,7 @@ fun PaymentScaffold(content: @Composable () -> Unit) { interactionSource = remember { MutableInteractionSource() } ) { if (scrimDetails.cancellable) { - payments.cancelPayment() + payments.cancelPayment(fromUser = true) } } ) diff --git a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PublicPaymentConfirmation.kt b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PublicPaymentConfirmation.kt index 0e80e9335..3f372151c 100644 --- a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PublicPaymentConfirmation.kt +++ b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/payments/PublicPaymentConfirmation.kt @@ -1,5 +1,6 @@ package xyz.flipchat.app.features.payments +import androidx.activity.compose.BackHandler import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.Text @@ -42,6 +43,11 @@ internal fun PublicPaymentConfirmation( derivedStateOf { confirmation?.amount } } + BackHandler { + onCancel() + } + + Modal(modifier) { val amount = requestedAmount if (state != null && amount != null) { From 020d00f482de7338fb1d642805999b1abda24bd2 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Mon, 10 Feb 2025 12:34:44 -0500 Subject: [PATCH 08/11] chore: tighten up spacing in MessageList Signed-off-by: Brandon McAnsh --- .../getcode/ui/components/chat/MessageList.kt | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/MessageList.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/MessageList.kt index f3cc1d570..b09273787 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/MessageList.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/MessageList.kt @@ -49,9 +49,9 @@ sealed interface MessageListEvent { data class OnMarkupEvent(val markup: Markup.Interactive) : MessageListEvent data class ReplyToMessage(val message: ChatItem.Message) : MessageListEvent data class ViewOriginalMessage(val messageId: ID, val originalMessageId: ID) : MessageListEvent - data object UnreadStateHandled: MessageListEvent - data class TipMessage(val message: ChatItem.Message): MessageListEvent - data class ShowTipsForMessage(val tips: List): MessageListEvent + data object UnreadStateHandled : MessageListEvent + data class TipMessage(val message: ChatItem.Message) : MessageListEvent + data class ShowTipsForMessage(val tips: List) : MessageListEvent } data class MessageListPointer( @@ -94,7 +94,8 @@ fun MessageList( state = listState, reverseLayout = true, contentPadding = PaddingValues( - vertical = CodeTheme.dimens.inset, + top = CodeTheme.dimens.inset, + bottom = CodeTheme.dimens.grid.x2, ), verticalArrangement = Arrangement.Top, ) { @@ -132,16 +133,18 @@ fun MessageList( } val spacingAfter = when { index > messages.itemCount -> 0.dp - item.message is MessageContent.Announcement -> CodeTheme.dimens.inset + item.message is MessageContent.Announcement -> CodeTheme.dimens.grid.x2 isNextGrouped -> 3.dp - else -> CodeTheme.dimens.grid.x3 + else -> CodeTheme.dimens.grid.x2 } val showTimestamp = remember(isPreviousGrouped, isNextGrouped, item.date, next?.date) { !isPreviousGrouped || !isNextGrouped - || next?.date?.epochSeconds?.div(60) != item.date.epochSeconds.div(60) + || next?.date?.epochSeconds?.div(60) != item.date.epochSeconds.div( + 60 + ) } val updatedSender by rememberUpdatedState(item.sender) From 7c7be253ce3ec230317f4734c6f60dd3e22cd6d4 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Mon, 10 Feb 2025 12:35:04 -0500 Subject: [PATCH 09/11] chore(fc): tighten up handling for returning to spectator mode after IME resigns Signed-off-by: Brandon McAnsh --- .../chat/conversation/ConversationChatInput.kt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/chat/conversation/ConversationChatInput.kt b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/chat/conversation/ConversationChatInput.kt index 44f542163..49bceb393 100644 --- a/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/chat/conversation/ConversationChatInput.kt +++ b/flipchatApp/src/main/kotlin/xyz/flipchat/app/features/chat/conversation/ConversationChatInput.kt @@ -42,6 +42,7 @@ import com.getcode.util.resources.LocalResources import com.getcode.utils.Kin import com.getcode.utils.formatAmountString import kotlinx.coroutines.delay +import kotlinx.coroutines.withTimeoutOrNull import xyz.flipchat.app.R @Composable @@ -121,14 +122,18 @@ fun ConversationChatInput( } } + var wasKeyboardVisible by remember { mutableStateOf(false) } + LaunchedEffect(keyboardVisible) { - delay(300) - if (!keyboardVisible) { - if (chattableState is ChattableState.TemporarilyEnabled) { + if (wasKeyboardVisible && !keyboardVisible) { + delay(150) // Short delay to prevent accidental blips + if (!keyboardVisible && chattableState is ChattableState.TemporarilyEnabled) { dispatchEvent(ConversationViewModel.Event.ResetToSpectator) } } + wasKeyboardVisible = keyboardVisible } + } } From dbd726ca1750132fe2e0de9d877a80b2a9ecd46a Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Mon, 10 Feb 2025 12:40:59 -0500 Subject: [PATCH 10/11] chore(fc): add support for variances in deeplinks for opening flipchats Signed-off-by: Brandon McAnsh --- flipchatApp/src/main/AndroidManifest.xml | 46 ++++++++++++ .../kotlin/xyz/flipchat/app/util/Router.kt | 70 ++++++++++++++++--- .../flipchat/controllers/ChatsController.kt | 4 ++ 3 files changed, 110 insertions(+), 10 deletions(-) diff --git a/flipchatApp/src/main/AndroidManifest.xml b/flipchatApp/src/main/AndroidManifest.xml index a5b8cac79..6a4172b25 100644 --- a/flipchatApp/src/main/AndroidManifest.xml +++ b/flipchatApp/src/main/AndroidManifest.xml @@ -52,6 +52,7 @@ + @@ -72,6 +73,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -91,7 +134,9 @@ + + @@ -111,6 +156,7 @@ +