Skip to content

Commit 64b3356

Browse files
committed
Merge branch 'fix/home-performance'
2 parents c19814e + 6b9e74a commit 64b3356

File tree

11 files changed

+152
-54
lines changed

11 files changed

+152
-54
lines changed

app/build.gradle.kts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,6 @@ android {
4949
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api" +
5050
"-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi"
5151

52-
freeCompilerArgs += listOf(
53-
"-P",
54-
"plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" +
55-
"${projectDir.absolutePath}/compose_stability.conf"
56-
)
57-
5852
val buildDir = layout.buildDirectory.asFile.get().absolutePath
5953
if (project.findProperty("composeCompilerReports") == "true") {
6054
freeCompilerArgs += listOf(
@@ -75,6 +69,10 @@ android {
7569
buildConfig = true
7670
}
7771

72+
composeCompiler {
73+
stabilityConfigurationFile.set(project.layout.projectDirectory.file("compose_stability.conf"))
74+
}
75+
7876
packaging {
7977
resources {
8078
excludes += "/META-INF/{AL2.0,LGPL2.1}"
@@ -134,6 +132,8 @@ dependencies {
134132

135133
implementation("androidx.datastore:datastore-preferences:1.1.1")
136134

135+
implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.8")
136+
137137
implementation("dev.olshevski.navigation:reimagined:1.5.0")
138138

139139
implementation("commons-codec:commons-codec:1.15")

app/src/main/java/com/xinto/mauth/domain/otp/model/DomainOtpRealtimeData.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import androidx.compose.runtime.Immutable
66
sealed interface DomainOtpRealtimeData {
77
val code: String
88

9+
@Immutable
910
data class Totp(
1011
override val code: String,
1112
val progress: Float,
1213
val countdown: Int,
1314
) : DomainOtpRealtimeData
1415

16+
@Immutable
1517
data class Hotp(
1618
override val code: String,
1719
val count: Int,

app/src/main/java/com/xinto/mauth/ui/screen/home/HomeScreen.kt

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package com.xinto.mauth.ui.screen.home
33
import androidx.activity.compose.rememberLauncherForActivityResult
44
import androidx.activity.result.PickVisualMediaRequest
55
import androidx.activity.result.contract.ActivityResultContracts
6-
import androidx.compose.foundation.layout.Box
76
import androidx.compose.foundation.layout.fillMaxSize
87
import androidx.compose.foundation.layout.padding
98
import androidx.compose.material3.TopAppBarDefaults
@@ -12,6 +11,8 @@ import androidx.compose.runtime.getValue
1211
import androidx.compose.runtime.mutableStateOf
1312
import androidx.compose.runtime.remember
1413
import androidx.compose.runtime.setValue
14+
import androidx.compose.runtime.snapshots.SnapshotStateList
15+
import androidx.compose.runtime.snapshots.SnapshotStateMap
1516
import androidx.compose.ui.Modifier
1617
import androidx.compose.ui.input.nestedscroll.nestedScroll
1718
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -25,6 +26,8 @@ import com.xinto.mauth.ui.screen.home.state.HomeScreenEmpty
2526
import com.xinto.mauth.ui.screen.home.state.HomeScreenError
2627
import com.xinto.mauth.ui.screen.home.state.HomeScreenLoading
2728
import com.xinto.mauth.ui.screen.home.state.HomeScreenSuccess
29+
import com.xinto.mauth.ui.util.collectAsStateListWithLifecycle
30+
import com.xinto.mauth.ui.util.collectAsStateMapWithLifecycle
2831
import org.koin.androidx.compose.koinViewModel
2932
import java.util.UUID
3033

@@ -40,8 +43,8 @@ fun HomeScreen(
4043
) {
4144
val viewModel: HomeViewModel = koinViewModel()
4245
val state by viewModel.state.collectAsStateWithLifecycle()
43-
val realTimeData by viewModel.realTimeData.collectAsStateWithLifecycle()
44-
val selectedAccounts by viewModel.selectedAccounts.collectAsStateWithLifecycle()
46+
val realTimeData = viewModel.realTimeData.collectAsStateMapWithLifecycle()
47+
val selectedAccounts = viewModel.selectedAccounts.collectAsStateListWithLifecycle()
4548
val activeSortSetting by viewModel.activeSortSetting.collectAsStateWithLifecycle()
4649

4750
val photoPickerLauncher = rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
@@ -96,8 +99,8 @@ fun HomeScreen(
9699
onAccountCounterIncrease: (UUID) -> Unit,
97100
onAccountCopyCode: (String, String, Boolean) -> Unit,
98101
state: HomeScreenState,
99-
accountRealtimeData: Map<UUID, DomainOtpRealtimeData>,
100-
selectedAccounts: List<UUID>,
102+
accountRealtimeData: SnapshotStateMap<UUID, DomainOtpRealtimeData>,
103+
selectedAccounts: SnapshotStateList<UUID>,
101104
activeSortSetting: SortSetting,
102105
onActiveSortChange: (SortSetting) -> Unit
103106
) {
@@ -118,33 +121,33 @@ fun HomeScreen(
118121
onActiveSortChange = onActiveSortChange,
119122
scrollBehavior = scrollBehavior
120123
) {
121-
Box(
122-
modifier = Modifier
124+
val modifier = remember {
125+
Modifier
123126
.fillMaxSize()
124127
.padding(it)
125128
.nestedScroll(scrollBehavior.nestedScrollConnection)
126-
) {
127-
when (state) {
128-
is HomeScreenState.Loading -> {
129-
HomeScreenLoading()
130-
}
131-
is HomeScreenState.Empty -> {
132-
HomeScreenEmpty()
133-
}
134-
is HomeScreenState.Success -> {
135-
HomeScreenSuccess(
136-
onAccountSelect = onAccountSelect,
137-
onAccountEdit = onAccountEdit,
138-
onAccountCounterIncrease = onAccountCounterIncrease,
139-
onAccountCopyCode = onAccountCopyCode,
140-
accounts = state.accounts,
141-
selectedAccounts = selectedAccounts,
142-
accountRealtimeData = accountRealtimeData
143-
)
144-
}
145-
is HomeScreenState.Error -> {
146-
HomeScreenError()
147-
}
129+
}
130+
when (state) {
131+
is HomeScreenState.Loading -> {
132+
HomeScreenLoading(modifier)
133+
}
134+
is HomeScreenState.Empty -> {
135+
HomeScreenEmpty(modifier)
136+
}
137+
is HomeScreenState.Success -> {
138+
HomeScreenSuccess(
139+
modifier = modifier,
140+
onAccountSelect = onAccountSelect,
141+
onAccountEdit = onAccountEdit,
142+
onAccountCounterIncrease = onAccountCounterIncrease,
143+
onAccountCopyCode = onAccountCopyCode,
144+
accounts = state.accounts,
145+
selectedAccounts = selectedAccounts,
146+
accountRealtimeData = accountRealtimeData
147+
)
148+
}
149+
is HomeScreenState.Error -> {
150+
HomeScreenError(modifier)
148151
}
149152
}
150153
}

app/src/main/java/com/xinto/mauth/ui/screen/home/HomeScreenState.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.xinto.mauth.ui.screen.home
22

33
import androidx.compose.runtime.Immutable
44
import com.xinto.mauth.domain.account.model.DomainAccount
5+
import kotlinx.collections.immutable.ImmutableList
56

67
@Immutable
78
sealed interface HomeScreenState {
@@ -14,7 +15,7 @@ sealed interface HomeScreenState {
1415

1516
@Immutable
1617
@JvmInline
17-
value class Success(val accounts: List<DomainAccount>) : HomeScreenState
18+
value class Success(val accounts: ImmutableList<DomainAccount>) : HomeScreenState
1819

1920
@Immutable
2021
@JvmInline

app/src/main/java/com/xinto/mauth/ui/screen/home/HomeViewModel.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import com.xinto.mauth.domain.account.AccountRepository
2222
import com.xinto.mauth.domain.account.model.DomainAccountInfo
2323
import com.xinto.mauth.domain.otp.OtpRepository
2424
import com.xinto.mauth.util.catchMap
25+
import kotlinx.collections.immutable.adapters.ImmutableListAdapter
2526
import kotlinx.coroutines.flow.MutableStateFlow
2627
import kotlinx.coroutines.flow.SharingStarted
2728
import kotlinx.coroutines.flow.asStateFlow
@@ -43,7 +44,7 @@ class HomeViewModel(
4344
val state = accounts.getAccounts()
4445
.map {
4546
when (it.isNotEmpty()) {
46-
true -> HomeScreenState.Success(it)
47+
true -> HomeScreenState.Success(ImmutableListAdapter(it))
4748
false -> HomeScreenState.Empty
4849
}
4950
}.catchMap {

app/src/main/java/com/xinto/mauth/ui/screen/home/component/HomeAccountCard.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.Arrangement
1212
import androidx.compose.foundation.layout.Box
1313
import androidx.compose.foundation.layout.Column
1414
import androidx.compose.foundation.layout.Row
15-
import androidx.compose.foundation.layout.Spacer
1615
import androidx.compose.foundation.layout.fillMaxWidth
1716
import androidx.compose.foundation.layout.padding
1817
import androidx.compose.foundation.layout.size
@@ -107,13 +106,16 @@ fun HomeAccountCard(
107106
)
108107
},
109108
bottomContent = {
110-
Row(verticalAlignment = Alignment.CenterVertically) {
109+
Row(
110+
modifier = Modifier.fillMaxWidth(),
111+
verticalAlignment = Alignment.CenterVertically,
112+
horizontalArrangement = Arrangement.SpaceBetween
113+
) {
111114
RealtimeInformation(
112115
realtimeData = realtimeData,
113116
showCode = showCode,
114117
onCounterClick = onCounterClick
115118
)
116-
Spacer(modifier = Modifier.weight(1f))
117119
InteractionButtons(
118120
showCode = showCode,
119121
onShowCodeChange = {

app/src/main/java/com/xinto/mauth/ui/screen/home/state/HomeScreenEmpty.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.xinto.mauth.ui.screen.home.state
22

33
import androidx.compose.foundation.layout.Arrangement
44
import androidx.compose.foundation.layout.Column
5-
import androidx.compose.foundation.layout.fillMaxSize
65
import androidx.compose.foundation.layout.size
76
import androidx.compose.material3.Icon
87
import androidx.compose.material3.MaterialTheme
@@ -17,9 +16,9 @@ import androidx.compose.ui.unit.dp
1716
import com.xinto.mauth.R
1817

1918
@Composable
20-
fun HomeScreenEmpty() {
19+
fun HomeScreenEmpty(modifier: Modifier = Modifier) {
2120
Column(
22-
modifier = Modifier.fillMaxSize(),
21+
modifier = modifier,
2322
verticalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterVertically),
2423
horizontalAlignment = Alignment.CenterHorizontally
2524
) {

app/src/main/java/com/xinto/mauth/ui/screen/home/state/HomeScreenError.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.xinto.mauth.ui.screen.home.state
22

33
import androidx.compose.foundation.layout.Arrangement
44
import androidx.compose.foundation.layout.Column
5-
import androidx.compose.foundation.layout.fillMaxSize
65
import androidx.compose.material3.Icon
76
import androidx.compose.material3.Text
87
import androidx.compose.runtime.Composable
@@ -14,9 +13,9 @@ import androidx.compose.ui.unit.dp
1413
import com.xinto.mauth.R
1514

1615
@Composable
17-
fun HomeScreenError() {
16+
fun HomeScreenError(modifier: Modifier = Modifier) {
1817
Column(
19-
modifier = Modifier.fillMaxSize(),
18+
modifier = modifier,
2019
verticalArrangement = Arrangement.spacedBy(2.dp, Alignment.CenterVertically),
2120
horizontalAlignment = Alignment.CenterHorizontally
2221
) {

app/src/main/java/com/xinto/mauth/ui/screen/home/state/HomeScreenLoading.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package com.xinto.mauth.ui.screen.home.state
22

33
import androidx.compose.foundation.layout.Box
4-
import androidx.compose.foundation.layout.fillMaxSize
54
import androidx.compose.material3.CircularProgressIndicator
65
import androidx.compose.runtime.Composable
76
import androidx.compose.ui.Alignment
87
import androidx.compose.ui.Modifier
98

109
@Composable
11-
fun HomeScreenLoading() {
10+
fun HomeScreenLoading(modifier: Modifier = Modifier) {
1211
Box(
13-
modifier = Modifier.fillMaxSize(),
12+
modifier = modifier,
1413
contentAlignment = Alignment.Center
1514
) {
1615
CircularProgressIndicator()

app/src/main/java/com/xinto/mauth/ui/screen/home/state/HomeScreenSuccess.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,33 @@ package com.xinto.mauth.ui.screen.home.state
22

33
import androidx.compose.foundation.layout.Arrangement
44
import androidx.compose.foundation.layout.PaddingValues
5-
import androidx.compose.foundation.layout.fillMaxSize
65
import androidx.compose.foundation.lazy.grid.GridCells
76
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
87
import androidx.compose.foundation.lazy.grid.items
98
import androidx.compose.runtime.Composable
9+
import androidx.compose.runtime.snapshots.SnapshotStateList
10+
import androidx.compose.runtime.snapshots.SnapshotStateMap
1011
import androidx.compose.ui.Modifier
1112
import androidx.compose.ui.unit.dp
1213
import com.xinto.mauth.domain.account.model.DomainAccount
1314
import com.xinto.mauth.domain.otp.model.DomainOtpRealtimeData
1415
import com.xinto.mauth.ui.screen.home.component.HomeAccountCard
16+
import kotlinx.collections.immutable.ImmutableList
1517
import java.util.UUID
1618

1719
@Composable
1820
fun HomeScreenSuccess(
21+
modifier: Modifier = Modifier,
1922
onAccountSelect: (UUID) -> Unit,
2023
onAccountEdit: (UUID) -> Unit,
2124
onAccountCounterIncrease: (UUID) -> Unit,
2225
onAccountCopyCode: (String, String, Boolean) -> Unit,
23-
accounts: List<DomainAccount>,
24-
selectedAccounts: List<UUID>,
25-
accountRealtimeData: Map<UUID, DomainOtpRealtimeData>,
26+
accounts: ImmutableList<DomainAccount>,
27+
selectedAccounts: SnapshotStateList<UUID>,
28+
accountRealtimeData: SnapshotStateMap<UUID, DomainOtpRealtimeData>,
2629
) {
2730
LazyVerticalGrid(
28-
modifier = Modifier.fillMaxSize(),
31+
modifier = modifier,
2932
contentPadding = PaddingValues(16.dp),
3033
verticalArrangement = Arrangement.spacedBy(12.dp),
3134
horizontalArrangement = Arrangement.spacedBy(12.dp),

0 commit comments

Comments
 (0)