VaultLockTimer.kt

1.8 KB · raw

1package com.peachpasswords.vault23import androidx.annotation.VisibleForTesting4import kotlinx.coroutines.CoroutineScope5import kotlinx.coroutines.Dispatchers6import kotlinx.coroutines.Job7import kotlinx.coroutines.SupervisorJob8import kotlinx.coroutines.delay9import kotlinx.coroutines.launch10import javax.inject.Inject11import javax.inject.Singleton1213/**14 * Idle auto-lock timer. The vault locks [VaultSettings.autoLockMinutes] after the15 * last user interaction; a null (or non-positive) setting means "never". [poke]16 * restarts the countdown, so only the final interaction before the idle window17 * elapses triggers the lock. Reads the live setting from [VaultRepository] each18 * time so a settings change takes effect on the next interaction without rewiring.19 */20@Singleton21class VaultLockTimer @Inject constructor(22    private val vault: VaultRepository,23) {24    // Test seam: replaced with a TestScope so the countdown can be driven on25    // virtual time. Defaults to a process-lifetime background scope in production.26    @VisibleForTesting27    internal var scope: CoroutineScope = CoroutineScope(Dispatchers.Default + SupervisorJob())2829    private var timerJob: Job? = null3031    /** Reset the idle countdown. No-op (and cancels) when auto-lock is off or locked. */32    fun poke() {33        val minutes = vault.settings.value.autoLockMinutes34        if (minutes == null || minutes <= 0 || !vault.isUnlocked.value) {35            cancel()36            return37        }38        timerJob?.cancel()39        timerJob = scope.launch {40            delay(minutes * 60_000L)41            vault.lock()42        }43    }4445    /** Begin the idle countdown after an unlock. */46    fun start() = poke()4748    /** Stop the countdown (manual lock, background lock). */49    fun cancel() {50        timerJob?.cancel()51        timerJob = null52    }53}