diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 01c2f33de..da6a5a1de 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -74,6 +74,9 @@ dependencies { implementation("com.github.topjohnwu:lz4-java:1.7.1") implementation("com.jakewharton.timber:timber:4.7.1") implementation("org.bouncycastle:bcpkix-jdk15on:1.70") + implementation("dev.rikka.rikkax.layoutinflater:layoutinflater:1.2.0") + implementation("dev.rikka.rikkax.insets:insets:1.1.1") + implementation("dev.rikka.rikkax.recyclerview:recyclerview-ktx:1.3.1") val vBAdapt = "4.0.0" val bindingAdapter = "me.tatarka.bindingcollectionadapter2:bindingcollectionadapter" diff --git a/app/src/main/java/com/topjohnwu/magisk/arch/BaseUIActivity.kt b/app/src/main/java/com/topjohnwu/magisk/arch/BaseUIActivity.kt index f4d679c28..81d38b0a4 100644 --- a/app/src/main/java/com/topjohnwu/magisk/arch/BaseUIActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/arch/BaseUIActivity.kt @@ -14,9 +14,10 @@ import androidx.navigation.NavController import androidx.navigation.NavDirections import androidx.navigation.fragment.NavHostFragment import com.topjohnwu.magisk.BR -import com.topjohnwu.magisk.arch.inflater.LayoutInflaterFactory import com.topjohnwu.magisk.core.Config import com.topjohnwu.magisk.core.base.BaseActivity +import rikka.insets.WindowInsetsHelper +import rikka.layoutinflater.view.LayoutInflaterFactory abstract class BaseUIActivity : BaseActivity(), BaseUIComponent { @@ -44,6 +45,7 @@ abstract class BaseUIActivity : override fun onCreate(savedInstanceState: Bundle?) { layoutInflater.factory2 = LayoutInflaterFactory(delegate) + .addOnViewCreatedListener(WindowInsetsHelper.LISTENER) super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/topjohnwu/magisk/arch/inflater/LayoutInflaterFactory.kt b/app/src/main/java/com/topjohnwu/magisk/arch/inflater/LayoutInflaterFactory.kt deleted file mode 100644 index 46b7817ec..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/arch/inflater/LayoutInflaterFactory.kt +++ /dev/null @@ -1,85 +0,0 @@ -package com.topjohnwu.magisk.arch.inflater - -import android.content.Context -import android.util.AttributeSet -import android.view.InflateException -import android.view.LayoutInflater -import android.view.View -import androidx.appcompat.app.AppCompatDelegate -import androidx.collection.SimpleArrayMap -import java.lang.reflect.Constructor - -open class LayoutInflaterFactory(private val delegate: AppCompatDelegate) : LayoutInflater.Factory2 { - - override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { - return onCreateView(null, name, context, attrs) - } - - override fun onCreateView(parent: View?, name: String, context: Context, attrs: AttributeSet): View? { - val view = delegate.createView(parent, name, context, attrs) - ?: LayoutInflaterFactoryDefaultImpl.createViewFromTag(context, name, attrs) - onViewCreated(view, parent, name, context, attrs) - return view - } - - open fun onViewCreated(view: View?, parent: View?, name: String, context: Context, attrs: AttributeSet) { - if (view == null) return - - WindowInsetsHelper.attach(view, attrs) - } -} - -private object LayoutInflaterFactoryDefaultImpl { - - private val constructorSignature = arrayOf( - Context::class.java, AttributeSet::class.java) - - private val classPrefixList = arrayOf( - "android.widget.", - "android.view.", - "android.webkit." - ) - - private val constructorMap = SimpleArrayMap>() - - fun createViewFromTag(context: Context, name: String, attrs: AttributeSet): View? { - var name = name - if (name == "view") { - name = attrs.getAttributeValue(null, "class") - } - return try { - if (-1 == name.indexOf('.')) { - for (prefix in classPrefixList) { - val view: View? = createViewByPrefix(context, name, attrs, prefix) - if (view != null) { - return view - } - } - null - } else { - createViewByPrefix(context, name, attrs, null) - } - } catch (e: Exception) { - null - } - } - - @Throws(ClassNotFoundException::class, InflateException::class) - private fun createViewByPrefix(context: Context, name: String, attrs: AttributeSet, prefix: String?): View? { - var constructor = constructorMap[name] - return try { - if (constructor == null) { // Class not found in the cache, see if it's real, and try to add it - val clazz = Class.forName( - if (prefix != null) prefix + name else name, - false, - context.classLoader).asSubclass(View::class.java) - constructor = clazz.getConstructor(*constructorSignature) - constructorMap.put(name, constructor) - } - constructor!!.isAccessible = true - constructor.newInstance(context, attrs) - } catch (e: Exception) { - null - } - } -} diff --git a/app/src/main/java/com/topjohnwu/magisk/arch/inflater/WindowInsetsHelper.kt b/app/src/main/java/com/topjohnwu/magisk/arch/inflater/WindowInsetsHelper.kt deleted file mode 100644 index ea9c1ff2e..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/arch/inflater/WindowInsetsHelper.kt +++ /dev/null @@ -1,284 +0,0 @@ -@file:Suppress("unused") - -package com.topjohnwu.magisk.arch.inflater - -import android.annotation.SuppressLint -import android.annotation.TargetApi -import android.graphics.Rect -import android.os.Build -import android.util.AttributeSet -import android.view.Gravity.* -import android.view.View -import android.view.ViewGroup -import androidx.core.graphics.Insets -import androidx.core.view.OnApplyWindowInsetsListener -import androidx.core.view.ViewCompat -import androidx.core.view.WindowInsetsCompat -import com.topjohnwu.magisk.R - -private typealias ApplyInsetsCallback = (insets: Insets, left: Boolean, top: Boolean, right: Boolean, bottom: Boolean) -> T - -private class ApplyInsets(private val out: Rect) : ApplyInsetsCallback { - - override fun invoke(insets: Insets, left: Boolean, top: Boolean, right: Boolean, bottom: Boolean) { - out.left += if (left) insets.left else 0 - out.top += if (top) insets.top else 0 - out.right += if (right) insets.right else 0 - out.bottom += if (bottom) insets.bottom else 0 - } -} - -private class ConsumeInsets : ApplyInsetsCallback { - - override fun invoke(insets: Insets, left: Boolean, top: Boolean, right: Boolean, bottom: Boolean): Insets { - val insetsLeft = if (left) 0 else insets.left - val insetsTop = if (top) 0 else insets.top - val insetsRight = if (right) 0 else insets.right - val insetsBottom = if (bottom) 0 else insets.bottom - return Insets.of(insetsLeft, insetsTop, insetsRight, insetsBottom) - } -} - -@TargetApi(Build.VERSION_CODES.LOLLIPOP) -open class WindowInsetsHelper private constructor( - private val view: View, - private val fitSystemWindows: Int, - private val layout_fitsSystemWindowsInsets: Int, - private val consumeSystemWindows: Int) : OnApplyWindowInsetsListener { - - internal var initialPaddingLeft: Int = view.paddingLeft - internal var initialPaddingTop: Int = view.paddingTop - internal var initialPaddingRight: Int = view.paddingRight - internal var initialPaddingBottom: Int = view.paddingBottom - - private var initialMargin = false - internal var initialMarginLeft: Int = 0 - internal var initialMarginTop: Int = 0 - internal var initialMarginRight: Int = 0 - internal var initialMarginBottom: Int = 0 - internal var initialMarginStart: Int = 0 - internal var initialMarginEnd: Int = 0 - - private var lastInsets: WindowInsetsCompat? = null - - open fun setInitialPadding(left: Int, top: Int, right: Int, bottom: Int) { - initialPaddingLeft = left - initialPaddingTop = top - initialPaddingRight = right - initialPaddingBottom = bottom - - lastInsets?.let { applyWindowInsets(it) } - } - - open fun setInitialPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) { - val isRTL = view.layoutDirection == View.LAYOUT_DIRECTION_RTL - if (isRTL) { - setInitialPadding(start, top, end, bottom) - } else { - setInitialPadding(start, top, end, bottom) - } - } - - open fun setInitialMargin(left: Int, top: Int, right: Int, bottom: Int) { - initialPaddingLeft = left - initialPaddingTop = top - initialPaddingRight = right - initialPaddingBottom = bottom - - lastInsets?.let { applyWindowInsets(it) } - } - - open fun setInitialMarginRelative(start: Int, top: Int, end: Int, bottom: Int) { - initialMarginStart = start - initialMarginTop = top - initialMarginEnd = end - initialMarginBottom = bottom - - lastInsets?.let { applyWindowInsets(it) } - } - - @SuppressLint("RtlHardcoded") - private fun applyInsets(insets: Insets, fit: Int, callback: ApplyInsetsCallback): T { - val relativeMode = (fit and RELATIVE_LAYOUT_DIRECTION) == RELATIVE_LAYOUT_DIRECTION - - val isRTL = view.layoutDirection == View.LAYOUT_DIRECTION_RTL - - val left: Boolean - val top = fit and TOP == TOP - val right: Boolean - val bottom = fit and BOTTOM == BOTTOM - - if (relativeMode) { - val start = fit and START == START - val end = fit and END == END - left = (!isRTL && start) || (isRTL && end) - right = (!isRTL && end) || (isRTL && start) - } else { - left = fit and LEFT == LEFT - right = fit and RIGHT == RIGHT - } - - return callback.invoke(insets, left, top, right, bottom) - } - - private fun applyWindowInsets(windowInsets: WindowInsetsCompat): WindowInsetsCompat { - if (fitSystemWindows != 0) { - val padding = Rect(initialPaddingLeft, initialPaddingTop, initialPaddingRight, initialPaddingBottom) - applyInsets(windowInsets.systemWindowInsets, fitSystemWindows, ApplyInsets(padding)) - view.setPadding(padding.left, padding.top, padding.right, padding.bottom) - } - - if (layout_fitsSystemWindowsInsets != 0) { - if (!initialMargin) { - initialMarginLeft = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.leftMargin ?: 0 - initialMarginTop = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.topMargin ?: 0 - initialMarginRight = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.rightMargin ?: 0 - initialMarginBottom = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.bottomMargin ?: 0 - initialMarginStart = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.marginStart ?: 0 - initialMarginEnd = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.marginEnd ?: 0 - initialMargin = true - } - - val margin = if ((layout_fitsSystemWindowsInsets and RELATIVE_LAYOUT_DIRECTION) == RELATIVE_LAYOUT_DIRECTION) - Rect(initialMarginLeft, initialMarginTop, initialMarginRight, initialMarginBottom) - else - Rect(initialMarginStart, initialMarginTop, initialMarginEnd, initialMarginBottom) - - applyInsets(windowInsets.systemWindowInsets, layout_fitsSystemWindowsInsets, ApplyInsets(margin)) - - val lp = view.layoutParams - if (lp is ViewGroup.MarginLayoutParams) { - lp.topMargin = margin.top - lp.bottomMargin = margin.bottom - - if ((layout_fitsSystemWindowsInsets and RELATIVE_LAYOUT_DIRECTION) == RELATIVE_LAYOUT_DIRECTION) { - lp.marginStart = margin.left - lp.marginEnd = margin.right - } else { - lp.leftMargin = margin.left - lp.rightMargin = margin.right - } - - view.layoutParams = lp - } - } - - val systemWindowInsets = if (consumeSystemWindows != 0) applyInsets(windowInsets.systemWindowInsets, consumeSystemWindows, ConsumeInsets()) else windowInsets.systemWindowInsets - - return WindowInsetsCompat.Builder(windowInsets) - .setSystemWindowInsets(systemWindowInsets) - .build() - } - - override fun onApplyWindowInsets(view: View, insets: WindowInsetsCompat): WindowInsetsCompat { - if (lastInsets == insets) { - return insets - } - - lastInsets = insets - - return applyWindowInsets(insets) - } - - companion object { - - @JvmStatic - fun attach(view: View, attrs: AttributeSet) { - val a = view.context.obtainStyledAttributes(attrs, R.styleable.WindowInsetsHelper, 0, 0) - val edgeToEdge = a.getBoolean(R.styleable.WindowInsetsHelper_edgeToEdge, false) - val fitsSystemWindowsInsets = a.getInt(R.styleable.WindowInsetsHelper_fitsSystemWindowsInsets, 0) - val layout_fitsSystemWindowsInsets = a.getInt(R.styleable.WindowInsetsHelper_layout_fitsSystemWindowsInsets, 0) - val consumeSystemWindowsInsets = a.getInt(R.styleable.WindowInsetsHelper_consumeSystemWindowsInsets, 0) - a.recycle() - - attach(view, edgeToEdge, fitsSystemWindowsInsets, layout_fitsSystemWindowsInsets, consumeSystemWindowsInsets) - } - - @JvmStatic - fun attach(view: View, edgeToEdge: Boolean, fitsSystemWindowsInsets: Int, layout_fitsSystemWindowsInsets: Int, consumeSystemWindowsInsets: Int) { - if (edgeToEdge) { - view.systemUiVisibility = (view.systemUiVisibility - or View.SYSTEM_UI_FLAG_LAYOUT_STABLE - or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) - } - - if (fitsSystemWindowsInsets == 0 && layout_fitsSystemWindowsInsets == 0 && consumeSystemWindowsInsets == 0) { - return - } - - val listener = WindowInsetsHelper(view, fitsSystemWindowsInsets, layout_fitsSystemWindowsInsets, consumeSystemWindowsInsets) - ViewCompat.setOnApplyWindowInsetsListener(view, listener) - view.setTag(R.id.tag_rikka_material_WindowInsetsHelper, listener) - - if (!view.isAttachedToWindow) { - view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { - override fun onViewAttachedToWindow(v: View) { - v.removeOnAttachStateChangeListener(this) - v.requestApplyInsets() - } - - override fun onViewDetachedFromWindow(v: View) = Unit - }) - } - } - } -} - -val View.windowInsetsHelper: WindowInsetsHelper? - get() { - val value = getTag(R.id.tag_rikka_material_WindowInsetsHelper) - return if (value is WindowInsetsHelper) value else null - } - -val View.initialPaddingLeft: Int - get() = windowInsetsHelper?.initialPaddingLeft ?: 0 - -val View.initialPaddingTop: Int - get() = windowInsetsHelper?.initialPaddingTop ?: 0 - -val View.initialPaddingRight: Int - get() = windowInsetsHelper?.initialPaddingRight ?: 0 - -val View.initialPaddingBottom: Int - get() = windowInsetsHelper?.initialPaddingBottom ?: 0 - -val View.initialPaddingStart: Int - get() = if (layoutDirection == View.LAYOUT_DIRECTION_RTL) initialPaddingRight else initialPaddingLeft - -val View.initialPaddingEnd: Int - get() = if (layoutDirection == View.LAYOUT_DIRECTION_RTL) initialPaddingLeft else initialPaddingRight - -fun View.setInitialPadding(left: Int, top: Int, right: Int, bottom: Int) { - windowInsetsHelper?.setInitialPadding(left, top, right, bottom) -} - -fun View.setInitialPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) { - windowInsetsHelper?.setInitialPaddingRelative(start, top, end, bottom) -} - -val View.initialMarginLeft: Int - get() = windowInsetsHelper?.initialMarginLeft ?: 0 - -val View.initialMarginTop: Int - get() = windowInsetsHelper?.initialMarginTop ?: 0 - -val View.initialMarginRight: Int - get() = windowInsetsHelper?.initialMarginRight ?: 0 - -val View.initialMarginBottom: Int - get() = windowInsetsHelper?.initialMarginBottom ?: 0 - -val View.initialMarginStart: Int - get() = windowInsetsHelper?.initialMarginStart ?: 0 - -val View.initialMarginEnd: Int - get() = windowInsetsHelper?.initialMarginEnd ?: 0 - -fun View.setInitialMargin(left: Int, top: Int, right: Int, bottom: Int) { - windowInsetsHelper?.setInitialMargin(left, top, right, bottom) -} - -fun View.setInitialMarginRelative(start: Int, top: Int, end: Int, bottom: Int) { - windowInsetsHelper?.setInitialMarginRelative(start, top, end, bottom) -} diff --git a/app/src/main/java/com/topjohnwu/magisk/ktx/RecyclerView.kt b/app/src/main/java/com/topjohnwu/magisk/ktx/RecyclerView.kt deleted file mode 100644 index 292cc823d..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/ktx/RecyclerView.kt +++ /dev/null @@ -1,193 +0,0 @@ -@file:Suppress("unused") - -package com.topjohnwu.magisk.ktx - -import android.graphics.Canvas -import android.graphics.Rect -import android.view.View -import android.widget.EdgeEffect -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import com.topjohnwu.magisk.R - -fun RecyclerView.addInvalidateItemDecorationsObserver() { - - adapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { - override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { - invalidateItemDecorations() - } - - override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { - invalidateItemDecorations() - } - - override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) { - invalidateItemDecorations() - } - }) -} - -fun RecyclerView.addVerticalPadding(paddingTop: Int = 0, paddingBottom: Int = 0) { - addItemDecoration(VerticalPaddingDecoration(paddingTop, paddingBottom)) -} - -private class VerticalPaddingDecoration(private val paddingTop: Int = 0, private val paddingBottom: Int = 0) : RecyclerView.ItemDecoration() { - - private var allowTop: Boolean = true - private var allowBottom: Boolean = true - - override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { - val adapter = parent.adapter ?: return - val position = parent.getChildAdapterPosition(view) - val count = adapter.itemCount - if (position == 0 && allowTop) { - outRect.top = paddingTop - } else if (position == count - 1 && allowBottom) { - outRect.bottom = paddingBottom - } - } -} - -fun RecyclerView.addSimpleItemDecoration( - left: Int = 0, - top: Int = 0, - right: Int = 0, - bottom: Int = 0, -) { - addItemDecoration(SimpleItemDecoration(left, top, right, bottom)) -} - -private class SimpleItemDecoration( - private val left: Int = 0, - private val top: Int = 0, - private val right: Int = 0, - private val bottom: Int = 0 -) : RecyclerView.ItemDecoration() { - - private var allowLeft: Boolean = true - private var allowTop: Boolean = true - private var allowRight: Boolean = true - private var allowBottom: Boolean = true - - override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { - if (parent.adapter == null) { - return - } - if (allowLeft) { - outRect.left = left - } - if (allowTop) { - outRect.top = top - } - if (allowRight) { - outRect.right = right - } - if (allowBottom) { - outRect.top = bottom - } - } -} - -fun RecyclerView.fixEdgeEffect(overScrollIfContentScrolls: Boolean = true, alwaysClipToPadding: Boolean = true) { - if (overScrollIfContentScrolls) { - val listener = OverScrollIfContentScrollsListener() - addOnLayoutChangeListener(listener) - setTag(R.id.tag_rikka_recyclerView_OverScrollIfContentScrollsListener, listener) - } else { - val listener = getTag(R.id.tag_rikka_recyclerView_OverScrollIfContentScrollsListener) as? OverScrollIfContentScrollsListener - if (listener != null) { - removeOnLayoutChangeListener(listener) - setTag(R.id.tag_rikka_recyclerView_OverScrollIfContentScrollsListener, null) - } - } - - edgeEffectFactory = if (alwaysClipToPadding && !clipToPadding) { - AlwaysClipToPaddingEdgeEffectFactory() - } else { - RecyclerView.EdgeEffectFactory() - } -} - -private class OverScrollIfContentScrollsListener : View.OnLayoutChangeListener { - private var show = true - override fun onLayoutChange(v: View, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) { - if (shouldDrawOverScroll(v as RecyclerView) != show) { - show = !show - if (show) { - v.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS) - } else { - v.setOverScrollMode(View.OVER_SCROLL_NEVER) - } - } - } - - fun shouldDrawOverScroll(recyclerView: RecyclerView): Boolean { - if (recyclerView.layoutManager == null || recyclerView.adapter == null || recyclerView.adapter!!.itemCount == 0) { - return false - } - if (recyclerView.layoutManager is LinearLayoutManager) { - val itemCount = recyclerView.layoutManager!!.itemCount - val firstPosition: Int = (recyclerView.layoutManager as LinearLayoutManager?)!!.findFirstCompletelyVisibleItemPosition() - val lastPosition: Int = (recyclerView.layoutManager as LinearLayoutManager?)!!.findLastCompletelyVisibleItemPosition() - return firstPosition != 0 || lastPosition != itemCount - 1 - } - return true - } -} - -private class AlwaysClipToPaddingEdgeEffectFactory : RecyclerView.EdgeEffectFactory() { - - override fun createEdgeEffect(view: RecyclerView, direction: Int): EdgeEffect { - - return object : EdgeEffect(view.context) { - private var ensureSize = false - - private fun ensureSize() { - if (ensureSize) return - ensureSize = true - - when (direction) { - DIRECTION_LEFT -> { - setSize(view.measuredHeight - view.paddingTop - view.paddingBottom, - view.measuredWidth - view.paddingLeft - view.paddingRight) - } - DIRECTION_TOP -> { - setSize(view.measuredWidth - view.paddingLeft - view.paddingRight, - view.measuredHeight - view.paddingTop - view.paddingBottom) - } - DIRECTION_RIGHT -> { - setSize(view.measuredHeight - view.paddingTop - view.paddingBottom, - view.measuredWidth - view.paddingLeft - view.paddingRight) - } - DIRECTION_BOTTOM -> { - setSize(view.measuredWidth - view.paddingLeft - view.paddingRight, - view.measuredHeight - view.paddingTop - view.paddingBottom) - } - } - } - - override fun draw(c: Canvas): Boolean { - ensureSize() - - val restore = c.save() - when (direction) { - DIRECTION_LEFT -> { - c.translate(view.paddingBottom.toFloat(), 0f) - } - DIRECTION_TOP -> { - c.translate(view.paddingLeft.toFloat(), view.paddingTop.toFloat()) - } - DIRECTION_RIGHT -> { - c.translate(-view.paddingTop.toFloat(), 0f) - } - DIRECTION_BOTTOM -> { - c.translate(view.paddingRight.toFloat(), view.paddingBottom.toFloat()) - } - } - val res = super.draw(c) - c.restoreToCount(restore) - return res - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/deny/DenyListFragment.kt b/app/src/main/java/com/topjohnwu/magisk/ui/deny/DenyListFragment.kt index d4bfff31d..124429c28 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/deny/DenyListFragment.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/deny/DenyListFragment.kt @@ -12,10 +12,10 @@ import com.topjohnwu.magisk.R import com.topjohnwu.magisk.arch.BaseUIFragment import com.topjohnwu.magisk.databinding.FragmentDenyMd2Binding import com.topjohnwu.magisk.di.viewModel -import com.topjohnwu.magisk.ktx.addSimpleItemDecoration -import com.topjohnwu.magisk.ktx.addVerticalPadding -import com.topjohnwu.magisk.ktx.fixEdgeEffect import com.topjohnwu.magisk.ktx.hideKeyboard +import rikka.recyclerview.addEdgeSpacing +import rikka.recyclerview.addItemSpacing +import rikka.recyclerview.fixEdgeEffect class DenyListFragment : BaseUIFragment() { @@ -39,20 +39,11 @@ class DenyListFragment : BaseUIFragment() { @@ -47,20 +47,11 @@ class LogFragment : BaseUIFragment() { isMagiskLogVisible = true } - val resource = requireContext().resources - val l_50 = resource.getDimensionPixelSize(R.dimen.l_50) - val l1 = resource.getDimensionPixelSize(R.dimen.l1) - binding.logFilterSuperuser.logSuperuser.addVerticalPadding( - 0, - l1 - ) - binding.logFilterSuperuser.logSuperuser.addSimpleItemDecoration( - left = l1, - top = l_50, - right = l1, - bottom = l_50, - ) - binding.logFilterSuperuser.logSuperuser.fixEdgeEffect() + binding.logFilterSuperuser.logSuperuser.apply { + addEdgeSpacing(bottom = R.dimen.l1) + addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1) + fixEdgeEffect() + } } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleFragment.kt b/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleFragment.kt index 6c4edc060..912c995f0 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleFragment.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleFragment.kt @@ -1,48 +1,20 @@ package com.topjohnwu.magisk.ui.module import android.os.Bundle -import android.view.Menu -import android.view.MenuInflater -import android.view.MenuItem import android.view.View -import androidx.core.view.isVisible -import androidx.recyclerview.widget.RecyclerView import com.topjohnwu.magisk.R import com.topjohnwu.magisk.arch.BaseUIFragment -import com.topjohnwu.magisk.arch.ReselectionTarget import com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding import com.topjohnwu.magisk.di.viewModel -import com.topjohnwu.magisk.ktx.* -import com.topjohnwu.magisk.ui.MainActivity -import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener -import com.topjohnwu.magisk.utils.MotionRevealHelper +import rikka.recyclerview.addEdgeSpacing +import rikka.recyclerview.addInvalidateItemDecorationsObserver +import rikka.recyclerview.addItemSpacing +import rikka.recyclerview.fixEdgeEffect -class ModuleFragment : BaseUIFragment(), - ReselectionTarget { +class ModuleFragment : BaseUIFragment() { override val layoutRes = R.layout.fragment_module_md2 override val viewModel by viewModel() - override val snackbarAnchorView: View - get() { - return if (isFilterVisible) { - binding.moduleFilterInclude.moduleFilterTitleSearch - } else { - binding.moduleFilterToggle - } - } - - private val listeners = hashSetOf() - - private var isFilterVisible - get() = binding.moduleFilter.isVisible - set(value) { - if (!value) hideKeyboard() - MotionRevealHelper.withViews(binding.moduleFilter, binding.moduleFilterToggle, value) - with(activity as MainActivity) { - requestNavigationHidden(value) - setDisplayHomeAsUpEnabled(value) - } - } override fun onStart() { super.onStart() @@ -53,92 +25,14 @@ class ModuleFragment : BaseUIFragment override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding.moduleFilterToggle.setOnClickListener { - isFilterVisible = true - } - binding.moduleFilterInclude.moduleFilterDone.setOnClickListener { - isFilterVisible = false - } - binding.moduleFilterInclude.moduleFilterList.addOnScrollListener(object : - RecyclerView.OnScrollListener() { - override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { - if (newState != RecyclerView.SCROLL_STATE_IDLE) hideKeyboard() - } - }) - - val resource = requireContext().resources - val l_50 = resource.getDimensionPixelSize(R.dimen.l_50) - val l1 = resource.getDimensionPixelSize(R.dimen.l1) binding.moduleList.apply { - addVerticalPadding( - l_50, - l1 + l_50 + resource.getDimensionPixelSize(R.dimen.internal_action_bar_size) - ) - addSimpleItemDecoration( - left = l1, - top = l_50, - right = l1, - bottom = l_50, - ) - fixEdgeEffect() - post { - addInvalidateItemDecorationsObserver() - } - } - - binding.moduleFilterInclude.moduleFilterList.apply { - addVerticalPadding( - l_50, - l_50 - ) - addSimpleItemDecoration( - left = l1, - top = l_50, - right = l1, - bottom = l_50, - ) + addEdgeSpacing(top = R.dimen.l_50, bottom = R.dimen.l1) + addItemSpacing(R.dimen.l1, R.dimen.l_50, R.dimen.l1) fixEdgeEffect() + post { addInvalidateItemDecorationsObserver() } } } - override fun onDestroyView() { - listeners.forEach { - binding.moduleList.removeOnScrollListener(it) - binding.moduleFilterInclude.moduleFilterList.removeOnScrollListener(it) - } - super.onDestroyView() - } - - override fun onBackPressed(): Boolean { - if (isFilterVisible) { - isFilterVisible = false - return true - } - return super.onBackPressed() - } - - // --- - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflate(R.menu.menu_module_md2, menu) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { - R.id.action_refresh -> viewModel.forceRefresh() - } - return super.onOptionsItemSelected(item) - } - - // --- - - override fun onReselected() { - binding.moduleList.scrollToPosition(10) - binding.moduleList.also { it.post { it.smoothScrollToPosition(0) } } - } - - // --- - override fun onPreBind(binding: FragmentModuleMd2Binding) = Unit } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt index 5371717de..aa7f62ed1 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsFragment.kt @@ -6,10 +6,9 @@ import com.topjohnwu.magisk.R import com.topjohnwu.magisk.arch.BaseUIFragment import com.topjohnwu.magisk.databinding.FragmentSettingsMd2Binding import com.topjohnwu.magisk.di.viewModel -import com.topjohnwu.magisk.ktx.addSimpleItemDecoration -import com.topjohnwu.magisk.ktx.addVerticalPadding -import com.topjohnwu.magisk.ktx.fixEdgeEffect -import com.topjohnwu.magisk.ktx.setOnViewReadyListener +import rikka.recyclerview.addEdgeSpacing +import rikka.recyclerview.addItemSpacing +import rikka.recyclerview.fixEdgeEffect class SettingsFragment : BaseUIFragment() { @@ -24,24 +23,11 @@ class SettingsFragment : BaseUIFragment() { @@ -23,20 +23,11 @@ class SuperuserFragment : BaseUIFragment - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml index 7be52e7fb..ec81f4f39 100644 --- a/app/src/main/res/values/ids.xml +++ b/app/src/main/res/values/ids.xml @@ -2,7 +2,4 @@ - - -