Cleaned up extensions and utilities in redesign

This commit is contained in:
Viktor De Pasquale 2019-12-06 16:28:41 +01:00
parent 8a03c366b8
commit c79b79b37e
13 changed files with 148 additions and 150 deletions

View File

@ -0,0 +1,43 @@
package com.topjohnwu.magisk.redesign.compat
import androidx.databinding.ViewDataBinding
import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.utils.DiffObservableList
import com.topjohnwu.magisk.utils.FilterableDiffObservableList
import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter
import me.tatarka.bindingcollectionadapter2.ItemBinding
import me.tatarka.bindingcollectionadapter2.OnItemBind
inline fun <T : ComparableRvItem<*>> diffListOf(
vararg newItems: T
) = DiffObservableList(object : DiffObservableList.Callback<T> {
override fun areItemsTheSame(oldItem: T, newItem: T) = oldItem.genericItemSameAs(newItem)
override fun areContentsTheSame(oldItem: T, newItem: T) = oldItem.genericContentSameAs(newItem)
}).also { it.update(newItems.toList()) }
inline fun <T : ComparableRvItem<*>> filterableListOf(
vararg newItems: T
) = FilterableDiffObservableList(object : DiffObservableList.Callback<T> {
override fun areItemsTheSame(oldItem: T, newItem: T) = oldItem.genericItemSameAs(newItem)
override fun areContentsTheSame(oldItem: T, newItem: T) = oldItem.genericContentSameAs(newItem)
}).also { it.update(newItems.toList()) }
fun <T : ComparableRvItem<*>> adapterOf() = object : BindingRecyclerViewAdapter<T>() {
override fun onBindBinding(
binding: ViewDataBinding,
variableId: Int,
layoutRes: Int,
position: Int,
item: T
) {
super.onBindBinding(binding, variableId, layoutRes, position, item)
item.onBindingBound(binding)
}
}
inline fun <T : ComparableRvItem<*>> itemBindingOf(
crossinline body: (ItemBinding<*>) -> Unit = {}
) = OnItemBind<T> { itemBinding, _, item ->
item.bind(itemBinding)
body(itemBinding)
}

View File

@ -1,8 +1,5 @@
package com.topjohnwu.magisk.redesign.hide
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.Insets
import android.os.Bundle
@ -10,23 +7,15 @@ import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.core.animation.addListener
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.marginBottom
import androidx.core.view.marginEnd
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.circularreveal.CircularRevealCompat
import com.google.android.material.circularreveal.CircularRevealWidget
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.FragmentHideMd2Binding
import com.topjohnwu.magisk.redesign.compat.CompatFragment
import com.topjohnwu.magisk.redesign.compat.hideKeyboard
import com.topjohnwu.magisk.utils.MotionRevealHelper
import org.koin.androidx.viewmodel.ext.android.viewModel
import kotlin.math.hypot
class HideFragment : CompatFragment<HideViewModel, FragmentHideMd2Binding>() {
@ -94,71 +83,4 @@ class HideFragment : CompatFragment<HideViewModel, FragmentHideMd2Binding>() {
return super.onOptionsItemSelected(item)
}
}
object MotionRevealHelper {
fun <CV> withViews(
revealable: CV,
fab: FloatingActionButton,
expanded: Boolean
) where CV : CircularRevealWidget, CV : View {
revealable.revealInfo = revealable.createRevealInfo(!expanded)
val revealInfo = revealable.createRevealInfo(expanded)
val revealAnim = revealable.createRevealAnim(revealInfo)
val moveAnim = fab.createMoveAnim(revealInfo)
AnimatorSet().also {
if (expanded) {
it.play(revealAnim).after(moveAnim)
} else {
it.play(moveAnim).after(revealAnim)
}
}.start()
}
private fun <CV> CV.createRevealAnim(
revealInfo: CircularRevealWidget.RevealInfo
): Animator where CV : CircularRevealWidget, CV : View =
CircularRevealCompat.createCircularReveal(
this,
revealInfo.centerX,
revealInfo.centerY,
revealInfo.radius
).apply {
addListener(onStart = {
isVisible = true
}, onEnd = {
if (revealInfo.radius == 0f) {
isInvisible = true
}
})
}
private fun FloatingActionButton.createMoveAnim(
revealInfo: CircularRevealWidget.RevealInfo
): Animator = AnimatorSet().also {
it.interpolator = FastOutSlowInInterpolator()
it.addListener(onStart = { show() }, onEnd = { if (revealInfo.radius != 0f) hide() })
val maxX = revealInfo.centerX - marginEnd - measuredWidth / 2f
val targetX = if (revealInfo.radius == 0f) 0f else -maxX
val moveX = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, targetX)
val maxY = revealInfo.centerY - marginBottom - measuredHeight / 2f
val targetY = if (revealInfo.radius == 0f) 0f else -maxY
val moveY = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, targetY)
it.playTogether(moveX, moveY)
}
private fun View.createRevealInfo(expanded: Boolean): CircularRevealWidget.RevealInfo {
val cX = measuredWidth / 2f
val cY = measuredHeight / 2f - paddingBottom
return CircularRevealWidget.RevealInfo(cX, cY, if (expanded) hypot(cX, cY) else 0f)
}
}
}

