From 39aceea9da6e2e30c89961213660bf75cabd2b80 Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 22 Apr 2020 20:56:11 -0400 Subject: [PATCH] Using Controller Extensions Cleanup some unused backup consts/methods --- .../tachiyomi/data/backup/BackupConst.kt | 9 - .../ui/base/controller/ConductorExtensions.kt | 32 ---- .../ui/setting/SettingsBackupController.kt | 12 +- .../util/view/ControllerExtensions.kt | 178 ++++++++++++++++++ .../tachiyomi/util/view/ViewExtensions.kt | 141 -------------- 5 files changed, 179 insertions(+), 193 deletions(-) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/ConductorExtensions.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt index 8a8cc45fba..e894750722 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupConst.kt @@ -6,16 +6,7 @@ object BackupConst { const val INTENT_FILTER = "SettingsBackupFragment" const val ACTION_BACKUP_COMPLETED_DIALOG = "$ID.$INTENT_FILTER.ACTION_BACKUP_COMPLETED_DIALOG" const val ACTION_ERROR_BACKUP_DIALOG = "$ID.$INTENT_FILTER.ACTION_ERROR_BACKUP_DIALOG" - const val ACTION_ERROR_RESTORE_DIALOG = "$ID.$INTENT_FILTER.ACTION_ERROR_RESTORE_DIALOG" const val ACTION = "$ID.$INTENT_FILTER.ACTION" - const val EXTRA_PROGRESS = "$ID.$INTENT_FILTER.EXTRA_PROGRESS" - const val EXTRA_AMOUNT = "$ID.$INTENT_FILTER.EXTRA_AMOUNT" - const val EXTRA_ERRORS = "$ID.$INTENT_FILTER.EXTRA_ERRORS" - const val EXTRA_CONTENT = "$ID.$INTENT_FILTER.EXTRA_CONTENT" const val EXTRA_ERROR_MESSAGE = "$ID.$INTENT_FILTER.EXTRA_ERROR_MESSAGE" const val EXTRA_URI = "$ID.$INTENT_FILTER.EXTRA_URI" - const val EXTRA_TIME = "$ID.$INTENT_FILTER.EXTRA_TIME" - const val EXTRA_ERROR_FILE_PATH = "$ID.$INTENT_FILTER.EXTRA_ERROR_FILE_PATH" - const val EXTRA_ERROR_FILE = "$ID.$INTENT_FILTER.EXTRA_ERROR_FILE" - const val EXTRA_MINI_ERROR = "$ID.$INTENT_FILTER.EXTRA_MINI_ERROR" } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/ConductorExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/ConductorExtensions.kt deleted file mode 100644 index dec5c99bcc..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/ConductorExtensions.kt +++ /dev/null @@ -1,32 +0,0 @@ -package eu.kanade.tachiyomi.ui.base.controller - -import android.content.pm.PackageManager.PERMISSION_GRANTED -import androidx.core.content.ContextCompat -import com.bluelinelabs.conductor.Controller -import com.bluelinelabs.conductor.Router -import com.bluelinelabs.conductor.RouterTransaction -import com.bluelinelabs.conductor.changehandler.FadeChangeHandler - -fun Router.popControllerWithTag(tag: String): Boolean { - val controller = getControllerWithTag(tag) - if (controller != null) { - popController(controller) - return true - } - return false -} - -fun Controller.requestPermissionsSafe(permissions: Array, requestCode: Int) { - val activity = activity ?: return - permissions.forEach { permission -> - if (ContextCompat.checkSelfPermission(activity, permission) != PERMISSION_GRANTED) { - requestPermissions(arrayOf(permission), requestCode) - } - } -} - -fun Controller.withFadeTransaction(): RouterTransaction { - return RouterTransaction.with(this) - .pushChangeHandler(FadeChangeHandler()) - .popChangeHandler(FadeChangeHandler()) -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt index 3ccea49652..f1be175d2c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt @@ -23,12 +23,11 @@ import eu.kanade.tachiyomi.data.backup.BackupRestoreService import eu.kanade.tachiyomi.data.backup.models.Backup import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.ui.base.controller.DialogController -import eu.kanade.tachiyomi.ui.base.controller.popControllerWithTag -import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe import eu.kanade.tachiyomi.util.system.getFilePicker import eu.kanade.tachiyomi.util.system.registerLocalReceiver import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.unregisterLocalReceiver +import eu.kanade.tachiyomi.util.view.requestPermissionsSafe import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class SettingsBackupController : SettingsController() { @@ -285,16 +284,10 @@ class SettingsBackupController : SettingsController() { override fun onReceive(context: Context, intent: Intent) { when (intent.getStringExtra(BackupConst.ACTION)) { BackupConst.ACTION_BACKUP_COMPLETED_DIALOG -> { - router.popControllerWithTag(TAG_CREATING_BACKUP_DIALOG) val uri = Uri.parse(intent.getStringExtra(BackupConst.EXTRA_URI)) CreatedBackupDialog(uri).showDialog(router) } BackupConst.ACTION_ERROR_BACKUP_DIALOG -> { - router.popControllerWithTag(TAG_CREATING_BACKUP_DIALOG) - context.toast(intent.getStringExtra(BackupConst.EXTRA_ERROR_MESSAGE)) - } - BackupConst.ACTION_ERROR_RESTORE_DIALOG -> { - router.popControllerWithTag(TAG_RESTORING_BACKUP_DIALOG) context.toast(intent.getStringExtra(BackupConst.EXTRA_ERROR_MESSAGE)) } } @@ -305,8 +298,5 @@ class SettingsBackupController : SettingsController() { const val CODE_BACKUP_CREATE = 501 const val CODE_BACKUP_RESTORE = 502 const val CODE_BACKUP_DIR = 503 - - const val TAG_CREATING_BACKUP_DIALOG = "CreatingBackupDialog" - const val TAG_RESTORING_BACKUP_DIALOG = "RestoringBackupDialog" } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt new file mode 100644 index 0000000000..49fdfffe2c --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt @@ -0,0 +1,178 @@ +package eu.kanade.tachiyomi.util.view + +import android.R +import android.animation.ValueAnimator +import android.content.Context +import android.content.pm.PackageManager +import android.view.WindowInsets +import android.view.inputmethod.InputMethodManager +import androidx.appcompat.widget.SearchView +import androidx.core.content.ContextCompat +import androidx.core.math.MathUtils +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import com.bluelinelabs.conductor.Controller +import com.bluelinelabs.conductor.ControllerChangeHandler +import com.bluelinelabs.conductor.ControllerChangeType +import com.bluelinelabs.conductor.RouterTransaction +import com.bluelinelabs.conductor.changehandler.FadeChangeHandler +import eu.kanade.tachiyomi.util.system.dpToPx +import kotlinx.android.synthetic.main.main_activity.* +import kotlin.math.abs + +fun Controller.setOnQueryTextChangeListener( + searchView: SearchView, + onlyOnSubmit: Boolean = false, + f: (text: String?) -> Boolean +) { + searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextChange(newText: String?): Boolean { + if (!onlyOnSubmit && router.backstack.lastOrNull() + ?.controller() == this@setOnQueryTextChangeListener + ) { + return f(newText) + } + return false + } + + override fun onQueryTextSubmit(query: String?): Boolean { + if (router.backstack.lastOrNull()?.controller() == this@setOnQueryTextChangeListener) { + val imm = + activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager + ?: return f(query) + imm.hideSoftInputFromWindow(searchView.windowToken, 0) + return f(query) + } + return true + } + }) +} + +fun Controller.scrollViewWith( + recycler: RecyclerView, + padBottom: Boolean = false, + customPadding: Boolean = false, + skipFirstSnap: Boolean = false, + swipeRefreshLayout: SwipeRefreshLayout? = null, + afterInsets: ((WindowInsets) -> Unit)? = null +) { + var statusBarHeight = -1 + activity?.appbar?.y = 0f + val attrsArray = intArrayOf(R.attr.actionBarSize) + val array = recycler.context.obtainStyledAttributes(attrsArray) + var appBarHeight = if (activity!!.toolbar.height > 0) activity!!.toolbar.height + else array.getDimensionPixelSize(0, 0) + array.recycle() + swipeRefreshLayout?.setDistanceToTriggerSync(150.dpToPx) + activity!!.toolbar.post { + if (activity!!.toolbar.height > 0) { + appBarHeight = activity!!.toolbar.height + recycler.requestApplyInsets() + } + } + recycler.doOnApplyWindowInsets { view, insets, _ -> + val headerHeight = insets.systemWindowInsetTop + appBarHeight + if (!customPadding) view.updatePaddingRelative( + top = headerHeight, + bottom = if (padBottom) insets.systemWindowInsetBottom else view.paddingBottom + ) + swipeRefreshLayout?.setProgressViewOffset( + true, headerHeight + (-60).dpToPx, headerHeight + 10.dpToPx + ) + statusBarHeight = insets.systemWindowInsetTop + afterInsets?.invoke(insets) + } + var elevationAnim: ValueAnimator? = null + var elevate = false + val elevateFunc: (Boolean) -> Unit = { el -> + elevate = el + elevationAnim?.cancel() + elevationAnim = ValueAnimator.ofFloat( + activity!!.appbar.elevation, if (el) 15f else 0f + ) + elevationAnim?.addUpdateListener { valueAnimator -> + activity!!.appbar.elevation = valueAnimator.animatedValue as Float + } + elevationAnim?.start() + } + addLifecycleListener(object : Controller.LifecycleListener() { + override fun onChangeStart( + controller: Controller, + changeHandler: ControllerChangeHandler, + changeType: ControllerChangeType + ) { + super.onChangeStart(controller, changeHandler, changeType) + if (changeType.isEnter) + elevateFunc(elevate) + } + }) + elevateFunc(recycler.canScrollVertically(-1)) + recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + if (router?.backstack?.lastOrNull() + ?.controller() == this@scrollViewWith && statusBarHeight > -1 && activity != null && activity!!.appbar.height > 0 + ) { + if (!recycler.canScrollVertically(-1)) { + val shortAnimationDuration = resources?.getInteger( + android.R.integer.config_shortAnimTime + ) ?: 0 + activity!!.appbar.animate().y(0f).setDuration(shortAnimationDuration.toLong()) + .start() + if (elevate) elevateFunc(false) + } else { + activity!!.appbar.y -= dy + activity!!.appbar.y = MathUtils.clamp( + activity!!.appbar.y, -activity!!.appbar.height.toFloat(), 0f + ) + if ((activity!!.appbar.y <= -activity!!.appbar.height.toFloat() || + dy == 0 && activity!!.appbar.y == 0f) && !elevate) + elevateFunc(true) + } + } + } + + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + super.onScrollStateChanged(recyclerView, newState) + if (newState == RecyclerView.SCROLL_STATE_IDLE) { + if (router?.backstack?.lastOrNull() + ?.controller() == this@scrollViewWith && statusBarHeight > -1 && activity != null && activity!!.appbar.height > 0 + ) { + val halfWay = abs((-activity!!.appbar.height.toFloat()) / 2) + val shortAnimationDuration = resources?.getInteger( + android.R.integer.config_shortAnimTime + ) ?: 0 + val closerToTop = abs(activity!!.appbar.y) - halfWay > 0 + val atTop = (!customPadding && + (recycler.layoutManager as LinearLayoutManager) + .findFirstVisibleItemPosition() < 2 && !skipFirstSnap) || + !recycler.canScrollVertically(-1) + activity!!.appbar.animate().y( + if (closerToTop && !atTop) (-activity!!.appbar.height.toFloat()) + else 0f + ).setDuration(shortAnimationDuration.toLong()).start() + if (recycler.canScrollVertically(-1) && !elevate) + elevateFunc(true) + else if (!recycler.canScrollVertically(-1) && elevate) + elevateFunc(false) + } + } + } + }) +} + +fun Controller.requestPermissionsSafe(permissions: Array, requestCode: Int) { + val activity = activity ?: return + permissions.forEach { permission -> + if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { + requestPermissions(arrayOf(permission), requestCode) + } + } +} + +fun Controller.withFadeTransaction(): RouterTransaction { + return RouterTransaction.with(this) + .pushChangeHandler(FadeChangeHandler()) + .popChangeHandler(FadeChangeHandler()) +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt index 08965dbb13..15ce792913 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt @@ -274,147 +274,6 @@ data class ViewPaddingState( val end: Int ) -fun Controller.setOnQueryTextChangeListener( - searchView: SearchView, - onlyOnSubmit: Boolean = false, - f: (text: String?) -> Boolean -) { - searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { - override fun onQueryTextChange(newText: String?): Boolean { - if (!onlyOnSubmit && router.backstack.lastOrNull() - ?.controller() == this@setOnQueryTextChangeListener - ) { - return f(newText) - } - return false - } - - override fun onQueryTextSubmit(query: String?): Boolean { - if (router.backstack.lastOrNull()?.controller() == this@setOnQueryTextChangeListener) { - val imm = - activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager - ?: return f(query) - imm.hideSoftInputFromWindow(searchView.windowToken, 0) - return f(query) - } - return true - } - }) -} - -fun Controller.scrollViewWith( - recycler: RecyclerView, - padBottom: Boolean = false, - customPadding: Boolean = false, - skipFirstSnap: Boolean = false, - swipeRefreshLayout: SwipeRefreshLayout? = null, - afterInsets: ((WindowInsets) -> Unit)? = null -) { - var statusBarHeight = -1 - activity?.appbar?.y = 0f - val attrsArray = intArrayOf(android.R.attr.actionBarSize) - val array = recycler.context.obtainStyledAttributes(attrsArray) - var appBarHeight = if (activity!!.toolbar.height > 0) activity!!.toolbar.height - else array.getDimensionPixelSize(0, 0) - array.recycle() - swipeRefreshLayout?.setDistanceToTriggerSync(150.dpToPx) - activity!!.toolbar.post { - if (activity!!.toolbar.height > 0) { - appBarHeight = activity!!.toolbar.height - recycler.requestApplyInsets() - } - } - recycler.doOnApplyWindowInsets { view, insets, _ -> - val headerHeight = insets.systemWindowInsetTop + appBarHeight - if (!customPadding) view.updatePaddingRelative( - top = headerHeight, - bottom = if (padBottom) insets.systemWindowInsetBottom else view.paddingBottom - ) - swipeRefreshLayout?.setProgressViewOffset( - true, headerHeight + (-60).dpToPx, headerHeight + 10.dpToPx - ) - statusBarHeight = insets.systemWindowInsetTop - afterInsets?.invoke(insets) - } - var elevationAnim: ValueAnimator? = null - var elevate = false - val elevateFunc: (Boolean) -> Unit = { el -> - elevate = el - elevationAnim?.cancel() - elevationAnim = ValueAnimator.ofFloat( - activity!!.appbar.elevation, if (el) 15f else 0f - ) - elevationAnim?.addUpdateListener { valueAnimator -> - activity!!.appbar.elevation = valueAnimator.animatedValue as Float - } - elevationAnim?.start() - } - addLifecycleListener(object : Controller.LifecycleListener() { - override fun onChangeStart( - controller: Controller, - changeHandler: ControllerChangeHandler, - changeType: ControllerChangeType - ) { - super.onChangeStart(controller, changeHandler, changeType) - if (changeType.isEnter) - elevateFunc(elevate) - } - }) - elevateFunc(recycler.canScrollVertically(-1)) - recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() { - override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { - super.onScrolled(recyclerView, dx, dy) - if (router?.backstack?.lastOrNull() - ?.controller() == this@scrollViewWith && statusBarHeight > -1 && activity != null && activity!!.appbar.height > 0 - ) { - if (!recycler.canScrollVertically(-1)) { - val shortAnimationDuration = resources?.getInteger( - android.R.integer.config_shortAnimTime - ) ?: 0 - activity!!.appbar.animate().y(0f).setDuration(shortAnimationDuration.toLong()) - .start() - if (elevate) elevateFunc(false) - } else { - activity!!.appbar.y -= dy - activity!!.appbar.y = clamp( - activity!!.appbar.y, -activity!!.appbar.height.toFloat(), 0f - ) - if ((activity!!.appbar.y <= -activity!!.appbar.height.toFloat() || - dy == 0 && activity!!.appbar.y == 0f) && !elevate) - elevateFunc(true) - } - } - } - - override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { - super.onScrollStateChanged(recyclerView, newState) - if (newState == RecyclerView.SCROLL_STATE_IDLE) { - if (router?.backstack?.lastOrNull() - ?.controller() == this@scrollViewWith && statusBarHeight > -1 && activity != null && activity!!.appbar.height > 0 - ) { - val halfWay = abs((-activity!!.appbar.height.toFloat()) / 2) - val shortAnimationDuration = resources?.getInteger( - android.R.integer.config_shortAnimTime - ) ?: 0 - val closerToTop = abs(activity!!.appbar.y) - halfWay > 0 - val atTop = (!customPadding && - (recycler.layoutManager as LinearLayoutManager) - .findFirstVisibleItemPosition() < 2 && !skipFirstSnap) || - !recycler.canScrollVertically(-1) - activity!!.appbar.animate().y( - if (closerToTop && !atTop) (-activity!!.appbar.height.toFloat()) - else 0f - ).setDuration(shortAnimationDuration.toLong()).start() - if (recycler.canScrollVertically(-1) && !elevate) - elevateFunc(true) - else if (!recycler.canScrollVertically(-1) && elevate) - elevateFunc(false) - } - } - } - }) -} - inline fun View.updatePaddingRelative( @Px start: Int = paddingStart, @Px top: Int = paddingTop,