11package com.flipcash.app.balance.internal.components
22
3- import androidx.compose.foundation.clickable
4- import androidx.compose.foundation.layout.Arrangement
3+ import androidx.compose.animation.AnimatedContent
4+ import androidx.compose.animation.animateColorAsState
5+ import androidx.compose.animation.core.animateDpAsState
6+ import androidx.compose.animation.slideInVertically
7+ import androidx.compose.animation.slideOutVertically
8+ import androidx.compose.animation.togetherWith
9+ import androidx.compose.foundation.background
10+ import androidx.compose.foundation.layout.Box
511import androidx.compose.foundation.layout.Column
6- import androidx.compose.foundation.layout.Row
7- import androidx.compose.foundation.layout.padding
8- import androidx.compose.material.Text
12+ import androidx.compose.foundation.layout.Spacer
13+ import androidx.compose.foundation.layout.fillMaxWidth
14+ import androidx.compose.material.Surface
915import androidx.compose.runtime.Composable
10- import androidx.compose.runtime.derivedStateOf
16+ import androidx.compose.runtime.CompositionLocalProvider
1117import androidx.compose.runtime.getValue
12- import androidx.compose.runtime.remember
13- import androidx.compose.ui.Alignment
1418import androidx.compose.ui.Modifier
19+ import androidx.compose.ui.graphics.Color
20+ import androidx.compose.ui.graphics.compositeOver
21+ import androidx.compose.ui.platform.LocalContext
22+ import androidx.compose.ui.tooling.preview.Preview
23+ import androidx.compose.ui.unit.dp
24+ import com.flipcash.app.balance.internal.BalanceViewModel
1525import com.flipcash.app.core.feed.ActivityFeedMessage
1626import com.flipcash.app.core.feed.MessageMetadata
17- import com.flipcash.app.core.ui.FlagWithFiat
18- import com.flipcash.services.models.ActivityFeedNotification
19- import com.flipcash.services.models.NotificationMetadata
27+ import com.flipcash.app.core.feed.MessageState
28+ import com.flipcash.app.theme.FlipcashDesignSystem
29+ import com.getcode.ed25519.Ed25519
30+ import com.getcode.opencode.compose.ExchangeStub
31+ import com.getcode.opencode.compose.LocalExchange
2032import com.getcode.opencode.model.financial.CurrencyCode
33+ import com.getcode.opencode.model.financial.LocalFiat
34+ import com.getcode.opencode.model.financial.Rate
35+ import com.getcode.opencode.model.financial.toFiat
36+ import com.getcode.solana.keys.PublicKey
2137import com.getcode.theme.CodeTheme
22- import com.getcode.util.DateUtils
23- import com.getcode.util.format
38+ import com.getcode.utils.decodeBase58
2439import kotlinx.datetime.Instant
2540
2641@Composable
2742internal fun FeedItem (
2843 message : ActivityFeedMessage ,
44+ canViewDetails : Boolean ,
45+ isExpanded : Boolean ,
2946 modifier : Modifier = Modifier ,
30- onCancelRequested : () -> Unit ,
47+ dispatch : (BalanceViewModel . Event ) -> Unit ,
3148) {
32- val canCancel by remember(message.metadata) {
33- derivedStateOf {
34- message.metadata ? : return @derivedStateOf false
35- val metadata = (message.metadata as ? MessageMetadata .SentUsdc ) ? : return @derivedStateOf false
36- metadata.canCancel
37- }
38- }
49+ val elevation by animateDpAsState(if (isExpanded) 8 .dp else 0 .dp)
3950
40- Row (
41- modifier = modifier
42- .clickable(enabled = canCancel) { onCancelRequested() }
43- .padding(
44- horizontal = CodeTheme .dimens.inset,
45- vertical = CodeTheme .dimens.inset,
46- ),
47- horizontalArrangement = Arrangement .SpaceBetween
51+ Column (
52+ modifier = modifier,
4853 ) {
49- Column (
50- modifier = Modifier .weight(1f ),
54+ Surface (
55+ color = CodeTheme .colors.background,
56+ elevation = elevation,
5157 ) {
52- Text (
53- text = message.text,
54- style = CodeTheme .typography.textMedium,
55- color = CodeTheme .colors.textMain
56- )
57- Text (
58- text = message.timestamp.formatRelativeToToday(),
59- style = CodeTheme .typography.textSmall,
60- color = CodeTheme .colors.textSecondary
58+ FeedItemSummary (
59+ message = message,
60+ canViewDetails = canViewDetails,
61+ modifier = Modifier
62+ .fillMaxWidth(),
63+ dispatch = dispatch,
6164 )
6265 }
6366
64- message.amount?.let { amount ->
65- Column (
66- horizontalAlignment = Alignment .End
67- ) {
68- FlagWithFiat (fiat = amount.converted)
67+ AnimatedContent (
68+ targetState = isExpanded,
69+ modifier = Modifier .fillMaxWidth(),
70+ transitionSpec = {
71+ slideInVertically { - it } togetherWith slideOutVertically { - it }
72+ }
73+ ) { expanded ->
74+ if (expanded) {
75+ FeedItemDetails (
76+ message = message,
77+ modifier = Modifier .fillMaxWidth(),
78+ dispatch = dispatch
79+ )
80+ } else {
81+ Spacer (modifier = Modifier .fillMaxWidth())
82+ }
83+ }
84+ }
85+ }
86+
87+
88+ private val cadUsdRate = Rate (fx = 1.371881 , currency = CurrencyCode .CAD )
89+ private val usdCadRate = Rate (fx = 1.0 / 1.371881 , currency = CurrencyCode .CAD )
90+ private val oneDollarCad = 1.00 .toFiat(CurrencyCode .CAD )
91+
92+ val rates = mapOf (
93+ CurrencyCode .CAD to cadUsdRate,
94+ CurrencyCode .USD to usdCadRate
95+ )
96+ private val oneDollarLocalized = LocalFiat (
97+ usdc = oneDollarCad.convertingTo(usdCadRate),
98+ converted = oneDollarCad,
99+ )
100+ private val sampleItem = ActivityFeedMessage (
101+ id = " 3GHjGey5F3fVProC3mYpiBpi7dCegFNz3wYtHSTiQnPt" .decodeBase58().toList(),
102+ text = " Gave" ,
103+ amount = oneDollarLocalized,
104+ timestamp = Instant .parse(" 2025-06-03T16:25:00-04:00" ),
105+ state = MessageState .COMPLETED ,
106+ metadata = MessageMetadata .GaveUsdc
107+ )
108+
109+ @Preview
110+ @Composable
111+ private fun Preview_CollapsedItem () {
112+ FlipcashDesignSystem {
113+ CompositionLocalProvider (
114+ LocalExchange provides ExchangeStub (
115+ providedRates = rates,
116+ context = LocalContext .current
117+ )
118+ ) {
119+ Box (modifier = Modifier .background(CodeTheme .colors.background)) {
120+ FeedItem (
121+ message = sampleItem,
122+ isExpanded = false ,
123+ canViewDetails = true ,
124+ ) { }
69125 }
70126 }
71127 }
72128}
73129
74- private fun Instant.formatRelativeToToday (): String {
75- if (DateUtils .isToday(toEpochMilliseconds())) {
76- return format(" hh:mm a" )
130+ @Preview
131+ @Composable
132+ private fun Preview_ExpandedItem () {
133+ FlipcashDesignSystem {
134+ CompositionLocalProvider (
135+ LocalExchange provides ExchangeStub (
136+ providedRates = rates,
137+ context = LocalContext .current
138+ )
139+ ) {
140+ Box (modifier = Modifier .background(CodeTheme .colors.background)) {
141+ FeedItem (
142+ message = sampleItem,
143+ isExpanded = true ,
144+ canViewDetails = true ,
145+ ) { }
146+ }
147+ }
77148 }
78- return format(" MMMM dd, yyyy" )
79149}
0 commit comments