Skip to content

Commit 316a02a

Browse files
committed
Merge branch 'master' into chore/update-deps
# Conflicts: # app/src/main/java/to/bitkit/ui/screens/wallets/activity/ActivityDetailScreen.kt
2 parents ce263bd + 8873f41 commit 316a02a

File tree

6 files changed

+494
-149
lines changed

6 files changed

+494
-149
lines changed

app/src/main/java/to/bitkit/ui/ContentView.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1166,7 +1166,6 @@ private fun NavGraphBuilder.activityItem(
11661166
}
11671167
composableWithDefaultTransitions<Routes.ActivityExplore> {
11681168
ActivityExploreScreen(
1169-
listViewModel = activityListViewModel,
11701169
route = it.toRoute(),
11711170
onBackClick = { navController.popBackStack() },
11721171
)

app/src/main/java/to/bitkit/ui/screens/wallets/activity/ActivityDetailScreen.kt

Lines changed: 163 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ import androidx.compose.foundation.layout.size
1717
import androidx.compose.foundation.layout.width
1818
import androidx.compose.foundation.rememberScrollState
1919
import androidx.compose.foundation.verticalScroll
20+
import androidx.compose.material3.CircularProgressIndicator
2021
import androidx.compose.material3.HorizontalDivider
2122
import androidx.compose.material3.Icon
2223
import androidx.compose.runtime.Composable
24+
import androidx.compose.runtime.DisposableEffect
2325
import androidx.compose.runtime.LaunchedEffect
2426
import androidx.compose.runtime.ReadOnlyComposable
2527
import androidx.compose.runtime.getValue
@@ -77,7 +79,6 @@ import to.bitkit.ui.theme.AppThemeSurface
7779
import to.bitkit.ui.theme.Colors
7880
import to.bitkit.ui.utils.copyToClipboard
7981
import to.bitkit.ui.utils.getScreenTitleRes
80-
import to.bitkit.utils.Logger
8182
import to.bitkit.viewmodels.ActivityDetailViewModel
8283
import to.bitkit.viewmodels.ActivityListViewModel
8384

@@ -91,129 +92,185 @@ fun ActivityDetailScreen(
9192
onCloseClick: () -> Unit,
9293
onChannelClick: ((String) -> Unit)? = null,
9394
) {
94-
val activities by listViewModel.filteredActivities.collectAsStateWithLifecycle()
95-
val item = activities?.find { it.rawId() == route.id }
96-
if (item == null) {
97-
Logger.error("Activity not found")
98-
return
99-
}
95+
val uiState by detailViewModel.uiState.collectAsStateWithLifecycle()
10096

101-
val app = appViewModel ?: return
102-
val copyToastTitle = stringResource(R.string.common__copied)
103-
104-
val tags by detailViewModel.tags.collectAsStateWithLifecycle()
105-
val boostSheetVisible by detailViewModel.boostSheetVisible.collectAsStateWithLifecycle()
106-
var showAddTagSheet by remember { mutableStateOf(false) }
107-
var isCpfpChild by remember { mutableStateOf(false) }
108-
var boostTxDoesExist by remember { mutableStateOf<Map<String, Boolean>>(emptyMap()) }
109-
110-
LaunchedEffect(item) {
111-
detailViewModel.setActivity(item)
112-
if (item is Activity.Onchain) {
113-
isCpfpChild = detailViewModel.isCpfpChildTransaction(item.v1.txId)
114-
boostTxDoesExist = if (item.v1.boostTxIds.isNotEmpty()) {
115-
detailViewModel.getBoostTxDoesExist(item.v1.boostTxIds)
116-
} else {
117-
emptyMap()
118-
}
119-
} else {
120-
isCpfpChild = false
121-
boostTxDoesExist = emptyMap()
122-
}
97+
// Load activity on composition
98+
LaunchedEffect(route.id) {
99+
detailViewModel.loadActivity(route.id)
123100
}
124101

125-
// Update boostTxDoesExist when boostTxIds change
126-
LaunchedEffect(if (item is Activity.Onchain) item.v1.boostTxIds else emptyList()) {
127-
if (item is Activity.Onchain && item.v1.boostTxIds.isNotEmpty()) {
128-
boostTxDoesExist = detailViewModel.getBoostTxDoesExist(item.v1.boostTxIds)
102+
// Clear state on disposal
103+
DisposableEffect(Unit) {
104+
onDispose {
105+
detailViewModel.clearActivityState()
129106
}
130107
}
131108

132-
val context = LocalContext.current
133-
134109
Box(
135110
modifier = Modifier.fillMaxWidth()
136111
) {
137-
Column(
138-
modifier = Modifier.background(Colors.Black)
139-
) {
140-
AppTopBar(
141-
titleText = stringResource(
142-
if (isCpfpChild) {
143-
R.string.wallet__activity_boost_fee
144-
} else {
145-
item.getScreenTitleRes()
146-
}
147-
),
148-
onBackClick = onBackClick,
149-
actions = { DrawerNavIcon() },
150-
)
151-
ActivityDetailContent(
152-
item = item,
153-
tags = tags,
154-
onRemoveTag = { detailViewModel.removeTag(it) },
155-
onAddTagClick = { showAddTagSheet = true },
156-
onClickBoost = detailViewModel::onClickBoost,
157-
onExploreClick = onExploreClick,
158-
onChannelClick = onChannelClick,
159-
detailViewModel = detailViewModel,
160-
isCpfpChild = isCpfpChild,
161-
boostTxDoesExist = boostTxDoesExist,
162-
onCopy = { text ->
163-
app.toast(
164-
type = Toast.ToastType.SUCCESS,
165-
title = copyToastTitle,
166-
description = text.ellipsisMiddle(40)
112+
when (val loadState = uiState.activityLoadState) {
113+
is ActivityDetailViewModel.ActivityLoadState.Initial,
114+
is ActivityDetailViewModel.ActivityLoadState.Loading,
115+
-> {
116+
Column(modifier = Modifier.background(Colors.Black)) {
117+
AppTopBar(
118+
titleText = stringResource(R.string.wallet__activity),
119+
onBackClick = onBackClick,
120+
actions = { DrawerNavIcon() },
167121
)
122+
Box(
123+
modifier = Modifier
124+
.fillMaxSize()
125+
.padding(16.dp),
126+
contentAlignment = Alignment.Center
127+
) {
128+
CircularProgressIndicator()
129+
}
168130
}
169-
)
170-
if (showAddTagSheet) {
171-
ActivityAddTagSheet(
172-
listViewModel = listViewModel,
173-
activityViewModel = detailViewModel,
174-
onDismiss = { showAddTagSheet = false },
175-
)
176131
}
177-
}
178132

179-
if (boostSheetVisible) {
180-
(item as? Activity.Onchain)?.let {
181-
@SuppressLint("LocalContextGetResourceValueCall")
182-
BoostTransactionSheet(
183-
onDismiss = detailViewModel::onDismissBoostSheet,
184-
item = it,
185-
onSuccess = {
186-
app.toast(
187-
type = Toast.ToastType.SUCCESS,
188-
title = context.getString(R.string.wallet__boost_success_title),
189-
description = context.getString(R.string.wallet__boost_success_msg)
133+
is ActivityDetailViewModel.ActivityLoadState.Error -> {
134+
Column(modifier = Modifier.background(Colors.Black)) {
135+
AppTopBar(
136+
titleText = stringResource(R.string.wallet__activity),
137+
onBackClick = onBackClick,
138+
actions = { DrawerNavIcon() },
139+
)
140+
Column(
141+
modifier = Modifier
142+
.fillMaxSize()
143+
.padding(16.dp),
144+
horizontalAlignment = Alignment.CenterHorizontally,
145+
verticalArrangement = Arrangement.Center
146+
) {
147+
BodySSB(
148+
text = loadState.message,
149+
modifier = Modifier.padding(bottom = 16.dp)
190150
)
191-
listViewModel.resync()
192-
onCloseClick()
193-
},
194-
onFailure = {
195-
app.toast(
196-
type = Toast.ToastType.ERROR,
197-
title = context.getString(R.string.wallet__boost_error_title),
198-
description = context.getString(R.string.wallet__boost_error_msg)
151+
PrimaryButton(
152+
text = stringResource(R.string.common__back),
153+
onClick = onBackClick
199154
)
200-
detailViewModel.onDismissBoostSheet()
201-
},
202-
onMaxFee = {
203-
app.toast(
204-
type = Toast.ToastType.ERROR,
205-
title = context.getString(R.string.wallet__send_fee_error),
206-
description = context.getString(R.string.wallet__boost_error_msg_max)
155+
}
156+
}
157+
}
158+
159+
is ActivityDetailViewModel.ActivityLoadState.Success -> {
160+
val item = loadState.activity
161+
val app = appViewModel ?: return@Box
162+
val copyToastTitle = stringResource(R.string.common__copied)
163+
164+
val tags by detailViewModel.tags.collectAsStateWithLifecycle()
165+
val boostSheetVisible by detailViewModel.boostSheetVisible.collectAsStateWithLifecycle()
166+
var showAddTagSheet by remember { mutableStateOf(false) }
167+
var isCpfpChild by remember { mutableStateOf(false) }
168+
var boostTxDoesExist by remember { mutableStateOf<Map<String, Boolean>>(emptyMap()) }
169+
170+
LaunchedEffect(item) {
171+
if (item is Activity.Onchain) {
172+
isCpfpChild = detailViewModel.isCpfpChildTransaction(item.v1.txId)
173+
boostTxDoesExist = if (item.v1.boostTxIds.isNotEmpty()) {
174+
detailViewModel.getBoostTxDoesExist(item.v1.boostTxIds)
175+
} else {
176+
emptyMap()
177+
}
178+
} else {
179+
isCpfpChild = false
180+
boostTxDoesExist = emptyMap()
181+
}
182+
}
183+
184+
// Update boostTxDoesExist when boostTxIds change
185+
LaunchedEffect(if (item is Activity.Onchain) item.v1.boostTxIds else emptyList()) {
186+
if (item is Activity.Onchain && item.v1.boostTxIds.isNotEmpty()) {
187+
boostTxDoesExist = detailViewModel.getBoostTxDoesExist(item.v1.boostTxIds)
188+
}
189+
}
190+
191+
val context = LocalContext.current
192+
193+
Column(
194+
modifier = Modifier.background(Colors.Black)
195+
) {
196+
AppTopBar(
197+
titleText = stringResource(
198+
if (isCpfpChild) {
199+
R.string.wallet__activity_boost_fee
200+
} else {
201+
item.getScreenTitleRes()
202+
}
203+
),
204+
onBackClick = onBackClick,
205+
actions = { DrawerNavIcon() },
206+
)
207+
ActivityDetailContent(
208+
item = item,
209+
tags = tags,
210+
onRemoveTag = { detailViewModel.removeTag(it) },
211+
onAddTagClick = { showAddTagSheet = true },
212+
onClickBoost = detailViewModel::onClickBoost,
213+
onExploreClick = onExploreClick,
214+
onChannelClick = onChannelClick,
215+
detailViewModel = detailViewModel,
216+
isCpfpChild = isCpfpChild,
217+
boostTxDoesExist = boostTxDoesExist,
218+
onCopy = { text ->
219+
app.toast(
220+
type = Toast.ToastType.SUCCESS,
221+
title = copyToastTitle,
222+
description = text.ellipsisMiddle(40)
223+
)
224+
}
225+
)
226+
if (showAddTagSheet) {
227+
ActivityAddTagSheet(
228+
listViewModel = listViewModel,
229+
activityViewModel = detailViewModel,
230+
onDismiss = { showAddTagSheet = false },
207231
)
208-
},
209-
onMinFee = {
210-
app.toast(
211-
type = Toast.ToastType.ERROR,
212-
title = context.getString(R.string.wallet__send_fee_error),
213-
description = context.getString(R.string.wallet__send_fee_error_min)
232+
}
233+
}
234+
235+
if (boostSheetVisible) {
236+
(item as? Activity.Onchain)?.let {
237+
BoostTransactionSheet(
238+
onDismiss = detailViewModel::onDismissBoostSheet,
239+
item = it,
240+
onSuccess = {
241+
app.toast(
242+
type = Toast.ToastType.SUCCESS,
243+
title = context.getString(R.string.wallet__boost_success_title),
244+
description = context.getString(R.string.wallet__boost_success_msg)
245+
)
246+
listViewModel.resync()
247+
onCloseClick()
248+
},
249+
onFailure = {
250+
app.toast(
251+
type = Toast.ToastType.ERROR,
252+
title = context.getString(R.string.wallet__boost_error_title),
253+
description = context.getString(R.string.wallet__boost_error_msg)
254+
)
255+
detailViewModel.onDismissBoostSheet()
256+
},
257+
onMaxFee = {
258+
app.toast(
259+
type = Toast.ToastType.ERROR,
260+
title = context.getString(R.string.wallet__send_fee_error),
261+
description = context.getString(R.string.wallet__send_fee_error_max)
262+
)
263+
},
264+
onMinFee = {
265+
app.toast(
266+
type = Toast.ToastType.ERROR,
267+
title = context.getString(R.string.wallet__send_fee_error),
268+
description = context.getString(R.string.wallet__send_fee_error_min)
269+
)
270+
}
214271
)
215272
}
216-
)
273+
}
217274
}
218275
}
219276
}

0 commit comments

Comments
 (0)