View File

@ -4,7 +4,6 @@ import android.content.pm.ApplicationInfo
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.data.repository.MagiskRepository
import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.extensions.toggle
import com.topjohnwu.magisk.model.entity.HideAppInfo
@ -15,9 +14,8 @@ import com.topjohnwu.magisk.model.entity.recycler.HideItem
import com.topjohnwu.magisk.model.entity.recycler.HideProcessItem
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
import com.topjohnwu.magisk.redesign.compat.Queryable
import com.topjohnwu.magisk.redesign.home.itemBindingOf
import com.topjohnwu.magisk.utils.DiffObservableList
import com.topjohnwu.magisk.utils.FilterableDiffObservableList
import com.topjohnwu.magisk.redesign.compat.filterableListOf
import com.topjohnwu.magisk.redesign.compat.itemBindingOf
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.magisk.utils.currentLocale
@ -127,9 +125,3 @@ class HideViewModel(
}
inline fun <T : ComparableRvItem<*>> filterableListOf(
vararg newItems: T
) = FilterableDiffObservableList(object : DiffObservableList.Callback<T> {
override fun areItemsTheSame(oldItem: T, newItem: T) = oldItem.genericItemSameAs(newItem)
override fun areContentsTheSame(oldItem: T, newItem: T) = oldItem.genericContentSameAs(newItem)
}).also { it.update(newItems.toList()) }

View File

@ -7,7 +7,6 @@ import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.Info
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.repository.MagiskRepository
import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.extensions.*
import com.topjohnwu.magisk.model.download.RemoteFileService
import com.topjohnwu.magisk.model.entity.MagiskJson
@ -24,12 +23,11 @@ import com.topjohnwu.magisk.model.events.dialog.UninstallDialog
import com.topjohnwu.magisk.model.navigation.Navigation
import com.topjohnwu.magisk.model.observer.Observer
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
import com.topjohnwu.magisk.redesign.compat.itemBindingOf
import com.topjohnwu.magisk.ui.home.MagiskState
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.superuser.Shell
import me.tatarka.bindingcollectionadapter2.BR
import me.tatarka.bindingcollectionadapter2.ItemBinding
import me.tatarka.bindingcollectionadapter2.OnItemBind
import kotlin.math.roundToInt
class HomeViewModel(
@ -179,6 +177,12 @@ class HomeViewModel(
}
}
private fun String.clipVersion(other: String = ""): String {
val thisVersion = substringBefore('-')
val otherVersion = other.substringBefore('-')
return if (thisVersion != otherVersion) thisVersion else substringAfter('-')
}
}
@Suppress("unused")
@ -190,16 +194,3 @@ val ManagerJson.isUpdateChannelCorrect
get() = versionCode > 0
val ManagerJson.isObsolete
get() = BuildConfig.VERSION_CODE < versionCode
fun String.clipVersion(other: String = ""): String {
val thisVersion = substringBefore('-')
val otherVersion = other.substringBefore('-')
return if (thisVersion != otherVersion) thisVersion else substringAfter('-')
}
inline fun <T : ComparableRvItem<*>> itemBindingOf(
crossinline body: (ItemBinding<*>) -> Unit = {}
) = OnItemBind<T> { itemBinding, _, item ->
item.bind(itemBinding)
body(itemBinding)
}

View File

