Update MagiskHide list

This commit is contained in:
topjohnwu
2020-08-10 07:05:07 -07:00
parent c7e30ac63e
commit 9df6b0618a
8 changed files with 89 additions and 80 deletions

View File

@@ -5,14 +5,12 @@ import android.graphics.drawable.Drawable
import com.topjohnwu.magisk.ktx.packageInfo
import com.topjohnwu.magisk.ktx.processes
class HideAppInfo(
data class HideAppInfo(
val info: ApplicationInfo,
val name: String,
val icon: Drawable
) {
val processes = info.packageInfo?.processes?.distinct() ?: listOf(info.packageName)
}
data class StatefulProcess(
@@ -21,7 +19,7 @@ data class StatefulProcess(
val isHidden: Boolean
)
class ProcessHideApp(
data class HideAppTarget(
val info: HideAppInfo,
val processes: List<StatefulProcess>
)

View File

@@ -7,60 +7,64 @@ import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ObservableItem
import com.topjohnwu.magisk.ktx.startAnimations
import com.topjohnwu.magisk.model.entity.ProcessHideApp
import com.topjohnwu.magisk.model.entity.HideAppTarget
import com.topjohnwu.magisk.model.entity.StatefulProcess
import com.topjohnwu.magisk.ui.hide.HideViewModel
import com.topjohnwu.magisk.utils.addOnPropertyChangedCallback
import com.topjohnwu.magisk.utils.set
import kotlin.math.roundToInt
class HideItem(val item: ProcessHideApp) : ObservableItem<HideItem>() {
class HideItem(
val item: HideAppTarget,
viewModel: HideViewModel
) : ObservableItem<HideItem>() {
override val layoutRes = R.layout.item_hide_md2
val packageName = item.info.info.packageName.orEmpty()
val items = item.processes.map { HideProcessItem(it) }
val items = item.processes.map { HideProcessItem(it, viewModel) }
@get:Bindable
var isExpanded = false
set(value) = set(value, field, { field = it }, BR.expanded)
@get:Bindable
var itemsChecked = 0
set(value) = set(value, field, { field = it }, BR.itemsChecked, BR.itemsCheckedPercent)
set(value) = set(value, field, { field = it }, BR.itemsCheckedPercent)
@get:Bindable
val itemsCheckedPercent get() = (itemsChecked.toFloat() / items.size * 100).roundToInt()
private val isHidden get() = itemsChecked == items.size
private var state: Boolean? = false
set(value) = set(value, field, { field = it }, BR.hiddenState)
@get:Bindable
var hiddenState: Boolean?
get() = state
set(value) = set(value, state, { state = it }, BR.hiddenState) {
if (value == true) {
items.filterNot { it.isHidden }
} else {
items
}.forEach { it.toggle() }
}
init {
items.forEach { it.addOnPropertyChangedCallback(BR.hidden) { recalculateChecked() } }
recalculateChecked()
}
fun collapse(v: View) {
(v.parent.parent as? ViewGroup)?.startAnimations()
isExpanded = false
}
fun toggle(v: View) {
fun toggleExpand(v: View) {
(v.parent as? ViewGroup)?.startAnimations()
isExpanded = !isExpanded
}
fun toggle(viewModel: HideViewModel): Boolean {
// contract implies that isHidden == all checked
if (!isHidden) {
items.filterNot { it.isHidden }
} else {
items
}.forEach { it.toggle(viewModel) }
return true
}
private fun recalculateChecked() {
itemsChecked = items.count { it.isHidden }
state = when (itemsChecked) {
0 -> false
items.size -> true
else -> null
}
}
override fun contentSameAs(other: HideItem): Boolean = item == other.item
@@ -68,18 +72,21 @@ class HideItem(val item: ProcessHideApp) : ObservableItem<HideItem>() {
}
class HideProcessItem(val item: StatefulProcess) : ObservableItem<HideProcessItem>() {
class HideProcessItem(
val item: StatefulProcess,
val viewModel: HideViewModel
) : ObservableItem<HideProcessItem>() {
override val layoutRes = R.layout.item_hide_process_md2
@get:Bindable
var isHidden = item.isHidden
set(value) = set(value, field, { field = it }, BR.hidden)
set(value) = set(value, field, { field = it }, BR.hidden) {
viewModel.toggleItem(this)
}
fun toggle(viewModel: HideViewModel) {
fun toggle() {
isHidden = !isHidden
viewModel.toggleItem(this)
}
override fun contentSameAs(other: HideProcessItem) = item == other.item

View File

@@ -8,8 +8,8 @@ import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.data.repository.MagiskRepository
import com.topjohnwu.magisk.model.entity.HideAppInfo
import com.topjohnwu.magisk.model.entity.HideAppTarget
import com.topjohnwu.magisk.model.entity.HideTarget
import com.topjohnwu.magisk.model.entity.ProcessHideApp
import com.topjohnwu.magisk.model.entity.StatefulProcess
import com.topjohnwu.magisk.model.entity.recycler.HideItem
import com.topjohnwu.magisk.model.entity.recycler.HideProcessItem
@@ -54,7 +54,10 @@ class HideViewModel(
val apps = magiskRepo.fetchApps()
val hides = magiskRepo.fetchHideTargets()
val (appList, diff) = withContext(Dispatchers.Default) {
val list = apps.map { mergeAppTargets(it, hides) }.map { HideItem(it) }.sort()
val list = apps
.map { createTarget(it, hides) }
.map { HideItem(it, this@HideViewModel) }
.sort()
list to items.calculateDiff(list)
}
items.update(appList, diff)
@@ -64,12 +67,13 @@ class HideViewModel(
// ---
private fun mergeAppTargets(a: HideAppInfo, ts: List<HideTarget>): ProcessHideApp {
val relevantTargets = ts.filter { it.packageName == a.info.packageName }
val packageName = a.info.packageName
val processes = a.processes
.map { StatefulProcess(it, packageName, relevantTargets.any { i -> it == i.process }) }
return ProcessHideApp(a, processes)
private fun createTarget(app: HideAppInfo, hideList: List<HideTarget>): HideAppTarget {
val hidden = hideList.filter { it.packageName == app.info.packageName }
val packageName = app.info.packageName
val processes = app.processes.map { name ->
StatefulProcess(name, packageName, hidden.any { name == it.process })
}
return HideAppTarget(app, processes)
}
private fun List<HideItem>.sort() = compareByDescending<HideItem> { it.itemsChecked != 0 }

View File

@@ -14,6 +14,8 @@ import androidx.annotation.DrawableRes
import androidx.appcompat.widget.Toolbar
import androidx.core.view.updateLayoutParams
import androidx.databinding.BindingAdapter
import androidx.databinding.InverseBindingAdapter
import androidx.databinding.InverseBindingListener
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.recyclerview.widget.*
import com.google.android.material.button.MaterialButton
@@ -23,6 +25,7 @@ import com.google.android.material.textfield.TextInputLayout
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.ktx.replaceRandomWithSpecial
import com.topjohnwu.superuser.internal.UiThreadHandler
import com.topjohnwu.widget.IndeterminateCheckBox
import kotlinx.coroutines.*
import kotlin.math.roundToInt
@@ -246,3 +249,23 @@ fun RecyclerView.setSpanCount(count: Int) {
is StaggeredGridLayoutManager -> lama.spanCount = count
}
}
@BindingAdapter("state")
fun setState(view: IndeterminateCheckBox, state: Boolean?) {
if (view.state != state)
view.state = state
}
@InverseBindingAdapter(attribute = "state")
fun getState(view: IndeterminateCheckBox) = view.state
@BindingAdapter("stateAttrChanged")
fun setListeners(
view: IndeterminateCheckBox,
attrChange: InverseBindingListener
) {
view.setOnStateChangedListener { _, _ ->
attrChange.onChange()
}
}