From 2bee8b549f930e58574e50c8218c0b49681dfeb7 Mon Sep 17 00:00:00 2001 From: Sergejs Luhmirins Date: Mon, 29 Sep 2025 16:03:57 +0300 Subject: [PATCH 1/3] MS-1188 Cleanup navigation to login actions in dashboard graph --- .../feature/dashboard/base/BaseFragment.kt | 2 +- .../logout/sync/LogoutSyncFragment.kt | 2 +- .../syncdecline/LogoutSyncDeclineFragment.kt | 2 +- .../dashboard/settings/about/AboutFragment.kt | 4 ++-- .../main/res/navigation/graph_dashboard.xml | 23 +------------------ 5 files changed, 6 insertions(+), 27 deletions(-) diff --git a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/base/BaseFragment.kt b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/base/BaseFragment.kt index baed5f8516..9a66322268 100644 --- a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/base/BaseFragment.kt +++ b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/base/BaseFragment.kt @@ -18,7 +18,7 @@ internal class BaseFragment : Fragment(R.layout.fragment_base) { if (authStore.signedInProjectId.isNotEmpty()) { findNavController().navigateSafely(this, BaseFragmentDirections.actionBaseFragmentToMainFragment()) } else { - findNavController().navigateSafely(this, BaseFragmentDirections.actionBaseFragmentToRequestLoginFragment()) + findNavController().navigateSafely(this, BaseFragmentDirections.actionToRequestLoginFragment()) } } } diff --git a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragment.kt b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragment.kt index 5bdcd83226..b13dcf6401 100644 --- a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragment.kt +++ b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragment.kt @@ -54,7 +54,7 @@ class LogoutSyncFragment : Fragment(R.layout.fragment_logout_sync) { viewModel.logoutEventLiveData.observe(viewLifecycleOwner) { findNavController().navigateSafely( this@LogoutSyncFragment, - R.id.action_logoutSyncFragment_to_requestLoginFragment, + LogoutSyncFragmentDirections.actionToRequestLoginFragment(null), ) } } diff --git a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/syncdecline/LogoutSyncDeclineFragment.kt b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/syncdecline/LogoutSyncDeclineFragment.kt index 0271f6debe..9ba9ba7918 100644 --- a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/syncdecline/LogoutSyncDeclineFragment.kt +++ b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/syncdecline/LogoutSyncDeclineFragment.kt @@ -74,7 +74,7 @@ class LogoutSyncDeclineFragment : Fragment(R.layout.fragment_logout_sync_decline viewModel.logoutEventLiveData.observe(viewLifecycleOwner) { findNavController().navigateSafely( this@LogoutSyncDeclineFragment, - LogoutSyncDeclineFragmentDirections.actionLogoutSyncDeclineFragmentToRequestLoginFragment(), + LogoutSyncDeclineFragmentDirections.actionToRequestLoginFragment(null), ) } } diff --git a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/settings/about/AboutFragment.kt b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/settings/about/AboutFragment.kt index 60cf05f8b9..fc105b5a4b 100644 --- a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/settings/about/AboutFragment.kt +++ b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/settings/about/AboutFragment.kt @@ -19,9 +19,9 @@ import com.simprints.feature.dashboard.R import com.simprints.feature.dashboard.databinding.FragmentSettingsAboutBinding import com.simprints.feature.dashboard.settings.password.SettingsPasswordDialogFragment import com.simprints.infra.config.store.models.GeneralConfiguration.Modality.FINGERPRINT -import com.simprints.infra.uibase.view.applySystemBarInsets import com.simprints.infra.uibase.navigation.navigateSafely import com.simprints.infra.uibase.system.Clipboard +import com.simprints.infra.uibase.view.applySystemBarInsets import com.simprints.infra.uibase.viewbinding.viewBinding import dagger.hilt.android.AndroidEntryPoint import java.util.Locale @@ -96,7 +96,7 @@ internal class AboutFragment : PreferenceFragmentCompat() { LiveDataEventWithContentObserver { val destination = when (it) { LogoutDestination.LogoutDataSyncScreen -> AboutFragmentDirections.actionAboutFragmentToLogoutNavigation() - LogoutDestination.LoginScreen -> AboutFragmentDirections.actionAboutFragmentToRequestLoginFragment() + LogoutDestination.LoginScreen -> AboutFragmentDirections.actionToRequestLoginFragment() } findNavController().navigateSafely(this, destination) }, diff --git a/feature/dashboard/src/main/res/navigation/graph_dashboard.xml b/feature/dashboard/src/main/res/navigation/graph_dashboard.xml index 0cbfa21964..91eb617620 100644 --- a/feature/dashboard/src/main/res/navigation/graph_dashboard.xml +++ b/feature/dashboard/src/main/res/navigation/graph_dashboard.xml @@ -33,11 +33,6 @@ android:name="com.simprints.feature.dashboard.base.BaseFragment" android:label="BaseFragment" tools:layout="@layout/fragment_base"> - - @@ -141,11 +131,6 @@ - @@ -157,13 +142,7 @@ android:id="@+id/logOutSyncDeclineFragment" android:name="com.simprints.feature.dashboard.logout.syncdecline.LogoutSyncDeclineFragment" android:label="LogoutSyncDeclineFragment" - tools:layout="@layout/fragment_logout_sync_decline"> - - + tools:layout="@layout/fragment_logout_sync_decline" /> Date: Tue, 30 Sep 2025 12:21:36 +0300 Subject: [PATCH 2/3] MS-1188 Ensure that logout use case is executed before anything else happens in the UI --- .../feature/dashboard/logout/LogoutSyncViewModel.kt | 5 +---- .../feature/dashboard/logout/usecase/LogoutUseCase.kt | 5 +++-- .../feature/dashboard/settings/syncinfo/SyncInfoViewModel.kt | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/LogoutSyncViewModel.kt b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/LogoutSyncViewModel.kt index e55a0ad2aa..c6ca37ee2d 100644 --- a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/LogoutSyncViewModel.kt +++ b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/LogoutSyncViewModel.kt @@ -19,7 +19,6 @@ import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map -import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel @@ -52,9 +51,7 @@ internal class LogoutSyncViewModel @Inject constructor( } fun logout() { - viewModelScope.launch { - logoutUseCase() - } + logoutUseCase() } private companion object { diff --git a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/usecase/LogoutUseCase.kt b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/usecase/LogoutUseCase.kt index 0910f7cf06..7db3251a52 100644 --- a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/usecase/LogoutUseCase.kt +++ b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/usecase/LogoutUseCase.kt @@ -6,7 +6,7 @@ import com.simprints.infra.enrolment.records.repository.EnrolmentRecordRepositor import com.simprints.infra.enrolment.records.repository.local.migration.RealmToRoomMigrationFlagsStore import com.simprints.infra.sync.SyncOrchestrator import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.withContext +import kotlinx.coroutines.runBlocking import javax.inject.Inject internal class LogoutUseCase @Inject constructor( @@ -16,7 +16,8 @@ internal class LogoutUseCase @Inject constructor( private val enrolmentRecordRepository: EnrolmentRecordRepository, @DispatcherIO private val ioDispatcher: CoroutineDispatcher, ) { - suspend operator fun invoke() = withContext(ioDispatcher) { + // To prevent a race between wiping data and navigation, this use case must block the executing thread + operator fun invoke() = runBlocking(ioDispatcher) { // Cancel all background sync syncOrchestrator.cancelBackgroundWork() syncOrchestrator.deleteEventSyncInfo() diff --git a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/settings/syncinfo/SyncInfoViewModel.kt b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/settings/syncinfo/SyncInfoViewModel.kt index 5e461166e4..820b6d6324 100644 --- a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/settings/syncinfo/SyncInfoViewModel.kt +++ b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/settings/syncinfo/SyncInfoViewModel.kt @@ -171,7 +171,7 @@ internal class SyncInfoViewModel @Inject constructor( } fun performLogout() { - viewModelScope.launch { logoutUseCase() } + logoutUseCase() } fun requestNavigationToLogin() { From d7467de4cbac4266d490dac9de4768ca87c6cb79 Mon Sep 17 00:00:00 2001 From: Sergejs Luhmirins Date: Tue, 30 Sep 2025 12:40:34 +0300 Subject: [PATCH 3/3] MS-1188 Remove redundant logout navigation from logout sync wrapper fragment --- .../dashboard/logout/sync/LogoutSyncFragment.kt | 6 ------ .../logout/sync/LogoutSyncFragmentTest.kt | 14 -------------- 2 files changed, 20 deletions(-) diff --git a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragment.kt b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragment.kt index b13dcf6401..06d36708ff 100644 --- a/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragment.kt +++ b/feature/dashboard/src/main/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragment.kt @@ -51,11 +51,5 @@ class LogoutSyncFragment : Fragment(R.layout.fragment_logout_sync) { } } } - viewModel.logoutEventLiveData.observe(viewLifecycleOwner) { - findNavController().navigateSafely( - this@LogoutSyncFragment, - LogoutSyncFragmentDirections.actionToRequestLoginFragment(null), - ) - } } } diff --git a/feature/dashboard/src/test/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragmentTest.kt b/feature/dashboard/src/test/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragmentTest.kt index 9e74d7593e..7176f73921 100644 --- a/feature/dashboard/src/test/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragmentTest.kt +++ b/feature/dashboard/src/test/java/com/simprints/feature/dashboard/logout/sync/LogoutSyncFragmentTest.kt @@ -61,18 +61,4 @@ internal class LogoutSyncFragmentTest { onView(withId(R.id.logout_sync_info)).check(matches(not(isDisplayed()))) onView(withId(R.id.logoutWithoutSyncButton)).check(matches(not(isDisplayed()))) } - - @Test - fun `should navigate to requestLoginFragment when logout event received`() { - every { logoutSyncViewModel.logoutEventLiveData } returns mockk { - every { observe(any(), any()) } answers { - secondArg>().onChanged(Unit) - } - } - val navController = testNavController(R.navigation.graph_dashboard, R.id.logout_navigation) - launchFragmentInHiltContainer(navController = navController) - - assertThat(navController.currentDestination?.id) - .isEqualTo(R.id.requestLoginFragment) - } }