mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	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:
		| @@ -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) | ||||
|     } | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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 | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -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" | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
|                         } | ||||
|                     } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -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 | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										149
									
								
								app/src/main/java/exh/ui/lock/FingerLockPreference.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								app/src/main/java/exh/ui/lock/FingerLockPreference.kt
									
									
									
									
									
										Normal 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() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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)) | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -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() | ||||
|     } | ||||
|   | ||||
| @@ -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") | ||||
|   | ||||
| @@ -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() | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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" | ||||
							
								
								
									
										7
									
								
								app/src/main/java/exh/ui/login/LoginPresenter.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								app/src/main/java/exh/ui/login/LoginPresenter.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| package exh.ui.login | ||||
|  | ||||
| import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter | ||||
|  | ||||
| class LoginPresenter: BasePresenter<LoginController>() { | ||||
|  | ||||
| } | ||||
							
								
								
									
										8
									
								
								app/src/main/java/exh/util/ViewUtil.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								app/src/main/java/exh/util/ViewUtil.kt
									
									
									
									
									
										Normal 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() | ||||
| } | ||||
		Reference in New Issue
	
	Block a user