Commit c7cad7e4 authored by Viktor De Pasquale's avatar Viktor De Pasquale

Updated modules so they are properly arranged to respective sections

Small updates to module UI
parent 1c8988d3
package com.topjohnwu.magisk.model.entity.recycler
import android.content.res.Resources
import android.view.View
import android.view.ViewGroup
import androidx.annotation.StringRes
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ComparableRvItem
......@@ -13,8 +11,6 @@ import com.topjohnwu.magisk.model.entity.module.Module
import com.topjohnwu.magisk.model.entity.module.Repo
import com.topjohnwu.magisk.redesign.module.ModuleViewModel
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.magisk.utils.rotationTo
import com.topjohnwu.magisk.utils.setRevealed
class ModuleRvItem(val item: Module) : ComparableRvItem<ModuleRvItem>() {
......@@ -83,22 +79,29 @@ class ModuleItem(val item: Module) : ComparableRvItem<ModuleItem>() {
override val layoutRes = R.layout.item_module_md2
val isExpanded = KObservableField(false)
val isEnabled = KObservableField(item.enable)
val isRemoved = KObservableField(item.remove)
val isUpdated get() = item.updated
val isModified get() = item.enable != isEnabled.value
val isModified get() = item.remove || item.updated
init {
isEnabled.addOnPropertyChangedCallback {
item.enable = it ?: return@addOnPropertyChangedCallback
}
isRemoved.addOnPropertyChangedCallback {
item.remove = it ?: return@addOnPropertyChangedCallback
}
}
fun toggle(viewModel: ModuleViewModel) {
isEnabled.toggle()
viewModel.moveToState(this)
viewModel.updateState()
}
fun toggle(view: View) {
isExpanded.toggle()
view.rotationTo(if (isExpanded.value) 225 else 180)
(view.parent as ViewGroup)
.findViewById<View>(R.id.module_expand_container)
.setRevealed(isExpanded.value)
fun delete(viewModel: ModuleViewModel) {
isRemoved.toggle()
viewModel.updateState()
}
override fun contentSameAs(other: ModuleItem): Boolean = item.version == other.item.version
......
package com.topjohnwu.magisk.redesign.module
import androidx.annotation.WorkerThread
import androidx.recyclerview.widget.DiffUtil
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.model.entity.module.Module
......@@ -7,6 +9,8 @@ import com.topjohnwu.magisk.model.entity.recycler.ModuleItem
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.DiffObservableList
import com.topjohnwu.magisk.utils.currentLocale
import io.reactivex.Single
class ModuleViewModel : CompatViewModel() {
......@@ -19,31 +23,65 @@ class ModuleViewModel : CompatViewModel() {
override fun refresh() = Single.fromCallable { Module.loadModules() }
.map { it.map { ModuleItem(it) } }
.map { it to items.calculateDiff(it) }
.subscribeK {
items.update(it.first, it.second)
items.forEach { moveToState(it) }
}
fun moveToState(item: ModuleItem) {
val isActive = items.indexOfFirst { it.itemSameAs(item) } != -1
val isPending = itemsPending.indexOfFirst { it.itemSameAs(item) } != -1
.map { it.order() }
.subscribeK { it.forEach { it.update() } }
when {
isActive && isPending -> if (item.isModified) {
items.remove(item)
} else {
itemsPending.remove(item)
@WorkerThread
private fun List<ModuleItem>.order() = sortedBy { it.item.name.toLowerCase(currentLocale) }
.groupBy {
when {
it.isModified -> ModuleState.Modified
else -> ModuleState.Normal
}
isActive && item.isModified -> {
items.remove(item)
itemsPending.add(item)
}
isPending && !item.isModified -> {
itemsPending.remove(item)
items.add(item)
}
.map {
val diff = when (it.key) {
ModuleState.Modified -> itemsPending
ModuleState.Normal -> items
}.calculateDiff(it.value)
ResultEnclosure(it.key, it.value, diff)
}
.ensureAllStates()
private fun List<ResultEnclosure>.ensureAllStates(): List<ResultEnclosure> {
val me = this as? MutableList<ResultEnclosure> ?: this.toMutableList()
ModuleState.values().forEach {
if (me.none { rit -> it == rit.state }) {
me.add(ResultEnclosure(it, listOf(), null))
}
}
return me
}
fun updateState() {
// I don't feel like bothering with moving every single item to its updated state,
// so this kind of wasteful operation helps with that
Single.fromCallable { items + itemsPending }
.map { it.order() }
.subscribeK { it.forEach { it.update() } }
}
private enum class ModuleState {
Modified, Normal
}
private data class ResultEnclosure(
val state: ModuleState,
val list: List<ModuleItem>,
val diff: DiffUtil.DiffResult?
)
private fun ResultEnclosure.update() = when (state) {
ModuleState.Modified -> itemsPending
ModuleState.Normal -> items
}.update(list, diff)
private fun <T> DiffObservableList<T>.update(list: List<T>, diff: DiffUtil.DiffResult?) {
diff ?: let {
update(list)
return
}
update(list, diff)
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_restart" android:state_selected="true" />
<item android:drawable="@drawable/ic_delete_md2" />
</selector>
\ No newline at end of file
......@@ -5,6 +5,8 @@
<data>
<import type="com.topjohnwu.magisk.R" />
<import type="com.topjohnwu.magisk.Config" />
<variable
......@@ -19,7 +21,7 @@
<com.google.android.material.card.MaterialCardView
style="?styleCardVariant"
isEnabled="@{!Config.coreOnly}"
isEnabled="@{!Config.coreOnly &amp;&amp; !item.isRemoved()}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="@{item.isEnabled() &amp;&amp; !Config.coreOnly ? 1f : .5f}"
......@@ -33,28 +35,41 @@
android:layout_height="wrap_content"
android:paddingBottom="@dimen/l1">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/module_state_icon"
style="?styleImageSmall"
gone="@{!item.isRemoved &amp;&amp; !item.updated}"
srcCompat="@{item.isRemoved ? R.drawable.ic_delete_md2 : R.drawable.ic_update_md2}"
android:layout_marginStart="@dimen/l1"
android:background="@null"
app:layout_constraintBottom_toBottomOf="@+id/module_version_author"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/module_title"
tools:srcCompat="@drawable/ic_update_md2" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/module_title"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/l1"
android:layout_marginTop="@dimen/l1"
android:layout_marginEnd="32dp"
android:text="@{item.item.name}"
android:textAppearance="?appearanceTextBodyNormal"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/module_remove"
app:layout_constraintStart_toEndOf="@+id/module_state_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/lorem" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/module_version_author"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/l1"
android:layout_marginEnd="@dimen/l1"
android:text="@{@string/module_version_author(item.item.version, item.item.author)}"
android:textAppearance="?appearanceTextCaptionVariant"
app:layout_constraintEnd_toStartOf="@+id/module_remove"
app:layout_constraintStart_toEndOf="@+id/module_state_icon"
app:layout_constraintTop_toBottomOf="@+id/module_title"
tools:text="v1 by topjohnwu" />
......@@ -71,34 +86,17 @@
tools:lines="4"
tools:text="@tools:sample/lorem/random" />
</androidx.constraintlayout.widget.ConstraintLayout>
<FrameLayout
android:id="@+id/module_expand_container"
revealFix="@{item.isExpanded}"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?colorSurfaceVariant"
android:visibility="gone">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/module_remove"
style="?styleIconNormal"
isSelected="@{item.isRemoved}"
android:alpha=".5"
android:onClick="@{(v) -> item.delete(viewModel)}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_delete_restore" />
<com.google.android.material.button.MaterialButton
style="?styleButtonError"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Remove"
android:textAllCaps="false"
app:icon="@drawable/ic_delete_md2" />
</FrameLayout>
<androidx.appcompat.widget.AppCompatImageView
style="?styleIconNormal"
isSelected="@{item.isExpanded}"
android:layout_gravity="top|end"
android:onClick="@{(v) -> item.toggle(v)}"
android:rotation="@{item.isExpanded ? 225 : 180}"
app:srcCompat="@drawable/ic_more_collapse" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment