Adjust app lock mechanism (#7924)

Now uses enum to also handle timed lock
This commit is contained in:
Ivan Iskandar 2022-09-02 22:48:48 +07:00 committed by GitHub
parent ff4a217730
commit 774a87a42a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 11 deletions

View File

@ -39,7 +39,6 @@ import eu.kanade.tachiyomi.glance.UpdatesGridGlanceWidget
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate
import eu.kanade.tachiyomi.util.preference.asHotFlow import eu.kanade.tachiyomi.util.preference.asHotFlow
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil
import eu.kanade.tachiyomi.util.system.WebViewUtil import eu.kanade.tachiyomi.util.system.WebViewUtil
import eu.kanade.tachiyomi.util.system.animatorDurationScale import eu.kanade.tachiyomi.util.system.animatorDurationScale
import eu.kanade.tachiyomi.util.system.isDevFlavor import eu.kanade.tachiyomi.util.system.isDevFlavor
@ -60,7 +59,6 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.security.Security import java.security.Security
import java.util.Date
class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
@ -175,10 +173,7 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
} }
override fun onStop(owner: LifecycleOwner) { override fun onStop(owner: LifecycleOwner) {
preferences.lastAppClosed().set(Date().time) SecureActivityDelegate.onApplicationStopped()
if (!AuthenticatorUtil.isAuthenticating && preferences.lockAppAfter().get() >= 0) {
SecureActivityDelegate.locked = true
}
} }
override fun getPackageName(): String { override fun getPackageName(): String {

View File

@ -53,6 +53,10 @@ class PreferencesHelper(val context: Context) {
fun lockAppAfter() = flowPrefs.getInt("lock_app_after", 0) fun lockAppAfter() = flowPrefs.getInt("lock_app_after", 0)
/**
* For app lock. Will be set when there is a pending timed lock.
* Otherwise this pref should be deleted.
*/
fun lastAppClosed() = flowPrefs.getLong("last_app_closed", 0) fun lastAppClosed() = flowPrefs.getLong("last_app_closed", 0)
fun secureScreen() = flowPrefs.getEnum("secure_screen_v2", Values.SecureScreenMode.INCOGNITO) fun secureScreen() = flowPrefs.getEnum("secure_screen_v2", Values.SecureScreenMode.INCOGNITO)

View File

@ -8,11 +8,14 @@ import androidx.lifecycle.lifecycleScope
import eu.kanade.tachiyomi.data.preference.PreferenceValues import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.security.UnlockActivity import eu.kanade.tachiyomi.ui.security.UnlockActivity
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.isAuthenticationSupported import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.isAuthenticationSupported
import eu.kanade.tachiyomi.util.view.setSecureScreen import eu.kanade.tachiyomi.util.view.setSecureScreen
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.Date import java.util.Date
@ -20,10 +23,36 @@ interface SecureActivityDelegate {
fun registerSecureActivity(activity: AppCompatActivity) fun registerSecureActivity(activity: AppCompatActivity)
companion object { companion object {
var locked: Boolean = true fun onApplicationStopped() {
val preferences = Injekt.get<PreferencesHelper>()
if (!preferences.useAuthenticator().get()) return
if (lockState != LockState.ACTIVE) {
preferences.lastAppClosed().set(Date().time)
}
if (!AuthenticatorUtil.isAuthenticating) {
lockState = if (preferences.lockAppAfter().get() >= 0) {
LockState.PENDING
} else {
LockState.ACTIVE
}
}
}
fun unlock() {
lockState = LockState.INACTIVE
Injekt.get<PreferencesHelper>().lastAppClosed().delete()
}
} }
} }
private var lockState = LockState.INACTIVE
private enum class LockState {
INACTIVE,
PENDING,
ACTIVE
}
class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObserver { class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObserver {
private lateinit var activity: AppCompatActivity private lateinit var activity: AppCompatActivity
@ -57,6 +86,7 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
private fun setAppLock() { private fun setAppLock() {
if (!preferences.useAuthenticator().get()) return if (!preferences.useAuthenticator().get()) return
if (activity.isAuthenticationSupported()) { if (activity.isAuthenticationSupported()) {
updatePendingLockStatus()
if (!isAppLocked()) return if (!isAppLocked()) return
activity.startActivity(Intent(activity, UnlockActivity::class.java)) activity.startActivity(Intent(activity, UnlockActivity::class.java))
activity.overridePendingTransition(0, 0) activity.overridePendingTransition(0, 0)
@ -65,9 +95,23 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
} }
} }
private fun updatePendingLockStatus() {
val lastClosedPref = preferences.lastAppClosed()
val lockDelay = 60000 * preferences.lockAppAfter().get()
if (lastClosedPref.isSet() && lockDelay > 0) {
// Restore pending status in case app was killed
lockState = LockState.PENDING
}
if (lockState != LockState.PENDING) {
return
}
if (Date().time >= lastClosedPref.get() + lockDelay) {
// Activate lock after delay
lockState = LockState.ACTIVE
}
}
private fun isAppLocked(): Boolean { private fun isAppLocked(): Boolean {
if (!SecureActivityDelegate.locked) return false return lockState == LockState.ACTIVE
return preferences.lockAppAfter().get() <= 0 ||
Date().time >= preferences.lastAppClosed().get() + 60 * 1000 * preferences.lockAppAfter().get()
} }
} }

View File

@ -37,7 +37,7 @@ class UnlockActivity : BaseActivity() {
result: BiometricPrompt.AuthenticationResult, result: BiometricPrompt.AuthenticationResult,
) { ) {
super.onAuthenticationSucceeded(activity, result) super.onAuthenticationSucceeded(activity, result)
SecureActivityDelegate.locked = false SecureActivityDelegate.unlock()
finish() finish()
} }
}, },