diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen.kt b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen.kt index f570653..d429452 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardScreen.kt @@ -61,6 +61,7 @@ import androidx.compose.material3.rememberDrawerState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableLongStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -441,7 +442,8 @@ fun DashboardScreen2( contentAlignment = Alignment.Center ) { SummaryCard( - onClickLastSync + onClickLastSync = onClickLastSync, + lastSyncTime = dashboardUiState.lastSyncTime ) } //pager section @@ -511,10 +513,29 @@ private fun AdvertisingArea() { } } +private fun formatRelativeTime(timestamp: Long?, now: Long): String { + if (timestamp == null) return "Never" + val diff = now - timestamp + return when { + diff < 60_000L -> "Just now" + diff < 3_600_000L -> "${diff / 60_000L} mins ago" + diff < 86_400_000L -> "${diff / 3_600_000L} hours ago" + else -> "${diff / 86_400_000L} days ago" + } +} + @Composable private fun SummaryCard( - onClickLastSync: () -> Unit + onClickLastSync: () -> Unit, + lastSyncTime: Long? ) { + var now by remember { mutableLongStateOf(System.currentTimeMillis()) } + LaunchedEffect(Unit) { + while (true) { + delay(30_000) + now = System.currentTimeMillis() + } + } var isRotating by remember { mutableStateOf(false) } val rotation by animateFloatAsState( targetValue = if (isRotating) 360f else 0f, @@ -596,7 +617,7 @@ private fun SummaryCard( Spacer(Modifier.height(6.dp)) Text( - text = "5 mins ago", + text = formatRelativeTime(lastSyncTime, now), fontSize = 18.sp, color = Color.LegacyRed, fontWeight = FontWeight.SemiBold diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardUiState.kt b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardUiState.kt index 41134f1..6cb9020 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardUiState.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardUiState.kt @@ -11,5 +11,6 @@ data class TrnxRecord( ) data class DashboardUiState( - val recentTransactions: List = emptyList() + val recentTransactions: List = emptyList(), + val lastSyncTime: Long? = null ) diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardViewModel.kt index 05b0d45..145fc9a 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardViewModel.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/dashboard/DashboardViewModel.kt @@ -1,11 +1,13 @@ package com.mob.utsmyanmar.ui.dashboard +import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.asFlow import androidx.lifecycle.viewModelScope import com.utsmyanmar.baselib.repo.Repository import com.utsmyanmar.paylibs.model.PayDetail import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -15,7 +17,8 @@ import javax.inject.Inject @HiltViewModel class DashboardViewModel @Inject constructor( - private val repository: Repository + private val repository: Repository, + @ApplicationContext private val context: Context ) : ViewModel() { private val _uiState = MutableStateFlow(DashboardUiState()) @@ -31,6 +34,14 @@ class DashboardViewModel @Inject constructor( } } } + refreshLastSyncTime() + } + + fun refreshLastSyncTime() { + val time = context.getSharedPreferences("mobpos_prefs", Context.MODE_PRIVATE) + .getLong("last_sync_time", 0L) + .takeIf { it > 0L } + _uiState.update { it.copy(lastSyncTime = time) } } } diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt index 7deac01..c86383d 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/navigation/AppNavGraph.kt @@ -110,6 +110,11 @@ fun AppNavGraph( val deviceInfo by deviceInfoViewModel.uiState.collectAsStateWithLifecycle() val tmsSetupViewModel: TmsSetupViewModel = hiltViewModel() androidx.compose.runtime.LaunchedEffect(Unit) { deviceInfoViewModel.loadDeviceInfo() } + androidx.compose.runtime.LaunchedEffect(tmsSetupViewModel) { + tmsSetupViewModel.onSyncCompleted.collect { + dashboardViewModel.refreshLastSyncTime() + } + } DashboardScreen2( dashboardUiState = dashboardUiState, deviceInfo = deviceInfo, diff --git a/app/src/main/java/com/mob/utsmyanmar/ui/tms_setup/TmsSetupViewModel.kt b/app/src/main/java/com/mob/utsmyanmar/ui/tms_setup/TmsSetupViewModel.kt index 3706629..ebdd9f9 100644 --- a/app/src/main/java/com/mob/utsmyanmar/ui/tms_setup/TmsSetupViewModel.kt +++ b/app/src/main/java/com/mob/utsmyanmar/ui/tms_setup/TmsSetupViewModel.kt @@ -1,6 +1,7 @@ package com.mob.utsmyanmar.ui.tms_setup import android.annotation.SuppressLint +import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.mob.utsmyanmar.model.sirius.SiriusResponse @@ -14,6 +15,7 @@ import com.utsmyanmar.baselib.network.model.sirius.SiriusRequest import com.utsmyanmar.baselib.repo.Repository import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.schedulers.Schedulers @@ -42,7 +44,8 @@ data class TmsSetupUiState( @HiltViewModel class TmsSetupViewModel @Inject constructor( private val repository: Repository, - private val emvParamOperation: EmvParamOperation + private val emvParamOperation: EmvParamOperation, + @ApplicationContext private val context: Context ) : ViewModel() { private val _uiState = MutableStateFlow(TmsSetupUiState()) @@ -54,6 +57,9 @@ class TmsSetupViewModel @Inject constructor( private val _navigateToDisable = MutableSharedFlow() val navigateToDisable: SharedFlow = _navigateToDisable.asSharedFlow() + private val _onSyncCompleted = MutableSharedFlow() + val onSyncCompleted: SharedFlow = _onSyncCompleted.asSharedFlow() + private val disposables = CompositeDisposable() private val tmsSetups = TMSSetupsImpl() @@ -132,8 +138,15 @@ class TmsSetupViewModel @Inject constructor( val validity = TMSUtil.getInstance().checkParams() if (validity.status == ValidityStatus.SUCCESS) { + context.getSharedPreferences("mobpos_prefs", Context.MODE_PRIVATE) + .edit() + .putLong("last_sync_time", System.currentTimeMillis()) + .apply() _uiState.update { it.copy(isLoading = false, statusText = "Ready.") } - viewModelScope.launch { _navigateToDashboard.emit(Unit) } + viewModelScope.launch { + _onSyncCompleted.emit(Unit) + _navigateToDashboard.emit(Unit) + } } else { _uiState.update { it.copy(