Added implementation of hide screen
Very much wip and doesn't work at all
This commit is contained in:
parent
722fba7805
commit
f76c020dd7
@ -17,7 +17,7 @@ import org.koin.dsl.module
|
|||||||
|
|
||||||
val redesignModule = module {
|
val redesignModule = module {
|
||||||
viewModel { FlashViewModel() }
|
viewModel { FlashViewModel() }
|
||||||
viewModel { HideViewModel() }
|
viewModel { HideViewModel(get(), get()) }
|
||||||
viewModel { HomeViewModel(get()) }
|
viewModel { HomeViewModel(get()) }
|
||||||
viewModel { LogViewModel() }
|
viewModel { LogViewModel() }
|
||||||
viewModel { ModuleViewModel() }
|
viewModel { ModuleViewModel() }
|
||||||
|
@ -197,5 +197,8 @@ fun <T> ObservableField<T>.toObservable(): Observable<T> {
|
|||||||
|
|
||||||
fun <T : Any> T.toSingle() = Single.just(this)
|
fun <T : Any> T.toSingle() = Single.just(this)
|
||||||
|
|
||||||
fun <T1, T2, R> zip(t1: Single<T1>, t2: Single<T2>, zipper: (T1, T2) -> R) =
|
inline fun <T1, T2, R> zip(
|
||||||
Single.zip(t1, t2, BiFunction<T1, T2, R> { rt1, rt2 -> zipper(rt1, rt2) })
|
t1: Single<T1>,
|
||||||
|
t2: Single<T2>,
|
||||||
|
crossinline zipper: (T1, T2) -> R
|
||||||
|
) = Single.zip(t1, t2, BiFunction<T1, T2, R> { rt1, rt2 -> zipper(rt1, rt2) })
|
@ -14,3 +14,13 @@ class HideAppInfo(
|
|||||||
val processes = info.packageInfo?.processes?.distinct() ?: listOf(info.packageName)
|
val processes = info.packageInfo?.processes?.distinct() ?: listOf(info.packageName)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class StatefulProcess(
|
||||||
|
val name: String,
|
||||||
|
val isHidden: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
class ProcessHideApp(
|
||||||
|
val info: HideAppInfo,
|
||||||
|
val processes: List<StatefulProcess>
|
||||||
|
)
|
@ -1,18 +1,69 @@
|
|||||||
package com.topjohnwu.magisk.model.entity.recycler
|
package com.topjohnwu.magisk.model.entity.recycler
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||||
import com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
|
import com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
|
||||||
import com.topjohnwu.magisk.extensions.inject
|
import com.topjohnwu.magisk.extensions.inject
|
||||||
|
import com.topjohnwu.magisk.extensions.startAnimations
|
||||||
import com.topjohnwu.magisk.extensions.toggle
|
import com.topjohnwu.magisk.extensions.toggle
|
||||||
import com.topjohnwu.magisk.model.entity.HideAppInfo
|
import com.topjohnwu.magisk.model.entity.HideAppInfo
|
||||||
import com.topjohnwu.magisk.model.entity.HideTarget
|
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.state.IndeterminateState
|
import com.topjohnwu.magisk.model.entity.state.IndeterminateState
|
||||||
import com.topjohnwu.magisk.model.events.HideProcessEvent
|
import com.topjohnwu.magisk.model.events.HideProcessEvent
|
||||||
import com.topjohnwu.magisk.utils.DiffObservableList
|
import com.topjohnwu.magisk.utils.DiffObservableList
|
||||||
import com.topjohnwu.magisk.utils.KObservableField
|
import com.topjohnwu.magisk.utils.KObservableField
|
||||||
import com.topjohnwu.magisk.utils.RxBus
|
import com.topjohnwu.magisk.utils.RxBus
|
||||||
|
|
||||||
|
class HideItem(val item: ProcessHideApp) : ComparableRvItem<HideItem>() {
|
||||||
|
|
||||||
|
override val layoutRes = R.layout.item_hide_md2
|
||||||
|
|
||||||
|
val items = item.processes.map { HideProcessItem(it) }
|
||||||
|
|
||||||
|
val isExpanded = KObservableField(false)
|
||||||
|
val itemsChecked = KObservableField(0)
|
||||||
|
val isHidden get() = itemsChecked.value == items.size
|
||||||
|
|
||||||
|
init {
|
||||||
|
items.forEach { it.isHidden.addOnPropertyChangedCallback { recalculateChecked() } }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun collapse(v: View) {
|
||||||
|
(v.parent.parent as? ViewGroup)?.startAnimations()
|
||||||
|
isExpanded.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun expand(v: View) {
|
||||||
|
(v.parent as? ViewGroup)?.startAnimations()
|
||||||
|
isExpanded.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun recalculateChecked() {
|
||||||
|
itemsChecked.value = items.count { it.isHidden.value }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun contentSameAs(other: HideItem): Boolean = item == other.item
|
||||||
|
override fun itemSameAs(other: HideItem): Boolean = item.info == other.item.info
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class HideProcessItem(val item: StatefulProcess) : ComparableRvItem<HideProcessItem>() {
|
||||||
|
|
||||||
|
override val layoutRes = R.layout.item_hide_process_md2
|
||||||
|
|
||||||
|
val isHidden = KObservableField(item.isHidden)
|
||||||
|
|
||||||
|
fun toggle() = isHidden.toggle()
|
||||||
|
|
||||||
|
override fun contentSameAs(other: HideProcessItem) = item == other.item
|
||||||
|
override fun itemSameAs(other: HideProcessItem) = item.name == other.item.name
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class HideRvItem(val item: HideAppInfo, targets: List<HideTarget>) :
|
class HideRvItem(val item: HideAppInfo, targets: List<HideTarget>) :
|
||||||
ComparableRvItem<HideRvItem>() {
|
ComparableRvItem<HideRvItem>() {
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.topjohnwu.magisk.redesign.hide
|
package com.topjohnwu.magisk.redesign.hide
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.Insets
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.databinding.FragmentHideMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentHideMd2Binding
|
||||||
import com.topjohnwu.magisk.redesign.compat.CompatFragment
|
import com.topjohnwu.magisk.redesign.compat.CompatFragment
|
||||||
@ -11,6 +12,8 @@ class HideFragment : CompatFragment<HideViewModel, FragmentHideMd2Binding>() {
|
|||||||
override val layoutRes = R.layout.fragment_hide_md2
|
override val layoutRes = R.layout.fragment_hide_md2
|
||||||
override val viewModel by viewModel<HideViewModel>()
|
override val viewModel by viewModel<HideViewModel>()
|
||||||
|
|
||||||
|
override fun consumeSystemWindowInsets(insets: Insets) = insets
|
||||||
|
|
||||||
override fun onAttach(context: Context) {
|
override fun onAttach(context: Context) {
|
||||||
super.onAttach(context)
|
super.onAttach(context)
|
||||||
|
|
||||||
|
@ -1,5 +1,124 @@
|
|||||||
package com.topjohnwu.magisk.redesign.hide
|
package com.topjohnwu.magisk.redesign.hide
|
||||||
|
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import com.topjohnwu.magisk.BR
|
||||||
|
import com.topjohnwu.magisk.data.repository.MagiskRepository
|
||||||
|
import com.topjohnwu.magisk.extensions.subscribeK
|
||||||
|
import com.topjohnwu.magisk.extensions.toSingle
|
||||||
|
import com.topjohnwu.magisk.model.entity.HideAppInfo
|
||||||
|
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
|
||||||
|
import com.topjohnwu.magisk.model.entity.recycler.HideProcessRvItem
|
||||||
|
import com.topjohnwu.magisk.model.events.HideProcessEvent
|
||||||
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
|
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.utils.KObservableField
|
||||||
|
import com.topjohnwu.magisk.utils.RxBus
|
||||||
|
import com.topjohnwu.magisk.utils.currentLocale
|
||||||
|
import io.reactivex.disposables.Disposable
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class HideViewModel : CompatViewModel()
|
class HideViewModel(
|
||||||
|
private val magiskRepo: MagiskRepository,
|
||||||
|
rxBus: RxBus
|
||||||
|
) : CompatViewModel() {
|
||||||
|
|
||||||
|
@Volatile
|
||||||
|
private var cache = listOf<HideItem>()
|
||||||
|
set(value) {
|
||||||
|
field = Collections.synchronizedList(value)
|
||||||
|
}
|
||||||
|
private var queryJob: Disposable? = null
|
||||||
|
set(value) {
|
||||||
|
field?.dispose()
|
||||||
|
field = value
|
||||||
|
}
|
||||||
|
|
||||||
|
val query = KObservableField("")
|
||||||
|
val isShowSystem = KObservableField(true)
|
||||||
|
val items = diffListOf<HideItem>()
|
||||||
|
val itemBinding = itemBindingOf<HideItem> {
|
||||||
|
it.bindExtra(BR.viewModel, this)
|
||||||
|
}
|
||||||
|
val itemInternalBinding = itemBindingOf<HideProcessItem> {
|
||||||
|
it.bindExtra(BR.viewModel, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
rxBus.register<HideProcessEvent>()
|
||||||
|
.subscribeK { toggleItem(it.item) }
|
||||||
|
.add()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refresh() = magiskRepo.fetchApps()
|
||||||
|
.map { it to magiskRepo.fetchHideTargets().blockingGet() }
|
||||||
|
.map { pair -> pair.first.map { mergeAppTargets(it, pair.second) } }
|
||||||
|
.flattenAsFlowable { it }
|
||||||
|
.map { HideItem(it) }
|
||||||
|
.toList()
|
||||||
|
.map { it.sort() }
|
||||||
|
.subscribeK {
|
||||||
|
cache = it
|
||||||
|
queryIfNecessary()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
queryJob?.dispose()
|
||||||
|
super.onCleared()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
private fun mergeAppTargets(a: HideAppInfo, ts: List<HideTarget>): ProcessHideApp {
|
||||||
|
val relevantTargets = ts.filter { it.packageName == a.info.packageName }
|
||||||
|
val processes = a.processes
|
||||||
|
.map { StatefulProcess(it, relevantTargets.any { i -> it == i.process }) }
|
||||||
|
return ProcessHideApp(a, processes)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun List<HideItem>.sort() = sortedWith(compareBy(
|
||||||
|
{ it.isHidden },
|
||||||
|
{ it.item.info.name.toLowerCase(currentLocale) },
|
||||||
|
{ it.item.info.info.packageName }
|
||||||
|
))
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
/** We don't need to re-query when the app count matches. */
|
||||||
|
private fun queryIfNecessary() {
|
||||||
|
if (items.size != cache.size) {
|
||||||
|
query()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun query(
|
||||||
|
query: String = this.query.value,
|
||||||
|
showSystem: Boolean = isShowSystem.value
|
||||||
|
) = cache.toSingle()
|
||||||
|
.flattenAsFlowable { it }
|
||||||
|
.parallel()
|
||||||
|
.filter { showSystem || it.item.info.info.flags and ApplicationInfo.FLAG_SYSTEM == 0 }
|
||||||
|
.filter {
|
||||||
|
val inName = it.item.info.name.contains(query, true)
|
||||||
|
val inPackage = it.item.info.info.packageName.contains(query, true)
|
||||||
|
val inProcesses = it.item.processes.any { it.name.contains(query, true) }
|
||||||
|
inName || inPackage || inProcesses
|
||||||
|
}
|
||||||
|
.sequential()
|
||||||
|
.toList()
|
||||||
|
.map { it to items.calculateDiff(it) }
|
||||||
|
.subscribeK { items.update(it.first, it.second) }
|
||||||
|
.let { queryJob = it }
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
private fun toggleItem(item: HideProcessRvItem) = magiskRepo
|
||||||
|
.toggleHide(item.isHidden.value, item.packageName, item.process)
|
||||||
|
.subscribeK()
|
||||||
|
.add()
|
||||||
|
|
||||||
|
}
|
@ -22,6 +22,27 @@
|
|||||||
</vector>
|
</vector>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/collapsed_selected"
|
||||||
|
android:state_selected="true">
|
||||||
|
<vector
|
||||||
|
android:name="vector"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<group
|
||||||
|
android:name="group"
|
||||||
|
android:pivotX="12"
|
||||||
|
android:pivotY="12">
|
||||||
|
<path
|
||||||
|
android:name="path"
|
||||||
|
android:fillColor="#000"
|
||||||
|
android:pathData="M 12 2 C 9.349 2 6.804 3.054 4.929 4.929 C 3.054 6.804 2 9.349 2 12 C 2 14.651 3.054 17.196 4.929 19.071 C 6.804 20.946 9.349 22 12 22 C 13.755 22 15.48 21.538 17 20.66 C 18.52 19.783 19.783 18.52 20.66 17 C 21.538 15.48 22 13.755 22 12 C 22 10.245 21.538 8.52 20.66 7 C 19.783 5.48 18.52 4.217 17 3.34 C 15.48 2.462 13.755 2 12 2 Z" />
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
|
</item>
|
||||||
|
|
||||||
<item android:id="@+id/expanded">
|
<item android:id="@+id/expanded">
|
||||||
<vector
|
<vector
|
||||||
android:name="vector"
|
android:name="vector"
|
||||||
@ -52,4 +73,14 @@
|
|||||||
android:fromId="@+id/collapsed"
|
android:fromId="@+id/collapsed"
|
||||||
android:toId="@id/expanded" />
|
android:toId="@id/expanded" />
|
||||||
|
|
||||||
|
<transition
|
||||||
|
android:drawable="@drawable/avd_circle_from_filled"
|
||||||
|
android:fromId="@+id/expanded"
|
||||||
|
android:toId="@+id/collapsed_selected" />
|
||||||
|
|
||||||
|
<transition
|
||||||
|
android:drawable="@drawable/avd_circle_to_filled"
|
||||||
|
android:fromId="@+id/collapsed_selected"
|
||||||
|
android:toId="@id/expanded" />
|
||||||
|
|
||||||
</animated-selector>
|
</animated-selector>
|
@ -1,23 +1,32 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
|
|
||||||
|
<import type="com.topjohnwu.magisk.R" />
|
||||||
|
|
||||||
<variable
|
<variable
|
||||||
name="viewModel"
|
name="viewModel"
|
||||||
type="com.topjohnwu.magisk.redesign.hide.HideViewModel" />
|
type="com.topjohnwu.magisk.redesign.hide.HideViewModel" />
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
dividerVertical="@{R.drawable.divider_l1}"
|
||||||
|
itemBinding="@{viewModel.itemBinding}"
|
||||||
|
items="@{viewModel.items}"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fillViewport="true">
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical"
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
android:paddingStart="@dimen/l1"
|
||||||
android:layout_width="match_parent"
|
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size + (int) @dimen/l1}"
|
||||||
android:layout_height="wrap_content" />
|
android:paddingEnd="@dimen/l1"
|
||||||
|
android:paddingBottom="@{viewModel.insets.bottom}"
|
||||||
</androidx.core.widget.NestedScrollView>
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
tools:listitem="@layout/item_hide_md2"
|
||||||
|
tools:paddingTop="40dp" />
|
||||||
|
|
||||||
</layout>
|
</layout>
|
118
app/src/main/res/layout/item_hide_md2.xml
Normal file
118
app/src/main/res/layout/item_hide_md2.xml
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="item"
|
||||||
|
type="com.topjohnwu.magisk.model.entity.recycler.HideItem" />
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="viewModel"
|
||||||
|
type="com.topjohnwu.magisk.redesign.hide.HideViewModel" />
|
||||||
|
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
style="?styleCardNormal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:layout_gravity="center"
|
||||||
|
tools:layout_marginBottom="@dimen/l1">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
invisible="@{item.isExpanded}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?selectableItemBackground"
|
||||||
|
android:onClick="@{(v) -> item.expand(v)}">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/hide_icon"
|
||||||
|
style="?styleImageNormal"
|
||||||
|
android:layout_margin="@dimen/l1"
|
||||||
|
android:src="@{item.item.info.icon}"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:src="@drawable/ic_magisk" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/hide_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/l1"
|
||||||
|
android:ellipsize="middle"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@{item.item.info.name}"
|
||||||
|
android:textAppearance="?appearanceTextBodyNormal"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/hide_package"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/hide_expand_icon"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/hide_icon"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_chainStyle="packed"
|
||||||
|
tools:text="@string/app_name" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/hide_package"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?appearanceTextCaptionVariant"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="@+id/hide_name"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/hide_name"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/hide_name"
|
||||||
|
tools:text="com.topjohnwu.magisk" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/hide_expand_icon"
|
||||||
|
style="?styleIconNormal"
|
||||||
|
invisible="@{item.item.processes.empty}"
|
||||||
|
android:background="@null"
|
||||||
|
android:rotation="180"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/ic_back_md2" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
goneUnless="@{item.isExpanded}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
style="?styleToolbar"
|
||||||
|
onNavigationClick="@{(v) -> item.collapse(v)}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
app:navigationIcon="@drawable/ic_back_md2"
|
||||||
|
app:title="Processes"
|
||||||
|
app:titleTextAppearance="?appearanceTextBodyNormal" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
itemBinding="@{viewModel.itemInternalBinding}"
|
||||||
|
items="@{item.items}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
tools:listitem="@layout/item_hide_process_md2" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
style="?styleProgressDeterminate"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_gravity="top"
|
||||||
|
android:max="@{item.items.size()}"
|
||||||
|
android:progress="@{item.itemsChecked}" />
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
</layout>
|
56
app/src/main/res/layout/item_hide_process_md2.xml
Normal file
56
app/src/main/res/layout/item_hide_process_md2.xml
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="item"
|
||||||
|
type="com.topjohnwu.magisk.model.entity.recycler.HideProcessItem" />
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="viewModel"
|
||||||
|
type="com.topjohnwu.magisk.redesign.hide.HideViewModel" />
|
||||||
|
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/l1"
|
||||||
|
android:layout_marginTop="@dimen/l_50"
|
||||||
|
android:layout_marginEnd="@dimen/l1"
|
||||||
|
android:layout_marginBottom="@dimen/l_50"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="@{item.item.name}"
|
||||||
|
android:textAppearance="?appearanceTextCaptionVariant"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/hide_process_checkbox"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="com.topjohnwu.magisk" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/hide_process_checkbox"
|
||||||
|
style="?styleImageSmall"
|
||||||
|
isSelected="@{item.isHidden}"
|
||||||
|
android:layout_marginTop="@dimen/l_50"
|
||||||
|
android:layout_marginEnd="@dimen/l1"
|
||||||
|
android:layout_marginBottom="@dimen/l_50"
|
||||||
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
|
android:onClick="@{() -> item.toggle()}"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/ic_radio_check_button"
|
||||||
|
app:tint="?colorPrimary" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</layout>
|
Loading…
Reference in New Issue
Block a user