Pin code : add simple grace period

This commit is contained in:
ganfra 2023-10-11 20:52:19 +02:00
parent 8c115d2982
commit cb6a07b90d
4 changed files with 34 additions and 9 deletions

View file

@ -94,7 +94,7 @@ class LoggedInFlowNode @AssistedInject constructor(
private val notificationDrawerManager: NotificationDrawerManager, private val notificationDrawerManager: NotificationDrawerManager,
private val ftueState: FtueState, private val ftueState: FtueState,
private val pinEntryPoint: PinEntryPoint, private val pinEntryPoint: PinEntryPoint,
private val pinStateService PinStateService, private val pinStateService: PinStateService,
private val matrixClient: MatrixClient, private val matrixClient: MatrixClient,
snackbarDispatcher: SnackbarDispatcher, snackbarDispatcher: SnackbarDispatcher,
) : BackstackNode<LoggedInFlowNode.NavTarget>( ) : BackstackNode<LoggedInFlowNode.NavTarget>(
@ -134,9 +134,18 @@ class LoggedInFlowNode @AssistedInject constructor(
backstack.push(NavTarget.Ftue) backstack.push(NavTarget.Ftue)
} }
}, },
onResume = {
coroutineScope.launch {
pinStateService.entersForeground()
}
},
onPause = {
coroutineScope.launch {
pinStateService.entersBackground()
}
},
onStop = { onStop = {
coroutineScope.launch { coroutineScope.launch {
pinStateDataSource.lock()
//Counterpart startSync is done in observeSyncStateAndNetworkStatus method. //Counterpart startSync is done in observeSyncStateAndNetworkStatus method.
syncService.stopSync() syncService.stopSync()
} }
@ -336,7 +345,7 @@ class LoggedInFlowNode @AssistedInject constructor(
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
Box(modifier = modifier) { Box(modifier = modifier) {
val pinState by pinStateDataSource.pinState.collectAsState() val pinState by pinStateService.pinState.collectAsState()
when (pinState) { when (pinState) {
PinState.Unlocked -> { PinState.Unlocked -> {
Children( Children(

View file

@ -21,6 +21,7 @@ import kotlinx.coroutines.flow.StateFlow
interface PinStateService { interface PinStateService {
val pinState: StateFlow<PinState> val pinState: StateFlow<PinState>
suspend fun lock() suspend fun entersForeground()
suspend fun entersBackground()
suspend fun unlock() suspend fun unlock()
} }

View file

@ -24,7 +24,7 @@ import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
class PinAuthenticationPresenter @Inject constructor( class PinAuthenticationPresenter @Inject constructor(
private val pinStateService PinStateService, private val pinStateService: PinStateService,
private val coroutineScope: CoroutineScope, private val coroutineScope: CoroutineScope,
) : Presenter<PinAuthenticationState> { ) : Presenter<PinAuthenticationState> {
@ -33,7 +33,7 @@ class PinAuthenticationPresenter @Inject constructor(
fun handleEvents(event: PinAuthenticationEvents) { fun handleEvents(event: PinAuthenticationEvents) {
when (event) { when (event) {
PinAuthenticationEvents.Unlock -> coroutineScope.launch { pinStateDataSource.unlock() } PinAuthenticationEvents.Unlock -> coroutineScope.launch { pinStateService.unlock() }
} }
} }
return PinAuthenticationState( return PinAuthenticationState(

View file

@ -23,10 +23,16 @@ import io.element.android.libraries.di.AppScope
import io.element.android.libraries.di.SingleIn import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.api.FeatureFlags
import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
private const val GRACE_PERIOD_IN_MILLIS = 90 * 1000L
@SingleIn(AppScope::class) @SingleIn(AppScope::class)
@ContributesBinding(AppScope::class) @ContributesBinding(AppScope::class)
class DefaultPinStateService @Inject constructor( class DefaultPinStateService @Inject constructor(
@ -36,15 +42,24 @@ class DefaultPinStateService @Inject constructor(
private val _pinState = MutableStateFlow<PinState>(PinState.Unlocked) private val _pinState = MutableStateFlow<PinState>(PinState.Unlocked)
override val pinState: StateFlow<PinState> = _pinState override val pinState: StateFlow<PinState> = _pinState
private var lockJob: Job? = null
override suspend fun unlock() { override suspend fun unlock() {
if (featureFlagService.isFeatureEnabled(FeatureFlags.PinUnlock)) { if (featureFlagService.isFeatureEnabled(FeatureFlags.PinUnlock)) {
_pinState.value = PinState.Unlocked _pinState.value = PinState.Unlocked
} }
} }
override suspend fun lock() { override suspend fun entersForeground() {
if (featureFlagService.isFeatureEnabled(FeatureFlags.PinUnlock)) { lockJob?.cancel()
_pinState.value = PinState.Locked }
override suspend fun entersBackground(): Unit = coroutineScope {
lockJob = launch {
if (featureFlagService.isFeatureEnabled(FeatureFlags.PinUnlock)) {
delay(GRACE_PERIOD_IN_MILLIS)
_pinState.value = PinState.Locked
}
} }
} }
} }