Add fingerprint to lock UI

Migrate login UI to conductor
Fix batch add controller not saving EditText content onResume
Prevent double-locking of lock UI
Remove back button from lock UI
Fix login preference not updating
This commit is contained in:
NerdNumber9 2017-08-24 17:11:43 -04:00
parent 32d02f9329
commit b20b3d6f5c
21 changed files with 438 additions and 109 deletions

View File

@ -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'

View File

@ -10,6 +10,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.GET_TASKS"/>
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
@ -106,7 +107,7 @@
<!-- EH -->
<activity
android:name="exh.ui.login.LoginActivity"
android:name="exh.ui.login.LoginController"
android:label="@string/label_login">
<!-- TODO parent activity -->
</activity>

View File

@ -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)
}

View File

@ -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
}

View File

@ -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<String, String> = 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

View File

@ -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()

View File

@ -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
}
}

View File

@ -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"
}
}
}

View File

@ -35,7 +35,7 @@ class BatchAddController : NucleusController<BatchAddPresenter>() {
}
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<BatchAddPresenter>() {
.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<BatchAddPresenter>() {
}?.let {
progressSubscriptions += it
}
} else hideProgress(this)
} else if(it == BatchAddPresenter.STATE_PROGRESS_TO_INPUT) {
hideProgress(this)
presenter.currentlyAddingRelay.call(BatchAddPresenter.STATE_IDLE)
}
}
}
}

View File

@ -15,18 +15,18 @@ class BatchAddPresenter: BasePresenter<BatchAddController>() {
val progressTotalRelay = BehaviorRelay.create(0)!!
val progressRelay = BehaviorRelay.create(0)!!
var eventRelay: ReplayRelay<String>? = 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<String>()
@ -48,4 +48,10 @@ class BatchAddPresenter: BasePresenter<BatchAddController>() {
eventRelay?.call(summary)
}
}
companion object {
const val STATE_IDLE = 0
const val STATE_INPUT_TO_PROGRESS = 1
const val STATE_PROGRESS_TO_INPUT = 2
}
}

View File

@ -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()
}
}
}

View File

@ -23,8 +23,8 @@ class LockChangeHandler : AnimatorChangeHandler {
val viewAnimators = ArrayList<Animator>()
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))
}

View File

@ -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<LockPresenter>() {
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<LockPresenter>() {
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<LockPresenter>() {
}
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<LockPresenter>() {
}
}
@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()
}

View File

@ -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")

View File

@ -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<LockController>()
class LockPresenter: BasePresenter<LockController>() {
val prefs: PreferencesHelper by injectLazy()
val useFingerprint
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& Reprint.isHardwarePresent()
&& Reprint.hasFingerprintRegistered()
&& prefs.lockUseFingerprint().getOrDefault()
}

View File

@ -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<LoginPresenter>() {
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"

View File

@ -0,0 +1,7 @@
package exh.ui.login
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
class LoginPresenter: BasePresenter<LoginController>() {
}

View File

@ -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()
}

View File

@ -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">
<com.andrognito.pinlockview.PinLockView
@ -26,4 +27,19 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<android.support.v7.widget.CardView
android:id="@+id/swirl_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
card_view:cardCornerRadius="30dp"
card_view:cardElevation="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
</android.support.v7.widget.CardView>
</android.support.constraint.ConstraintLayout>

View File

@ -11,7 +11,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:padding="16dp ">
android:padding="16dp">
<TextView
android:id="@+id/input_title_view"
@ -19,7 +19,7 @@
android:layout_height="wrap_content"
android:text="Enter the galleries to add (separated by a new line):"
android:textAppearance="@style/TextAppearance.Medium.Title"
android:visibility="gone"
android:visibility="visible"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@ -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" />
<ScrollView
android:id="@+id/progress_log_wrapper"
@ -109,7 +109,7 @@
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:visibility="visible"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/progress_bar"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="@+id/progress_title_view"

View File

@ -24,6 +24,10 @@
<item name="android:divider">@color/dividerLight</item>
<item name="android:listDivider">@drawable/line_divider_light</item>
<!-- Swirl (EH) -->
<item name="swirl_ridgeColor">?android:attr/textColorSecondary</item>
<item name="swirl_errorColor">?android:attr/colorAccent</item>
<!-- Themes -->
<item name="windowActionModeOverlay">true</item>
<item name="actionBarTheme">@style/Theme.ActionBar.Light</item>