Skip to content

Commit

Permalink
feat #1620: swipe refresh state
Browse files Browse the repository at this point in the history
  • Loading branch information
PratyushSingh07 authored and therajanmaurya committed May 8, 2024
1 parent 9652b26 commit ac5b77c
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 50 deletions.
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[versions]
accompanistSwiperefreshVersion = "0.27.0"
appcompatVersion = "1.6.1"
androidGradlePlugin = "8.3.0"
compileSdk = "34"
Expand Down Expand Up @@ -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" }
Expand Down
3 changes: 3 additions & 0 deletions mifospay/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()) {
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()
)
}
}
}
}

is NotificationUiState.Success -> {
if (uiState.notificationList.isEmpty()) {
NotificationUiState.Empty -> {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
Expand All @@ -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
)
}
}
}
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit ac5b77c

Please sign in to comment.