mirror of
https://github.com/openMF/mobile-wallet.git
synced 2026-02-06 11:07:02 +00:00
feat #1620: swipe refresh state
This commit is contained in:
parent
9652b268ae
commit
ac5b77cf41
@ -1,4 +1,5 @@
|
||||
[versions]
|
||||
accompanistSwiperefreshVersion = "0.27.0"
|
||||
appcompatVersion = "1.6.1"
|
||||
androidGradlePlugin = "8.3.0"
|
||||
compileSdk = "34"
|
||||
@ -65,6 +66,7 @@ androidxBrowser = "1.8.0"
|
||||
playServicesCodeScanner = "16.1.0"
|
||||
|
||||
[libraries]
|
||||
accompanist-swiperefresh = { module = "com.google.accompanist:accompanist-swiperefresh", version.ref = "accompanistSwiperefreshVersion" }
|
||||
androidx-activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activityVersion" }
|
||||
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompatVersion" }
|
||||
androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayoutVersion" }
|
||||
|
||||
@ -152,6 +152,9 @@ dependencies {
|
||||
implementation("de.hdodenhof:circleimageview:3.1.0")
|
||||
implementation("com.github.yalantis:ucrop:2.2.2")
|
||||
|
||||
// Swipe Refresh
|
||||
implementation (libs.accompanist.swiperefresh)
|
||||
|
||||
kspTest(libs.hilt.compiler)
|
||||
|
||||
testImplementation(libs.junit)
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
package org.mifospay.notification.presenter
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.mifospay.core.model.domain.NotificationPayload
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import org.mifospay.core.data.base.UseCase
|
||||
import org.mifospay.core.data.base.UseCaseHandler
|
||||
import org.mifospay.core.data.domain.usecase.notification.FetchNotifications
|
||||
@ -22,6 +26,21 @@ class NotificationViewModel @Inject constructor(
|
||||
MutableStateFlow(NotificationUiState.Loading)
|
||||
val notificationUiState: StateFlow<NotificationUiState> = _notificationUiState
|
||||
|
||||
private val _isRefreshing = MutableStateFlow(false)
|
||||
val isRefreshing: StateFlow<Boolean> get() = _isRefreshing.asStateFlow()
|
||||
|
||||
fun refresh() {
|
||||
viewModelScope.launch {
|
||||
_isRefreshing.emit(true)
|
||||
delay(1000)
|
||||
_isRefreshing.emit(false)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
fetchNotifications()
|
||||
}
|
||||
|
||||
fun fetchNotifications() {
|
||||
mUseCaseHandler.execute(fetchNotificationsUseCase,
|
||||
FetchNotifications.RequestValues(
|
||||
|
||||
@ -23,6 +23,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.google.accompanist.swiperefresh.SwipeRefresh
|
||||
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
|
||||
import com.mifospay.core.model.domain.NotificationPayload
|
||||
import org.mifospay.R
|
||||
import org.mifospay.core.designsystem.component.MfLoadingWheel
|
||||
@ -36,36 +38,77 @@ import org.mifospay.notification.presenter.NotificationViewModel
|
||||
@Composable
|
||||
fun NotificationScreen(viewmodel: NotificationViewModel = hiltViewModel()) {
|
||||
val uiState by viewmodel.notificationUiState.collectAsStateWithLifecycle()
|
||||
NotificationScreen(uiState = uiState)
|
||||
val isRefreshing by viewmodel.isRefreshing.collectAsStateWithLifecycle()
|
||||
NotificationScreen(
|
||||
uiState = uiState,
|
||||
isRefreshing = isRefreshing,
|
||||
onRefresh = {
|
||||
viewmodel.refresh()
|
||||
viewmodel.fetchNotifications()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun NotificationScreen(uiState: NotificationUiState) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
fun NotificationScreen(
|
||||
uiState: NotificationUiState,
|
||||
isRefreshing: Boolean,
|
||||
onRefresh: () -> Unit
|
||||
) {
|
||||
val swipeRefreshState = rememberSwipeRefreshState(isRefreshing = isRefreshing)
|
||||
SwipeRefresh(
|
||||
state = swipeRefreshState,
|
||||
onRefresh = onRefresh
|
||||
) {
|
||||
MifosTopAppBar(titleRes = R.string.notifications)
|
||||
when (uiState) {
|
||||
is NotificationUiState.Error -> {
|
||||
EmptyContentScreen(
|
||||
modifier = Modifier,
|
||||
title = stringResource(id = R.string.error_oops),
|
||||
subTitle = stringResource(id = R.string.unexpected_error_subtitle),
|
||||
iconTint = Color.Black,
|
||||
iconImageVector = Icons.Rounded.Info
|
||||
)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
MifosTopAppBar(titleRes = R.string.notifications)
|
||||
when (uiState) {
|
||||
is NotificationUiState.Error -> {
|
||||
EmptyContentScreen(
|
||||
modifier = Modifier,
|
||||
title = stringResource(id = R.string.error_oops),
|
||||
subTitle = stringResource(id = R.string.unexpected_error_subtitle),
|
||||
iconTint = Color.Black,
|
||||
iconImageVector = Icons.Rounded.Info
|
||||
)
|
||||
}
|
||||
|
||||
NotificationUiState.Loading -> {
|
||||
MfLoadingWheel(
|
||||
contentDesc = stringResource(R.string.loading),
|
||||
backgroundColor = Color.White
|
||||
)
|
||||
}
|
||||
NotificationUiState.Loading -> {
|
||||
MfLoadingWheel(
|
||||
contentDesc = stringResource(R.string.loading),
|
||||
backgroundColor = Color.White
|
||||
)
|
||||
}
|
||||
|
||||
is NotificationUiState.Success -> {
|
||||
if (uiState.notificationList.isEmpty()) {
|
||||
is NotificationUiState.Success -> {
|
||||
if (uiState.notificationList.isEmpty()) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.no_notification_found),
|
||||
style = styleMedium16sp
|
||||
)
|
||||
}
|
||||
} else {
|
||||
LazyColumn {
|
||||
items(uiState.notificationList) { notification ->
|
||||
NotificationList(
|
||||
title = notification.title.toString(),
|
||||
body = notification.body.toString(),
|
||||
timestamp = notification.timestamp.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NotificationUiState.Empty -> {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
@ -76,29 +119,6 @@ fun NotificationScreen(uiState: NotificationUiState) {
|
||||
style = styleMedium16sp
|
||||
)
|
||||
}
|
||||
} else {
|
||||
LazyColumn {
|
||||
items(uiState.notificationList) { notification ->
|
||||
NotificationList(
|
||||
title = notification.title.toString(),
|
||||
body = notification.body.toString(),
|
||||
timestamp = notification.timestamp.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NotificationUiState.Empty -> {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.no_notification_found),
|
||||
style = styleMedium16sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -144,25 +164,32 @@ fun NotificationList(title: String, body: String, timestamp: String) {
|
||||
@Preview(showSystemUi = true, showBackground = true)
|
||||
@Composable
|
||||
private fun NotificationEmptyScreenPreview() {
|
||||
NotificationScreen(uiState = NotificationUiState.Empty)
|
||||
NotificationScreen(uiState = NotificationUiState.Empty, isRefreshing = true, onRefresh = {})
|
||||
}
|
||||
|
||||
@Preview(showSystemUi = true, showBackground = true)
|
||||
@Composable
|
||||
private fun NotificationLoadingPreview() {
|
||||
NotificationScreen(uiState = NotificationUiState.Loading)
|
||||
NotificationScreen(uiState = NotificationUiState.Loading, isRefreshing = true, onRefresh = {})
|
||||
}
|
||||
|
||||
@Preview(showSystemUi = true, showBackground = true)
|
||||
@Composable
|
||||
private fun NotificationSuccessPreview() {
|
||||
NotificationScreen(uiState = NotificationUiState.Success(sampleNotificationList))
|
||||
NotificationScreen(
|
||||
uiState = NotificationUiState.Success(sampleNotificationList),
|
||||
isRefreshing = true,
|
||||
onRefresh = {})
|
||||
}
|
||||
|
||||
@Preview(showSystemUi = true, showBackground = true)
|
||||
@Composable
|
||||
private fun NotificationErrorScreenPreview() {
|
||||
NotificationScreen(uiState = NotificationUiState.Error("Error Occurred"))
|
||||
NotificationScreen(
|
||||
uiState = NotificationUiState.Error("Error Occurred"),
|
||||
isRefreshing = true,
|
||||
onRefresh = {}
|
||||
)
|
||||
}
|
||||
|
||||
val sampleNotificationList = List(10) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user