Skip to content

Commit 401e6c0

Browse files
committed
Merge branch 'code/cash' into refactor/merge-account-info-into-profile
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
2 parents ddbac76 + d6e1592 commit 401e6c0

74 files changed

Lines changed: 136 additions & 4499 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: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ bugsnag {
118118
}
119119
}
120120

121+
composeCompiler {
122+
stabilityConfigurationFile.set(
123+
rootProject.layout.projectDirectory.file("compose_compiler_config.conf")
124+
)
125+
}
126+
121127
kotlin {
122128
jvmToolchain {
123129
languageVersion.set(JavaLanguageVersion.of(libs.versions.android.java.get()))

apps/flipcash/app/src/main/kotlin/com/flipcash/app/internal/ui/HomeViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ internal class HomeViewModel @Inject constructor(
3131
private val _requireBiometrics = MutableStateFlow<Boolean?>(null)
3232
val requireBiometrics = _requireBiometrics.stateIn(
3333
viewModelScope,
34-
started = SharingStarted.Eagerly,
34+
started = SharingStarted.WhileSubscribed(5_000),
3535
initialValue = null
3636
)
3737

apps/flipcash/features/lab/src/main/kotlin/com/flipcash/app/lab/internal/LabsScreenContent.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@ internal fun LabsScreenContent(viewModel: LabsScreenViewModel) {
5656
.sheetResignmentBehavior(state),
5757
contentPadding = PaddingValues(bottom = CodeTheme.dimens.grid.x3),
5858
) {
59-
item {
59+
item(contentType = "section_header") {
6060
SectionHeader(
6161
modifier = Modifier.padding(horizontal = CodeTheme.dimens.inset),
6262
title = stringResource(R.string.title_settingsSectionFeatures)
6363
)
6464
}
65-
items(betaFlags, key = { it.flag.key }) { feature ->
65+
items(betaFlags, key = { it.flag.key }, contentType = { "feature_flag" }) { feature ->
6666
if (feature.flag.isOptionFlag) {
6767
SettingsOptionRow(
6868
title = feature.flag.title,
@@ -91,7 +91,7 @@ internal fun LabsScreenContent(viewModel: LabsScreenViewModel) {
9191
}
9292

9393
if (betaFlags.isEmpty()) {
94-
item {
94+
item(contentType = "empty_state") {
9595
Box {
9696
Column(
9797
modifier = Modifier.align(Alignment.Center),
@@ -117,13 +117,13 @@ internal fun LabsScreenContent(viewModel: LabsScreenViewModel) {
117117
}
118118
}
119119

120-
item {
120+
item(contentType = "section_header") {
121121
SectionHeader(
122122
modifier = Modifier.padding(horizontal = CodeTheme.dimens.inset),
123123
title = stringResource(R.string.title_settingsSectionHomeScreen)
124124
)
125125
}
126-
item {
126+
item(contentType = "list_item") {
127127
ListItem(
128128
headline = stringResource(R.string.title_settingsButtonOrder),
129129
icon = painterResource(R.drawable.ic_bottom_navigation),
@@ -133,13 +133,13 @@ internal fun LabsScreenContent(viewModel: LabsScreenViewModel) {
133133
}
134134

135135
if (isStaff) {
136-
item {
136+
item(contentType = "section_header") {
137137
SectionHeader(
138138
modifier = Modifier.padding(horizontal = CodeTheme.dimens.inset),
139139
title = stringResource(R.string.title_settingsSectionDeveloper)
140140
)
141141
}
142-
item {
142+
item(contentType = "list_item") {
143143
ListItem(
144144
headline = stringResource(R.string.subtitle_settingsUserFlags),
145145
icon = rememberVectorPainter(Icons.Default.Token),

apps/flipcash/features/lab/src/main/kotlin/com/flipcash/app/lab/internal/LabsScreenViewModel.kt

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,17 @@ package com.flipcash.app.lab.internal
33
import androidx.lifecycle.ViewModel
44
import androidx.lifecycle.viewModelScope
55
import com.flipcash.app.userflags.UserFlagsCoordinator
6-
import com.flipcash.services.user.AuthState
7-
import com.flipcash.services.user.UserManager
86
import dagger.hilt.android.lifecycle.HiltViewModel
97
import kotlinx.coroutines.flow.SharingStarted
10-
import kotlinx.coroutines.flow.filterIsInstance
118
import kotlinx.coroutines.flow.map
129
import kotlinx.coroutines.flow.stateIn
1310
import javax.inject.Inject
1411

1512
@HiltViewModel
1613
class LabsScreenViewModel @Inject constructor(
17-
userManager: UserManager,
1814
userFlags: UserFlagsCoordinator,
1915
) : ViewModel() {
2016

21-
val isLoggedIn = userManager
22-
.state.map { it.authState }
23-
.filterIsInstance<AuthState.Ready>()
24-
.map { true }
25-
.stateIn(viewModelScope, started = SharingStarted.Eagerly, initialValue = false)
26-
2717
val isStaff = userFlags.resolvedFlags.map { it.isStaff.effectiveValue }
28-
.stateIn(viewModelScope, started = SharingStarted.Eagerly, initialValue = false)
18+
.stateIn(viewModelScope, started = SharingStarted.WhileSubscribed(5_000), initialValue = false)
2919
}

apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/internal/UserProfileScreenContent.kt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.padding
1313
import androidx.compose.foundation.layout.requiredSize
1414
import androidx.compose.foundation.layout.size
1515
import androidx.compose.foundation.lazy.LazyColumn
16+
import androidx.compose.foundation.lazy.items
1617
import androidx.compose.material.icons.Icons
1718
import androidx.compose.material.icons.filled.Add
1819
import androidx.compose.material.icons.filled.ContentCopy
@@ -130,8 +131,8 @@ internal fun UserProfileScreenContent(
130131
}
131132

132133
// Display Name section
133-
item { SectionHeader(stringResource(R.string.title_sectionDisplayName)) }
134-
item {
134+
item(contentType = "section_header") { SectionHeader(stringResource(R.string.title_sectionDisplayName)) }
135+
item(contentType = "profile_value") {
135136
val name = state.displayName
136137
if (!name.isNullOrEmpty()) {
137138
CardRow { ProfileValueRow(value = name) }
@@ -151,8 +152,8 @@ internal fun UserProfileScreenContent(
151152
}
152153

153154
// Phone section
154-
item { SectionHeader(stringResource(R.string.title_sectionPhone)) }
155-
item {
155+
item(contentType = "section_header") { SectionHeader(stringResource(R.string.title_sectionPhone)) }
156+
item(contentType = "contact_method") {
156157
if (state.phoneNumber != null) {
157158
SwipeActionRow(
158159
onDelete = { dispatch(UserProfileViewModel.Event.UnlinkPhoneClicked) },
@@ -178,8 +179,8 @@ internal fun UserProfileScreenContent(
178179
}
179180

180181
// Email section
181-
item { SectionHeader(stringResource(R.string.title_sectionEmail)) }
182-
item {
182+
item(contentType = "section_header") { SectionHeader(stringResource(R.string.title_sectionEmail)) }
183+
item(contentType = "contact_method") {
183184
if (state.emailAddress != null) {
184185
SwipeActionRow(
185186
onDelete = { dispatch(UserProfileViewModel.Event.UnlinkEmailClicked) },
@@ -203,9 +204,9 @@ internal fun UserProfileScreenContent(
203204
}
204205

205206
// Social Accounts section
206-
item { SectionHeader(stringResource(R.string.title_sectionSocialAccounts)) }
207+
item(contentType = "section_header") { SectionHeader(stringResource(R.string.title_sectionSocialAccounts)) }
207208
if (state.socialAccounts.isEmpty()) {
208-
item {
209+
item(contentType = "empty_state") {
209210
CardRow {
210211
Text(
211212
text = stringResource(R.string.subtitle_noSocialAccounts),
@@ -219,9 +220,9 @@ internal fun UserProfileScreenContent(
219220
}
220221
}
221222
} else {
222-
state.socialAccounts.forEach { account ->
223+
items(state.socialAccounts, key = { it.id }, contentType = { "social_account" }) { account ->
223224
when (account) {
224-
is SocialAccount.TwitterX -> item(key = account.id) {
225+
is SocialAccount.TwitterX -> {
225226
SwipeActionRow(
226227
onDelete = {
227228
dispatch(

apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/UserFlagsEditor.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,21 @@ private fun UserFlagsEditor(
7474
contentPadding = PaddingValues(bottom = CodeTheme.dimens.grid.x3),
7575
) {
7676
// Read-only section
77-
item { SectionHeader("Read-Only") }
77+
item(contentType = "section_header") { SectionHeader("Read-Only") }
7878
items(
7979
items = state.readOnlyEntries,
8080
key = { it.label },
81+
contentType = { "read_only_row" },
8182
) { entry ->
8283
ReadOnlyRow(entry)
8384
}
8485

8586
// Editable section
86-
item { SectionHeader("Overridable") }
87+
item(contentType = "section_header") { SectionHeader("Overridable") }
8788
items(
8889
items = state.editableEntries,
8990
key = { it.field.label },
91+
contentType = { "editable_row" },
9092
) { entry ->
9193
EditableRow(
9294
modifier = Modifier.fillMaxWidth(),

apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/TokenList.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,19 @@ fun TokenList(
8282
state = listState
8383
) {
8484
if (tokens != null && tokens.isEmpty() && emptyState != null) {
85-
item {
85+
item(contentType = "empty_state") {
8686
emptyState()
8787
}
8888
} else {
8989
header?.let { content ->
90-
item {
90+
item(contentType = "header") {
9191
content()
9292
}
9393
}
9494
items(
9595
items = filteredTokens.orEmpty(),
96-
key = { item -> item.token.address.base58() }) { item ->
96+
key = { item -> item.token.address.base58() },
97+
contentType = { "token_row" }) { item ->
9798
TokenBalanceRow(
9899
modifier = Modifier
99100
.fillParentMaxWidth()
@@ -113,7 +114,7 @@ fun TokenList(
113114
Fiat(0.0, cashReserves.rate.currency)
114115
)
115116
) {
116-
item {
117+
item(contentType = "reserves") {
117118
it(Mint.usdf, cashReserves)
118119
HorizontalDivider(
119120
modifier = Modifier.padding(bottom = CodeTheme.dimens.inset),
@@ -124,7 +125,7 @@ fun TokenList(
124125
}
125126

126127
footer?.let {
127-
item {
128+
item(contentType = "footer") {
128129
Box(modifier = Modifier.alpha(if (footerSettled) 1f else 0f)) {
129130
it(false)
130131
}

build-logic/convention/src/main/kotlin/AndroidLibraryComposeConventionPlugin.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import org.gradle.api.artifacts.VersionCatalogsExtension
55
import org.gradle.kotlin.dsl.configure
66
import org.gradle.kotlin.dsl.dependencies
77
import org.gradle.kotlin.dsl.getByType
8+
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginExtension
89

910
class AndroidLibraryComposeConventionPlugin : Plugin<Project> {
1011
override fun apply(target: Project) {
@@ -20,6 +21,12 @@ class AndroidLibraryComposeConventionPlugin : Plugin<Project> {
2021
}
2122
}
2223

24+
extensions.configure<ComposeCompilerGradlePluginExtension> {
25+
stabilityConfigurationFile.set(
26+
rootProject.layout.projectDirectory.file("compose_compiler_config.conf")
27+
)
28+
}
29+
2330
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
2431

2532
dependencies {

compose_compiler_config.conf

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Compose Compiler Stability Configuration
2+
// Types listed here are treated as stable by the Compose compiler,
3+
// enabling skipping optimizations for composables that accept them.
4+
//
5+
// Only types from non-Compose modules (where @Stable/@Immutable cannot
6+
// be applied directly) belong here.
7+
8+
// Kotlin / JDK time types
9+
kotlin.time.Instant
10+
java.time.Instant
11+
12+
// Solana key hierarchy (open class chain with List<Byte> internals)
13+
com.getcode.solana.keys.Key32
14+
com.getcode.solana.keys.PublicKey
15+
com.getcode.solana.keys.Mint
16+
17+
// Financial model types (services/opencode — no Compose dependency)
18+
com.getcode.opencode.model.financial.Fiat
19+
com.getcode.opencode.model.financial.Rate
20+
com.getcode.opencode.model.financial.LocalFiat
21+
com.getcode.opencode.model.financial.MintMetadata
22+
com.getcode.opencode.model.financial.TokenWithBalance
23+
com.getcode.opencode.model.financial.TokenWithLocalizedBalance
24+
com.getcode.opencode.model.financial.VmMetadata
25+
com.getcode.opencode.model.financial.LaunchpadMetadata
26+
com.getcode.opencode.model.financial.HolderMetrics
27+
com.getcode.opencode.model.financial.HolderMetrics.HolderDelta
28+
com.getcode.opencode.model.financial.SocialLink
29+
com.getcode.opencode.model.financial.SocialLink.Website
30+
com.getcode.opencode.model.financial.SocialLink.X
31+
com.getcode.opencode.model.financial.SocialLink.Telegram
32+
com.getcode.opencode.model.financial.SocialLink.Discord
33+
34+
// Bill customization (contains ByteArray, custom equals)
35+
com.getcode.opencode.model.ui.TokenBillCustomizations
36+

0 commit comments

Comments
 (0)