mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 23:07:38 +00:00
Added empty states for all remaining screens
Fixed some issues in the process as the MergeObservableList doesn't support additions or deletions, duh...
This commit is contained in:
parent
7342509b2e
commit
904948dc7d
@ -10,6 +10,7 @@ import com.topjohnwu.magisk.extensions.subscribeK
|
|||||||
import com.topjohnwu.magisk.model.binding.BindingAdapter
|
import com.topjohnwu.magisk.model.binding.BindingAdapter
|
||||||
import com.topjohnwu.magisk.model.entity.recycler.ConsoleItem
|
import com.topjohnwu.magisk.model.entity.recycler.ConsoleItem
|
||||||
import com.topjohnwu.magisk.model.entity.recycler.LogItem
|
import com.topjohnwu.magisk.model.entity.recycler.LogItem
|
||||||
|
import com.topjohnwu.magisk.model.entity.recycler.TextItem
|
||||||
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
||||||
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
|
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
|
||||||
import com.topjohnwu.magisk.redesign.compat.diffListOf
|
import com.topjohnwu.magisk.redesign.compat.diffListOf
|
||||||
@ -27,6 +28,11 @@ class LogViewModel(
|
|||||||
private val repo: LogRepository
|
private val repo: LogRepository
|
||||||
) : CompatViewModel() {
|
) : CompatViewModel() {
|
||||||
|
|
||||||
|
// --- empty view
|
||||||
|
|
||||||
|
val itemEmpty = TextItem(R.string.log_data_none)
|
||||||
|
val itemMagiskEmpty = TextItem(R.string.log_data_magisk_none)
|
||||||
|
|
||||||
// --- main view
|
// --- main view
|
||||||
|
|
||||||
val items = diffListOf<LogItem>()
|
val items = diffListOf<LogItem>()
|
||||||
|
@ -2,6 +2,7 @@ package com.topjohnwu.magisk.redesign.module
|
|||||||
|
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
|
import androidx.databinding.ObservableArrayList
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.Config
|
import com.topjohnwu.magisk.Config
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
@ -61,6 +62,13 @@ class ModuleViewModel(
|
|||||||
private val itemNoneInstalled = TextItem(R.string.module_install_none)
|
private val itemNoneInstalled = TextItem(R.string.module_install_none)
|
||||||
private val itemNoneUpdatable = TextItem(R.string.module_update_none)
|
private val itemNoneUpdatable = TextItem(R.string.module_update_none)
|
||||||
|
|
||||||
|
private val itemsInstalledHelpers = ObservableArrayList<TextItem>().also {
|
||||||
|
it.add(itemNoneInstalled)
|
||||||
|
}
|
||||||
|
private val itemsUpdatableHelpers = ObservableArrayList<TextItem>().also {
|
||||||
|
it.add(itemNoneUpdatable)
|
||||||
|
}
|
||||||
|
|
||||||
private val itemsInstalled = diffListOf<ModuleItem>()
|
private val itemsInstalled = diffListOf<ModuleItem>()
|
||||||
private val itemsUpdatable = diffListOf<RepoItem.Update>()
|
private val itemsUpdatable = diffListOf<RepoItem.Update>()
|
||||||
private val itemsRemote = diffListOf<RepoItem.Remote>()
|
private val itemsRemote = diffListOf<RepoItem.Remote>()
|
||||||
@ -68,11 +76,11 @@ class ModuleViewModel(
|
|||||||
val adapter = adapterOf<ComparableRvItem<*>>()
|
val adapter = adapterOf<ComparableRvItem<*>>()
|
||||||
val items = MergeObservableList<ComparableRvItem<*>>()
|
val items = MergeObservableList<ComparableRvItem<*>>()
|
||||||
.insertItem(sectionActive)
|
.insertItem(sectionActive)
|
||||||
.insertItem(itemNoneInstalled)
|
.insertList(itemsInstalledHelpers)
|
||||||
.insertList(itemsInstalled)
|
.insertList(itemsInstalled)
|
||||||
.insertItem(InstallModule)
|
.insertItem(InstallModule)
|
||||||
.insertItem(sectionUpdate)
|
.insertItem(sectionUpdate)
|
||||||
.insertItem(itemNoneUpdatable)
|
.insertList(itemsUpdatableHelpers)
|
||||||
.insertList(itemsUpdatable)
|
.insertList(itemsUpdatable)
|
||||||
.insertItem(sectionRemote)
|
.insertItem(sectionRemote)
|
||||||
.insertList(itemsRemote)!!
|
.insertList(itemsRemote)!!
|
||||||
@ -155,13 +163,17 @@ class ModuleViewModel(
|
|||||||
.applyViewModel(this)
|
.applyViewModel(this)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.doOnSuccess { itemsInstalled.update(it.first, it.second) }
|
.doOnSuccess { itemsInstalled.update(it.first, it.second) }
|
||||||
.doOnSuccess { if (itemsInstalled.isNotEmpty()) items.remove(itemNoneInstalled) }
|
.doOnSuccess {
|
||||||
|
if (itemsInstalled.isNotEmpty()) itemsInstalledHelpers.remove(itemNoneInstalled)
|
||||||
|
}
|
||||||
.observeOn(Schedulers.io())
|
.observeOn(Schedulers.io())
|
||||||
.map { loadUpdates(it.first) }
|
.map { loadUpdates(it.first) }
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.map { it to itemsUpdatable.calculateDiff(it) }
|
.map { it to itemsUpdatable.calculateDiff(it) }
|
||||||
.doOnSuccess { itemsUpdatable.update(it.first, it.second) }
|
.doOnSuccess { itemsUpdatable.update(it.first, it.second) }
|
||||||
.doOnSuccess { if (itemsUpdatable.isNotEmpty()) items.remove(itemNoneUpdatable) }
|
.doOnSuccess {
|
||||||
|
if (itemsUpdatable.isNotEmpty()) itemsUpdatableHelpers.remove(itemNoneUpdatable)
|
||||||
|
}
|
||||||
.ignoreElement()!!
|
.ignoreElement()!!
|
||||||
|
|
||||||
fun loadRemoteImplicit() = let { itemsRemote.clear(); itemsSearch.clear() }
|
fun loadRemoteImplicit() = let { itemsRemote.clear(); itemsSearch.clear() }
|
||||||
|
@ -2,6 +2,7 @@ package com.topjohnwu.magisk.redesign.superuser
|
|||||||
|
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
|
import androidx.databinding.ObservableArrayList
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.data.database.PolicyDao
|
import com.topjohnwu.magisk.data.database.PolicyDao
|
||||||
@ -12,17 +13,20 @@ import com.topjohnwu.magisk.extensions.toggle
|
|||||||
import com.topjohnwu.magisk.model.entity.MagiskPolicy
|
import com.topjohnwu.magisk.model.entity.MagiskPolicy
|
||||||
import com.topjohnwu.magisk.model.entity.recycler.PolicyItem
|
import com.topjohnwu.magisk.model.entity.recycler.PolicyItem
|
||||||
import com.topjohnwu.magisk.model.entity.recycler.TappableHeadlineItem
|
import com.topjohnwu.magisk.model.entity.recycler.TappableHeadlineItem
|
||||||
|
import com.topjohnwu.magisk.model.entity.recycler.TextItem
|
||||||
import com.topjohnwu.magisk.model.events.PolicyUpdateEvent
|
import com.topjohnwu.magisk.model.events.PolicyUpdateEvent
|
||||||
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
||||||
import com.topjohnwu.magisk.model.events.dialog.BiometricDialog
|
import com.topjohnwu.magisk.model.events.dialog.BiometricDialog
|
||||||
import com.topjohnwu.magisk.model.events.dialog.SuperuserRevokeDialog
|
import com.topjohnwu.magisk.model.events.dialog.SuperuserRevokeDialog
|
||||||
import com.topjohnwu.magisk.model.navigation.Navigation
|
import com.topjohnwu.magisk.model.navigation.Navigation
|
||||||
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
|
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
|
||||||
|
import com.topjohnwu.magisk.redesign.compat.adapterOf
|
||||||
import com.topjohnwu.magisk.redesign.compat.diffListOf
|
import com.topjohnwu.magisk.redesign.compat.diffListOf
|
||||||
import com.topjohnwu.magisk.redesign.compat.itemBindingOf
|
import com.topjohnwu.magisk.redesign.compat.itemBindingOf
|
||||||
import com.topjohnwu.magisk.utils.BiometricHelper
|
import com.topjohnwu.magisk.utils.BiometricHelper
|
||||||
import com.topjohnwu.magisk.utils.currentLocale
|
import com.topjohnwu.magisk.utils.currentLocale
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
import me.tatarka.bindingcollectionadapter2.collections.MergeObservableList
|
||||||
|
|
||||||
class SuperuserViewModel(
|
class SuperuserViewModel(
|
||||||
private val db: PolicyDao,
|
private val db: PolicyDao,
|
||||||
@ -30,19 +34,24 @@ class SuperuserViewModel(
|
|||||||
private val resources: Resources
|
private val resources: Resources
|
||||||
) : CompatViewModel(), TappableHeadlineItem.Listener {
|
) : CompatViewModel(), TappableHeadlineItem.Listener {
|
||||||
|
|
||||||
val items = diffListOf<ComparableRvItem<*>>()
|
private val itemNoData = TextItem(R.string.superuser_policy_none)
|
||||||
|
|
||||||
|
private val itemsPolicies = diffListOf<PolicyItem>()
|
||||||
|
private val itemsHelpers = ObservableArrayList<TextItem>().also {
|
||||||
|
it.add(itemNoData)
|
||||||
|
}
|
||||||
|
|
||||||
|
val adapter = adapterOf<ComparableRvItem<*>>()
|
||||||
|
val items = MergeObservableList<ComparableRvItem<*>>()
|
||||||
|
.insertItem(TappableHeadlineItem.Hide)
|
||||||
|
.insertItem(TappableHeadlineItem.Safetynet)
|
||||||
|
.insertList(itemsHelpers)
|
||||||
|
.insertList(itemsPolicies)
|
||||||
val itemBinding = itemBindingOf<ComparableRvItem<*>> {
|
val itemBinding = itemBindingOf<ComparableRvItem<*>> {
|
||||||
it.bindExtra(BR.viewModel, this)
|
it.bindExtra(BR.viewModel, this)
|
||||||
it.bindExtra(BR.listener, this)
|
it.bindExtra(BR.listener, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val menuOptions = listOf(
|
|
||||||
TappableHeadlineItem.Hide,
|
|
||||||
TappableHeadlineItem.Safetynet
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
override fun refresh() = db.fetchAll()
|
override fun refresh() = db.fetchAll()
|
||||||
@ -57,11 +66,15 @@ class SuperuserViewModel(
|
|||||||
).compare(o1, o2)
|
).compare(o1, o2)
|
||||||
}
|
}
|
||||||
.toList()
|
.toList()
|
||||||
.map { menuOptions + it }
|
.map { it to itemsPolicies.calculateDiff(it) }
|
||||||
.map { it to items.calculateDiff(it) }
|
|
||||||
.applySchedulers()
|
.applySchedulers()
|
||||||
.applyViewModel(this)
|
.applyViewModel(this)
|
||||||
.subscribeK { items.update(it.first, it.second) }
|
.subscribeK {
|
||||||
|
itemsPolicies.update(it.first, it.second)
|
||||||
|
if (itemsPolicies.isNotEmpty()) {
|
||||||
|
itemsHelpers.remove(itemNoData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
@ -77,7 +90,12 @@ class SuperuserViewModel(
|
|||||||
|
|
||||||
fun deletePressed(item: PolicyItem) {
|
fun deletePressed(item: PolicyItem) {
|
||||||
fun updateState() = deletePolicy(item.item)
|
fun updateState() = deletePolicy(item.item)
|
||||||
.subscribeK { items.removeAll { it.genericItemSameAs(item) } }
|
.subscribeK {
|
||||||
|
itemsPolicies.removeAll { it.genericItemSameAs(item) }
|
||||||
|
if (itemsPolicies.isEmpty() && itemsHelpers.isEmpty()) {
|
||||||
|
itemsHelpers.add(itemNoData)
|
||||||
|
}
|
||||||
|
}
|
||||||
.add()
|
.add()
|
||||||
|
|
||||||
if (BiometricHelper.isEnabled) {
|
if (BiometricHelper.isEnabled) {
|
||||||
|
@ -61,6 +61,20 @@
|
|||||||
|
|
||||||
</com.google.android.material.circularreveal.cardview.CircularRevealCardView>
|
</com.google.android.material.circularreveal.cardview.CircularRevealCardView>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
gone="@{!viewModel.items.empty}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center">
|
||||||
|
|
||||||
|
<include
|
||||||
|
item="@{viewModel.itemEmpty}"
|
||||||
|
layout="@layout/item_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
</layout>
|
</layout>
|
@ -18,6 +18,8 @@
|
|||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/superuser_list"
|
||||||
|
adapter="@{viewModel.adapter}"
|
||||||
dividerHorizontal="@{R.drawable.divider_l1}"
|
dividerHorizontal="@{R.drawable.divider_l1}"
|
||||||
dividerVertical="@{R.drawable.divider_l1}"
|
dividerVertical="@{R.drawable.divider_l1}"
|
||||||
goneUnless="@{viewModel.loaded || !viewModel.items.empty}"
|
goneUnless="@{viewModel.loaded || !viewModel.items.empty}"
|
||||||
@ -25,7 +27,6 @@
|
|||||||
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"
|
||||||
|
@ -11,24 +11,44 @@
|
|||||||
|
|
||||||
</data>
|
</data>
|
||||||
|
|
||||||
<HorizontalScrollView
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<HorizontalScrollView
|
||||||
adapter="@{viewModel.consoleAdapter}"
|
android:layout_width="match_parent"
|
||||||
itemBinding="@{viewModel.itemConsoleBinding}"
|
android:layout_height="match_parent">
|
||||||
items="@{viewModel.itemsConsole}"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:clipToPadding="false"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}"
|
|
||||||
android:paddingBottom="@{viewModel.insets.bottom}"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
|
||||||
tools:listitem="@layout/item_console"
|
|
||||||
tools:paddingTop="24dp" />
|
|
||||||
|
|
||||||
</HorizontalScrollView>
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
adapter="@{viewModel.consoleAdapter}"
|
||||||
|
itemBinding="@{viewModel.itemConsoleBinding}"
|
||||||
|
items="@{viewModel.itemsConsole}"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}"
|
||||||
|
android:paddingBottom="@{viewModel.insets.bottom}"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
tools:listitem="@layout/item_console"
|
||||||
|
tools:paddingTop="24dp" />
|
||||||
|
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
gone="@{!viewModel.itemsConsole.empty}"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center">
|
||||||
|
|
||||||
|
<include
|
||||||
|
item="@{viewModel.itemMagiskEmpty}"
|
||||||
|
layout="@layout/item_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
</layout>
|
</layout>
|
@ -91,10 +91,14 @@
|
|||||||
<string name="superuser_toggle_log">Logs</string>
|
<string name="superuser_toggle_log">Logs</string>
|
||||||
<string name="superuser_toggle_notification">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="superuser_policy_none">No app has asked for superuser permission yet.</string>
|
||||||
|
|
||||||
<string name="hide_filter_hint">Filter by name</string>
|
<string name="hide_filter_hint">Filter by name</string>
|
||||||
<string name="hide_scroll_up">Scroll up</string>
|
<string name="hide_scroll_up">Scroll up</string>
|
||||||
<string name="hide_filters">Filters</string>
|
<string name="hide_filters">Filters</string>
|
||||||
<string name="hide_search">Search</string>
|
<string name="hide_search">Search</string>
|
||||||
|
|
||||||
|
<string name="log_data_none">You\'re log-free, try using your SU enabled apps more.</string>
|
||||||
|
<string name="log_data_magisk_none">Magisk logs are empty, that\'s weird.</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user