Updated policy (apps) layout to be more compact
Added pinch in to increase list span count / out to decrease The setting will be remembered across the whole app (every list that uses Staggered Grid) Updated indication of whether the policy has root access enabled permitted or not Displays crossed out app logo if not permitted
This commit is contained in:
parent
eb929160b3
commit
8737be2623
@ -55,6 +55,7 @@ object Config : PreferenceModel, DBConfig {
|
|||||||
const val SAFETY = "safety_notice"
|
const val SAFETY = "safety_notice"
|
||||||
const val THEME_ORDINAL = "theme_ordinal"
|
const val THEME_ORDINAL = "theme_ordinal"
|
||||||
const val BOOT_ID = "boot_id"
|
const val BOOT_ID = "boot_id"
|
||||||
|
const val LIST_SPAN_COUNT = "list_span_count"
|
||||||
|
|
||||||
// system state
|
// system state
|
||||||
const val MAGISKHIDE = "magiskhide"
|
const val MAGISKHIDE = "magiskhide"
|
||||||
@ -109,8 +110,7 @@ object Config : PreferenceModel, DBConfig {
|
|||||||
Value.CANARY_DEBUG_CHANNEL
|
Value.CANARY_DEBUG_CHANNEL
|
||||||
else
|
else
|
||||||
Value.CANARY_CHANNEL
|
Value.CANARY_CHANNEL
|
||||||
}
|
} else Value.DEFAULT_CHANNEL
|
||||||
else Value.DEFAULT_CHANNEL
|
|
||||||
|
|
||||||
var bootId by preference(Key.BOOT_ID, "")
|
var bootId by preference(Key.BOOT_ID, "")
|
||||||
|
|
||||||
@ -137,6 +137,7 @@ object Config : PreferenceModel, DBConfig {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
var coreOnly by preference(Key.COREONLY, false)
|
var coreOnly by preference(Key.COREONLY, false)
|
||||||
var showSystemApp by preference(Key.SHOW_SYSTEM_APP, false)
|
var showSystemApp by preference(Key.SHOW_SYSTEM_APP, false)
|
||||||
|
var listSpanCount by preference(Key.LIST_SPAN_COUNT, 2)
|
||||||
|
|
||||||
var customChannelUrl by preference(Key.CUSTOM_CHANNEL, "")
|
var customChannelUrl by preference(Key.CUSTOM_CHANNEL, "")
|
||||||
var locale by preference(Key.LOCALE, "")
|
var locale by preference(Key.LOCALE, "")
|
||||||
@ -149,8 +150,9 @@ object Config : PreferenceModel, DBConfig {
|
|||||||
var keyStoreRaw by dbStrings(Key.KEYSTORE, "", true)
|
var keyStoreRaw by dbStrings(Key.KEYSTORE, "", true)
|
||||||
|
|
||||||
// Always return a path in external storage where we can write
|
// Always return a path in external storage where we can write
|
||||||
val downloadDirectory get() =
|
val downloadDirectory
|
||||||
Utils.ensureDownloadPath(downloadPath) ?: get<Context>().getExternalFilesDir(null)!!
|
get() =
|
||||||
|
Utils.ensureDownloadPath(downloadPath) ?: get<Context>().getExternalFilesDir(null)!!
|
||||||
|
|
||||||
private const val SU_FINGERPRINT = "su_fingerprint"
|
private const val SU_FINGERPRINT = "su_fingerprint"
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.model.entity.recycler
|
package com.topjohnwu.magisk.model.entity.recycler
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
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
|
||||||
@ -14,8 +12,6 @@ import com.topjohnwu.magisk.model.events.PolicyUpdateEvent
|
|||||||
import com.topjohnwu.magisk.redesign.superuser.SuperuserViewModel
|
import com.topjohnwu.magisk.redesign.superuser.SuperuserViewModel
|
||||||
import com.topjohnwu.magisk.utils.KObservableField
|
import com.topjohnwu.magisk.utils.KObservableField
|
||||||
import com.topjohnwu.magisk.utils.RxBus
|
import com.topjohnwu.magisk.utils.RxBus
|
||||||
import com.topjohnwu.magisk.utils.rotationTo
|
|
||||||
import com.topjohnwu.magisk.utils.setRevealed
|
|
||||||
|
|
||||||
class PolicyRvItem(val item: MagiskPolicy, val icon: Drawable) : ComparableRvItem<PolicyRvItem>() {
|
class PolicyRvItem(val item: MagiskPolicy, val icon: Drawable) : ComparableRvItem<PolicyRvItem>() {
|
||||||
|
|
||||||
@ -73,18 +69,15 @@ class PolicyItem(val item: MagiskPolicy, val icon: Drawable) : ComparableRvItem<
|
|||||||
|
|
||||||
fun toggle(viewModel: SuperuserViewModel) {
|
fun toggle(viewModel: SuperuserViewModel) {
|
||||||
if (isExpanded.value) {
|
if (isExpanded.value) {
|
||||||
|
toggle()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isEnabled.toggle()
|
isEnabled.toggle()
|
||||||
viewModel.togglePolicy(this, isEnabled.value)
|
viewModel.togglePolicy(this, isEnabled.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggle(view: View) {
|
fun toggle() {
|
||||||
isExpanded.toggle()
|
isExpanded.toggle()
|
||||||
view.rotationTo(if (isExpanded.value) 225 else 180)
|
|
||||||
(view.parent as ViewGroup)
|
|
||||||
.findViewById<View>(R.id.policy_expand_container)
|
|
||||||
.setRevealed(isExpanded.value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleNotify(viewModel: SuperuserViewModel) {
|
fun toggleNotify(viewModel: SuperuserViewModel) {
|
||||||
|
@ -19,6 +19,7 @@ import com.topjohnwu.magisk.redesign.compat.CompatFragment
|
|||||||
import com.topjohnwu.magisk.redesign.compat.hideKeyboard
|
import com.topjohnwu.magisk.redesign.compat.hideKeyboard
|
||||||
import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener
|
import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener
|
||||||
import com.topjohnwu.magisk.utils.MotionRevealHelper
|
import com.topjohnwu.magisk.utils.MotionRevealHelper
|
||||||
|
import com.topjohnwu.magisk.utils.PinchZoomTouchListener
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
|
|
||||||
class ModuleFragment : CompatFragment<ModuleViewModel, FragmentModuleMd2Binding>(),
|
class ModuleFragment : CompatFragment<ModuleViewModel, FragmentModuleMd2Binding>(),
|
||||||
@ -67,13 +68,18 @@ class ModuleFragment : CompatFragment<ModuleViewModel, FragmentModuleMd2Binding>
|
|||||||
if (newState != RecyclerView.SCROLL_STATE_IDLE) hideKeyboard()
|
if (newState != RecyclerView.SCROLL_STATE_IDLE) hideKeyboard()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
PinchZoomTouchListener.attachTo(binding.moduleFilterInclude.moduleFilterList)
|
||||||
|
PinchZoomTouchListener.attachTo(binding.moduleList)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
binding.moduleRemote.removeOnScrollListener(it)
|
binding.moduleList.removeOnScrollListener(it)
|
||||||
binding.moduleFilterInclude.moduleFilterList.removeOnScrollListener(it)
|
binding.moduleFilterInclude.moduleFilterList.removeOnScrollListener(it)
|
||||||
}
|
}
|
||||||
|
PinchZoomTouchListener.clear(binding.moduleList)
|
||||||
|
PinchZoomTouchListener.clear(binding.moduleFilterInclude.moduleFilterList)
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,14 +107,14 @@ class ModuleFragment : CompatFragment<ModuleViewModel, FragmentModuleMd2Binding>
|
|||||||
// ---
|
// ---
|
||||||
|
|
||||||
override fun onReselected() {
|
override fun onReselected() {
|
||||||
binding.moduleRemote
|
binding.moduleList
|
||||||
.takeIf {
|
.takeIf {
|
||||||
(it.layoutManager as? StaggeredGridLayoutManager)?.let {
|
(it.layoutManager as? StaggeredGridLayoutManager)?.let {
|
||||||
it.findFirstVisibleItemPositions(IntArray(it.spanCount)).min()
|
it.findFirstVisibleItemPositions(IntArray(it.spanCount)).min()
|
||||||
} ?: 0 > 10
|
} ?: 0 > 10
|
||||||
}
|
}
|
||||||
?.also { it.scrollToPosition(10) }
|
?.also { it.scrollToPosition(10) }
|
||||||
.let { binding.moduleRemote }
|
.let { binding.moduleList }
|
||||||
.also { it.post { it.smoothScrollToPosition(0) } }
|
.also { it.post { it.smoothScrollToPosition(0) } }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,11 +123,11 @@ class ModuleFragment : CompatFragment<ModuleViewModel, FragmentModuleMd2Binding>
|
|||||||
override fun onPreBind(binding: FragmentModuleMd2Binding) = Unit
|
override fun onPreBind(binding: FragmentModuleMd2Binding) = Unit
|
||||||
|
|
||||||
private fun setEndlessScroller() {
|
private fun setEndlessScroller() {
|
||||||
val lama = binding.moduleRemote.layoutManager ?: return
|
val lama = binding.moduleList.layoutManager ?: return
|
||||||
lama.isAutoMeasureEnabled = false
|
lama.isAutoMeasureEnabled = false
|
||||||
|
|
||||||
val listener = EndlessRecyclerScrollListener(lama, viewModel::loadRemote)
|
val listener = EndlessRecyclerScrollListener(lama, viewModel::loadRemote)
|
||||||
binding.moduleRemote.addOnScrollListener(listener)
|
binding.moduleList.addOnScrollListener(listener)
|
||||||
listeners.add(listener)
|
listeners.add(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package com.topjohnwu.magisk.redesign.settings
|
package com.topjohnwu.magisk.redesign.settings
|
||||||
|
|
||||||
import android.graphics.Insets
|
import android.graphics.Insets
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.databinding.FragmentSettingsMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentSettingsMd2Binding
|
||||||
import com.topjohnwu.magisk.redesign.compat.CompatFragment
|
import com.topjohnwu.magisk.redesign.compat.CompatFragment
|
||||||
|
import com.topjohnwu.magisk.utils.PinchZoomTouchListener
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
|
|
||||||
class SettingsFragment : CompatFragment<SettingsViewModel, FragmentSettingsMd2Binding>() {
|
class SettingsFragment : CompatFragment<SettingsViewModel, FragmentSettingsMd2Binding>() {
|
||||||
@ -19,6 +22,16 @@ class SettingsFragment : CompatFragment<SettingsViewModel, FragmentSettingsMd2Bi
|
|||||||
activity.title = resources.getString(R.string.section_settings)
|
activity.title = resources.getString(R.string.section_settings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
PinchZoomTouchListener.attachTo(binding.settingsList)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
PinchZoomTouchListener.clear(binding.settingsList)
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
viewModel.items.forEach { it.refresh() }
|
viewModel.items.forEach { it.refresh() }
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
package com.topjohnwu.magisk.redesign.superuser
|
package com.topjohnwu.magisk.redesign.superuser
|
||||||
|
|
||||||
import android.graphics.Insets
|
import android.graphics.Insets
|
||||||
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.databinding.FragmentSuperuserMd2Binding
|
import com.topjohnwu.magisk.databinding.FragmentSuperuserMd2Binding
|
||||||
import com.topjohnwu.magisk.model.navigation.Navigation
|
import com.topjohnwu.magisk.model.navigation.Navigation
|
||||||
import com.topjohnwu.magisk.redesign.compat.CompatFragment
|
import com.topjohnwu.magisk.redesign.compat.CompatFragment
|
||||||
|
import com.topjohnwu.magisk.utils.PinchZoomTouchListener
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
|
|
||||||
class SuperuserFragment : CompatFragment<SuperuserViewModel, FragmentSuperuserMd2Binding>() {
|
class SuperuserFragment : CompatFragment<SuperuserViewModel, FragmentSuperuserMd2Binding>() {
|
||||||
@ -23,6 +26,16 @@ class SuperuserFragment : CompatFragment<SuperuserViewModel, FragmentSuperuserMd
|
|||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
PinchZoomTouchListener.attachTo(binding.superuserList)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
PinchZoomTouchListener.clear(binding.superuserList)
|
||||||
|
super.onDestroyView()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
inflater.inflate(R.menu.menu_superuser_md2, menu)
|
inflater.inflate(R.menu.menu_superuser_md2, menu)
|
||||||
}
|
}
|
||||||
|
@ -449,3 +449,11 @@ fun View.setRotationNotAnimated(rotation: Int) {
|
|||||||
fun TextView.setTextSafe(text: Int) {
|
fun TextView.setTextSafe(text: Int) {
|
||||||
if (text == 0) this.text = null else setText(text)
|
if (text == 0) this.text = null else setText(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BindingAdapter("android:onLongClick")
|
||||||
|
fun View.setOnLongClickListenerBinding(listener: () -> Unit) {
|
||||||
|
setOnLongClickListener {
|
||||||
|
listener()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.topjohnwu.magisk.utils
|
||||||
|
|
||||||
|
import android.view.ScaleGestureDetector
|
||||||
|
|
||||||
|
abstract class PinchGestureCallback : ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
||||||
|
|
||||||
|
private var startFactor: Float = 1f
|
||||||
|
|
||||||
|
override fun onScaleBegin(detector: ScaleGestureDetector?): Boolean {
|
||||||
|
startFactor = detector?.scaleFactor ?: 1f
|
||||||
|
return super.onScaleBegin(detector)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onScaleEnd(detector: ScaleGestureDetector?) {
|
||||||
|
val endFactor = detector?.scaleFactor ?: 1f
|
||||||
|
|
||||||
|
if (endFactor > startFactor) onZoom()
|
||||||
|
else if (endFactor < startFactor) onPinch()
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun onPinch()
|
||||||
|
abstract fun onZoom()
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package com.topjohnwu.magisk.utils
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.ScaleGestureDetector
|
||||||
|
import android.view.View
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
||||||
|
import androidx.transition.TransitionManager
|
||||||
|
import com.topjohnwu.magisk.Config
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
class PinchZoomTouchListener private constructor(
|
||||||
|
private val view: RecyclerView,
|
||||||
|
private val max: Int = 3,
|
||||||
|
private val min: Int = 1
|
||||||
|
) : View.OnTouchListener {
|
||||||
|
|
||||||
|
private val layoutManager
|
||||||
|
get() = view.layoutManager
|
||||||
|
|
||||||
|
private val pinchListener = object : PinchGestureCallback() {
|
||||||
|
override fun onPinch() = updateSpanCount(Config.listSpanCount + 1)
|
||||||
|
override fun onZoom() = updateSpanCount(Config.listSpanCount - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val gestureDetector by lazy { ScaleGestureDetector(view.context, pinchListener) }
|
||||||
|
|
||||||
|
init {
|
||||||
|
updateSpanCount(Config.listSpanCount, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
|
||||||
|
gestureDetector.onTouchEvent(event)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateSpanCount(count: Int, animate: Boolean = true) {
|
||||||
|
if (animate) {
|
||||||
|
TransitionManager.beginDelayedTransition(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
val boundCount = max(min, min(max, count))
|
||||||
|
|
||||||
|
when (val l = layoutManager) {
|
||||||
|
is StaggeredGridLayoutManager -> l.spanCount = boundCount
|
||||||
|
is GridLayoutManager -> l.spanCount = boundCount
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
Config.listSpanCount = boundCount
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
fun attachTo(view: RecyclerView) = view.setOnTouchListener(PinchZoomTouchListener(view))
|
||||||
|
|
||||||
|
fun clear(view: View) = view.setOnTouchListener(null)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
app/src/main/res/drawable/ic_notifications_md2.xml
Normal file
10
app/src/main/res/drawable/ic_notifications_md2.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="?colorOnSurface"
|
||||||
|
android:pathData="M16,17H7V10.5C7,8 9,6 11.5,6C14,6 16,8 16,10.5M18,16V10.5C18,7.43 15.86,4.86 13,4.18V3.5A1.5,1.5 0 0,0 11.5,2A1.5,1.5 0 0,0 10,3.5V4.18C7.13,4.86 5,7.43 5,10.5V16L3,18V19H20V18M11.5,22A2,2 0 0,0 13.5,20H9.5A2,2 0 0,0 11.5,22Z" />
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_off.xml
Normal file
10
app/src/main/res/drawable/ic_off.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="?colorError"
|
||||||
|
android:pathData="M22.11 21.46L2.39 1.73L1.11 3L4.06 5.95C2.78 7.63 2 9.72 2 12C2 17.5 6.5 22 12 22C14.28 22 16.37 21.23 18.05 19.94L20.84 22.73L22.11 21.46M12 20C7.58 20 4 16.42 4 12C4 10.27 4.56 8.68 5.5 7.38L16.62 18.5C15.32 19.45 13.73 20 12 20M8.17 4.97L6.72 3.5C8.25 2.56 10.06 2 12 2C17.5 2 22 6.5 22 12C22 13.94 21.44 15.75 20.5 17.28L19.03 15.83C19.65 14.69 20 13.39 20 12C20 7.58 16.42 4 12 4C10.61 4 9.31 4.35 8.17 4.97Z" />
|
||||||
|
</vector>
|
@ -20,7 +20,7 @@
|
|||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/module_remote"
|
android:id="@+id/module_list"
|
||||||
adapter="@{viewModel.adapter}"
|
adapter="@{viewModel.adapter}"
|
||||||
dividerHorizontal="@{R.drawable.divider_l1}"
|
dividerHorizontal="@{R.drawable.divider_l1}"
|
||||||
dividerVertical="@{R.drawable.divider_l1}"
|
dividerVertical="@{R.drawable.divider_l1}"
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
dividerVertical="@{R.drawable.divider_l_50}"
|
dividerVertical="@{R.drawable.divider_l_50}"
|
||||||
itemBinding="@{viewModel.itemBinding}"
|
itemBinding="@{viewModel.itemBinding}"
|
||||||
items="@{viewModel.items}"
|
items="@{viewModel.items}"
|
||||||
|
android:id="@+id/settings_list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:focusableInTouchMode="false"
|
android:focusableInTouchMode="false"
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
items="@{viewModel.items}"
|
items="@{viewModel.items}"
|
||||||
nestedScrollingEnabled="@{false}"
|
nestedScrollingEnabled="@{false}"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
android:id="@+id/superuser_list"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
@ -22,137 +22,159 @@
|
|||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:alpha="@{item.isEnabled() ? 1f : .5f}"
|
android:alpha="@{item.isEnabled() ? 1f : .5f}"
|
||||||
android:onClick="@{() -> item.toggle(viewModel)}"
|
android:onClick="@{() -> item.toggle(viewModel)}"
|
||||||
|
android:onLongClick="@{() -> item.toggle()}"
|
||||||
tools:layout_marginBottom="@dimen/l1"
|
tools:layout_marginBottom="@dimen/l1"
|
||||||
tools:layout_marginEnd="@dimen/l1"
|
tools:layout_marginEnd="@dimen/l1"
|
||||||
tools:layout_width="200dp">
|
tools:layout_width="200dp">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:paddingTop="@dimen/l2"
|
android:orientation="vertical">
|
||||||
android:paddingBottom="@dimen/l2">
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/policy_app_icon"
|
android:layout_width="match_parent"
|
||||||
style="@style/WidgetFoundation.Image.Big"
|
android:layout_height="wrap_content">
|
||||||
android:src="@{item.icon}"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:srcCompat="@drawable/ic_logo" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
android:id="@+id/policy_app_name"
|
android:id="@+id/policy_app_icon"
|
||||||
android:layout_width="0dp"
|
style="@style/WidgetFoundation.Image"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginStart="@dimen/l1"
|
||||||
android:layout_marginLeft="@dimen/margin_generic"
|
android:layout_marginTop="@dimen/l1"
|
||||||
android:layout_marginTop="@dimen/l1"
|
android:layout_marginBottom="@dimen/l1"
|
||||||
android:layout_marginRight="@dimen/margin_generic"
|
android:src="@{item.icon}"
|
||||||
android:ellipsize="middle"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:gravity="center"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
android:singleLine="true"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
android:text="@{item.item.appName}"
|
app:layout_constraintVertical_bias="0"
|
||||||
android:textAppearance="@style/AppearanceFoundation.Title"
|
tools:srcCompat="@drawable/ic_logo" />
|
||||||
android:textIsSelectable="false"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/policy_app_icon"
|
|
||||||
tools:text="@string/app_name" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
android:id="@+id/policy_package_name"
|
style="@style/WidgetFoundation.Image.Big"
|
||||||
android:layout_width="0dp"
|
gone="@{item.isEnabled()}"
|
||||||
android:layout_height="wrap_content"
|
android:visibility="gone"
|
||||||
android:ellipsize="middle"
|
app:layout_constraintBottom_toBottomOf="@+id/policy_app_icon"
|
||||||
android:gravity="center"
|
app:layout_constraintEnd_toEndOf="@+id/policy_app_icon"
|
||||||
android:singleLine="true"
|
app:layout_constraintStart_toStartOf="@+id/policy_app_icon"
|
||||||
android:text="@{item.item.packageName}"
|
app:layout_constraintTop_toTopOf="@+id/policy_app_icon"
|
||||||
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
app:srcCompat="@drawable/ic_off"
|
||||||
android:textColor="@android:color/tertiary_text_dark"
|
app:tint="?colorSurface"
|
||||||
android:textIsSelectable="false"
|
tools:visibility="visible" />
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="@id/policy_app_name"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/policy_app_name"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/policy_app_name"
|
|
||||||
tools:text="com.topjohnwu.magisk" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/policy_app_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="@dimen/margin_generic"
|
||||||
|
android:layout_marginRight="@dimen/margin_generic"
|
||||||
|
android:ellipsize="middle"
|
||||||
|
android:gravity="start"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:text="@{item.item.appName}"
|
||||||
|
android:textAppearance="@style/AppearanceFoundation.Body"
|
||||||
|
android:textIsSelectable="false"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/policy_app_icon"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/policy_app_icon"
|
||||||
|
tools:text="@string/app_name" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
android:id="@+id/policy_expand_container"
|
android:id="@+id/policy_package_name"
|
||||||
revealFix="@{item.isExpanded()}"
|
android:layout_width="0dp"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_marginBottom="@dimen/l1"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/policy_package_name"
|
android:ellipsize="middle"
|
||||||
android:background="?colorSurfaceVariant"
|
android:gravity="start"
|
||||||
android:visibility="invisible"
|
android:maxLines="2"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:text="@{item.item.packageName}"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
android:textAppearance="@style/AppearanceFoundation.Caption.Variant"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
android:textColor="@android:color/tertiary_text_dark"
|
||||||
tools:alpha="0.9"
|
android:textIsSelectable="false"
|
||||||
tools:visibility="visible">
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/policy_app_name"
|
||||||
|
app:layout_constraintStart_toStartOf="@id/policy_app_name"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/policy_app_name"
|
||||||
|
app:layout_constraintVertical_bias="0"
|
||||||
|
tools:text="com.topjohnwu.magisk" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
android:id="@+id/policy_notify"
|
|
||||||
style="@style/WidgetFoundation.Icon"
|
|
||||||
android:background="?selectableItemBackground"
|
|
||||||
isSelected="@{item.shouldNotify}"
|
|
||||||
tooltipText="@{@string/superuser_toggle_notification}"
|
|
||||||
android:contentDescription="@string/superuser_toggle_notification"
|
|
||||||
android:onClick="@{() -> item.toggleNotify(viewModel)}"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/policy_delete"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/policy_log"
|
|
||||||
app:layout_constraintHorizontal_chainStyle="packed"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
|
||||||
app:srcCompat="@drawable/ic_notifications"
|
|
||||||
app:tint="@color/color_state_primary_transient" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/policy_log"
|
android:id="@+id/policy_expand_container"
|
||||||
style="@style/WidgetFoundation.Icon"
|
gone="@{!item.isExpanded}"
|
||||||
android:background="?selectableItemBackground"
|
android:layout_width="match_parent"
|
||||||
isSelected="@{item.shouldLog}"
|
android:layout_height="match_parent"
|
||||||
tooltipText="@{@string/superuser_toggle_log}"
|
android:background="?colorSurfaceVariant"
|
||||||
android:contentDescription="@string/superuser_toggle_log"
|
android:visibility="gone"
|
||||||
android:onClick="@{() -> item.toggleLog(viewModel)}"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/policy_notify"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/policy_notify"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/policy_notify"
|
|
||||||
app:srcCompat="@drawable/ic_bug_report"
|
|
||||||
app:tint="@color/color_state_primary_transient" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/policy_delete"
|
|
||||||
style="@style/WidgetFoundation.Button.Text"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:onClick="@{() -> viewModel.deletePressed(item)}"
|
|
||||||
android:text="@string/superuser_toggle_revoke"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textColor="?colorError"
|
|
||||||
android:textSize="12sp"
|
|
||||||
app:icon="@drawable/ic_delete_md2"
|
|
||||||
app:iconTint="?colorError"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/policy_notify"
|
app:layout_constraintTop_toBottomOf="@+id/policy_package_name"
|
||||||
app:rippleColor="?colorError" />
|
tools:visibility="visible">
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/policy_notify"
|
||||||
|
style="@style/WidgetFoundation.Button.Text"
|
||||||
|
isSelected="@{item.shouldNotify}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="24dp"
|
||||||
|
android:onClick="@{() -> item.toggleNotify(viewModel)}"
|
||||||
|
android:text="@string/superuser_toggle_notification"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textAppearance="@style/AppearanceFoundation.Tiny"
|
||||||
|
android:textColor="@color/color_state_primary_transient"
|
||||||
|
app:icon="@drawable/ic_notifications_md2"
|
||||||
|
app:iconTint="@color/color_state_primary_transient"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:tint="@color/color_state_primary_transient" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
<com.google.android.material.button.MaterialButton
|
||||||
style="@style/WidgetFoundation.Icon"
|
android:id="@+id/policy_log"
|
||||||
isEnabled="@{item.isEnabled}"
|
style="@style/WidgetFoundation.Button.Text"
|
||||||
isSelected="@{item.isExpanded}"
|
isSelected="@{item.shouldLog}"
|
||||||
android:layout_gravity="top|right"
|
android:layout_width="match_parent"
|
||||||
android:onClick="@{(view) -> item.toggle(view)}"
|
android:layout_height="wrap_content"
|
||||||
android:rotation="@{item.isExpanded ? 225 : 180}"
|
android:minHeight="24dp"
|
||||||
app:srcCompat="@drawable/ic_more_collapse"
|
android:onClick="@{() -> item.toggleLog(viewModel)}"
|
||||||
tools:ignore="RtlHardcoded" />
|
android:text="@string/superuser_toggle_log"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textAppearance="@style/AppearanceFoundation.Tiny"
|
||||||
|
android:textColor="@color/color_state_primary_transient"
|
||||||
|
app:icon="@drawable/ic_bug_md2"
|
||||||
|
app:iconTint="@color/color_state_primary_transient"
|
||||||
|
app:layout_constrainedWidth="true"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/policy_notify"
|
||||||
|
app:tint="@color/color_state_primary_transient" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/policy_delete"
|
||||||
|
style="@style/WidgetFoundation.Button.Text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="24dp"
|
||||||
|
android:onClick="@{() -> viewModel.deletePressed(item)}"
|
||||||
|
android:text="@string/superuser_toggle_revoke"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="?colorError"
|
||||||
|
android:textSize="12sp"
|
||||||
|
app:icon="@drawable/ic_delete_md2"
|
||||||
|
app:iconTint="?colorError"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/policy_log"
|
||||||
|
app:rippleColor="?colorError" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
@ -86,8 +86,8 @@
|
|||||||
<string name="module_state_restore">Restore</string>
|
<string name="module_state_restore">Restore</string>
|
||||||
<string name="module_action_install_external">Install from storage</string>
|
<string name="module_action_install_external">Install from storage</string>
|
||||||
|
|
||||||
<string name="superuser_toggle_log">Toggles logging</string>
|
<string name="superuser_toggle_log">Logs</string>
|
||||||
<string name="superuser_toggle_notification">Toggles “toast” notifications</string>
|
<string name="superuser_toggle_notification">Notifications</string>
|
||||||
<string name="superuser_toggle_revoke">Revoke</string>
|
<string name="superuser_toggle_revoke">Revoke</string>
|
||||||
|
|
||||||
<string name="hide_filter_hint">Filter by name</string>
|
<string name="hide_filter_hint">Filter by name</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user