@ -11,7 +11,7 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.FragmentLogMd2Binding
import com.topjohnwu.magisk.redesign.MainActivity
import com.topjohnwu.magisk.redesign.compat.CompatFragment
import com.topjohnwu.magisk.redesign.hide.MotionRevealHelper
import com.topjohnwu.magisk.utils.MotionRevealHelper
import org.koin.androidx.viewmodel.ext.android.viewModel
class LogFragment : CompatFragment<LogViewModel, FragmentLogMd2Binding>() {

View File

@ -12,8 +12,8 @@ import com.topjohnwu.magisk.model.entity.recycler.ConsoleItem
import com.topjohnwu.magisk.model.entity.recycler.LogItem
import com.topjohnwu.magisk.model.events.SnackbarEvent
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
import com.topjohnwu.magisk.redesign.home.itemBindingOf
import com.topjohnwu.magisk.redesign.superuser.diffListOf
import com.topjohnwu.magisk.redesign.compat.diffListOf
import com.topjohnwu.magisk.redesign.compat.itemBindingOf
import com.topjohnwu.superuser.Shell
import io.reactivex.Completable
import io.reactivex.android.schedulers.AndroidSchedulers

View File

@ -17,8 +17,8 @@ import com.topjohnwu.magisk.redesign.MainActivity
import com.topjohnwu.magisk.redesign.ReselectionTarget
import com.topjohnwu.magisk.redesign.compat.CompatFragment
import com.topjohnwu.magisk.redesign.compat.hideKeyboard
import com.topjohnwu.magisk.redesign.hide.MotionRevealHelper
import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener
import com.topjohnwu.magisk.utils.MotionRevealHelper
import org.koin.androidx.viewmodel.ext.android.viewModel
class ModuleFragment : CompatFragment<ModuleViewModel, FragmentModuleMd2Binding>(),

View File

@ -2,7 +2,6 @@ package com.topjohnwu.magisk.redesign.module
import androidx.annotation.WorkerThread
import androidx.databinding.Bindable
import androidx.databinding.ViewDataBinding
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.Config
import com.topjohnwu.magisk.R
@ -19,17 +18,13 @@ import com.topjohnwu.magisk.model.entity.recycler.*
import com.topjohnwu.magisk.model.events.InstallExternalModuleEvent
import com.topjohnwu.magisk.model.events.OpenChangelogEvent
import com.topjohnwu.magisk.model.events.dialog.ModuleInstallDialog
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
import com.topjohnwu.magisk.redesign.compat.Queryable
import com.topjohnwu.magisk.redesign.home.itemBindingOf
import com.topjohnwu.magisk.redesign.superuser.diffListOf
import com.topjohnwu.magisk.redesign.compat.*
import com.topjohnwu.magisk.tasks.RepoUpdater
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.magisk.utils.currentLocale
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter
import timber.log.Timber
import kotlin.math.roundToInt
@ -293,17 +288,4 @@ class ModuleViewModel(
private fun <T> List<T>.prependIfNotEmpty(item: () -> T) =
prependIf(isNotEmpty(), item)
}
fun <T : ComparableRvItem<*>> adapterOf() = object : BindingRecyclerViewAdapter<T>() {
override fun onBindBinding(
binding: ViewDataBinding,
variableId: Int,
layoutRes: Int,
position: Int,
item: T
) {
super.onBindBinding(binding, variableId, layoutRes, position, item)
item.onBindingBound(binding)
}
}

View File

@ -17,9 +17,9 @@ import com.topjohnwu.magisk.model.events.RecreateEvent
import com.topjohnwu.magisk.model.events.dialog.BiometricDialog
import com.topjohnwu.magisk.model.navigation.Navigation
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
import com.topjohnwu.magisk.redesign.home.itemBindingOf
import com.topjohnwu.magisk.redesign.module.adapterOf
import com.topjohnwu.magisk.redesign.superuser.diffListOf
import com.topjohnwu.magisk.redesign.compat.adapterOf
import com.topjohnwu.magisk.redesign.compat.diffListOf
import com.topjohnwu.magisk.redesign.compat.itemBindingOf
import com.topjohnwu.magisk.utils.PatchAPK
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.superuser.Shell

View File

@ -18,9 +18,9 @@ import com.topjohnwu.magisk.model.events.dialog.BiometricDialog
import com.topjohnwu.magisk.model.events.dialog.SuperuserRevokeDialog
import com.topjohnwu.magisk.model.navigation.Navigation
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
import com.topjohnwu.magisk.redesign.home.itemBindingOf
import com.topjohnwu.magisk.redesign.compat.diffListOf
import com.topjohnwu.magisk.redesign.compat.itemBindingOf
import com.topjohnwu.magisk.utils.BiometricHelper
import com.topjohnwu.magisk.utils.DiffObservableList
import com.topjohnwu.magisk.utils.currentLocale
import io.reactivex.Single
@ -142,11 +142,4 @@ class SuperuserViewModel(
private fun deletePolicy(policy: MagiskPolicy) =
db.delete(policy.uid).andThen(Single.just(policy))
}
inline fun <T : ComparableRvItem<*>> diffListOf(
vararg newItems: T
) = DiffObservableList(object : DiffObservableList.Callback<T> {
override fun areItemsTheSame(oldItem: T, newItem: T) = oldItem.genericItemSameAs(newItem)
override fun areContentsTheSame(oldItem: T, newItem: T) = oldItem.genericContentSameAs(newItem)
}).also { it.update(newItems.toList()) }
}

