Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -14,10 +14,6 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import javax.inject.Inject
import javax.inject.Singleton
Expand All @@ -31,7 +27,6 @@ class ObserveFingerprintScanStatusUseCase @Inject constructor(
@ApplicationContext private val context: Context,
) {
private var observeJob: Job? = null
private var previousState: FingerprintScanState = FingerprintScanState.Idle
private var ledsMode: Vero2Configuration.LedsMode? = BASIC
private val preference = PreferenceManager.getDefaultSharedPreferences(context)

Expand All @@ -43,32 +38,23 @@ class ObserveFingerprintScanStatusUseCase @Inject constructor(
ledsMode = configManager.getProjectConfiguration().fingerprint?.getSdkConfiguration(
fingerprintSdk
)?.vero2?.ledsMode

statusTracker.state
.onEach { state ->
if (state is FingerprintScanState.ScanCompleted) {
provideFeedback(state)// Handle ScanCompleted immediately to let the user know to remove the finger
}
}
.filterNot { it is FingerprintScanState.ScanCompleted } // Exclude ScanCompleted
.flatMapConcat { state ->
flow { emit(provideFeedback(state)) } // Process other states sequentially
}
.collect {
// Do nothing
launch {
statusTracker.scanCompleted.collect {
playRemoveFingerAudio()
}
}
statusTracker.state.collect {
provideFeedback(it)
}
}
}

private suspend fun provideFeedback(state: FingerprintScanState) {
when (state) {
is FingerprintScanState.Idle -> turnOnFlashingWhiteSmileLeds()
is FingerprintScanState.Scanning -> turnOffSmileLeds()
is FingerprintScanState.ScanCompleted -> playRemoveFingerAudio()
is FingerprintScanState.ImageQualityChecking.Good -> setUiAfterScan(true)
is FingerprintScanState.ImageQualityChecking.Bad -> setUiAfterScan(false)
}
previousState = state
private suspend fun provideFeedback(state: FingerprintScanState) = when (state) {
is FingerprintScanState.Idle -> turnOnFlashingWhiteSmileLeds()
is FingerprintScanState.Scanning -> turnOffSmileLeds()
is FingerprintScanState.ScanCompleted -> playRemoveFingerAudio()
is FingerprintScanState.ImageQualityChecking.Good -> setUiAfterScan(true)
is FingerprintScanState.ImageQualityChecking.Bad -> setUiAfterScan(false)
}

fun stopObserving() {
Expand All @@ -90,23 +76,19 @@ class ObserveFingerprintScanStatusUseCase @Inject constructor(
}

private suspend fun setUiAfterScan(isGoodScan: Boolean) {
// Check if the previous state was ScanCompleted to avoid displaying the bad or good scan UI twice
// There's no need to check the configuration, as the good/bad scan visual notifications apply across all LED modes.
if (previousState == FingerprintScanState.ScanCompleted) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to check previous state anymore?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discovered that this check was part of an old implementation where FingerprintScanState.ScanCompleted was being sent twice, which is not valid now.

with(scannerManager.scanner) {
if (isGoodScan) setUiGoodCapture()
else setUiBadCapture()
with(scannerManager.scanner) {
if (isGoodScan) setUiGoodCapture()
else setUiBadCapture()

//Wait before turn of the leds
delay(LONG_DELAY)
turnOffSmileLeds()
}
//Wait before turn of the leds
delay(LONG_DELAY)
turnOffSmileLeds()
}

}

private fun playRemoveFingerAudio() {
// Verify that the previous state was not "ScanCompleted" to prevent the sound from playing twice.
if (previousState == FingerprintScanState.ScanCompleted) return

if (isAudioEnabled()) playAudioBeep()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.simprints.core.DispatcherBG
import com.simprints.fingerprint.infra.scanner.capture.FingerprintScanState.Idle
import com.simprints.fingerprint.infra.scanner.capture.FingerprintScanState.ImageQualityChecking.Bad
import com.simprints.fingerprint.infra.scanner.capture.FingerprintScanState.ImageQualityChecking.Good
import com.simprints.fingerprint.infra.scanner.capture.FingerprintScanState.ScanCompleted
import com.simprints.fingerprint.infra.scanner.capture.FingerprintScanState.Scanning
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
Expand All @@ -24,9 +23,12 @@ class FingerprintScanningStatusTracker @Inject constructor(
MutableSharedFlow<FingerprintScanState>(replay = 1, extraBufferCapacity = 1)
val state: SharedFlow<FingerprintScanState> = _state

private val _scanCompleted = MutableSharedFlow<Unit>(replay = 0)
val scanCompleted: SharedFlow<Unit> = _scanCompleted

fun startScanning() = emitState(Scanning)

fun completeScan() = emitState(ScanCompleted)
suspend fun completeScan() = _scanCompleted.emit(Unit)

fun setImageQualityCheckingResult(isQualityOk: Boolean) =
emitState(if (isQualityOk) Good else Bad)
Expand Down