mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 19:05:21 +00:00
animate
This commit is contained in:
@@ -52,7 +52,7 @@ import java.util.*
|
|||||||
fun ChatScreen(
|
fun ChatScreen(
|
||||||
viewModel: ChatViewModel,
|
viewModel: ChatViewModel,
|
||||||
onWalletClick: () -> Unit = {},
|
onWalletClick: () -> Unit = {},
|
||||||
onWalletClickWithToken: ((String) -> Unit)? = null
|
onWalletClickWithToken: ((com.bitchat.android.parsing.ParsedCashuToken) -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
val colorScheme = MaterialTheme.colorScheme
|
val colorScheme = MaterialTheme.colorScheme
|
||||||
val messages by viewModel.messages.observeAsState(emptyList())
|
val messages by viewModel.messages.observeAsState(emptyList())
|
||||||
@@ -112,7 +112,7 @@ fun ChatScreen(
|
|||||||
meshService = viewModel.meshService,
|
meshService = viewModel.meshService,
|
||||||
onCashuPaymentClick = { parsedToken ->
|
onCashuPaymentClick = { parsedToken ->
|
||||||
// Open wallet with the receive dialog pre-filled with this token
|
// Open wallet with the receive dialog pre-filled with this token
|
||||||
onWalletClickWithToken?.invoke(parsedToken.originalString) ?: onWalletClick()
|
onWalletClickWithToken?.invoke(parsedToken)
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.bitchat.android.ui
|
package com.bitchat.android.ui
|
||||||
|
|
||||||
|
import androidx.compose.animation.*
|
||||||
|
import androidx.compose.animation.core.*
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
@@ -50,15 +52,75 @@ fun MainAppScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Column(modifier = modifier.fillMaxSize()) {
|
Column(modifier = modifier.fillMaxSize()) {
|
||||||
// Content based on selected tab
|
// Animated content with slide transitions
|
||||||
when (selectedTab) {
|
AnimatedContent(
|
||||||
|
targetState = selectedTab,
|
||||||
|
transitionSpec = {
|
||||||
|
// Slide in from right when going to wallet (0 -> 1)
|
||||||
|
// Slide out to right when going back to chat (1 -> 0)
|
||||||
|
if (targetState > initialState) {
|
||||||
|
// Going forward (chat -> wallet)
|
||||||
|
slideInHorizontally(
|
||||||
|
initialOffsetX = { fullWidth -> fullWidth },
|
||||||
|
animationSpec = tween(
|
||||||
|
durationMillis = 300,
|
||||||
|
easing = FastOutSlowInEasing
|
||||||
|
)
|
||||||
|
) + fadeIn(
|
||||||
|
animationSpec = tween(
|
||||||
|
durationMillis = 300,
|
||||||
|
easing = FastOutSlowInEasing
|
||||||
|
)
|
||||||
|
) togetherWith slideOutHorizontally(
|
||||||
|
targetOffsetX = { fullWidth -> -fullWidth },
|
||||||
|
animationSpec = tween(
|
||||||
|
durationMillis = 300,
|
||||||
|
easing = FastOutSlowInEasing
|
||||||
|
)
|
||||||
|
) + fadeOut(
|
||||||
|
animationSpec = tween(
|
||||||
|
durationMillis = 300,
|
||||||
|
easing = FastOutSlowInEasing
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Going back (wallet -> chat)
|
||||||
|
slideInHorizontally(
|
||||||
|
initialOffsetX = { fullWidth -> -fullWidth },
|
||||||
|
animationSpec = tween(
|
||||||
|
durationMillis = 300,
|
||||||
|
easing = FastOutSlowInEasing
|
||||||
|
)
|
||||||
|
) + fadeIn(
|
||||||
|
animationSpec = tween(
|
||||||
|
durationMillis = 300,
|
||||||
|
easing = FastOutSlowInEasing
|
||||||
|
)
|
||||||
|
) togetherWith slideOutHorizontally(
|
||||||
|
targetOffsetX = { fullWidth -> fullWidth },
|
||||||
|
animationSpec = tween(
|
||||||
|
durationMillis = 300,
|
||||||
|
easing = FastOutSlowInEasing
|
||||||
|
)
|
||||||
|
) + fadeOut(
|
||||||
|
animationSpec = tween(
|
||||||
|
durationMillis = 300,
|
||||||
|
easing = FastOutSlowInEasing
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label = "tab_transition",
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
) { tabIndex ->
|
||||||
|
when (tabIndex) {
|
||||||
0 -> ChatScreen(
|
0 -> ChatScreen(
|
||||||
viewModel = chatViewModel,
|
viewModel = chatViewModel,
|
||||||
onWalletClick = { selectedTab = 1 }, // Switch to wallet tab when header button is clicked
|
onWalletClick = { selectedTab = 1 }, // Switch to wallet tab when header button is clicked
|
||||||
onWalletClickWithToken = { token ->
|
onWalletClickWithToken = { parsedToken ->
|
||||||
// Switch to wallet and open receive dialog with the token
|
// Switch to wallet and open receive dialog with the parsed token immediately
|
||||||
selectedTab = 1
|
selectedTab = 1
|
||||||
walletViewModel.openReceiveDialogWithToken(token)
|
walletViewModel.openReceiveDialogWithParsedToken(parsedToken)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
1 -> WalletScreen(
|
1 -> WalletScreen(
|
||||||
@@ -66,6 +128,7 @@ fun MainAppScreen(
|
|||||||
onBackToChat = { selectedTab = 0 }
|
onBackToChat = { selectedTab = 0 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Bottom Navigation
|
// Bottom Navigation
|
||||||
AppBottomNavigation(
|
AppBottomNavigation(
|
||||||
|
|||||||
@@ -976,6 +976,45 @@ class WalletViewModel(application: Application) : AndroidViewModel(application)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open receive dialog with pre-parsed Cashu token data (immediate display)
|
||||||
|
*/
|
||||||
|
fun openReceiveDialogWithParsedToken(parsedToken: com.bitchat.android.parsing.ParsedCashuToken) {
|
||||||
|
try {
|
||||||
|
// Clear any existing state first
|
||||||
|
hideReceiveDialog()
|
||||||
|
_tokenInput.value = ""
|
||||||
|
_decodedToken.value = null
|
||||||
|
|
||||||
|
// Set the receive type to Cashu
|
||||||
|
_receiveType.value = ReceiveType.CASHU
|
||||||
|
|
||||||
|
// Set the token input
|
||||||
|
_tokenInput.value = parsedToken.originalString
|
||||||
|
|
||||||
|
// Create CashuToken from ParsedCashuToken immediately (no async needed)
|
||||||
|
val cashuToken = com.bitchat.android.wallet.data.CashuToken(
|
||||||
|
token = parsedToken.originalString,
|
||||||
|
amount = java.math.BigDecimal(parsedToken.amount),
|
||||||
|
unit = parsedToken.unit,
|
||||||
|
mint = parsedToken.mintUrl,
|
||||||
|
memo = parsedToken.memo
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set the decoded token immediately
|
||||||
|
_decodedToken.value = cashuToken
|
||||||
|
|
||||||
|
// Show the receive dialog immediately
|
||||||
|
_showReceiveDialog.value = true
|
||||||
|
|
||||||
|
Log.d(TAG, "Opened receive dialog with parsed token: ${parsedToken.amount} ${parsedToken.unit}")
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Error opening receive dialog with parsed token", e)
|
||||||
|
_errorMessage.value = "Failed to process token: ${e.message}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get full transaction history (not just last 10)
|
* Get full transaction history (not just last 10)
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user