diff --git a/app/build.gradle b/app/build.gradle
index 058b0e089..5dd61f9d4 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -219,9 +219,16 @@ dependencies {
//JVE (Regex) (EH)
compile 'ru.lanwen.verbalregex:java-verbal-expressions:1.4'
- //Pin lock view
+ //Pin lock view (EXH)
compile 'com.andrognito.pinlockview:pinlockview:1.0.1'
+ //Reprint (EXH)
+ compile 'com.github.ajalt.reprint:core:3.1.0@aar' // required: supports marshmallow devices
+ compile 'com.github.ajalt.reprint:rxjava:3.1.0@aar' // optional: the RxJava 1 interface
+
+ //Swirl (EXH)
+ compile 'com.mattprecious.swirl:swirl:1.0.0'
+
// Tests
//Paper DB screws up tests
/*testCompile 'junit:junit:4.12'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5762deea3..2447e6800 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -10,6 +10,7 @@
+
@@ -106,7 +107,7 @@
diff --git a/app/src/main/java/eu/kanade/tachiyomi/App.kt b/app/src/main/java/eu/kanade/tachiyomi/App.kt
index af89227b6..4997f2587 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/App.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/App.kt
@@ -5,6 +5,7 @@ import android.content.Context
import android.content.res.Configuration
import android.support.multidex.MultiDex
import com.evernote.android.job.JobManager
+import com.github.ajalt.reprint.core.Reprint
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.updater.UpdateCheckerJob
@@ -26,6 +27,7 @@ open class App : Application() {
setupJobManager()
Paper.init(this) //Setup metadata DB (EH)
+ Reprint.initialize(this) //Setup fingerprint (EH)
LocaleHelper.updateConfiguration(this, resources.configuration)
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
index 46cedc1bf..586a4c0c4 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
@@ -199,5 +199,7 @@ class PreferencesHelper(val context: Context) {
fun lockSalt() = rxPrefs.getString("lock_salt", null)
fun lockLength() = rxPrefs.getInteger("lock_length", -1)
+
+ fun lockUseFingerprint() = rxPrefs.getBoolean("lock_finger", false)
// <-- EH
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt
index 0217a417c..53077e13b 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/EHentai.kt
@@ -19,7 +19,7 @@ import rx.Observable
import uy.kohesive.injekt.injectLazy
import java.net.URLEncoder
import java.util.*
-import exh.ui.login.LoginActivity
+import exh.ui.login.LoginController
import exh.util.UriFilter
import exh.util.UriGroup
import okhttp3.CacheControl
@@ -323,9 +323,9 @@ class EHentai(override val id: Long,
val cookiesHeader by lazy {
val cookies: MutableMap = mutableMapOf()
if(prefs.enableExhentai().getOrDefault()) {
- cookies.put(LoginActivity.MEMBER_ID_COOKIE, prefs.memberIdVal().get()!!)
- cookies.put(LoginActivity.PASS_HASH_COOKIE, prefs.passHashVal().get()!!)
- cookies.put(LoginActivity.IGNEOUS_COOKIE, prefs.igneousVal().get()!!)
+ cookies.put(LoginController.MEMBER_ID_COOKIE, prefs.memberIdVal().get()!!)
+ cookies.put(LoginController.PASS_HASH_COOKIE, prefs.passHashVal().get()!!)
+ cookies.put(LoginController.IGNEOUS_COOKIE, prefs.igneousVal().get()!!)
}
//Setup settings
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt
index 2adeadc5f..642ab27bf 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt
@@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.main
import android.animation.ObjectAnimator
import android.app.ActivityManager
import android.app.Service
-import android.app.usage.UsageStats
import android.app.usage.UsageStatsManager
import android.content.Intent
import android.graphics.Color
@@ -15,8 +14,6 @@ import android.support.v7.graphics.drawable.DrawerArrowDrawable
import android.view.ViewGroup
import com.bluelinelabs.conductor.*
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
-import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler
-import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
import eu.kanade.tachiyomi.Migrations
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@@ -40,7 +37,6 @@ import exh.ui.lock.lockEnabled
import exh.ui.lock.notifyLockSecurity
import kotlinx.android.synthetic.main.main_activity.*
import uy.kohesive.injekt.injectLazy
-import java.util.*
class MainActivity : BaseActivity() {
@@ -49,7 +45,7 @@ class MainActivity : BaseActivity() {
val preferences: PreferencesHelper by injectLazy()
- private var drawerArrow: DrawerArrowDrawable? = null
+ var drawerArrow: DrawerArrowDrawable? = null
private var secondaryDrawer: ViewGroup? = null
@@ -153,6 +149,8 @@ class MainActivity : BaseActivity() {
if (savedInstanceState == null) {
val lockEnabled = lockEnabled(preferences)
if (lockEnabled) {
+ //Special case first lock
+ toolbar.navigationIcon = null
doLock()
//Check lock security
@@ -236,6 +234,16 @@ class MainActivity : BaseActivity() {
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
}
+ // --> EH
+ //Special case and hide drawer arrow for lock controller
+ if(to is LockController) {
+ supportActionBar?.setDisplayHomeAsUpEnabled(false)
+ } else {
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ toolbar.navigationIcon = drawerArrow
+ }
+ // <-- EH
+
ObjectAnimator.ofFloat(drawerArrow, "progress", if (showHamburger) 0f else 1f).start()
if (from is TabbedController) {
@@ -270,10 +278,9 @@ class MainActivity : BaseActivity() {
// --> EH
//Lock code
var willLock = false
- var disableLock = false
override fun onRestart() {
super.onRestart()
- if(willLock && lockEnabled() && !disableLock) {
+ if(willLock && lockEnabled()) {
doLock()
}
@@ -286,6 +293,10 @@ class MainActivity : BaseActivity() {
}
fun tryLock() {
+ //Do not double-lock
+ if(router.backstack.lastOrNull()?.controller() is LockController)
+ return
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val mUsageStatsManager = getSystemService("usagestats") as UsageStatsManager
val time = System.currentTimeMillis()
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt
index 650138ce5..74b2a1dee 100755
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsEhController.kt
@@ -1,9 +1,11 @@
package eu.kanade.tachiyomi.ui.setting
-import android.content.Intent
import android.support.v7.preference.PreferenceScreen
+import com.bluelinelabs.conductor.RouterTransaction
+import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
import exh.ui.migration.MetadataFetchDialog
-import exh.ui.login.LoginActivity
+import exh.ui.login.LoginController
+import rx.android.schedulers.AndroidSchedulers
/**
* EH Settings fragment
@@ -20,9 +22,11 @@ class SettingsEhController : SettingsController() {
isPersistent = false
defaultValue = false
preferences.enableExhentai()
- .asObservable().subscribeUntilDestroy {
+ .asObservable()
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribeUntilDestroy {
isChecked = it
- }
+ }
onChange { newVal ->
newVal as Boolean
@@ -30,7 +34,9 @@ class SettingsEhController : SettingsController() {
preferences.enableExhentai().set(false)
true
} else {
- startActivity(Intent(context, LoginActivity::class.java))
+ router.pushController(RouterTransaction.with(LoginController())
+ .pushChangeHandler(FadeChangeHandler())
+ .popChangeHandler(FadeChangeHandler()))
false
}
}
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 ee2a241f9..1ac99c63c 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,6 +4,7 @@ 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
@@ -13,6 +14,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.util.LocaleHelper
+import exh.ui.lock.FingerLockPreference
import exh.ui.lock.LockPreference
import kotlinx.android.synthetic.main.pref_library_columns.view.*
import rx.Observable
@@ -176,12 +178,25 @@ class SettingsGeneralController : SettingsController() {
true
}
}
- LockPreference(context).apply {
- key = "pref_app_lock"
+ preferenceCategory {
title = "Application lock"
- isPersistent = false
- addPreference(this)
+ LockPreference(context).apply {
+ key = "pref_app_lock"
+ isPersistent = false
+
+ addPreference(this)
+ }
+
+ FingerLockPreference(context).apply {
+ key = "pref_lock_finger"
+ isPersistent = false
+
+ addPreference(this)
+
+ //Call after addPreference
+ dependency = "pref_app_lock"
+ }
}
}
diff --git a/app/src/main/java/exh/ui/batchadd/BatchAddController.kt b/app/src/main/java/exh/ui/batchadd/BatchAddController.kt
index 401cd9120..bad59e8e2 100755
--- a/app/src/main/java/exh/ui/batchadd/BatchAddController.kt
+++ b/app/src/main/java/exh/ui/batchadd/BatchAddController.kt
@@ -35,7 +35,7 @@ class BatchAddController : NucleusController() {
}
progress_dismiss_btn.clicks().subscribeUntilDestroy {
- presenter.currentlyAddingRelay.call(false)
+ presenter.currentlyAddingRelay.call(BatchAddPresenter.STATE_PROGRESS_TO_INPUT)
}
val progressSubscriptions = CompositeSubscription()
@@ -44,7 +44,7 @@ class BatchAddController : NucleusController() {
.observeOn(AndroidSchedulers.mainThread())
.subscribeUntilDestroy {
progressSubscriptions.clear()
- if(it) {
+ if(it == BatchAddPresenter.STATE_INPUT_TO_PROGRESS) {
showProgress(this)
progressSubscriptions += presenter.progressRelay
.observeOn(AndroidSchedulers.mainThread())
@@ -79,7 +79,10 @@ class BatchAddController : NucleusController() {
}?.let {
progressSubscriptions += it
}
- } else hideProgress(this)
+ } else if(it == BatchAddPresenter.STATE_PROGRESS_TO_INPUT) {
+ hideProgress(this)
+ presenter.currentlyAddingRelay.call(BatchAddPresenter.STATE_IDLE)
+ }
}
}
}
diff --git a/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt b/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt
index 40dffcb15..5e0a05076 100644
--- a/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt
+++ b/app/src/main/java/exh/ui/batchadd/BatchAddPresenter.kt
@@ -15,18 +15,18 @@ class BatchAddPresenter: BasePresenter() {
val progressTotalRelay = BehaviorRelay.create(0)!!
val progressRelay = BehaviorRelay.create(0)!!
var eventRelay: ReplayRelay? = null
- val currentlyAddingRelay = BehaviorRelay.create(false)!!
+ val currentlyAddingRelay = BehaviorRelay.create(STATE_IDLE)!!
fun addGalleries(galleries: String) {
eventRelay = ReplayRelay.create()
- val splitGalleries = galleries.split("\n").map {
+ val splitGalleries = galleries.split("\n").mapNotNull {
it.trim().nullIfBlank()
- }.filterNotNull()
+ }
progressRelay.call(0)
progressTotalRelay.call(splitGalleries.size)
- currentlyAddingRelay.call(true)
+ currentlyAddingRelay.call(STATE_INPUT_TO_PROGRESS)
thread {
val succeeded = mutableListOf()
@@ -48,4 +48,10 @@ class BatchAddPresenter: BasePresenter() {
eventRelay?.call(summary)
}
}
+
+ companion object {
+ const val STATE_IDLE = 0
+ const val STATE_INPUT_TO_PROGRESS = 1
+ const val STATE_PROGRESS_TO_INPUT = 2
+ }
}
diff --git a/app/src/main/java/exh/ui/lock/FingerLockPreference.kt b/app/src/main/java/exh/ui/lock/FingerLockPreference.kt
new file mode 100644
index 000000000..6a29e2a7f
--- /dev/null
+++ b/app/src/main/java/exh/ui/lock/FingerLockPreference.kt
@@ -0,0 +1,149 @@
+package exh.ui.lock
+
+import android.annotation.SuppressLint
+import android.annotation.TargetApi
+import android.content.Context
+import android.os.Build
+import android.support.v7.preference.SwitchPreferenceCompat
+import android.support.v7.widget.LinearLayoutCompat
+import android.util.AttributeSet
+import android.view.Gravity
+import android.view.ViewGroup
+import android.widget.TextView
+import com.afollestad.materialdialogs.MaterialDialog
+import com.github.ajalt.reprint.core.AuthenticationResult
+import com.github.ajalt.reprint.core.Reprint
+import com.github.ajalt.reprint.rxjava.RxReprint
+import com.mattprecious.swirl.SwirlView
+import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.tachiyomi.data.preference.getOrDefault
+import eu.kanade.tachiyomi.ui.setting.onChange
+import exh.util.dpToPx
+import rx.android.schedulers.AndroidSchedulers
+import uy.kohesive.injekt.injectLazy
+
+class FingerLockPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
+ SwitchPreferenceCompat(context, attrs) {
+
+ val prefs: PreferencesHelper by injectLazy()
+
+ val fingerprintSupported
+ get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
+ && Reprint.isHardwarePresent()
+ && Reprint.hasFingerprintRegistered()
+
+ val useFingerprint
+ get() = fingerprintSupported
+ && prefs.lockUseFingerprint().getOrDefault()
+
+ @SuppressLint("NewApi")
+ override fun onAttached() {
+ super.onAttached()
+ if(fingerprintSupported) {
+ updateSummary()
+ onChange {
+ if(it as Boolean)
+ tryChange()
+ else
+ prefs.lockUseFingerprint().set(false)
+ !it
+ }
+ } else {
+ title = "Fingerprint unsupported"
+ shouldDisableView = true
+ summary = if(!Reprint.hasFingerprintRegistered())
+ "No fingerprints enrolled!"
+ else
+ "Fingerprint unlock is unsupported on this device!"
+ onChange { false }
+ }
+ }
+
+ private fun updateSummary() {
+ isChecked = useFingerprint
+ title = if(isChecked)
+ "Fingerprint enabled"
+ else
+ "Fingerprint disabled"
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ fun tryChange() {
+ val statusTextView = TextView(context).apply {
+ text = "Please touch the fingerprint sensor"
+ val size = ViewGroup.LayoutParams.WRAP_CONTENT
+ layoutParams = (layoutParams ?: ViewGroup.LayoutParams(
+ size, size
+ )).apply {
+ width = size
+ height = size
+ setPadding(0, 0, dpToPx(context, 8), 0)
+ }
+ }
+ val iconView = SwirlView(context).apply {
+ val size = dpToPx(context, 30)
+ layoutParams = (layoutParams ?: ViewGroup.LayoutParams(
+ size, size
+ )).apply {
+ width = size
+ height = size
+ }
+ setState(SwirlView.State.OFF, false)
+ }
+ val linearLayout = LinearLayoutCompat(context).apply {
+ orientation = LinearLayoutCompat.HORIZONTAL
+ gravity = Gravity.CENTER_VERTICAL
+ val size = LinearLayoutCompat.LayoutParams.WRAP_CONTENT
+ layoutParams = (layoutParams ?: LinearLayoutCompat.LayoutParams(
+ size, size
+ )).apply {
+ width = size
+ height = size
+ val pSize = dpToPx(context, 24)
+ setPadding(pSize, 0, pSize, 0)
+ }
+
+ addView(statusTextView)
+ addView(iconView)
+ }
+ val dialog = MaterialDialog.Builder(context)
+ .title("Fingerprint verification")
+ .customView(linearLayout, false)
+ .negativeText("Cancel")
+ .autoDismiss(true)
+ .cancelable(true)
+ .canceledOnTouchOutside(true)
+ .show()
+ iconView.setState(SwirlView.State.ON)
+ val subscription = RxReprint.authenticate()
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe { result ->
+ when (result.status) {
+ AuthenticationResult.Status.SUCCESS -> {
+ iconView.setState(SwirlView.State.ON)
+ prefs.lockUseFingerprint().set(true)
+ dialog.dismiss()
+ updateSummary()
+ }
+ AuthenticationResult.Status.NONFATAL_FAILURE -> {
+ iconView.setState(SwirlView.State.ERROR)
+ statusTextView.text = result.errorMessage
+ }
+ AuthenticationResult.Status.FATAL_FAILURE, null -> {
+ MaterialDialog.Builder(context)
+ .title("Fingerprint verification failed!")
+ .content(result.errorMessage)
+ .positiveText("Ok")
+ .autoDismiss(true)
+ .cancelable(true)
+ .canceledOnTouchOutside(false)
+ .show()
+ dialog.dismiss()
+ }
+ }
+ }
+ dialog.setOnDismissListener {
+ subscription.unsubscribe()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/exh/ui/lock/LockChangeHandler.kt b/app/src/main/java/exh/ui/lock/LockChangeHandler.kt
index e70227396..d72f7db42 100644
--- a/app/src/main/java/exh/ui/lock/LockChangeHandler.kt
+++ b/app/src/main/java/exh/ui/lock/LockChangeHandler.kt
@@ -23,8 +23,8 @@ class LockChangeHandler : AnimatorChangeHandler {
val viewAnimators = ArrayList()
if (!isPush && from != null) {
- viewAnimators.add(ObjectAnimator.ofFloat(from, View.SCALE_X, 5f))
- viewAnimators.add(ObjectAnimator.ofFloat(from, View.SCALE_Y, 5f))
+ viewAnimators.add(ObjectAnimator.ofFloat(from, View.SCALE_X, 3f))
+ viewAnimators.add(ObjectAnimator.ofFloat(from, View.SCALE_Y, 3f))
viewAnimators.add(ObjectAnimator.ofFloat(from, View.ALPHA, 0f))
}
diff --git a/app/src/main/java/exh/ui/lock/LockController.kt b/app/src/main/java/exh/ui/lock/LockController.kt
index 59e5ff6b3..4ab9621dd 100755
--- a/app/src/main/java/exh/ui/lock/LockController.kt
+++ b/app/src/main/java/exh/ui/lock/LockController.kt
@@ -1,19 +1,35 @@
package exh.ui.lock
+import android.annotation.SuppressLint
import android.os.Bundle
+import android.support.v4.hardware.fingerprint.FingerprintManagerCompat
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.widget.CardView
+import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.FrameLayout
import com.afollestad.materialdialogs.MaterialDialog
import com.andrognito.pinlockview.PinLockListener
+import com.github.ajalt.reprint.core.AuthenticationResult
+import com.github.ajalt.reprint.core.Reprint
+import com.github.ajalt.reprint.rxjava.RxReprint
+import com.mattprecious.swirl.SwirlView
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
+import eu.kanade.tachiyomi.ui.main.MainActivity
+import exh.util.dpToPx
import kotlinx.android.synthetic.main.activity_lock.view.*
+import kotlinx.android.synthetic.main.main_activity.view.*
import uy.kohesive.injekt.injectLazy
class LockController : NucleusController() {
+
+ val prefs: PreferencesHelper by injectLazy()
+
override fun inflateView(inflater: LayoutInflater, container: ViewGroup)
= inflater.inflate(R.layout.activity_lock, container, false)!!
@@ -21,8 +37,6 @@ class LockController : NucleusController() {
override fun getTitle() = "Application locked"
- val prefs: PreferencesHelper by injectLazy()
-
override fun onViewCreated(view: View, savedViewState: Bundle?) {
super.onViewCreated(view, savedViewState)
@@ -32,6 +46,7 @@ class LockController : NucleusController() {
}
with(view) {
+ //Setup pin lock
pin_lock_view.attachIndicatorDots(indicator_dots)
pin_lock_view.pinLength = prefs.lockLength().getOrDefault()
@@ -60,6 +75,61 @@ class LockController : NucleusController() {
}
}
+ @SuppressLint("NewApi")
+ override fun onAttach(view: View) {
+ super.onAttach(view)
+
+ with(view) {
+ //Fingerprint
+ if (presenter.useFingerprint) {
+ swirl_container.removeAllViews()
+ val icon = SwirlView(context).apply {
+ val size = dpToPx(context, 60)
+ layoutParams = (layoutParams ?: ViewGroup.LayoutParams(
+ size, size
+ )).apply {
+ width = size
+ height = size
+
+ val pSize = dpToPx(context, 8)
+ setPadding(pSize, pSize, pSize, pSize)
+ }
+ val typedVal = TypedValue()
+ activity!!.theme!!.resolveAttribute(android.R.attr.windowBackground, typedVal, true)
+ setBackgroundColor(typedVal.data)
+ //Disable elevation if dark theme is active
+ if (typedVal.data == resources.getColor(R.color.backgroundDark, activity!!.theme!!))
+ this@with.swirl_container.cardElevation = 0f
+ setState(SwirlView.State.OFF, false)
+ }
+ swirl_container.addView(icon)
+ icon.setState(SwirlView.State.ON)
+ RxReprint.authenticate()
+ .subscribeUntilDetach {
+ when (it.status) {
+ AuthenticationResult.Status.SUCCESS -> closeLock()
+ AuthenticationResult.Status.NONFATAL_FAILURE -> icon.setState(SwirlView.State.ERROR)
+ AuthenticationResult.Status.FATAL_FAILURE, null -> {
+ MaterialDialog.Builder(context)
+ .title("Fingerprint error!")
+ .content(it.errorMessage)
+ .cancelable(false)
+ .canceledOnTouchOutside(false)
+ .positiveText("Ok")
+ .autoDismiss(true)
+ .show()
+ icon.setState(SwirlView.State.OFF)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ override fun onDetach(view: View) {
+ super.onDetach(view)
+ }
+
fun closeLock() {
router.popCurrentController()
}
diff --git a/app/src/main/java/exh/ui/lock/LockPreference.kt b/app/src/main/java/exh/ui/lock/LockPreference.kt
index 8985d3e21..824b2376e 100755
--- a/app/src/main/java/exh/ui/lock/LockPreference.kt
+++ b/app/src/main/java/exh/ui/lock/LockPreference.kt
@@ -2,11 +2,14 @@ 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
import com.afollestad.materialdialogs.MaterialDialog
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.tachiyomi.ui.setting.onChange
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
@@ -15,7 +18,7 @@ import java.math.BigInteger
import java.security.SecureRandom
class LockPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
- Preference(context, attrs) {
+ SwitchPreferenceCompat(context, attrs) {
private val secureRandom by lazy { SecureRandom() }
@@ -24,17 +27,24 @@ class LockPreference @JvmOverloads constructor(context: Context, attrs: Attribut
override fun onAttached() {
super.onAttached()
updateSummary()
+ onChange {
+ tryChange()
+ false
+ }
}
private fun updateSummary() {
- summary = if(lockEnabled(prefs))
- "Application is locked"
- else
- "Application is not locked, tap to lock"
+ isChecked = lockEnabled(prefs)
+ if(isChecked) {
+ title = "Lock enabled"
+ summary = "Tap to disable or change pin code"
+ } else {
+ title = "Lock disabled"
+ summary = "Tap to enable"
+ }
}
- override fun onClick() {
- super.onClick()
+ fun tryChange() {
if(!notifyLockSecurity(context)) {
MaterialDialog.Builder(context)
.title("Lock application")
diff --git a/app/src/main/java/exh/ui/lock/LockPresenter.kt b/app/src/main/java/exh/ui/lock/LockPresenter.kt
index 22c02d31c..5941e6f12 100644
--- a/app/src/main/java/exh/ui/lock/LockPresenter.kt
+++ b/app/src/main/java/exh/ui/lock/LockPresenter.kt
@@ -1,6 +1,19 @@
package exh.ui.lock
+import android.os.Build
+import com.github.ajalt.reprint.core.Reprint
+import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import uy.kohesive.injekt.injectLazy
-class LockPresenter: BasePresenter()
+class LockPresenter: BasePresenter() {
+ val prefs: PreferencesHelper by injectLazy()
+
+ val useFingerprint
+ get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
+ && Reprint.isHardwarePresent()
+ && Reprint.hasFingerprintRegistered()
+ && prefs.lockUseFingerprint().getOrDefault()
+}
diff --git a/app/src/main/java/exh/ui/login/LoginActivity.kt b/app/src/main/java/exh/ui/login/LoginController.kt
similarity index 66%
rename from app/src/main/java/exh/ui/login/LoginActivity.kt
rename to app/src/main/java/exh/ui/login/LoginController.kt
index a997969fb..7b495fb63 100755
--- a/app/src/main/java/exh/ui/login/LoginActivity.kt
+++ b/app/src/main/java/exh/ui/login/LoginController.kt
@@ -3,7 +3,9 @@ package exh.ui.login
import android.net.Uri
import android.os.Build
import android.os.Bundle
-import android.view.MenuItem
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
import android.webkit.CookieManager
import android.webkit.WebView
import android.webkit.WebViewClient
@@ -12,9 +14,9 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.all.EHentai
-import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
+import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import exh.EXH_SOURCE_ID
-import kotlinx.android.synthetic.main.eh_activity_login.*
+import kotlinx.android.synthetic.main.eh_activity_login.view.*
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
@@ -23,70 +25,75 @@ import uy.kohesive.injekt.injectLazy
import java.net.HttpCookie
/**
- * LoginActivity
+ * LoginController
*/
-class LoginActivity : BaseActivity() {
-
+class LoginController : NucleusController() {
val preferenceManager: PreferencesHelper by injectLazy()
val sourceManager: SourceManager by injectLazy()
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.eh_activity_login)
+ override fun getTitle() = "ExHentai login"
- setup()
- }
+ override fun createPresenter() = LoginPresenter()
- fun setup() {
- btn_cancel.setOnClickListener { onBackPressed() }
- btn_recheck.setOnClickListener { webview.loadUrl("http://exhentai.org/") }
+ override fun inflateView(inflater: LayoutInflater, container: ViewGroup) =
+ inflater.inflate(R.layout.eh_activity_login, container, false)!!
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- CookieManager.getInstance().removeAllCookies {
- runOnUiThread {
- startWebview()
+ override fun onViewCreated(view: View, savedViewState: Bundle?) {
+ super.onViewCreated(view, savedViewState)
+
+ with(view) {
+ btn_cancel.setOnClickListener { router.popCurrentController() }
+ btn_recheck.setOnClickListener { webview.loadUrl("http://exhentai.org/") }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ CookieManager.getInstance().removeAllCookies {
+ Observable.fromCallable {
+ startWebview(view)
+ }.subscribeOn(AndroidSchedulers.mainThread()).subscribe()
}
+ } else {
+ CookieManager.getInstance().removeAllCookie()
+ startWebview(view)
}
- } else {
- CookieManager.getInstance().removeAllCookie()
- startWebview()
}
}
- fun startWebview() {
- webview.settings.javaScriptEnabled = true
- webview.settings.domStorageEnabled = true
+ fun startWebview(view: View) {
+ with(view) {
+ webview.settings.javaScriptEnabled = true
+ webview.settings.domStorageEnabled = true
- webview.loadUrl("https://forums.e-hentai.org/index.php?act=Login")
+ webview.loadUrl("https://forums.e-hentai.org/index.php?act=Login")
- webview.setWebViewClient(object : WebViewClient() {
- override fun onPageFinished(view: WebView, url: String) {
- super.onPageFinished(view, url)
- Timber.d(url)
- val parsedUrl = Uri.parse(url)
- if(parsedUrl.host.equals("forums.e-hentai.org", ignoreCase = true)) {
- //Hide distracting content
- view.loadUrl(HIDE_JS)
+ webview.setWebViewClient(object : WebViewClient() {
+ override fun onPageFinished(view: WebView, url: String) {
+ super.onPageFinished(view, url)
+ Timber.d(url)
+ val parsedUrl = Uri.parse(url)
+ if (parsedUrl.host.equals("forums.e-hentai.org", ignoreCase = true)) {
+ //Hide distracting content
+ view.loadUrl(HIDE_JS)
- //Check login result
- if(parsedUrl.getQueryParameter("code")?.toInt() != 0) {
- if(checkLoginCookies(url)) view.loadUrl("http://exhentai.org/")
- }
- } else if(parsedUrl.host.equals("exhentai.org", ignoreCase = true)) {
- //At ExHentai, check that everything worked out...
- if(applyExHentaiCookies(url)) {
- preferenceManager.enableExhentai().set(true)
- finishLogin()
+ //Check login result
+ if (parsedUrl.getQueryParameter("code")?.toInt() != 0) {
+ if (checkLoginCookies(url)) view.loadUrl("http://exhentai.org/")
+ }
+ } else if (parsedUrl.host.equals("exhentai.org", ignoreCase = true)) {
+ //At ExHentai, check that everything worked out...
+ if (applyExHentaiCookies(url)) {
+ preferenceManager.enableExhentai().set(true)
+ finishLogin(view)
+ }
}
}
- }
- })
+ })
+ }
}
- fun finishLogin() {
- val progressDialog = MaterialDialog.Builder(this)
+ fun finishLogin(view: View) {
+ val progressDialog = MaterialDialog.Builder(view.context)
.title("Finalizing login")
.progress(true, 0)
.content("Please wait...")
@@ -108,7 +115,7 @@ class LoginActivity : BaseActivity() {
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
progressDialog.dismiss()
- onBackPressed()
+ router.popCurrentController()
}
}
@@ -164,14 +171,6 @@ class LoginActivity : BaseActivity() {
}
}
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- when (item.itemId) {
- android.R.id.home -> onBackPressed()
- else -> return super.onOptionsItemSelected(item)
- }
- return true
- }
-
companion object {
const val MEMBER_ID_COOKIE = "ipb_member_id"
const val PASS_HASH_COOKIE = "ipb_pass_hash"
diff --git a/app/src/main/java/exh/ui/login/LoginPresenter.kt b/app/src/main/java/exh/ui/login/LoginPresenter.kt
new file mode 100644
index 000000000..3d39afcc5
--- /dev/null
+++ b/app/src/main/java/exh/ui/login/LoginPresenter.kt
@@ -0,0 +1,7 @@
+package exh.ui.login
+
+import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+
+class LoginPresenter: BasePresenter() {
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/exh/util/ViewUtil.kt b/app/src/main/java/exh/util/ViewUtil.kt
new file mode 100644
index 000000000..edd35d1a9
--- /dev/null
+++ b/app/src/main/java/exh/util/ViewUtil.kt
@@ -0,0 +1,8 @@
+package exh.util
+
+import android.content.Context
+
+fun dpToPx(context: Context, dp: Int): Int {
+ val scale = context.resources.displayMetrics.density
+ return (dp * scale + 0.5f).toInt()
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_lock.xml b/app/src/main/res/layout/activity_lock.xml
index 7005ce1ba..ad4ac7150 100755
--- a/app/src/main/res/layout/activity_lock.xml
+++ b/app/src/main/res/layout/activity_lock.xml
@@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:background="@color/backgroundDark">
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/eh_fragment_batch_add.xml b/app/src/main/res/layout/eh_fragment_batch_add.xml
index 03faf0ec6..a4001371a 100755
--- a/app/src/main/res/layout/eh_fragment_batch_add.xml
+++ b/app/src/main/res/layout/eh_fragment_batch_add.xml
@@ -11,7 +11,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
- android:padding="16dp ">
+ android:padding="16dp">
@@ -31,7 +31,7 @@
android:ems="10"
android:hint="Example:\n\nhttp://e-hentai.org/g/12345/1a2b3c4e\nhttp://g.e-hentai.org/g/67890/6f7g8h9i\nhttp://exhentai.org/g/13579/1a3b5c7e\nhttps://exhentai.org/g/24680/2f4g6h8i\n"
android:inputType="textMultiLine"
- android:visibility="gone"
+ android:visibility="visible"
app:layout_constraintBottom_toTopOf="@+id/btn_add_galleries"
app:layout_constraintLeft_toLeftOf="@+id/input_title_view"
app:layout_constraintRight_toRightOf="@+id/input_title_view"
@@ -42,7 +42,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Add Galleries"
- android:visibility="gone"
+ android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="@+id/galleries_box"
app:layout_constraintRight_toRightOf="@+id/galleries_box" />
@@ -58,7 +58,7 @@
android:layout_marginTop="0dp"
android:text="Adding galleries..."
android:textAppearance="@style/TextAppearance.Medium.Title"
- android:visibility="visible"
+ android:visibility="gone"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@@ -71,7 +71,7 @@
android:layout_marginBottom="0dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
- android:visibility="visible"
+ android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/progress_dismiss_btn"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="@+id/progress_log_wrapper"
@@ -85,7 +85,7 @@
android:singleLine="true"
android:text=""
android:textAlignment="textEnd"
- android:visibility="visible"
+ android:visibility="gone"
app:layout_constraintRight_toRightOf="@+id/progress_log_wrapper"
app:layout_constraintTop_toTopOf="@+id/progress_bar" />
@@ -93,15 +93,15 @@
android:id="@+id/progress_dismiss_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
+ android:layout_marginBottom="0dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:text="Finish"
- android:visibility="visible"
- app:layout_constraintLeft_toLeftOf="@+id/progress_log_wrapper"
- app:layout_constraintRight_toRightOf="@+id/progress_log_wrapper"
- app:layout_constraintHorizontal_bias="0.0"
+ android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/btn_add_galleries"
- android:layout_marginBottom="0dp" />
+ app:layout_constraintHorizontal_bias="0.0"
+ app:layout_constraintLeft_toLeftOf="@+id/progress_log_wrapper"
+ app:layout_constraintRight_toRightOf="@+id/progress_log_wrapper" />
@color/dividerLight
- @drawable/line_divider_light
+
+ - ?android:attr/textColorSecondary
+ - ?android:attr/colorAccent
+
- true
- @style/Theme.ActionBar.Light