Fingerprint/Biometric Unlock Support
Version 0.9.3 set
This commit is contained in:
parent
5448a16b35
commit
51e735a9b6
@ -4,7 +4,7 @@ Tachiyomi is a free and open source manga reader for Android.
|
|||||||
![screenshots of app](./.github/readme-images/theming-screenshots.gif)
|
![screenshots of app](./.github/readme-images/theming-screenshots.gif)
|
||||||
|
|
||||||
## Newest Release
|
## Newest Release
|
||||||
[v0.9.2](https://github.com/Jays2Kings/tachiyomi/releases)
|
[v0.9.3](https://github.com/Jays2Kings/tachiyomi/releases)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ android {
|
|||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
versionCode 44
|
versionCode 45
|
||||||
versionName '0.9.2'
|
versionName '0.9.3'
|
||||||
|
|
||||||
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""
|
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""
|
||||||
buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\""
|
buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\""
|
||||||
@ -115,10 +115,11 @@ dependencies {
|
|||||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
implementation 'com.google.android.material:material:1.0.0'
|
implementation 'com.google.android.material:material:1.0.0'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.0.0'
|
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
implementation 'androidx.preference:preference:1.1.0'
|
implementation 'androidx.preference:preference:1.1.0'
|
||||||
implementation 'androidx.annotation:annotation:1.1.0'
|
implementation 'androidx.annotation:annotation:1.1.0'
|
||||||
implementation 'androidx.browser:browser:1.0.0'
|
implementation 'androidx.browser:browser:1.0.0'
|
||||||
|
implementation 'androidx.biometric:biometric:1.0.0'
|
||||||
|
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
|
|
||||||
@ -126,6 +127,10 @@ dependencies {
|
|||||||
|
|
||||||
standardImplementation 'com.google.firebase:firebase-core:17.2.1'
|
standardImplementation 'com.google.firebase:firebase-core:17.2.1'
|
||||||
|
|
||||||
|
final lifecycle_version = "2.1.0"
|
||||||
|
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||||
|
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
|
||||||
|
|
||||||
// ReactiveX
|
// ReactiveX
|
||||||
implementation 'io.reactivex:rxandroid:1.2.1'
|
implementation 'io.reactivex:rxandroid:1.2.1'
|
||||||
implementation 'io.reactivex:rxjava:1.3.8'
|
implementation 'io.reactivex:rxjava:1.3.8'
|
||||||
@ -245,7 +250,7 @@ dependencies {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.50'
|
ext.kotlin_version = '1.3.61'
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,8 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".ui.manga.info.WebViewActivity"
|
android:name=".ui.manga.info.WebViewActivity"
|
||||||
android:configChanges="uiMode|orientation|screenSize"/>
|
android:configChanges="uiMode|orientation|screenSize"/>
|
||||||
|
<activity
|
||||||
|
android:name=".ui.main.BiometricActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".widget.CustomLayoutPickerActivity"
|
android:name=".widget.CustomLayoutPickerActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
@ -3,18 +3,26 @@ package eu.kanade.tachiyomi
|
|||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleObserver
|
||||||
|
import androidx.lifecycle.OnLifecycleEvent
|
||||||
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
import androidx.multidex.MultiDex
|
import androidx.multidex.MultiDex
|
||||||
import com.evernote.android.job.JobManager
|
import com.evernote.android.job.JobManager
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
|
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.data.updater.UpdaterJob
|
import eu.kanade.tachiyomi.data.updater.UpdaterJob
|
||||||
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.util.LocaleHelper
|
import eu.kanade.tachiyomi.util.LocaleHelper
|
||||||
import org.acra.ACRA
|
import org.acra.ACRA
|
||||||
import org.acra.annotation.ReportsCrashes
|
import org.acra.annotation.ReportsCrashes
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.InjektScope
|
import uy.kohesive.injekt.api.InjektScope
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
import uy.kohesive.injekt.registry.default.DefaultRegistrar
|
import uy.kohesive.injekt.registry.default.DefaultRegistrar
|
||||||
|
|
||||||
@ReportsCrashes(
|
@ReportsCrashes(
|
||||||
@ -24,7 +32,7 @@ import uy.kohesive.injekt.registry.default.DefaultRegistrar
|
|||||||
buildConfigClass = BuildConfig::class,
|
buildConfigClass = BuildConfig::class,
|
||||||
excludeMatchingSharedPreferencesKeys = arrayOf(".*username.*", ".*password.*", ".*token.*")
|
excludeMatchingSharedPreferencesKeys = arrayOf(".*username.*", ".*password.*", ".*token.*")
|
||||||
)
|
)
|
||||||
open class App : Application() {
|
open class App : Application(), LifecycleObserver {
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
@ -38,6 +46,16 @@ open class App : Application() {
|
|||||||
setupNotificationChannels()
|
setupNotificationChannels()
|
||||||
|
|
||||||
LocaleHelper.updateConfiguration(this, resources.configuration)
|
LocaleHelper.updateConfiguration(this, resources.configuration)
|
||||||
|
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
|
||||||
|
fun onAppBackgrounded() {
|
||||||
|
//App in background
|
||||||
|
val preferences: PreferencesHelper by injectLazy()
|
||||||
|
if (preferences.lockAfter().getOrDefault() >= 0) {
|
||||||
|
MainActivity.unlocked = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
|
@ -117,6 +117,12 @@ object PreferenceKeys {
|
|||||||
|
|
||||||
const val downloadBadge = "display_download_badge"
|
const val downloadBadge = "display_download_badge"
|
||||||
|
|
||||||
|
const val useBiometrics = "use_biometrics"
|
||||||
|
|
||||||
|
const val lockAfter = "lock_after"
|
||||||
|
|
||||||
|
const val lastUnlock = "last_unlock"
|
||||||
|
|
||||||
@Deprecated("Use the preferences of the source")
|
@Deprecated("Use the preferences of the source")
|
||||||
fun sourceUsername(sourceId: Long) = "pref_source_username_$sourceId"
|
fun sourceUsername(sourceId: Long) = "pref_source_username_$sourceId"
|
||||||
|
|
||||||
|
@ -176,6 +176,12 @@ class PreferencesHelper(val context: Context) {
|
|||||||
|
|
||||||
fun skipRead() = prefs.getBoolean(Keys.skipRead, false)
|
fun skipRead() = prefs.getBoolean(Keys.skipRead, false)
|
||||||
|
|
||||||
|
fun useBiometrics() = rxPrefs.getBoolean(Keys.useBiometrics, false)
|
||||||
|
|
||||||
|
fun lockAfter() = rxPrefs.getInteger(Keys.lockAfter, 0)
|
||||||
|
|
||||||
|
fun lastUnlock() = rxPrefs.getLong(Keys.lastUnlock, 0)
|
||||||
|
|
||||||
fun migrateFlags() = rxPrefs.getInteger("migrate_flags", Int.MAX_VALUE)
|
fun migrateFlags() = rxPrefs.getInteger("migrate_flags", Int.MAX_VALUE)
|
||||||
|
|
||||||
fun trustedSignatures() = rxPrefs.getStringSet("trusted_signatures", emptySet())
|
fun trustedSignatures() = rxPrefs.getStringSet("trusted_signatures", emptySet())
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.main
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.biometric.BiometricPrompt
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
|
class BiometricActivity : BaseActivity() {
|
||||||
|
val executor = Executors.newSingleThreadExecutor()
|
||||||
|
|
||||||
|
val preferences: PreferencesHelper by injectLazy()
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
val biometricPrompt = BiometricPrompt(this, executor, object : BiometricPrompt
|
||||||
|
.AuthenticationCallback() {
|
||||||
|
|
||||||
|
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||||
|
super.onAuthenticationError(errorCode, errString)
|
||||||
|
finishAffinity()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
|
||||||
|
super.onAuthenticationSucceeded(result)
|
||||||
|
MainActivity.unlocked = true
|
||||||
|
preferences.lastUnlock().set(Date().time)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationFailed() {
|
||||||
|
super.onAuthenticationFailed()
|
||||||
|
// TODO("Called when a biometric is valid but not recognized.")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
val promptInfo = BiometricPrompt.PromptInfo.Builder()
|
||||||
|
.setTitle(getString(R.string.unlock_library))
|
||||||
|
.setNegativeButtonText(getString(android.R.string.cancel))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
biometricPrompt.authenticate(promptInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,6 +16,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
import androidx.biometric.BiometricManager
|
||||||
import androidx.core.graphics.ColorUtils
|
import androidx.core.graphics.ColorUtils
|
||||||
import com.bluelinelabs.conductor.*
|
import com.bluelinelabs.conductor.*
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
@ -23,6 +24,7 @@ import eu.kanade.tachiyomi.Migrations
|
|||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.*
|
import eu.kanade.tachiyomi.ui.base.controller.*
|
||||||
import eu.kanade.tachiyomi.ui.catalogue.CatalogueController
|
import eu.kanade.tachiyomi.ui.catalogue.CatalogueController
|
||||||
@ -46,6 +48,7 @@ import eu.kanade.tachiyomi.util.updatePaddingRelative
|
|||||||
import kotlinx.android.synthetic.main.main_activity.*
|
import kotlinx.android.synthetic.main.main_activity.*
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
class MainActivity : BaseActivity() {
|
class MainActivity : BaseActivity() {
|
||||||
|
|
||||||
@ -60,7 +63,6 @@ class MainActivity : BaseActivity() {
|
|||||||
private var snackBar:Snackbar? = null
|
private var snackBar:Snackbar? = null
|
||||||
var extraViewForUndo:View? = null
|
var extraViewForUndo:View? = null
|
||||||
private var canDismissSnackBar = false
|
private var canDismissSnackBar = false
|
||||||
|
|
||||||
fun setUndoSnackBar(snackBar: Snackbar?, extraViewToCheck: View? = null) {
|
fun setUndoSnackBar(snackBar: Snackbar?, extraViewToCheck: View? = null) {
|
||||||
this.snackBar = snackBar
|
this.snackBar = snackBar
|
||||||
canDismissSnackBar = false
|
canDismissSnackBar = false
|
||||||
@ -248,6 +250,22 @@ class MainActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
val useBiometrics = preferences.useBiometrics().getOrDefault()
|
||||||
|
if (useBiometrics && BiometricManager.from(this)
|
||||||
|
.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) {
|
||||||
|
if (!unlocked && (preferences.lockAfter().getOrDefault() <= 0 || Date().time >=
|
||||||
|
preferences.lastUnlock().getOrDefault() + 60 * 1000 * preferences.lockAfter().getOrDefault())) {
|
||||||
|
val intent = Intent(this, BiometricActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
this.overridePendingTransition(0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (useBiometrics)
|
||||||
|
preferences.useBiometrics().set(false)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent) {
|
override fun onNewIntent(intent: Intent) {
|
||||||
if (!handleIntentAction(intent)) {
|
if (!handleIntentAction(intent)) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
@ -314,6 +332,7 @@ class MainActivity : BaseActivity() {
|
|||||||
} else if (backstackSize == 1 && router.getControllerWithTag("$startScreenId") == null) {
|
} else if (backstackSize == 1 && router.getControllerWithTag("$startScreenId") == null) {
|
||||||
setSelectedDrawerItem(startScreenId)
|
setSelectedDrawerItem(startScreenId)
|
||||||
} else if (backstackSize == 1 || !router.handleBack()) {
|
} else if (backstackSize == 1 || !router.handleBack()) {
|
||||||
|
unlocked = false
|
||||||
super.onBackPressed()
|
super.onBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,6 +431,8 @@ class MainActivity : BaseActivity() {
|
|||||||
const val INTENT_SEARCH_FILTER = "filter"
|
const val INTENT_SEARCH_FILTER = "filter"
|
||||||
|
|
||||||
private const val URL_HELP = "https://tachiyomi.org/help/"
|
private const val URL_HELP = "https://tachiyomi.org/help/"
|
||||||
|
|
||||||
|
var unlocked = false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,15 +11,19 @@ import android.graphics.Bitmap
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import android.view.KeyEvent
|
||||||
import android.view.*
|
import android.view.Menu
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.WindowManager
|
||||||
import android.view.animation.Animation
|
import android.view.animation.Animation
|
||||||
import android.view.animation.AnimationUtils
|
import android.view.animation.AnimationUtils
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
import androidx.biometric.BiometricManager
|
||||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
@ -27,6 +31,8 @@ import eu.kanade.tachiyomi.data.notification.Notifications
|
|||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity
|
import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity
|
||||||
|
import eu.kanade.tachiyomi.ui.main.BiometricActivity
|
||||||
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.AddToLibraryFirst
|
import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.AddToLibraryFirst
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.Error
|
import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.Error
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.Success
|
import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.Success
|
||||||
@ -38,12 +44,17 @@ import eu.kanade.tachiyomi.ui.reader.viewer.pager.L2RPagerViewer
|
|||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.VerticalPagerViewer
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.VerticalPagerViewer
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
|
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
|
||||||
import eu.kanade.tachiyomi.util.*
|
import eu.kanade.tachiyomi.util.GLUtil
|
||||||
|
import eu.kanade.tachiyomi.util.getResourceColor
|
||||||
|
import eu.kanade.tachiyomi.util.getUriCompat
|
||||||
|
import eu.kanade.tachiyomi.util.gone
|
||||||
|
import eu.kanade.tachiyomi.util.launchUI
|
||||||
|
import eu.kanade.tachiyomi.util.plusAssign
|
||||||
|
import eu.kanade.tachiyomi.util.toast
|
||||||
|
import eu.kanade.tachiyomi.util.visible
|
||||||
import eu.kanade.tachiyomi.widget.SimpleAnimationListener
|
import eu.kanade.tachiyomi.widget.SimpleAnimationListener
|
||||||
import eu.kanade.tachiyomi.widget.SimpleSeekBarListener
|
import eu.kanade.tachiyomi.widget.SimpleSeekBarListener
|
||||||
import kotlinx.android.synthetic.main.reader_activity.*
|
import kotlinx.android.synthetic.main.reader_activity.*
|
||||||
import kotlinx.android.synthetic.main.reader_activity.toolbar
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import me.zhanghai.android.systemuihelper.SystemUiHelper
|
import me.zhanghai.android.systemuihelper.SystemUiHelper
|
||||||
@ -55,6 +66,7 @@ import rx.subscriptions.CompositeSubscription
|
|||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.Date
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -506,6 +518,23 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>(),
|
|||||||
presenter.shareImage(page)
|
presenter.shareImage(page)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
val useBiometrics = preferences.useBiometrics().getOrDefault()
|
||||||
|
if (useBiometrics && BiometricManager.from(this)
|
||||||
|
.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) {
|
||||||
|
if (!MainActivity.unlocked && (preferences.lockAfter().getOrDefault() <= 0 || Date()
|
||||||
|
.time >=
|
||||||
|
preferences.lastUnlock().getOrDefault() + 60 * 1000 * preferences.lockAfter().getOrDefault())) {
|
||||||
|
val intent = Intent(this, BiometricActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
this.overridePendingTransition(0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (useBiometrics)
|
||||||
|
preferences.useBiometrics().set(false)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called from the presenter when a page is ready to be shared. It shows Android's default
|
* Called from the presenter when a page is ready to be shared. It shows Android's default
|
||||||
* sharing tool.
|
* sharing tool.
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
package eu.kanade.tachiyomi.ui.setting
|
package eu.kanade.tachiyomi.ui.setting
|
||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
|
||||||
import androidx.preference.PreferenceScreen
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.biometric.BiometricManager
|
||||||
|
import androidx.preference.PreferenceScreen
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
@ -16,6 +15,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
import eu.kanade.tachiyomi.util.LocaleHelper
|
import eu.kanade.tachiyomi.util.LocaleHelper
|
||||||
|
import eu.kanade.tachiyomi.widget.preference.IntListPreference
|
||||||
import kotlinx.android.synthetic.main.pref_library_columns.view.*
|
import kotlinx.android.synthetic.main.pref_library_columns.view.*
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
@ -199,6 +199,36 @@ class SettingsGeneralController : SettingsController() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val biometricManager = BiometricManager.from(context)
|
||||||
|
if (biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) {
|
||||||
|
var preference:IntListPreference? = null
|
||||||
|
switchPreference {
|
||||||
|
key = Keys.useBiometrics
|
||||||
|
titleRes = R.string.lock_with_biometrics
|
||||||
|
defaultValue = false
|
||||||
|
|
||||||
|
onChange {
|
||||||
|
preference?.isVisible = it as Boolean
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
preference = intListPreference {
|
||||||
|
key = Keys.lockAfter
|
||||||
|
titleRes = R.string.lock_when_idle
|
||||||
|
isVisible = preferences.useBiometrics().getOrDefault()
|
||||||
|
val values = arrayOf("0", "2", "5", "10", "20", "30", "60", "90", "120", "-1")
|
||||||
|
entries = values.map {
|
||||||
|
when (it) {
|
||||||
|
"0" -> context.getString(R.string.lock_always)
|
||||||
|
"-1" -> context.getString(R.string.lock_never)
|
||||||
|
else -> context.getString(R.string.lock_after_mins, it)
|
||||||
|
}
|
||||||
|
}.toTypedArray()
|
||||||
|
entryValues = values
|
||||||
|
defaultValue = "0"
|
||||||
|
summary = "%s"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LibraryColumnsDialog : DialogController() {
|
class LibraryColumnsDialog : DialogController() {
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<changelog bulletedList="true">
|
<changelog bulletedList="true">
|
||||||
|
<changelogversion versionName="v0.9.3" changeDate="">
|
||||||
|
<changelogtext>Lock Tachiyomi using your fingerprint/Biometrics</changelogtext>
|
||||||
|
<changelogtext>Added search/sorting/mass enable/disable to catalouge sources</changelogtext>
|
||||||
|
<changelogtext>Extensions are now filtered to your locale, with an option to show other languages</changelogtext>
|
||||||
|
<changelogtext>Fixed AMOLED theme not having dark snackbar</changelogtext>
|
||||||
|
</changelogversion>
|
||||||
|
|
||||||
<changelogversion versionName="v0.9.2" changeDate="">
|
<changelogversion versionName="v0.9.2" changeDate="">
|
||||||
<changelogtext>Fixes notification text when there are multiple chapters</changelogtext>
|
<changelogtext>Fixes notification text when there are multiple chapters</changelogtext>
|
||||||
<changelogtext>Simplified errors now show after restoring a backup on the popup dialog</changelogtext>
|
<changelogtext>Simplified errors now show after restoring a backup on the popup dialog</changelogtext>
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
<string name="label_extensions">Extensions</string>
|
<string name="label_extensions">Extensions</string>
|
||||||
<string name="label_extension_info">Extension info</string>
|
<string name="label_extension_info">Extension info</string>
|
||||||
<string name="label_help">Help</string>
|
<string name="label_help">Help</string>
|
||||||
|
<string name="unlock_library">Unlock to access Library</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Actions -->
|
<!-- Actions -->
|
||||||
@ -161,6 +162,11 @@
|
|||||||
<string name="system_default">System default</string>
|
<string name="system_default">System default</string>
|
||||||
<string name="default_category">Default category</string>
|
<string name="default_category">Default category</string>
|
||||||
<string name="default_category_summary">Always ask</string>
|
<string name="default_category_summary">Always ask</string>
|
||||||
|
<string name="lock_with_biometrics">Lock with biometrics</string>
|
||||||
|
<string name="lock_when_idle">Lock when idle</string>
|
||||||
|
<string name="lock_always">Always</string>
|
||||||
|
<string name="lock_never">Never</string>
|
||||||
|
<string name="lock_after_mins">After %1$s minutes</string>
|
||||||
|
|
||||||
<!-- Extension section -->
|
<!-- Extension section -->
|
||||||
<string name="all_lang">All</string>
|
<string name="all_lang">All</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user