mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Adjust app lock mechanism (#7924)
Now uses enum to also handle timed lock
This commit is contained in:
		@@ -39,7 +39,6 @@ import eu.kanade.tachiyomi.glance.UpdatesGridGlanceWidget
 | 
			
		||||
import eu.kanade.tachiyomi.network.NetworkHelper
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate
 | 
			
		||||
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.animatorDurationScale
 | 
			
		||||
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.injectLazy
 | 
			
		||||
import java.security.Security
 | 
			
		||||
import java.util.Date
 | 
			
		||||
 | 
			
		||||
class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
 | 
			
		||||
 | 
			
		||||
@@ -175,10 +173,7 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onStop(owner: LifecycleOwner) {
 | 
			
		||||
        preferences.lastAppClosed().set(Date().time)
 | 
			
		||||
        if (!AuthenticatorUtil.isAuthenticating && preferences.lockAppAfter().get() >= 0) {
 | 
			
		||||
            SecureActivityDelegate.locked = true
 | 
			
		||||
        }
 | 
			
		||||
        SecureActivityDelegate.onApplicationStopped()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun getPackageName(): String {
 | 
			
		||||
 
 | 
			
		||||
@@ -53,6 +53,10 @@ class PreferencesHelper(val context: Context) {
 | 
			
		||||
 | 
			
		||||
    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 secureScreen() = flowPrefs.getEnum("secure_screen_v2", Values.SecureScreenMode.INCOGNITO)
 | 
			
		||||
 
 | 
			
		||||
@@ -8,11 +8,14 @@ import androidx.lifecycle.lifecycleScope
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
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.view.setSecureScreen
 | 
			
		||||
import kotlinx.coroutines.flow.combine
 | 
			
		||||
import kotlinx.coroutines.flow.launchIn
 | 
			
		||||
import kotlinx.coroutines.flow.onEach
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
import java.util.Date
 | 
			
		||||
 | 
			
		||||
@@ -20,10 +23,36 @@ interface SecureActivityDelegate {
 | 
			
		||||
    fun registerSecureActivity(activity: AppCompatActivity)
 | 
			
		||||
 | 
			
		||||
    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 {
 | 
			
		||||
 | 
			
		||||
    private lateinit var activity: AppCompatActivity
 | 
			
		||||
@@ -57,6 +86,7 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
 | 
			
		||||
    private fun setAppLock() {
 | 
			
		||||
        if (!preferences.useAuthenticator().get()) return
 | 
			
		||||
        if (activity.isAuthenticationSupported()) {
 | 
			
		||||
            updatePendingLockStatus()
 | 
			
		||||
            if (!isAppLocked()) return
 | 
			
		||||
            activity.startActivity(Intent(activity, UnlockActivity::class.java))
 | 
			
		||||
            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 {
 | 
			
		||||
        if (!SecureActivityDelegate.locked) return false
 | 
			
		||||
        return preferences.lockAppAfter().get() <= 0 ||
 | 
			
		||||
            Date().time >= preferences.lastAppClosed().get() + 60 * 1000 * preferences.lockAppAfter().get()
 | 
			
		||||
        return lockState == LockState.ACTIVE
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ class UnlockActivity : BaseActivity() {
 | 
			
		||||
                    result: BiometricPrompt.AuthenticationResult,
 | 
			
		||||
                ) {
 | 
			
		||||
                    super.onAuthenticationSucceeded(activity, result)
 | 
			
		||||
                    SecureActivityDelegate.locked = false
 | 
			
		||||
                    SecureActivityDelegate.unlock()
 | 
			
		||||
                    finish()
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user