diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f9b478510..0c7cda4e0 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,8 @@ + + EH + //Hook long press hamburger menu to lock + getToolbarNavigationIcon(toolbar)?.setOnLongClickListener { + doLock(true) + vibrate(50) // Notify user of lock + true + } + //Show lock if (savedInstanceState == null) { val lockEnabled = lockEnabled(preferences) if (lockEnabled) { //Special case first lock - toolbar.navigationIcon = null doLock() //Check lock security notifyLockSecurity(this) } } + // <-- EH syncActivityViewWithController(router.backstack.lastOrNull()?.controller()) @@ -233,6 +248,26 @@ class MainActivity : BaseActivity() { router.setRoot(controller.withFadeTransaction().tag(id.toString())) } + fun getToolbarNavigationIcon(toolbar: Toolbar): View? { + //check if contentDescription previously was set + val hadContentDescription = TextUtils.isEmpty(toolbar.navigationContentDescription) + val contentDescription = if (!hadContentDescription) toolbar.navigationContentDescription else "navigationIcon" + toolbar.navigationContentDescription = contentDescription + + val potentialViews = ArrayList() + + //find the view based on it's content description, set programmatically or with android:contentDescription + toolbar.findViewsWithText(potentialViews, contentDescription, View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION) + + //Nav icon is always instantiated at this point because calling setNavigationContentDescription ensures its existence + val navIcon = potentialViews.firstOrNull() + + //Clear content description if not previously present + if (hadContentDescription) + toolbar.navigationContentDescription = null + return navIcon + } + private fun syncActivityViewWithController(to: Controller?, from: Controller? = null) { if (from is DialogController || to is DialogController) { return @@ -249,6 +284,7 @@ class MainActivity : BaseActivity() { //Special case and hide drawer arrow for lock controller if(to is LockController) { supportActionBar?.setDisplayHomeAsUpEnabled(false) + toolbar.navigationIcon = null } else { supportActionBar?.setDisplayHomeAsUpEnabled(true) toolbar.navigationIcon = drawerArrow @@ -308,6 +344,10 @@ class MainActivity : BaseActivity() { if(router.backstack.lastOrNull()?.controller() is LockController) return + //Do not lock if manual lock enabled + if(preferences.eh_lockManually().getOrDefault()) + return + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { val mUsageStatsManager = getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager val time = System.currentTimeMillis() @@ -331,9 +371,9 @@ class MainActivity : BaseActivity() { } } - fun doLock() { + fun doLock(animate: Boolean = false) { router.pushController(RouterTransaction.with(LockController()) - .popChangeHandler(LockChangeHandler())) + .popChangeHandler(LockChangeHandler(animate))) } // <-- EH diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt index 84ef53d45..f7148c513 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt @@ -4,7 +4,6 @@ import android.app.Dialog import android.os.Bundle import android.os.Handler import android.support.v7.preference.PreferenceScreen -import android.support.v7.preference.SwitchPreference import android.view.View import com.afollestad.materialdialogs.MaterialDialog import eu.kanade.tachiyomi.R @@ -197,6 +196,14 @@ class SettingsGeneralController : SettingsController() { //Call after addPreference dependency = "pref_app_lock" } + + switchPreference { + key = Keys.eh_lock_manually + + title = "Lock manually only" + summary = "Disable automatic app locking. The app can still be locked manually by long-pressing the three-lines/back button in the top left corner." + defaultValue = false + } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/ContextExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/ContextExtensions.kt index 4824444c2..b236b000c 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/util/ContextExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/ContextExtensions.kt @@ -5,13 +5,17 @@ import android.app.Notification import android.app.NotificationManager import android.content.BroadcastReceiver import android.content.Context +import android.content.Context.VIBRATOR_SERVICE import android.content.Intent import android.content.IntentFilter import android.content.pm.PackageManager import android.content.res.Resources import android.net.ConnectivityManager import android.net.wifi.WifiManager +import android.os.Build import android.os.PowerManager +import android.os.VibrationEffect +import android.os.Vibrator import android.support.annotation.StringRes import android.support.v4.app.NotificationCompat import android.support.v4.content.ContextCompat @@ -20,6 +24,8 @@ import android.widget.Toast import com.nononsenseapps.filepicker.FilePickerActivity import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity + + /** * Display a toast in this context. * @@ -168,4 +174,13 @@ fun Context.isServiceRunning(serviceClass: Class<*>): Boolean { @Suppress("DEPRECATION") return manager.getRunningServices(Integer.MAX_VALUE) .any { className == it.service.className } +} + +fun Context.vibrate(time: Long) { + val vibeService = getSystemService(VIBRATOR_SERVICE) as Vibrator + if (Build.VERSION.SDK_INT >= 26) { + vibeService.vibrate(VibrationEffect.createOneShot(time, VibrationEffect.DEFAULT_AMPLITUDE)) + } else { + vibeService.vibrate(time) + } } \ No newline at end of file diff --git a/app/src/main/java/exh/ui/lock/FingerLockPreference.kt b/app/src/main/java/exh/ui/lock/FingerLockPreference.kt index 6a29e2a7f..2fc478a96 100644 --- a/app/src/main/java/exh/ui/lock/FingerLockPreference.kt +++ b/app/src/main/java/exh/ui/lock/FingerLockPreference.kt @@ -34,7 +34,7 @@ class FingerLockPreference @JvmOverloads constructor(context: Context, attrs: At val useFingerprint get() = fingerprintSupported - && prefs.lockUseFingerprint().getOrDefault() + && prefs.eh_lockUseFingerprint().getOrDefault() @SuppressLint("NewApi") override fun onAttached() { @@ -45,7 +45,7 @@ class FingerLockPreference @JvmOverloads constructor(context: Context, attrs: At if(it as Boolean) tryChange() else - prefs.lockUseFingerprint().set(false) + prefs.eh_lockUseFingerprint().set(false) !it } } else { @@ -121,7 +121,7 @@ class FingerLockPreference @JvmOverloads constructor(context: Context, attrs: At when (result.status) { AuthenticationResult.Status.SUCCESS -> { iconView.setState(SwirlView.State.ON) - prefs.lockUseFingerprint().set(true) + prefs.eh_lockUseFingerprint().set(true) dialog.dismiss() updateSummary() } diff --git a/app/src/main/java/exh/ui/lock/LockController.kt b/app/src/main/java/exh/ui/lock/LockController.kt index 918a5d900..b94312102 100755 --- a/app/src/main/java/exh/ui/lock/LockController.kt +++ b/app/src/main/java/exh/ui/lock/LockController.kt @@ -41,12 +41,12 @@ class LockController : NucleusController() { //Setup pin lock pin_lock_view.attachIndicatorDots(indicator_dots) - pin_lock_view.pinLength = prefs.lockLength().getOrDefault() + pin_lock_view.pinLength = prefs.eh_lockLength().getOrDefault() pin_lock_view.setPinLockListener(object : PinLockListener { override fun onEmpty() {} override fun onComplete(pin: String) { - if (sha512(pin, prefs.lockSalt().get()!!) == prefs.lockHash().get()) { + if (sha512(pin, prefs.eh_lockSalt().get()!!) == prefs.eh_lockHash().get()) { //Yay! closeLock() } else { @@ -120,7 +120,7 @@ class LockController : NucleusController() { private fun resolvColor(color: Int): Int { val typedVal = TypedValue() - activity!!.theme!!.resolveAttribute(android.R.attr.windowBackground, typedVal, true) + activity!!.theme!!.resolveAttribute(color, typedVal, true) return typedVal.data } diff --git a/app/src/main/java/exh/ui/lock/LockPreference.kt b/app/src/main/java/exh/ui/lock/LockPreference.kt index 824b2376e..43cb261c6 100755 --- a/app/src/main/java/exh/ui/lock/LockPreference.kt +++ b/app/src/main/java/exh/ui/lock/LockPreference.kt @@ -1,8 +1,6 @@ package exh.ui.lock import android.content.Context -import android.support.v7.preference.Preference -import android.support.v7.preference.SwitchPreference import android.support.v7.preference.SwitchPreferenceCompat import android.text.InputType import android.util.AttributeSet @@ -87,8 +85,8 @@ class LockPreference @JvmOverloads constructor(context: Context, attrs: Attribut hash = sha512(password, salt) length = password.length } - prefs.lockSalt().set(salt) - prefs.lockHash().set(hash) - prefs.lockLength().set(length) + prefs.eh_lockSalt().set(salt) + prefs.eh_lockHash().set(hash) + prefs.eh_lockLength().set(length) } } diff --git a/app/src/main/java/exh/ui/lock/LockPresenter.kt b/app/src/main/java/exh/ui/lock/LockPresenter.kt index 5941e6f12..3bdc532f7 100644 --- a/app/src/main/java/exh/ui/lock/LockPresenter.kt +++ b/app/src/main/java/exh/ui/lock/LockPresenter.kt @@ -14,6 +14,6 @@ class LockPresenter: BasePresenter() { get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Reprint.isHardwarePresent() && Reprint.hasFingerprintRegistered() - && prefs.lockUseFingerprint().getOrDefault() + && prefs.eh_lockUseFingerprint().getOrDefault() } diff --git a/app/src/main/java/exh/ui/lock/LockUtils.kt b/app/src/main/java/exh/ui/lock/LockUtils.kt index 3ecc4aec0..2173293ca 100755 --- a/app/src/main/java/exh/ui/lock/LockUtils.kt +++ b/app/src/main/java/exh/ui/lock/LockUtils.kt @@ -1,7 +1,6 @@ package exh.ui.lock import android.annotation.TargetApi -import android.app.Activity import android.app.AppOpsManager import android.content.Context import android.content.Intent @@ -40,17 +39,20 @@ fun sha512(passwordToHash: String, salt: String): String { * Check if lock is enabled */ fun lockEnabled(prefs: PreferencesHelper = Injekt.get()) - = prefs.lockHash().get() != null - && prefs.lockSalt().get() != null - && prefs.lockLength().getOrDefault() != -1 + = prefs.eh_lockHash().get() != null + && prefs.eh_lockSalt().get() != null + && prefs.eh_lockLength().getOrDefault() != -1 /** * Check if the lock will function properly * * @return true if action is required, false if lock is working properly */ -fun notifyLockSecurity(context: Context): Boolean { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !hasAccessToUsageStats(context)) { +fun notifyLockSecurity(context: Context, + prefs: PreferencesHelper = Injekt.get()): Boolean { + if (!prefs.eh_lockManually().getOrDefault() + && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP + && !hasAccessToUsageStats(context)) { MaterialDialog.Builder(context) .title("Permission required") .content("${context.getString(R.string.app_name)} requires the usage stats permission to detect when you leave the app. " +