mirror of
https://github.com/mihonapp/mihon.git
synced 2025-06-28 20:17:51 +02:00
Migrate to Tachiyomi 6.1
Rewrite batch add UI Rewrite lock UI
This commit is contained in:
@ -56,68 +56,75 @@ class GalleryAdder {
|
||||
val outJson = JsonParser().parse(networkHelper.client.newCall(Request.Builder()
|
||||
.url(API_BASE)
|
||||
.post(RequestBody.create(JSON, json.toString()))
|
||||
.build()).execute().body().string()).obj
|
||||
.build()).execute().body()!!.string()).obj
|
||||
|
||||
val obj = outJson["tokenlist"].array.first()
|
||||
return "${uri.scheme}://${uri.host}/g/${obj["gid"].int}/${obj["token"].string}/"
|
||||
}
|
||||
|
||||
fun addGallery(url: String, fav: Boolean = false): Manga {
|
||||
val urlObj = Uri.parse(url)
|
||||
val source = when(urlObj.host) {
|
||||
"g.e-hentai.org", "e-hentai.org" -> EH_SOURCE_ID
|
||||
"exhentai.org" -> EXH_SOURCE_ID
|
||||
else -> throw MalformedURLException("Not a valid gallery URL!")
|
||||
}
|
||||
|
||||
val realUrl = when (urlObj.pathSegments.first().toLowerCase()) {
|
||||
"g" -> {
|
||||
//Is already gallery page, do nothing
|
||||
url
|
||||
}
|
||||
"s" -> {
|
||||
//Is page, fetch gallery token and use that
|
||||
getGalleryUrlFromPage(url)
|
||||
}
|
||||
else -> {
|
||||
throw MalformedURLException("Not a valid gallery URL!")
|
||||
}
|
||||
}
|
||||
|
||||
val sourceObj = sourceManager.get(source)
|
||||
?: throw IllegalStateException("Could not find EH source!")
|
||||
|
||||
val pathOnlyUrl = getUrlWithoutDomain(realUrl)
|
||||
|
||||
//Use manga in DB if possible, otherwise, make a new manga
|
||||
val manga = db.getManga(pathOnlyUrl, source).executeAsBlocking()
|
||||
?: Manga.create(source).apply {
|
||||
this.url = pathOnlyUrl
|
||||
title = realUrl
|
||||
}
|
||||
|
||||
//Copy basics
|
||||
manga.copyFrom(sourceObj.fetchMangaDetails(manga).toBlocking().first())
|
||||
|
||||
//Apply metadata
|
||||
metadataHelper.fetchEhMetadata(realUrl, isExSource(source))?.copyTo(manga)
|
||||
|
||||
if(fav) manga.favorite = true
|
||||
|
||||
db.insertManga(manga).executeAsBlocking().insertedId()?.let {
|
||||
manga.id = it
|
||||
}
|
||||
|
||||
//Fetch and copy chapters
|
||||
fun addGallery(url: String, fav: Boolean = false): GalleryAddEvent {
|
||||
try {
|
||||
sourceObj.fetchChapterList(manga).map {
|
||||
syncChaptersWithSource(db, it, manga, sourceObj)
|
||||
}.toBlocking().first()
|
||||
} catch (e: Exception) {
|
||||
Timber.w(e, "Failed to update chapters for gallery: ${manga.title}!")
|
||||
}
|
||||
val urlObj = Uri.parse(url)
|
||||
val source = when (urlObj.host) {
|
||||
"g.e-hentai.org", "e-hentai.org" -> EH_SOURCE_ID
|
||||
"exhentai.org" -> EXH_SOURCE_ID
|
||||
else -> return GalleryAddEvent.Fail.UnknownType(url)
|
||||
}
|
||||
|
||||
return manga
|
||||
val realUrl = when (urlObj.pathSegments.first().toLowerCase()) {
|
||||
"g" -> {
|
||||
//Is already gallery page, do nothing
|
||||
url
|
||||
}
|
||||
"s" -> {
|
||||
//Is page, fetch gallery token and use that
|
||||
getGalleryUrlFromPage(url)
|
||||
}
|
||||
else -> {
|
||||
return GalleryAddEvent.Fail.UnknownType(url)
|
||||
}
|
||||
}
|
||||
|
||||
val sourceObj = sourceManager.get(source)
|
||||
?: return GalleryAddEvent.Fail.Error(url, "Could not find EH source!")
|
||||
|
||||
val pathOnlyUrl = getUrlWithoutDomain(realUrl)
|
||||
|
||||
//Use manga in DB if possible, otherwise, make a new manga
|
||||
val manga = db.getManga(pathOnlyUrl, source).executeAsBlocking()
|
||||
?: Manga.create(source).apply {
|
||||
this.url = pathOnlyUrl
|
||||
title = realUrl
|
||||
}
|
||||
|
||||
//Copy basics
|
||||
manga.copyFrom(sourceObj.fetchMangaDetails(manga).toBlocking().first())
|
||||
|
||||
//Apply metadata
|
||||
metadataHelper.fetchEhMetadata(realUrl, isExSource(source))?.copyTo(manga)
|
||||
|
||||
if (fav) manga.favorite = true
|
||||
|
||||
db.insertManga(manga).executeAsBlocking().insertedId()?.let {
|
||||
manga.id = it
|
||||
}
|
||||
|
||||
//Fetch and copy chapters
|
||||
try {
|
||||
sourceObj.fetchChapterList(manga).map {
|
||||
syncChaptersWithSource(db, it, manga, sourceObj)
|
||||
}.toBlocking().first()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Failed to update chapters for gallery: ${manga.title}!")
|
||||
return GalleryAddEvent.Fail.Error(url, "Failed to update chapters for gallery: $url")
|
||||
}
|
||||
|
||||
return GalleryAddEvent.Success(url, manga)
|
||||
} catch(e: Exception) {
|
||||
Timber.e(e, "Could not add gallery!")
|
||||
return GalleryAddEvent.Fail.Error(url,
|
||||
((e.message ?: "Unknown error!") + " (Gallery: $url)").trim())
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUrlWithoutDomain(orig: String): String {
|
||||
@ -133,4 +140,28 @@ class GalleryAdder {
|
||||
return orig
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class GalleryAddEvent {
|
||||
abstract val logMessage: String
|
||||
abstract val galleryUrl: String
|
||||
open val galleryTitle: String? = null
|
||||
|
||||
class Success(override val galleryUrl: String,
|
||||
val manga: Manga): GalleryAddEvent() {
|
||||
override val logMessage = "[OK] Added gallery: $galleryTitle"
|
||||
override val galleryTitle: String
|
||||
get() = manga.title
|
||||
}
|
||||
|
||||
sealed class Fail: GalleryAddEvent() {
|
||||
class UnknownType(override val galleryUrl: String): Fail() {
|
||||
override val logMessage = "[ERROR] Unknown gallery type for gallery: $galleryUrl"
|
||||
}
|
||||
|
||||
class Error(override val galleryUrl: String,
|
||||
val message: String): Fail() {
|
||||
override val logMessage = "[ERROR] $message"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,131 +1,145 @@
|
||||
package exh.ui.batchadd
|
||||
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.jakewharton.rxbinding.view.clicks
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.base.fragment.BaseFragment
|
||||
import exh.GalleryAdder
|
||||
import exh.metadata.nullIfBlank
|
||||
import kotlinx.android.synthetic.main.eh_fragment_batch_add.*
|
||||
import timber.log.Timber
|
||||
import kotlin.concurrent.thread
|
||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||
import eu.kanade.tachiyomi.util.combineLatest
|
||||
import eu.kanade.tachiyomi.util.plusAssign
|
||||
import kotlinx.android.synthetic.main.eh_fragment_batch_add.view.*
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import rx.subscriptions.CompositeSubscription
|
||||
|
||||
/**
|
||||
* LoginActivity
|
||||
* Batch add screen
|
||||
*/
|
||||
class BatchAddController : NucleusController<BatchAddPresenter>() {
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup) =
|
||||
inflater.inflate(R.layout.eh_fragment_batch_add, container, false)!!
|
||||
|
||||
class BatchAddFragment : BaseFragment() {
|
||||
override fun getTitle() = "Batch add"
|
||||
|
||||
private val galleryAdder by lazy { GalleryAdder() }
|
||||
override fun createPresenter() = BatchAddPresenter()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedState: Bundle?)
|
||||
= inflater.inflate(R.layout.eh_fragment_batch_add, container, false)!!
|
||||
override fun onViewCreated(view: View, savedViewState: Bundle?) {
|
||||
super.onViewCreated(view, savedViewState)
|
||||
|
||||
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
|
||||
setToolbarTitle("Batch add")
|
||||
|
||||
setup()
|
||||
}
|
||||
|
||||
fun setup() {
|
||||
btn_add_galleries.setOnClickListener {
|
||||
val galleries = galleries_box.text.toString()
|
||||
//Check text box has content
|
||||
if(galleries.isNullOrBlank()) {
|
||||
noGalleriesSpecified()
|
||||
return@setOnClickListener
|
||||
with(view) {
|
||||
btn_add_galleries.clicks().subscribeUntilDestroy {
|
||||
addGalleries(galleries_box.text.toString())
|
||||
}
|
||||
|
||||
//Too lazy to actually deal with orientation changes
|
||||
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
|
||||
progress_dismiss_btn.clicks().subscribeUntilDestroy {
|
||||
presenter.currentlyAddingRelay.call(false)
|
||||
}
|
||||
|
||||
val splitGalleries = galleries.split("\n").map {
|
||||
it.trim().nullIfBlank()
|
||||
}.filterNotNull()
|
||||
val progressSubscriptions = CompositeSubscription()
|
||||
|
||||
val dialog = MaterialDialog.Builder(context)
|
||||
.title("Adding galleries...")
|
||||
.progress(false, splitGalleries.size, true)
|
||||
.cancelable(false)
|
||||
.canceledOnTouchOutside(false)
|
||||
presenter.currentlyAddingRelay
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeUntilDestroy {
|
||||
progressSubscriptions.clear()
|
||||
if(it) {
|
||||
showProgress(this)
|
||||
progressSubscriptions += presenter.progressRelay
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.combineLatest(presenter.progressTotalRelay, { progress, total ->
|
||||
//Show hide dismiss button
|
||||
progress_dismiss_btn.visibility =
|
||||
if(progress == total)
|
||||
View.VISIBLE
|
||||
else View.GONE
|
||||
|
||||
formatProgress(progress, total)
|
||||
}).subscribeUntilDestroy {
|
||||
progress_text.text = it
|
||||
}
|
||||
|
||||
progressSubscriptions += presenter.progressTotalRelay
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeUntilDestroy {
|
||||
progress_bar.max = it
|
||||
}
|
||||
|
||||
progressSubscriptions += presenter.progressRelay
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeUntilDestroy {
|
||||
progress_bar.progress = it
|
||||
}
|
||||
|
||||
presenter.eventRelay
|
||||
?.observeOn(AndroidSchedulers.mainThread())
|
||||
?.subscribeUntilDestroy {
|
||||
progress_log.append("$it\n")
|
||||
}?.let {
|
||||
progressSubscriptions += it
|
||||
}
|
||||
} else hideProgress(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val View.progressViews
|
||||
get() = listOf(
|
||||
progress_title_view,
|
||||
progress_log_wrapper,
|
||||
progress_bar,
|
||||
progress_text,
|
||||
progress_dismiss_btn
|
||||
)
|
||||
|
||||
private val View.inputViews
|
||||
get() = listOf(
|
||||
input_title_view,
|
||||
galleries_box,
|
||||
btn_add_galleries
|
||||
)
|
||||
|
||||
private var List<View>.visibility: Int
|
||||
get() = throw UnsupportedOperationException()
|
||||
set(v) { forEach { it.visibility = v } }
|
||||
|
||||
private fun showProgress(target: View? = view) {
|
||||
target?.apply {
|
||||
progressViews.visibility = View.VISIBLE
|
||||
inputViews.visibility = View.GONE
|
||||
}?.progress_log?.text = ""
|
||||
}
|
||||
|
||||
private fun hideProgress(target: View? = view) {
|
||||
target?.apply {
|
||||
progressViews.visibility = View.GONE
|
||||
inputViews.visibility = View.VISIBLE
|
||||
}?.galleries_box?.setText("", TextView.BufferType.EDITABLE)
|
||||
}
|
||||
|
||||
private fun formatProgress(progress: Int, total: Int) = "$progress/$total"
|
||||
|
||||
private fun addGalleries(galleries: String) {
|
||||
//Check text box has content
|
||||
if(galleries.isBlank()) {
|
||||
noGalleriesSpecified()
|
||||
return
|
||||
}
|
||||
|
||||
presenter.addGalleries(galleries)
|
||||
}
|
||||
|
||||
private fun noGalleriesSpecified() {
|
||||
activity?.let {
|
||||
MaterialDialog.Builder(it)
|
||||
.title("No galleries to add!")
|
||||
.content("You must specify at least one gallery to add!")
|
||||
.positiveText("Ok")
|
||||
.onPositive { materialDialog, _ -> materialDialog.dismiss() }
|
||||
.cancelable(true)
|
||||
.canceledOnTouchOutside(true)
|
||||
.show()
|
||||
|
||||
val succeeded = mutableListOf<String>()
|
||||
val failed = mutableListOf<String>()
|
||||
|
||||
thread {
|
||||
splitGalleries.forEachIndexed { i, s ->
|
||||
activity.runOnUiThread {
|
||||
dialog.setContent("Processing: $s")
|
||||
}
|
||||
if(addGallery(s)) {
|
||||
succeeded.add(s)
|
||||
} else {
|
||||
failed.add(s)
|
||||
}
|
||||
activity.runOnUiThread {
|
||||
dialog.setProgress(i + 1)
|
||||
}
|
||||
}
|
||||
|
||||
//Show report
|
||||
val succeededCount = succeeded.size
|
||||
val failedCount = failed.size
|
||||
|
||||
if(succeeded.isEmpty()) succeeded += "None"
|
||||
if(failed.isEmpty()) failed += "None"
|
||||
val succeededReport = succeeded.joinToString(separator = "\n", prefix = "Added:\n")
|
||||
val failedReport = failed.joinToString(separator = "\n", prefix = "Failed:\n")
|
||||
|
||||
val summary = "Summary:\nAdded: $succeededCount gallerie(s)\nFailed: $failedCount gallerie(s)"
|
||||
|
||||
val report = listOf(succeededReport, failedReport, summary).joinToString(separator = "\n\n")
|
||||
|
||||
activity.runOnUiThread {
|
||||
//Enable orientation changes again
|
||||
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
|
||||
|
||||
dialog.dismiss()
|
||||
|
||||
MaterialDialog.Builder(context)
|
||||
.title("Batch add report")
|
||||
.content(report)
|
||||
.positiveText("Ok")
|
||||
.cancelable(true)
|
||||
.canceledOnTouchOutside(true)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun addGallery(url: String): Boolean {
|
||||
try {
|
||||
galleryAdder.addGallery(url, true)
|
||||
} catch(t: Throwable) {
|
||||
Timber.e(t, "Could not add gallery!")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun noGalleriesSpecified() {
|
||||
MaterialDialog.Builder(context)
|
||||
.title("No galleries to add!")
|
||||
.content("You must specify at least one gallery to add!")
|
||||
.positiveText("Ok")
|
||||
.onPositive { materialDialog, _ -> materialDialog.dismiss() }
|
||||
.cancelable(true)
|
||||
.canceledOnTouchOutside(true)
|
||||
.show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newInstance() = BatchAddFragment()
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,51 @@
|
||||
package exh.ui.batchadd
|
||||
|
||||
/**
|
||||
* Created by nulldev on 8/23/17.
|
||||
*/
|
||||
import com.jakewharton.rxrelay.BehaviorRelay
|
||||
import com.jakewharton.rxrelay.ReplayRelay
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import exh.GalleryAddEvent
|
||||
import exh.GalleryAdder
|
||||
import exh.metadata.nullIfBlank
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class BatchAddPresenter: BasePresenter<BatchAddController>() {
|
||||
|
||||
private val galleryAdder by lazy { GalleryAdder() }
|
||||
|
||||
val progressTotalRelay = BehaviorRelay.create(0)!!
|
||||
val progressRelay = BehaviorRelay.create(0)!!
|
||||
var eventRelay: ReplayRelay<String>? = null
|
||||
val currentlyAddingRelay = BehaviorRelay.create(false)!!
|
||||
|
||||
fun addGalleries(galleries: String) {
|
||||
eventRelay = ReplayRelay.create()
|
||||
val splitGalleries = galleries.split("\n").map {
|
||||
it.trim().nullIfBlank()
|
||||
}.filterNotNull()
|
||||
|
||||
progressRelay.call(0)
|
||||
progressTotalRelay.call(splitGalleries.size)
|
||||
|
||||
currentlyAddingRelay.call(true)
|
||||
|
||||
thread {
|
||||
val succeeded = mutableListOf<String>()
|
||||
val failed = mutableListOf<String>()
|
||||
|
||||
splitGalleries.forEachIndexed { i, s ->
|
||||
val result = galleryAdder.addGallery(s, true)
|
||||
if(result is GalleryAddEvent.Success) {
|
||||
succeeded.add(s)
|
||||
} else {
|
||||
failed.add(s)
|
||||
}
|
||||
progressRelay.call(i + 1)
|
||||
eventRelay?.call(result.logMessage)
|
||||
}
|
||||
|
||||
//Show report
|
||||
val summary = "\nSummary:\nAdded: ${succeeded.size} gallerie(s)\nFailed: ${failed.size} gallerie(s)"
|
||||
eventRelay?.call(summary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,11 @@ import android.view.MenuItem
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaActivity
|
||||
import exh.GalleryAdder
|
||||
import kotlinx.android.synthetic.main.toolbar.*
|
||||
import timber.log.Timber
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
//TODO :(
|
||||
class InterceptActivity : BaseActivity() {
|
||||
|
||||
private val galleryAdder = GalleryAdder()
|
||||
@ -19,12 +18,9 @@ class InterceptActivity : BaseActivity() {
|
||||
var finished = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setAppTheme()
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.eh_activity_intercept)
|
||||
|
||||
setupToolbar(toolbar, backNavigation = false)
|
||||
|
||||
if(savedInstanceState == null)
|
||||
thread { setup() }
|
||||
}
|
||||
@ -54,8 +50,9 @@ class InterceptActivity : BaseActivity() {
|
||||
if(Intent.ACTION_VIEW == intent.action) {
|
||||
val manga = galleryAdder.addGallery(intent.dataString)
|
||||
|
||||
if(!finished)
|
||||
startActivity(MangaActivity.newIntent(this, manga, true))
|
||||
//TODO
|
||||
// if(!finished)
|
||||
// startActivity(MangaActivity.newIntent(this, manga, true))
|
||||
onBackPressed()
|
||||
}
|
||||
}
|
||||
|
@ -1,60 +0,0 @@
|
||||
package exh.ui.lock
|
||||
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.andrognito.pinlockview.PinLockListener
|
||||
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.activity.BaseActivity
|
||||
import kotlinx.android.synthetic.main.activity_lock.*
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class LockActivity : BaseActivity() {
|
||||
|
||||
val prefs: PreferencesHelper by injectLazy()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
disableLock = true
|
||||
|
||||
setTheme(R.style.Theme_Tachiyomi_Dark)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if(!lockEnabled(prefs)) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_lock)
|
||||
|
||||
pin_lock_view.attachIndicatorDots(indicator_dots)
|
||||
|
||||
pin_lock_view.pinLength = prefs.lockLength().getOrDefault()
|
||||
pin_lock_view.setPinLockListener(object : PinLockListener {
|
||||
override fun onEmpty() {}
|
||||
|
||||
override fun onComplete(pin: String) {
|
||||
if(sha512(pin, prefs.lockSalt().get()!!) == prefs.lockHash().get()) {
|
||||
//Yay!
|
||||
finish()
|
||||
} else {
|
||||
MaterialDialog.Builder(this@LockActivity)
|
||||
.title("PIN code incorrect")
|
||||
.content("The PIN code you entered is incorrect. Please try again.")
|
||||
.cancelable(true)
|
||||
.canceledOnTouchOutside(true)
|
||||
.positiveText("Ok")
|
||||
.autoDismiss(true)
|
||||
.show()
|
||||
pin_lock_view.resetPinLockView()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPinChange(pinLength: Int, intermediatePin: String?) {}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
moveTaskToBack(true)
|
||||
}
|
||||
}
|
41
app/src/main/java/exh/ui/lock/LockChangeHandler.kt
Normal file
41
app/src/main/java/exh/ui/lock/LockChangeHandler.kt
Normal file
@ -0,0 +1,41 @@
|
||||
package exh.ui.lock
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorSet
|
||||
import android.animation.ObjectAnimator
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
import com.bluelinelabs.conductor.changehandler.AnimatorChangeHandler
|
||||
import java.util.ArrayList
|
||||
|
||||
class LockChangeHandler : AnimatorChangeHandler {
|
||||
constructor(): super()
|
||||
|
||||
constructor(removesFromViewOnPush: Boolean) : super(removesFromViewOnPush)
|
||||
|
||||
constructor(duration: Long) : super(duration)
|
||||
|
||||
constructor(duration: Long, removesFromViewOnPush: Boolean) : super(duration, removesFromViewOnPush)
|
||||
|
||||
override fun getAnimator(container: ViewGroup, from: View?, to: View?, isPush: Boolean, toAddedToContainer: Boolean): Animator {
|
||||
val animator = AnimatorSet()
|
||||
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.ALPHA, 0f))
|
||||
}
|
||||
|
||||
animator.playTogether(viewAnimators)
|
||||
return animator
|
||||
}
|
||||
|
||||
override fun resetFromView(from: View) {}
|
||||
|
||||
override fun copy(): ControllerChangeHandler =
|
||||
LockChangeHandler(animationDuration, removesFromViewOnPush())
|
||||
|
||||
}
|
||||
|
68
app/src/main/java/exh/ui/lock/LockController.kt
Executable file
68
app/src/main/java/exh/ui/lock/LockController.kt
Executable file
@ -0,0 +1,68 @@
|
||||
package exh.ui.lock
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.andrognito.pinlockview.PinLockListener
|
||||
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 kotlinx.android.synthetic.main.activity_lock.view.*
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class LockController : NucleusController<LockPresenter>() {
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup)
|
||||
= inflater.inflate(R.layout.activity_lock, container, false)!!
|
||||
|
||||
override fun createPresenter() = LockPresenter()
|
||||
|
||||
override fun getTitle() = "Application locked"
|
||||
|
||||
val prefs: PreferencesHelper by injectLazy()
|
||||
|
||||
override fun onViewCreated(view: View, savedViewState: Bundle?) {
|
||||
super.onViewCreated(view, savedViewState)
|
||||
|
||||
if(!lockEnabled(prefs)) {
|
||||
closeLock()
|
||||
return
|
||||
}
|
||||
|
||||
with(view) {
|
||||
pin_lock_view.attachIndicatorDots(indicator_dots)
|
||||
|
||||
pin_lock_view.pinLength = prefs.lockLength().getOrDefault()
|
||||
pin_lock_view.setPinLockListener(object : PinLockListener {
|
||||
override fun onEmpty() {}
|
||||
|
||||
override fun onComplete(pin: String) {
|
||||
if (sha512(pin, prefs.lockSalt().get()!!) == prefs.lockHash().get()) {
|
||||
//Yay!
|
||||
closeLock()
|
||||
} else {
|
||||
MaterialDialog.Builder(context)
|
||||
.title("PIN code incorrect")
|
||||
.content("The PIN code you entered is incorrect. Please try again.")
|
||||
.cancelable(true)
|
||||
.canceledOnTouchOutside(true)
|
||||
.positiveText("Ok")
|
||||
.autoDismiss(true)
|
||||
.show()
|
||||
pin_lock_view.resetPinLockView()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPinChange(pinLength: Int, intermediatePin: String?) {}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun closeLock() {
|
||||
router.popCurrentController()
|
||||
}
|
||||
|
||||
override fun handleBack() = true
|
||||
}
|
@ -17,7 +17,7 @@ import java.security.SecureRandom
|
||||
class LockPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
Preference(context, attrs) {
|
||||
|
||||
val secureRandom by lazy { SecureRandom() }
|
||||
private val secureRandom by lazy { SecureRandom() }
|
||||
|
||||
val prefs: PreferencesHelper by injectLazy()
|
||||
|
||||
@ -26,12 +26,11 @@ class LockPreference @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||
updateSummary()
|
||||
}
|
||||
|
||||
fun updateSummary() {
|
||||
if(lockEnabled(prefs)) {
|
||||
summary = "Application is locked"
|
||||
} else {
|
||||
summary = "Application is not locked, tap to lock"
|
||||
}
|
||||
private fun updateSummary() {
|
||||
summary = if(lockEnabled(prefs))
|
||||
"Application is locked"
|
||||
else
|
||||
"Application is not locked, tap to lock"
|
||||
}
|
||||
|
||||
override fun onClick() {
|
||||
@ -65,7 +64,7 @@ class LockPreference @JvmOverloads constructor(context: Context, attrs: Attribut
|
||||
}
|
||||
}
|
||||
|
||||
fun savePassword(password: String) {
|
||||
private fun savePassword(password: String) {
|
||||
val salt: String?
|
||||
val hash: String?
|
||||
val length: Int
|
||||
|
6
app/src/main/java/exh/ui/lock/LockPresenter.kt
Normal file
6
app/src/main/java/exh/ui/lock/LockPresenter.kt
Normal file
@ -0,0 +1,6 @@
|
||||
package exh.ui.lock
|
||||
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
|
||||
class LockPresenter: BasePresenter<LockController>()
|
||||
|
@ -44,13 +44,6 @@ fun lockEnabled(prefs: PreferencesHelper = Injekt.get())
|
||||
&& prefs.lockSalt().get() != null
|
||||
&& prefs.lockLength().getOrDefault() != -1
|
||||
|
||||
/**
|
||||
* Lock the screen
|
||||
*/
|
||||
fun showLockActivity(activity: Activity) {
|
||||
activity.startActivity(Intent(activity, LockActivity::class.java))
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the lock will function properly
|
||||
*
|
||||
|
@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.source.online.all.EHentai
|
||||
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
||||
import exh.EXH_SOURCE_ID
|
||||
import kotlinx.android.synthetic.main.eh_activity_login.*
|
||||
import kotlinx.android.synthetic.main.toolbar.*
|
||||
import rx.Observable
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import rx.schedulers.Schedulers
|
||||
@ -34,13 +33,10 @@ class LoginActivity : BaseActivity() {
|
||||
val sourceManager: SourceManager by injectLazy()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setAppTheme()
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.eh_activity_login)
|
||||
|
||||
setup()
|
||||
|
||||
setupToolbar(toolbar, backNavigation = false)
|
||||
}
|
||||
|
||||
fun setup() {
|
||||
@ -187,7 +183,7 @@ class LoginActivity : BaseActivity() {
|
||||
document.getElementsByName('submit')[0].style.visibility = 'visible';
|
||||
document.querySelector('td[width="60%"][valign="top"]').style.visibility = 'visible';
|
||||
|
||||
function hide(e) {if(e !== null && e !== undefined) e.style.display = 'none';}
|
||||
function hide(e) {if(e != null) e.style.display = 'none';}
|
||||
|
||||
hide(document.querySelector(".errorwrap"));
|
||||
hide(document.querySelector('td[width="40%"][valign="top"]'));
|
||||
@ -202,7 +198,7 @@ class LoginActivity : BaseActivity() {
|
||||
hide(fd[2]);
|
||||
hide(child.querySelector('br'));
|
||||
var error = document.querySelector(".page > div > .borderwrap");
|
||||
if(error !== null) error.style.visibility = 'visible';
|
||||
if(error != null) error.style.visibility = 'visible';
|
||||
hide(fh[0]);
|
||||
hide(fh[1]);
|
||||
hide(document.querySelector("#gfooter"));
|
||||
@ -211,7 +207,7 @@ class LoginActivity : BaseActivity() {
|
||||
e.style.color = "white";
|
||||
});
|
||||
var pc = document.querySelector(".postcolor");
|
||||
if(pc !== null) pc.style.color = "#26353F";
|
||||
if(pc != null) pc.style.color = "#26353F";
|
||||
})()
|
||||
"""
|
||||
}
|
||||
|
Reference in New Issue
Block a user