Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5eebb52
MS-1145 Visual sync button responsiveness optimization
alex-vt Sep 9, 2025
c8691f0
[MS-1156] Change TokenizableString from Parcelable to Serializable
meladRaouf Sep 9, 2025
32f8615
Merge pull request #1356 from Simprints/sync-button-responsiveness-fix
alex-vt Sep 10, 2025
bc46a2d
Merge pull request #1357 from Simprints/MS-1156-tocknizatoin-params-i…
meladRaouf Sep 10, 2025
44b72c0
Improving UI performance by preserving key dependencies in memory
luhmirin-s Sep 11, 2025
dd57bb6
Merge pull request #1361 from Simprints/hotfix/performance-issues
luhmirin-s Sep 11, 2025
4c69e86
MS-1158 Handle missing project in sync info use case
luhmirin-s Sep 10, 2025
326f8d9
MS-1158 Restore logout from compromised devices on dashboard screen
luhmirin-s Sep 11, 2025
e2e7841
MS-1158 Reword comment about project data being inaccessible
luhmirin-s Sep 18, 2025
e188502
Merge pull request #1366 from Simprints/hotfix/MS-1158-compromised-lo…
luhmirin-s Sep 18, 2025
7625343
MS-1157 Revert material version to fix progress bars
luhmirin-s Sep 22, 2025
fab3f77
Don't require connection for event sync if CommCare downsync source i…
BurningAXE Sep 22, 2025
a1d2a58
Merge pull request #1371 from Simprints/bugfix/event-sync-requires-co…
BurningAXE Sep 23, 2025
63b06d0
MS-1179 Update auto-capture UI state on resume after settings
luhmirin-s Sep 23, 2025
cca6552
Merge pull request #1372 from Simprints/feature/MS-1179-capture-reset…
luhmirin-s Sep 23, 2025
293a6d2
Merge pull request #1370 from Simprints/feature/MS-1157-material-roll…
luhmirin-s Sep 23, 2025
63270b5
Prevent endless loop when initial sync is required
BurningAXE Sep 23, 2025
fbeaba3
Merge pull request #1373 from Simprints/bugfix/prevent-endless-loop-i…
BurningAXE Sep 23, 2025
062a1f5
Move showProgressNotification() to be the first thing in Workers' doW…
BurningAXE Sep 18, 2025
76e40cd
Merge pull request #1368 from Simprints/bugfix/foreground-service-tim…
BurningAXE Sep 23, 2025
d00645c
MS-1176 Only show image sync section if upload is enabled in at least…
luhmirin-s Sep 24, 2025
47b64d2
Add showProgressNotification() to workers that don't have it
BurningAXE Sep 24, 2025
79d1386
Merge pull request #1374 from Simprints/feature/MS-1176-disabled-imag…
luhmirin-s Sep 25, 2025
b6ecbd9
Merge pull request #1375 from Simprints/bugfix/foreground-service-tim…
BurningAXE Sep 25, 2025
2bee8b5
MS-1188 Cleanup navigation to login actions in dashboard graph
luhmirin-s Sep 29, 2025
2ea2e30
MS-1188 Ensure that logout use case is executed before anything else …
luhmirin-s Sep 30, 2025
d7467de
MS-1188 Remove redundant logout navigation from logout sync wrapper f…
luhmirin-s Sep 30, 2025
207e08b
Merge pull request #1381 from Simprints/feature/MS-1188-logout-fix
luhmirin-s Sep 30, 2025
66137f4
MS-1186 Enable "Try again" button for sync when online and not commca…
luhmirin-s Oct 1, 2025
4148935
Merge pull request #1382 from Simprints/feature/MS-1186-sync-try-agai…
luhmirin-s Oct 1, 2025
db7c28b
MS-1181 Add exit form handling to matcher screen
luhmirin-s Oct 1, 2025
6914e52
Merge pull request #1383 from Simprints/feature/MS-1181-grant-permission
luhmirin-s Oct 2, 2025
b26913c
Report sample upload event for firebase uploader
luhmirin-s Oct 2, 2025
c20ee23
Rename firestore to firebase classes to refer to the correct storage …
luhmirin-s Oct 2, 2025
db79a00
Merge pull request #1384 from Simprints/hotfix/track-firebase-sample-…
luhmirin-s Oct 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,7 @@ internal class LiveFeedbackFragment : Fragment(R.layout.fragment_live_feedback)
vm.initCapture(mainVm.bioSDK, mainVm.samplesToCapture, mainVm.attemptNumber)
}
}
if (vm.isAutoCapture) {
// Await until capture button is pressed
vm.holdOffAutoCapture()
binding.captureFeedbackBtn.isClickable = true
}
enableCaptureButtonIfAutoCapture()