View File

@ -1,19 +1,12 @@
package com.topjohnwu.magisk.redesign.theme
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.model.entity.recycler.TappableHeadlineItem
import com.topjohnwu.magisk.model.entity.recycler.ThemeItem
import com.topjohnwu.magisk.model.events.RecreateEvent
import com.topjohnwu.magisk.model.events.dialog.DarkThemeDialog
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
import com.topjohnwu.magisk.redesign.home.itemBindingOf
import com.topjohnwu.magisk.redesign.superuser.diffListOf
class ThemeViewModel : CompatViewModel(), TappableHeadlineItem.Listener {
val items = diffListOf(*Theme.values().map { ThemeItem(it) }.toTypedArray())
val itemBinding = itemBindingOf<ThemeItem> { it.bindExtra(BR.viewModel, this) }
val themeHeadline = TappableHeadlineItem.ThemeMode
override fun onItemPressed(item: TappableHeadlineItem) = when (item) {

View File

@ -0,0 +1,82 @@
package com.topjohnwu.magisk.utils
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.view.View
import androidx.core.animation.addListener
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.marginBottom
import androidx.core.view.marginEnd
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import com.google.android.material.circularreveal.CircularRevealCompat
import com.google.android.material.circularreveal.CircularRevealWidget
import com.google.android.material.floatingactionbutton.FloatingActionButton
import kotlin.math.hypot
object MotionRevealHelper {
fun <CV> withViews(
revealable: CV,
fab: FloatingActionButton,
expanded: Boolean
) where CV : CircularRevealWidget, CV : View {
revealable.revealInfo = revealable.createRevealInfo(!expanded)
val revealInfo = revealable.createRevealInfo(expanded)
val revealAnim = revealable.createRevealAnim(revealInfo)
val moveAnim = fab.createMoveAnim(revealInfo)
AnimatorSet().also {
if (expanded) {
it.play(revealAnim).after(moveAnim)
} else {
it.play(moveAnim).after(revealAnim)
}
}.start()
}
private fun <CV> CV.createRevealAnim(
revealInfo: CircularRevealWidget.RevealInfo
): Animator where CV : CircularRevealWidget, CV : View =
CircularRevealCompat.createCircularReveal(
this,
revealInfo.centerX,
revealInfo.centerY,
revealInfo.radius
).apply {
addListener(onStart = {
isVisible = true
}, onEnd = {
if (revealInfo.radius == 0f) {
isInvisible = true
}
})
}
private fun FloatingActionButton.createMoveAnim(
revealInfo: CircularRevealWidget.RevealInfo
): Animator = AnimatorSet().also {
it.interpolator = FastOutSlowInInterpolator()
it.addListener(onStart = { show() }, onEnd = { if (revealInfo.radius != 0f) hide() })
// fixme rtl
val maxX = revealInfo.centerX - marginEnd - measuredWidth / 2f
val targetX = if (revealInfo.radius == 0f) 0f else -maxX
val moveX = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, targetX)
val maxY = revealInfo.centerY - marginBottom - measuredHeight / 2f
val targetY = if (revealInfo.radius == 0f) 0f else -maxY
val moveY = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, targetY)
it.playTogether(moveX, moveY)
}
private fun View.createRevealInfo(expanded: Boolean): CircularRevealWidget.RevealInfo {
val cX = measuredWidth / 2f
val cY = measuredHeight / 2f - paddingBottom
return CircularRevealWidget.RevealInfo(cX, cY, if (expanded) hypot(cX, cY) else 0f)
}
}

View File

@ -19,7 +19,7 @@ import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.databinding.DialogMagiskBaseBinding
import com.topjohnwu.magisk.redesign.home.itemBindingOf
import com.topjohnwu.magisk.redesign.compat.itemBindingOf
import com.topjohnwu.magisk.utils.KObservableField
import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapters
import me.tatarka.bindingcollectionadapter2.ItemBinding