Skip to content

Commit fbb5d8a

Browse files
committed
feat(flipcash): stand up persistence layer and modules; persist activity feed and add paging
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 12f4a73 commit fbb5d8a

73 files changed

Lines changed: 1191 additions & 277 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/flipcash/app/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ dependencies {
116116
implementation(project(":services:flipcash-compose"))
117117

118118
implementation(project(":apps:flipcash:core"))
119+
implementation(project(":apps:flipcash:shared:authentication"))
120+
implementation(project(":apps:flipcash:shared:session"))
119121
implementation(project(":apps:flipcash:features:currency-selection:core"))
120122
implementation(project(":apps:flipcash:features:currency-selection:ui"))
121123
implementation(project(":apps:flipcash:features:accesskey"))

apps/flipcash/app/src/main/kotlin/com/flipcash/app/App.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ import cafe.adriel.voyager.navigator.Navigator
2121
import cafe.adriel.voyager.navigator.currentOrThrow
2222
import cafe.adriel.voyager.transitions.CrossfadeTransition
2323
import cafe.adriel.voyager.transitions.SlideTransition
24-
import com.flipcash.app.core.LocalSessionController
2524
import com.flipcash.app.core.LocalUserManager
2625
import com.flipcash.app.core.NavScreenProvider
2726
import com.flipcash.app.router.DeeplinkType
27+
import com.flipcash.app.session.LocalSessionController
2828
import com.flipcash.app.theme.FlipcashTheme
2929
import com.flipcash.app.ui.LocalRouter
3030
import com.flipcash.app.ui.navigation.AppScreenContent

apps/flipcash/app/src/main/kotlin/com/flipcash/app/FlipcashApp.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import coil3.disk.directory
1010
import coil3.request.CachePolicy
1111
import coil3.request.crossfade
1212
import com.bugsnag.android.Bugsnag
13-
import com.flipcash.app.core.auth.AuthManager
13+
import com.flipcash.app.auth.AuthManager
1414
import com.flipcash.app.currency.PreferredCurrencyController
1515
import com.getcode.crypt.MnemonicCache
1616
import com.getcode.opencode.repositories.EventRepository

apps/flipcash/app/src/main/kotlin/com/flipcash/app/MainActivity.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import androidx.activity.compose.setContent
99
import androidx.activity.enableEdgeToEdge
1010
import androidx.compose.runtime.CompositionLocalProvider
1111
import androidx.fragment.app.FragmentActivity
12-
import com.flipcash.app.core.LocalSessionController
1312
import com.flipcash.app.core.LocalUserManager
14-
import com.flipcash.app.core.SessionController
13+
import com.flipcash.app.session.SessionController
1514
import com.flipcash.app.router.Router
15+
import com.flipcash.app.session.LocalSessionController
1616
import com.flipcash.app.ui.LocalRouter
1717
import com.flipcash.services.LocalBillingClient
1818
import com.flipcash.services.billing.BillingClient

apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/Locals.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@ import androidx.compose.runtime.staticCompositionLocalOf
44
import com.flipcash.services.user.UserManager
55

66
val LocalUserManager = staticCompositionLocalOf<UserManager?> { null }
7-
val LocalSessionController = staticCompositionLocalOf<SessionController?> { null }
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.flipcash.app.core.feed
2+
3+
import com.getcode.opencode.model.core.ID
4+
import com.getcode.opencode.model.financial.LocalFiat
5+
import com.getcode.solana.keys.PublicKey
6+
import kotlinx.datetime.Instant
7+
import kotlinx.serialization.Serializable
8+
import kotlinx.serialization.json.Json
9+
10+
data class ActivityFeedMessage(
11+
val id: ID,
12+
val text: String,
13+
val amount: LocalFiat?,
14+
val timestamp: Instant,
15+
val state: MessageState,
16+
val metadata: MessageMetadata?
17+
)
18+
19+
enum class MessageState {
20+
UNKNOWN,
21+
PENDING,
22+
COMPLETED;
23+
24+
companion object {
25+
fun from(named: String) = try {
26+
valueOf(named.uppercase())
27+
} catch (e: IllegalArgumentException) {
28+
UNKNOWN
29+
}
30+
}
31+
}
32+
33+
@Serializable
34+
sealed interface MessageMetadata {
35+
@Serializable
36+
data object Unknown : MessageMetadata
37+
38+
@Serializable
39+
data object WelcomeBonus : MessageMetadata
40+
41+
@Serializable
42+
data object GaveUsdc : MessageMetadata
43+
44+
@Serializable
45+
data class SentUsdc(
46+
val creator: PublicKey,
47+
val canCancel: Boolean,
48+
) : MessageMetadata
49+
50+
@Serializable
51+
data object ReceivedUsdc : MessageMetadata
52+
53+
@Serializable
54+
data object WithdrewUsdc : MessageMetadata
55+
56+
companion object {
57+
fun from(named: String?): MessageMetadata? {
58+
named ?: return null
59+
return try {
60+
Json.decodeFromString<MessageMetadata>(named)
61+
} catch (e: IllegalArgumentException) {
62+
Unknown
63+
}
64+
}
65+
}
66+
}

apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/internal/share/ShareSheetController.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ import android.content.IntentFilter
99
import androidx.localbroadcastmanager.content.LocalBroadcastManager
1010
import com.flipcash.app.core.internal.Linkify
1111
import com.flipcash.app.core.money.formatted
12+
import com.flipcash.core.R
13+
import com.getcode.opencode.controllers.BalanceController
1214
import com.getcode.opencode.model.accounts.GiftCardAccount
1315
import com.getcode.opencode.model.accounts.entropy
16+
import com.getcode.opencode.model.financial.CurrencyCode
1417
import com.getcode.opencode.model.financial.LocalFiat
18+
import com.getcode.util.resources.ResourceHelper
1519
import dagger.hilt.android.qualifiers.ApplicationContext
1620
import kotlinx.coroutines.delay
1721
import java.security.SecureRandom
@@ -29,6 +33,8 @@ class ShareSheetController @Inject constructor(
2933
@ApplicationContext
3034
private val context: Context,
3135
private val clipboardManager: ClipboardManager,
36+
private val resources: ResourceHelper,
37+
private val balanceController: BalanceController,
3238
) {
3339
internal companion object {
3440
const val ACTION_SHARE_CASH_LINK = "com.flipcash.app.ACTION_SHARE_CASH_LINK"
@@ -39,6 +45,7 @@ class ShareSheetController @Inject constructor(
3945
private var sharedWithApp: String? = null
4046

4147
private var pendingEntropy = ""
48+
private var pendingAmount: LocalFiat? = null
4249

4350
var onShared: ((ShareResult) -> Unit)? = null
4451

@@ -53,6 +60,7 @@ class ShareSheetController @Inject constructor(
5360

5461
// if it was shared with an app, return successfully
5562
if (sharedWithApp != null) {
63+
pendingAmount?.let { balanceController.subtract(it) }
5664
onShared?.invoke(ShareResult.SharedToApp(sharedWithApp!!))
5765
return
5866
}
@@ -61,6 +69,7 @@ class ShareSheetController @Inject constructor(
6169
if (clipboardManager.hasPrimaryClip()) {
6270
val clippedText = clipboardManager.primaryClip?.getItemAt(0)?.text
6371
if (clippedText?.contains(pendingEntropy) == true) {
72+
pendingAmount?.let { balanceController.subtract(it) }
6473
onShared?.invoke(ShareResult.CopiedToClipboard)
6574
}
6675
}
@@ -80,6 +89,7 @@ class ShareSheetController @Inject constructor(
8089
amount: LocalFiat
8190
) {
8291
pendingEntropy = giftCardAccount.entropy
92+
pendingAmount = amount
8393
shareCashLink(giftCardAccount, amount)
8494
delay(300)
8595
isChecking = true
@@ -94,7 +104,12 @@ class ShareSheetController @Inject constructor(
94104
amount: LocalFiat,
95105
) {
96106
val url = Linkify.cashLink(giftCardAccount.entropy)
97-
val text = "${amount.formatted} $url"
107+
val suffix = amount.converted.currencyCode.takeIf {
108+
it != CurrencyCode.USD
109+
}?.let {
110+
resources.getString(R.string.subtitle_ofUsdSuffix)
111+
}
112+
val text = "${amount.formatted(suffix = suffix)} $url"
98113
val intent = Intent().apply {
99114
action = Intent.ACTION_SEND
100115
putExtra(Intent.EXTRA_TEXT, text)

apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/money/FormatUtils.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ fun Int.withCommas(): String {
3939
return this.toString().reversed().chunked(3).joinToString(",").reversed()
4040
}
4141

42-
val LocalFiat.formatted: String
43-
get() {
44-
return converted.formatted()
45-
}
42+
fun LocalFiat.formatted(suffix: String? = null, truncated: Boolean = false): String {
43+
return converted.formatted(suffix, truncated)
44+
}

apps/flipcash/core/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,6 @@
4646
<string name="prompt_description_cancelTransfer">The money will be returned to your wallet</string>
4747
<string name="action_cancelTransfer">Cancel Transfer</string>
4848
<string name="action_nevermind">Nevermind</string>
49+
50+
<string name="subtitle_ofUsdSuffix">of USD</string>
4951
</resources>

apps/flipcash/features/balance/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,10 @@ dependencies {
5353
implementation(Libs.compose_foundation)
5454
implementation(Libs.compose_material)
5555
implementation(Libs.compose_materialIconsExtended)
56+
implementation(Libs.compose_paging)
5657

5758
implementation(project(":apps:flipcash:core"))
59+
implementation(project(":apps:flipcash:shared:activityfeed"))
5860
implementation(project(":libs:datetime"))
5961
implementation(project(":libs:logging"))
6062
implementation(project(":libs:messaging"))
@@ -65,5 +67,6 @@ dependencies {
6567
implementation(project(":ui:navigation"))
6668
implementation(project(":ui:resources"))
6769
implementation(project(":ui:theme"))
70+
6871
implementation(Libs.rinku_compose)
6972
}

0 commit comments

Comments
 (0)