binding.captureInstructionsBtn.setOnClickListener {
findNavController().navigateSafely(
Expand Down Expand Up @@ -185,9 +181,12 @@ internal class LiveFeedbackFragment : Fragment(R.layout.fragment_live_feedback)

override fun onResume() {
super.onResume()

when {
requireActivity().hasPermission(Manifest.permission.CAMERA) -> setUpCamera()
requireActivity().hasPermission(Manifest.permission.CAMERA) -> {
setUpCamera()
enableCaptureButtonIfAutoCapture()
}

mainVm.shouldCheckCameraPermissions.getAndSet(false) -> {
// Check permission in onResume() so that if user left the app to go to Settings
// and give the permission, it's reflected when they come back to SID
Expand All @@ -202,6 +201,14 @@ internal class LiveFeedbackFragment : Fragment(R.layout.fragment_live_feedback)
}
}

private fun enableCaptureButtonIfAutoCapture() {
if (vm.isAutoCapture) {
// Await until capture button is pressed
vm.holdOffAutoCapture()
binding.captureFeedbackBtn.isClickable = true
}
}

override fun onStop() {
toggleTorche(false)
// Shut down our background executor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,19 @@ internal class DebugFragment : Fragment(R.layout.fragment_debug) {
}

binding.syncStart.setOnClickListener {
syncOrchestrator.startEventSync()
lifecycleScope.launch(dispatcher) {
syncOrchestrator.startEventSync()
}
}

binding.syncStop.setOnClickListener {
syncOrchestrator.stopEventSync()
}

binding.syncSchedule.setOnClickListener {
syncOrchestrator.rescheduleEventSync()
lifecycleScope.launch(dispatcher) {
syncOrchestrator.rescheduleEventSync()
}
}

binding.clearFirebaseToken.setOnClickListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -52,9 +51,7 @@ internal class LogoutSyncViewModel @Inject constructor(
}

fun logout() {
viewModelScope.launch {
logoutUseCase()
}
logoutUseCase()
}

private companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,5 @@ class LogoutSyncFragment : Fragment(R.layout.fragment_logout_sync) {
}
}
}
viewModel.logoutEventLiveData.observe(viewLifecycleOwner) {
findNavController().navigateSafely(
this@LogoutSyncFragment,
R.id.action_logoutSyncFragment_to_requestLoginFragment,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ data class SyncInfo(
val isLoggedIn: Boolean = true,
val isConfigurationLoadingProgressBarVisible: Boolean = false,
val isLoginPromptSectionVisible: Boolean = false,
val isImageSyncSectionVisible: Boolean = false,
val syncInfoSectionRecords: SyncInfoSectionRecords = SyncInfoSectionRecords(),
val syncInfoSectionImages: SyncInfoSectionImages = SyncInfoSectionImages(),
val syncInfoSectionModules: SyncInfoSectionModules = SyncInfoSectionModules(),
Expand Down Expand Up @@ -84,3 +85,8 @@ data class SyncInfoModuleCount(
val name: String,
val count: String = "",
)

enum class LogoutActionReason {
USER_ACTION,
PROJECT_ENDING_OR_DEVICE_COMPROMISED,
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
Expand All @@ -22,11 +23,14 @@ import com.google.android.material.progressindicator.LinearProgressIndicator
import com.simprints.core.tools.utils.TimeUtils
import com.simprints.feature.dashboard.R
import com.simprints.feature.dashboard.databinding.FragmentSyncInfoBinding
import com.simprints.feature.dashboard.requestlogin.LogoutReason
import com.simprints.feature.dashboard.requestlogin.RequestLoginFragmentArgs
import com.simprints.feature.dashboard.settings.syncinfo.modulecount.ModuleCount
import com.simprints.feature.dashboard.settings.syncinfo.modulecount.ModuleCountAdapter
import com.simprints.feature.dashboard.view.ConfigurableSyncInfoFragmentContainer
import com.simprints.feature.login.LoginContract
import com.simprints.infra.uibase.navigation.handleResult
import com.simprints.infra.uibase.navigation.navigateSafely
import com.simprints.infra.uibase.navigation.toBundle
import com.simprints.infra.uibase.view.applySystemBarInsets
import com.simprints.infra.uibase.view.setPulseAnimation
Expand Down Expand Up @@ -138,8 +142,20 @@ internal class SyncInfoFragment : Fragment(R.layout.fragment_sync_info) {

lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
viewModel.logoutEventFlow.collect {
viewModel.logoutEventFlow.collect { reason ->
viewModel.performLogout()

val logoutReason = reason?.takeIf { it == LogoutActionReason.PROJECT_ENDING_OR_DEVICE_COMPROMISED }?.let {
LogoutReason(
title = getString(IDR.string.dashboard_sync_project_ending_alert_title),
body = getString(IDR.string.dashboard_sync_project_ending_message),
)
}
findNavController().navigateSafely(
parentFragment,
R.id.action_to_requestLoginFragment,
RequestLoginFragmentArgs(logoutReason = logoutReason).toBundle(),
)
}
}
}
Expand Down Expand Up @@ -180,7 +196,7 @@ internal class SyncInfoFragment : Fragment(R.layout.fragment_sync_info) {
renderRecordsSection(syncInfo.syncInfoSectionRecords, config)

// Images section
binding.layoutImagesSync.isGone = !config.isSyncInfoImageSyncVisible
binding.layoutImagesSync.isVisible = config.isSyncInfoImageSyncVisible && syncInfo.isImageSyncSectionVisible
renderImagesSection(syncInfo.syncInfoSectionImages)

// Modules section
Expand Down
Loading