diff --git a/app/src/main/java/to/bitkit/ui/scaffold/AppScaffold.kt b/app/src/main/java/to/bitkit/ui/scaffold/AppScaffold.kt index bf7342c76..ad2b7c6d4 100644 --- a/app/src/main/java/to/bitkit/ui/scaffold/AppScaffold.kt +++ b/app/src/main/java/to/bitkit/ui/scaffold/AppScaffold.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Bolt -import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.outlined.Settings import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon @@ -26,7 +25,6 @@ import to.bitkit.ui.navigateToSettings fun AppScaffold( navController: NavController, titleText: String, - onRefresh: () -> Unit, content: @Composable () -> Unit, ) { Scaffold( @@ -37,12 +35,6 @@ fun AppScaffold( Title(text = titleText) }, actions = { - IconButton(onRefresh) { - Icon( - imageVector = Icons.Default.Refresh, - contentDescription = stringResource(R.string.sync), - ) - } IconButton(onClick = navController::navigateToNodeState) { Icon( imageVector = Icons.Default.Bolt, diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt index f1f396433..5f13cbdec 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt @@ -15,6 +15,12 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.pullrefresh.PullRefreshIndicator +import androidx.compose.material.pullrefresh.pullRefresh +import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -65,6 +71,7 @@ import to.bitkit.ui.utils.screenSlideIn import to.bitkit.ui.utils.screenSlideOut import to.bitkit.ui.utils.withAccent import to.bitkit.viewmodels.AppViewModel +import to.bitkit.viewmodels.MainUiState import to.bitkit.viewmodels.WalletViewModel @Composable @@ -73,7 +80,7 @@ fun HomeScreen( appViewModel: AppViewModel, rootNavController: NavController, ) { - val uiState by walletViewModel.uiState.collectAsState() + val uiState: MainUiState by walletViewModel.uiState.collectAsState() val currentSheet by appViewModel.currentSheet SheetHost( shouldExpand = currentSheet != null, @@ -103,13 +110,14 @@ fun HomeScreen( val walletNavController = rememberNavController() NavHost( navController = walletNavController, - startDestination = HomeRoutes.Home + startDestination = HomeRoutes.Home, ) { composable { HomeContentView( + uiState = uiState, rootNavController = rootNavController, walletNavController = walletNavController, - onRefresh = walletViewModel::refreshState, + onRefresh = walletViewModel::onPullToRefresh, ) } composable( @@ -162,8 +170,10 @@ fun HomeScreen( } } +@OptIn(ExperimentalMaterialApi::class) @Composable private fun HomeContentView( + uiState: MainUiState, rootNavController: NavController, walletNavController: NavController, onRefresh: () -> Unit, @@ -171,7 +181,6 @@ private fun HomeContentView( AppScaffold( navController = rootNavController, titleText = "Your Name", - onRefresh = onRefresh, ) { RequestNotificationPermissions() val balances = LocalBalances.current @@ -182,11 +191,18 @@ private fun HomeContentView( showEmptyStateSetting && balances.totalSats == 0uL } } - Box(modifier = Modifier.fillMaxSize()) { + val pullRefreshState = rememberPullRefreshState(refreshing = uiState.isRefreshing, onRefresh = onRefresh) + + Box( + modifier = Modifier + .fillMaxSize() + .pullRefresh(pullRefreshState) + ) { Column( modifier = Modifier .padding(horizontal = 16.dp) .fillMaxSize() + .verticalScroll(rememberScrollState()) ) { BalanceHeaderView(sats = balances.totalSats.toLong(), modifier = Modifier.fillMaxWidth()) if (!showEmptyState) { @@ -235,6 +251,12 @@ private fun HomeContentView( .align(Alignment.BottomCenter) ) } + + PullRefreshIndicator( + refreshing = uiState.isRefreshing, + state = pullRefreshState, + modifier = Modifier.align(Alignment.TopCenter) + ) } } } @@ -275,6 +297,7 @@ object HomeRoutes { private fun HomeContentViewPreview() { AppThemeSurface { HomeContentView( + uiState = MainUiState(), rootNavController = rememberNavController(), walletNavController = rememberNavController(), onRefresh = {}, diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/AllActivityScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/AllActivityScreen.kt index e19332031..0833a943e 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/AllActivityScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/AllActivityScreen.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider @@ -177,32 +176,22 @@ fun ActivityList( onActivityItemClick: (String) -> Unit, ) { if (items != null) { - LazyColumn( + Column( horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.fillMaxWidth() ) { - items( - items = items, - key = { - when (it) { - is Activity.Onchain -> it.v1.id - is Activity.Lightning -> it.v1.id - } - } - ) { item -> + items.forEach { item -> ActivityRow(item, onActivityItemClick) HorizontalDivider(color = Colors.White10) } - item { - if (items.isEmpty()) { - BodyMSB(stringResource(R.string.wallet__activity_no), Modifier.padding(16.dp)) - } else { - TertiaryButton( - text = stringResource(R.string.wallet__activity_show_all), - onClick = onAllActivityClick, - modifier = Modifier.wrapContentWidth().padding(top = 8.dp) - ) - } + if (items.isEmpty()) { + BodyMSB(stringResource(R.string.wallet__activity_no), Modifier.padding(16.dp)) + } else { + TertiaryButton( + text = stringResource(R.string.wallet__activity_show_all), + onClick = onAllActivityClick, + modifier = Modifier.wrapContentWidth().padding(top = 8.dp) + ) } } } else { diff --git a/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt index 576698a7d..6f73997db 100644 --- a/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt @@ -218,6 +218,19 @@ class WalletViewModel @Inject constructor( } } + fun onPullToRefresh() { + viewModelScope.launch { + _uiState.update { it.copy(isRefreshing = true) } + try { + sync() + } catch (e: Throwable) { + ToastEventBus.send(e) + } finally { + _uiState.update { it.copy(isRefreshing = false) } + } + } + } + private suspend fun registerForNotificationsIfNeeded() { val token = firebaseMessaging.token.await() val cachedToken = keychain.loadString(Keychain.Key.PUSH_NOTIFICATION_TOKEN.name) @@ -483,6 +496,7 @@ data class MainUiState( val nodeLifecycleState: NodeLifecycleState = NodeLifecycleState.Stopped, val peers: List = emptyList(), val channels: List = emptyList(), + val isRefreshing: Boolean = false, ) // endregion