Cleanup hide fragment code
This commit is contained in:
parent
b44dcc2da0
commit
84f92bd661
@ -1,23 +1,13 @@
|
|||||||
package com.topjohnwu.magisk.data.repository
|
package com.topjohnwu.magisk.data.repository
|
||||||
|
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||||
import com.topjohnwu.magisk.ktx.await
|
|
||||||
import com.topjohnwu.magisk.ktx.getLabel
|
|
||||||
import com.topjohnwu.magisk.ktx.packageName
|
|
||||||
import com.topjohnwu.magisk.ui.hide.HideAppInfo
|
|
||||||
import com.topjohnwu.magisk.ui.hide.HideTarget
|
|
||||||
import com.topjohnwu.superuser.Shell
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
class MagiskRepository(
|
class MagiskRepository(
|
||||||
private val apiRaw: GithubRawServices,
|
private val apiRaw: GithubRawServices
|
||||||
private val packageManager: PackageManager
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun fetchUpdate() = try {
|
suspend fun fetchUpdate() = try {
|
||||||
@ -40,35 +30,4 @@ class MagiskRepository(
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchApps() = withContext(Dispatchers.Default) {
|
|
||||||
packageManager.getInstalledApplications(0).filter {
|
|
||||||
it.enabled && !blacklist.contains(it.packageName)
|
|
||||||
}.map {
|
|
||||||
val label = it.getLabel(packageManager)
|
|
||||||
val icon = it.loadIcon(packageManager)
|
|
||||||
HideAppInfo(it, label, icon)
|
|
||||||
}.filter { it.processes.isNotEmpty() }
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun fetchHideTargets() =
|
|
||||||
Shell.su("magiskhide --ls").await().out.map { HideTarget(it) }
|
|
||||||
|
|
||||||
fun toggleHide(isEnabled: Boolean, packageName: String, process: String) =
|
|
||||||
Shell.su("magiskhide --${isEnabled.state} $packageName $process").submit()
|
|
||||||
|
|
||||||
private val Boolean.state get() = if (this) "add" else "rm"
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val blacklist by lazy { listOf(
|
|
||||||
packageName,
|
|
||||||
"android",
|
|
||||||
"com.android.chrome",
|
|
||||||
"com.chrome.beta",
|
|
||||||
"com.chrome.dev",
|
|
||||||
"com.chrome.canary",
|
|
||||||
"com.android.webview",
|
|
||||||
"com.google.android.webview"
|
|
||||||
) }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,17 @@ abstract class RvItem {
|
|||||||
|
|
||||||
abstract class ComparableRvItem<in T> : RvItem() {
|
abstract class ComparableRvItem<in T> : RvItem() {
|
||||||
|
|
||||||
abstract fun itemSameAs(other: T): Boolean
|
// Use Any.equals by default
|
||||||
abstract fun contentSameAs(other: T): Boolean
|
open fun itemSameAs(other: T) = this == other
|
||||||
|
|
||||||
|
// Use compareTo if this is Comparable or assume not same
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
open fun contentSameAs(other: T) =
|
||||||
|
(this as? Comparable<T>)?.run { compareTo(other) == 0 } ?: false
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
open fun genericItemSameAs(other: Any): Boolean = other::class == this::class && itemSameAs(other as T)
|
open fun genericItemSameAs(other: Any): Boolean = other::class == this::class && itemSameAs(other as T)
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
open fun genericContentSameAs(other: Any): Boolean = other::class == this::class && contentSameAs(other as T)
|
open fun genericContentSameAs(other: Any): Boolean = other::class == this::class && contentSameAs(other as T)
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import org.koin.dsl.module
|
|||||||
|
|
||||||
|
|
||||||
val repositoryModule = module {
|
val repositoryModule = module {
|
||||||
single { MagiskRepository(get(), get()) }
|
single { MagiskRepository(get()) }
|
||||||
single { LogRepository(get()) }
|
single { LogRepository(get()) }
|
||||||
single { StringRepository(get()) }
|
single { StringRepository(get()) }
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import org.koin.androidx.viewmodel.dsl.viewModel
|
|||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val viewModelModules = module {
|
val viewModelModules = module {
|
||||||
viewModel { HideViewModel(get()) }
|
viewModel { HideViewModel() }
|
||||||
viewModel { HomeViewModel(get()) }
|
viewModel { HomeViewModel(get()) }
|
||||||
viewModel { LogViewModel(get()) }
|
viewModel { LogViewModel(get()) }
|
||||||
viewModel { ModuleViewModel(get(), get(), get()) }
|
viewModel { ModuleViewModel(get(), get(), get()) }
|
||||||
|
@ -65,40 +65,22 @@ val PackageInfo.processes
|
|||||||
|
|
||||||
val Array<out ComponentInfo>.processNames get() = mapNotNull { it.processName }
|
val Array<out ComponentInfo>.processNames get() = mapNotNull { it.processName }
|
||||||
|
|
||||||
val ApplicationInfo.packageInfo: PackageInfo?
|
val ApplicationInfo.packageInfo: PackageInfo get() {
|
||||||
get() {
|
val pm = get<PackageManager>()
|
||||||
val pm: PackageManager by inject()
|
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val request = GET_ACTIVITIES or
|
val request = GET_ACTIVITIES or GET_SERVICES or GET_RECEIVERS or GET_PROVIDERS
|
||||||
GET_SERVICES or
|
|
||||||
GET_RECEIVERS or
|
|
||||||
GET_PROVIDERS
|
|
||||||
pm.getPackageInfo(packageName, request)
|
pm.getPackageInfo(packageName, request)
|
||||||
} catch (e1: Exception) {
|
} catch (e: Exception) {
|
||||||
try {
|
// Exceed binder data transfer limit, fetch each component type separately
|
||||||
pm.activities(packageName).apply {
|
pm.getPackageInfo(packageName, 0).apply {
|
||||||
services = pm.services(packageName)
|
runCatching { activities = pm.getPackageInfo(packageName, GET_ACTIVITIES).activities }
|
||||||
receivers = pm.receivers(packageName)
|
runCatching { services = pm.getPackageInfo(packageName, GET_SERVICES).services }
|
||||||
providers = pm.providers(packageName)
|
runCatching { receivers = pm.getPackageInfo(packageName, GET_RECEIVERS).receivers }
|
||||||
}
|
runCatching { providers = pm.getPackageInfo(packageName, GET_PROVIDERS).providers }
|
||||||
} catch (e2: Exception) {
|
|
||||||
null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun PackageManager.activities(packageName: String) =
|
|
||||||
getPackageInfo(packageName, GET_ACTIVITIES)
|
|
||||||
|
|
||||||
fun PackageManager.services(packageName: String) =
|
|
||||||
getPackageInfo(packageName, GET_SERVICES).services
|
|
||||||
|
|
||||||
fun PackageManager.receivers(packageName: String) =
|
|
||||||
getPackageInfo(packageName, GET_RECEIVERS).receivers
|
|
||||||
|
|
||||||
fun PackageManager.providers(packageName: String) =
|
|
||||||
getPackageInfo(packageName, GET_PROVIDERS).providers
|
|
||||||
|
|
||||||
fun Context.rawResource(id: Int) = resources.openRawResource(id)
|
fun Context.rawResource(id: Int) = resources.openRawResource(id)
|
||||||
|
|
||||||
|
47
app/src/main/java/com/topjohnwu/magisk/ui/hide/HideApp.kt
Normal file
47
app/src/main/java/com/topjohnwu/magisk/ui/hide/HideApp.kt
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package com.topjohnwu.magisk.ui.hide
|
||||||
|
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import com.topjohnwu.magisk.core.utils.currentLocale
|
||||||
|
import com.topjohnwu.magisk.ktx.getLabel
|
||||||
|
|
||||||
|
class HideTarget(line: String) {
|
||||||
|
val packageName: String
|
||||||
|
val process: String
|
||||||
|
|
||||||
|
init {
|
||||||
|
val split = line.split(Regex("\\|"), 2)
|
||||||
|
packageName = split[0]
|
||||||
|
process = split.getOrElse(1) { packageName }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HideAppInfo(info: ApplicationInfo, pm: PackageManager)
|
||||||
|
: ApplicationInfo(info), Comparable<HideAppInfo> {
|
||||||
|
|
||||||
|
val label = info.getLabel(pm)
|
||||||
|
val iconImage: Drawable = info.loadIcon(pm)
|
||||||
|
|
||||||
|
override fun compareTo(other: HideAppInfo) = comparator.compare(this, other)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val comparator = compareBy<HideAppInfo>(
|
||||||
|
{ it.label.toLowerCase(currentLocale) },
|
||||||
|
{ it.packageName }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class HideProcessInfo(
|
||||||
|
val name: String,
|
||||||
|
val packageName: String,
|
||||||
|
val isHidden: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
class HideAppTarget(
|
||||||
|
val info: HideAppInfo,
|
||||||
|
val processes: List<HideProcessInfo>
|
||||||
|
) : Comparable<HideAppTarget> {
|
||||||
|
override fun compareTo(other: HideAppTarget) = compareValuesBy(this, other) { it.info }
|
||||||
|
}
|
@ -1,25 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.ui.hide
|
|
||||||
|
|
||||||
import android.content.pm.ApplicationInfo
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import com.topjohnwu.magisk.ktx.packageInfo
|
|
||||||
import com.topjohnwu.magisk.ktx.processes
|
|
||||||
|
|
||||||
data class HideAppInfo(
|
|
||||||
val info: ApplicationInfo,
|
|
||||||
val name: String,
|
|
||||||
val icon: Drawable
|
|
||||||
) {
|
|
||||||
val processes = info.packageInfo?.processes?.distinct() ?: listOf(info.packageName)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class StatefulProcess(
|
|
||||||
val name: String,
|
|
||||||
val packageName: String,
|
|
||||||
val isHidden: Boolean
|
|
||||||
)
|
|
||||||
|
|
||||||
data class HideAppTarget(
|
|
||||||
val info: HideAppInfo,
|
|
||||||
val processes: List<StatefulProcess>
|
|
||||||
)
|
|
@ -9,27 +9,27 @@ import com.topjohnwu.magisk.databinding.ObservableItem
|
|||||||
import com.topjohnwu.magisk.ktx.startAnimations
|
import com.topjohnwu.magisk.ktx.startAnimations
|
||||||
import com.topjohnwu.magisk.utils.addOnPropertyChangedCallback
|
import com.topjohnwu.magisk.utils.addOnPropertyChangedCallback
|
||||||
import com.topjohnwu.magisk.utils.set
|
import com.topjohnwu.magisk.utils.set
|
||||||
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class HideItem(
|
class HideItem(
|
||||||
val item: HideAppTarget,
|
app: HideAppTarget
|
||||||
viewModel: HideViewModel
|
) : ObservableItem<HideItem>(), Comparable<HideItem> {
|
||||||
) : ObservableItem<HideItem>() {
|
|
||||||
|
|
||||||
override val layoutRes = R.layout.item_hide_md2
|
override val layoutRes = R.layout.item_hide_md2
|
||||||
|
|
||||||
val packageName = item.info.info.packageName.orEmpty()
|
val info = app.info
|
||||||
val items = item.processes.map { HideProcessItem(it, viewModel) }
|
val processes = app.processes.map { HideProcessItem(it) }
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var isExpanded = false
|
var isExpanded = false
|
||||||
set(value) = set(value, field, { field = it }, BR.expanded)
|
set(value) = set(value, field, { field = it }, BR.expanded)
|
||||||
|
|
||||||
var itemsChecked = 0
|
var itemsChecked = 0
|
||||||
set(value) = set(value, field, { field = it }, BR.itemsCheckedPercent)
|
set(value) = set(value, field, { field = it }, BR.checkedPercent)
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
val itemsCheckedPercent get() = (itemsChecked.toFloat() / items.size * 100).roundToInt()
|
val checkedPercent get() = (itemsChecked.toFloat() / processes.size * 100).roundToInt()
|
||||||
|
|
||||||
private var state: Boolean? = false
|
private var state: Boolean? = false
|
||||||
set(value) = set(value, field, { field = it }, BR.hiddenState)
|
set(value) = set(value, field, { field = it }, BR.hiddenState)
|
||||||
@ -39,14 +39,14 @@ class HideItem(
|
|||||||
get() = state
|
get() = state
|
||||||
set(value) = set(value, state, { state = it }, BR.hiddenState) {
|
set(value) = set(value, state, { state = it }, BR.hiddenState) {
|
||||||
if (value == true) {
|
if (value == true) {
|
||||||
items.filterNot { it.isHidden }
|
processes.filterNot { it.isHidden }
|
||||||
} else {
|
} else {
|
||||||
items
|
processes
|
||||||
}.forEach { it.toggle() }
|
}.forEach { it.toggle() }
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
items.forEach { it.addOnPropertyChangedCallback(BR.hidden) { recalculateChecked() } }
|
processes.forEach { it.addOnPropertyChangedCallback(BR.hidden) { recalculateChecked() } }
|
||||||
recalculateChecked()
|
recalculateChecked()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,37 +56,44 @@ class HideItem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun recalculateChecked() {
|
private fun recalculateChecked() {
|
||||||
itemsChecked = items.count { it.isHidden }
|
itemsChecked = processes.count { it.isHidden }
|
||||||
state = when (itemsChecked) {
|
state = when (itemsChecked) {
|
||||||
0 -> false
|
0 -> false
|
||||||
items.size -> true
|
processes.size -> true
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun contentSameAs(other: HideItem): Boolean = item == other.item
|
override fun compareTo(other: HideItem) = comparator.compare(this, other)
|
||||||
override fun itemSameAs(other: HideItem): Boolean = item.info == other.item.info
|
|
||||||
|
companion object {
|
||||||
|
private val comparator = compareBy<HideItem>(
|
||||||
|
{ it.itemsChecked == 0 },
|
||||||
|
{ it.info }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class HideProcessItem(
|
class HideProcessItem(
|
||||||
val item: StatefulProcess,
|
val process: HideProcessInfo
|
||||||
val viewModel: HideViewModel
|
|
||||||
) : ObservableItem<HideProcessItem>() {
|
) : ObservableItem<HideProcessItem>() {
|
||||||
|
|
||||||
override val layoutRes = R.layout.item_hide_process_md2
|
override val layoutRes = R.layout.item_hide_process_md2
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var isHidden = item.isHidden
|
var isHidden = process.isHidden
|
||||||
set(value) = set(value, field, { field = it }, BR.hidden) {
|
set(value) = set(value, field, { field = it }, BR.hidden) {
|
||||||
viewModel.toggleItem(this)
|
val arg = if (isHidden) "add" else "rm"
|
||||||
|
val (name, pkg) = process
|
||||||
|
Shell.su("magiskhide --$arg $pkg $name").submit()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggle() {
|
fun toggle() {
|
||||||
isHidden = !isHidden
|
isHidden = !isHidden
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun contentSameAs(other: HideProcessItem) = item == other.item
|
override fun contentSameAs(other: HideProcessItem) = process == other.process
|
||||||
override fun itemSameAs(other: HideProcessItem) = item.name == other.item.name
|
override fun itemSameAs(other: HideProcessItem) = process.name == other.process.name
|
||||||
|
|
||||||
}
|
}
|
@ -1,14 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.ui.hide
|
|
||||||
|
|
||||||
class HideTarget(line: String) {
|
|
||||||
|
|
||||||
val packageName: String
|
|
||||||
val process: String
|
|
||||||
|
|
||||||
init {
|
|
||||||
val split = line.split(Regex("\\|"), 2)
|
|
||||||
packageName = split[0]
|
|
||||||
process = split.getOrElse(1) { packageName }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.ui.hide
|
package com.topjohnwu.magisk.ui.hide
|
||||||
|
|
||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
@ -9,16 +10,17 @@ import com.topjohnwu.magisk.arch.Queryable
|
|||||||
import com.topjohnwu.magisk.arch.filterableListOf
|
import com.topjohnwu.magisk.arch.filterableListOf
|
||||||
import com.topjohnwu.magisk.arch.itemBindingOf
|
import com.topjohnwu.magisk.arch.itemBindingOf
|
||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.utils.currentLocale
|
import com.topjohnwu.magisk.ktx.get
|
||||||
import com.topjohnwu.magisk.data.repository.MagiskRepository
|
import com.topjohnwu.magisk.ktx.packageInfo
|
||||||
|
import com.topjohnwu.magisk.ktx.packageName
|
||||||
|
import com.topjohnwu.magisk.ktx.processes
|
||||||
import com.topjohnwu.magisk.utils.set
|
import com.topjohnwu.magisk.utils.set
|
||||||
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class HideViewModel(
|
class HideViewModel : BaseViewModel(), Queryable {
|
||||||
private val magiskRepo: MagiskRepository
|
|
||||||
) : BaseViewModel(), Queryable {
|
|
||||||
|
|
||||||
override val queryDelay = 1000L
|
override val queryDelay = 1000L
|
||||||
|
|
||||||
@ -45,63 +47,74 @@ class HideViewModel(
|
|||||||
|
|
||||||
override fun refresh() = viewModelScope.launch {
|
override fun refresh() = viewModelScope.launch {
|
||||||
state = State.LOADING
|
state = State.LOADING
|
||||||
val apps = magiskRepo.fetchApps()
|
val (apps, diff) = withContext(Dispatchers.Default) {
|
||||||
val hides = magiskRepo.fetchHideTargets()
|
val pm = get<PackageManager>()
|
||||||
val (appList, diff) = withContext(Dispatchers.Default) {
|
val hides = Shell.su("magiskhide --ls").exec().out.map { HideTarget(it) }
|
||||||
val list = apps
|
val apps = pm.getInstalledApplications(0)
|
||||||
|
.asSequence()
|
||||||
|
.filter { it.enabled && !blacklist.contains(it.packageName) }
|
||||||
|
.map { HideAppInfo(it, pm) }
|
||||||
.map { createTarget(it, hides) }
|
.map { createTarget(it, hides) }
|
||||||
.map { HideItem(it, this@HideViewModel) }
|
.filter { it.processes.isNotEmpty() }
|
||||||
.sort()
|
.map { HideItem(it) }
|
||||||
list to items.calculateDiff(list)
|
.toList()
|
||||||
|
.sorted()
|
||||||
|
apps to items.calculateDiff(apps)
|
||||||
}
|
}
|
||||||
items.update(appList, diff)
|
items.update(apps, diff)
|
||||||
submitQuery()
|
submitQuery()
|
||||||
state = State.LOADED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
private fun createTarget(app: HideAppInfo, hideList: List<HideTarget>): HideAppTarget {
|
private fun createTarget(info: HideAppInfo, hideList: List<HideTarget>): HideAppTarget {
|
||||||
val hidden = hideList.filter { it.packageName == app.info.packageName }
|
val pkg = info.packageName
|
||||||
val packageName = app.info.packageName
|
val hidden = hideList.filter { it.packageName == pkg }
|
||||||
val processes = app.processes.map { name ->
|
val processNames = info.packageInfo.processes.distinct()
|
||||||
StatefulProcess(name, packageName, hidden.any { name == it.process })
|
val processes = processNames.map { name ->
|
||||||
|
HideProcessInfo(name, pkg, hidden.any { name == it.process })
|
||||||
}
|
}
|
||||||
return HideAppTarget(app, processes)
|
return HideAppTarget(info, processes)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<HideItem>.sort() = compareByDescending<HideItem> { it.itemsChecked != 0 }
|
|
||||||
.thenBy { it.item.info.name.toLowerCase(currentLocale) }
|
|
||||||
.thenBy { it.item.info.info.packageName }
|
|
||||||
.let { sortedWith(it) }
|
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
override fun query() = items.filter {
|
override fun query() {
|
||||||
fun showHidden()= it.itemsChecked != 0
|
items.filter {
|
||||||
|
fun showHidden() = it.itemsChecked != 0
|
||||||
|
|
||||||
fun filterSystem(): Boolean {
|
fun filterSystem() =
|
||||||
return isShowSystem || it.item.info.info.flags and ApplicationInfo.FLAG_SYSTEM == 0
|
isShowSystem || it.info.flags and ApplicationInfo.FLAG_SYSTEM == 0
|
||||||
}
|
|
||||||
|
|
||||||
fun filterQuery(): Boolean {
|
fun filterQuery(): Boolean {
|
||||||
fun inName() = it.item.info.name.contains(query, true)
|
fun inName() = it.info.label.contains(query, true)
|
||||||
fun inPackage() = it.item.info.info.packageName.contains(query, true)
|
fun inPackage() = it.info.packageName.contains(query, true)
|
||||||
fun inProcesses() = it.item.processes.any { it.name.contains(query, true) }
|
fun inProcesses() = it.processes.any { p -> p.process.name.contains(query, true) }
|
||||||
return inName() || inPackage() || inProcesses()
|
return inName() || inPackage() || inProcesses()
|
||||||
}
|
}
|
||||||
|
|
||||||
showHidden() || (filterSystem() && filterQuery())
|
showHidden() || (filterSystem() && filterQuery())
|
||||||
}
|
}
|
||||||
|
state = State.LOADED
|
||||||
|
}
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
fun toggleItem(item: HideProcessItem) {
|
|
||||||
magiskRepo.toggleHide(item.isHidden, item.item.packageName, item.item.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun resetQuery() {
|
fun resetQuery() {
|
||||||
query = ""
|
query = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val blacklist by lazy { listOf(
|
||||||
|
packageName,
|
||||||
|
"android",
|
||||||
|
"com.android.chrome",
|
||||||
|
"com.chrome.beta",
|
||||||
|
"com.chrome.dev",
|
||||||
|
"com.chrome.canary",
|
||||||
|
"com.android.webview",
|
||||||
|
"com.google.android.webview"
|
||||||
|
) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,12 +39,12 @@
|
|||||||
android:id="@+id/hide_icon"
|
android:id="@+id/hide_icon"
|
||||||
style="@style/WidgetFoundation.Image"
|
style="@style/WidgetFoundation.Image"
|
||||||
android:layout_margin="@dimen/l1"
|
android:layout_margin="@dimen/l1"
|
||||||
android:src="@{item.item.info.icon}"
|
android:src="@{item.info.iconImage}"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintVertical_bias="0"
|
app:layout_constraintVertical_bias="0"
|
||||||
tools:src="@drawable/ic_magisk" />
|
tools:src="@drawable/ic_launcher" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/hide_name"
|
android:id="@+id/hide_name"
|
||||||
@ -53,7 +53,7 @@
|
|||||||
android:layout_marginStart="@dimen/l1"
|
android:layout_marginStart="@dimen/l1"
|
||||||
android:ellipsize="middle"
|
android:ellipsize="middle"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:text="@{item.item.info.name}"
|
android:text="@{item.info.label}"
|
||||||
android:textAppearance="@style/AppearanceFoundation.Body"
|
android:textAppearance="@style/AppearanceFoundation.Body"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/hide_package"
|
app:layout_constraintBottom_toTopOf="@+id/hide_package"
|
||||||
@ -65,10 +65,9 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/hide_package"
|
android:id="@+id/hide_package"
|
||||||
gone="@{item.item.info.info.packageName.empty}"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@{item.item.info.info.packageName}"
|
android:text="@{item.info.packageName}"
|
||||||
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="@+id/hide_name"
|
app:layout_constraintEnd_toEndOf="@+id/hide_name"
|
||||||
@ -90,7 +89,7 @@
|
|||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
goneUnless="@{item.isExpanded}"
|
goneUnless="@{item.isExpanded}"
|
||||||
itemBinding="@{viewModel.itemInternalBinding}"
|
itemBinding="@{viewModel.itemInternalBinding}"
|
||||||
items="@{item.items}"
|
items="@{item.processes}"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?colorSurfaceVariant"
|
android:background="?colorSurfaceVariant"
|
||||||
@ -105,7 +104,7 @@
|
|||||||
style="@style/WidgetFoundation.ProgressBar"
|
style="@style/WidgetFoundation.ProgressBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_gravity="top"
|
android:layout_gravity="top"
|
||||||
android:progress="@{item.itemsCheckedPercent}" />
|
android:progress="@{item.checkedPercent}" />
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
@ -29,7 +29,8 @@
|
|||||||
android:layout_marginEnd="@dimen/l1"
|
android:layout_marginEnd="@dimen/l1"
|
||||||
android:layout_marginBottom="@dimen/l_75"
|
android:layout_marginBottom="@dimen/l_75"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:text="@{item.item.name}"
|
android:ellipsize="middle"
|
||||||
|
android:text="@{item.process.name}"
|
||||||
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/hide_process_checkbox"
|
app:layout_constraintEnd_toStartOf="@+id/hide_process_checkbox"
|
||||||
|
Loading…
Reference in New Issue
Block a user