diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt index 1af52be7b..2f160e3b2 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/ModuleRvItem.kt @@ -1,6 +1,8 @@ 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 @@ -9,7 +11,10 @@ import com.topjohnwu.magisk.extensions.get import com.topjohnwu.magisk.extensions.toggle 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() { @@ -72,4 +77,35 @@ class RepoRvItem(val item: Repo) : ComparableRvItem() { override fun contentSameAs(other: RepoRvItem): Boolean = item == other.item override fun itemSameAs(other: RepoRvItem): Boolean = item.id == other.item.id +} + +class ModuleItem(val item: Module) : ComparableRvItem() { + + override val layoutRes = R.layout.item_module_md2 + + val isExpanded = KObservableField(false) + val isEnabled = KObservableField(item.enable) + + val isModified get() = item.enable != isEnabled.value + + fun toggle(viewModel: ModuleViewModel) { + isEnabled.toggle() + viewModel.moveToState(this) + } + + fun toggle(view: View) { + isExpanded.toggle() + view.rotationTo(if (isExpanded.value) 225 else 180) + (view.parent as ViewGroup) + .findViewById(R.id.module_expand_container) + .setRevealed(isExpanded.value) + } + + override fun contentSameAs(other: ModuleItem): Boolean = item.version == other.item.version + && item.versionCode == other.item.versionCode + && item.description == other.item.description + && item.name == other.item.name + + override fun itemSameAs(other: ModuleItem): Boolean = item.id == other.item.id + } \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/redesign/module/ModuleViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/redesign/module/ModuleViewModel.kt index 35979b2e7..0b65aabe4 100644 --- a/app/src/main/java/com/topjohnwu/magisk/redesign/module/ModuleViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/redesign/module/ModuleViewModel.kt @@ -1,16 +1,49 @@ package com.topjohnwu.magisk.redesign.module import com.topjohnwu.magisk.BR -import com.topjohnwu.magisk.model.entity.recycler.ModuleRvItem +import com.topjohnwu.magisk.extensions.subscribeK +import com.topjohnwu.magisk.model.entity.module.Module +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 io.reactivex.Single class ModuleViewModel : CompatViewModel() { - val items = diffListOf() - val itemBinding = itemBindingOf { + val items = diffListOf() + val itemsPending = diffListOf() + val itemBinding = itemBindingOf { it.bindExtra(BR.viewModel, this) } + 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 + + when { + isActive && isPending -> if (item.isModified) { + items.remove(item) + } else { + itemsPending.remove(item) + } + isActive && item.isModified -> { + items.remove(item) + itemsPending.add(item) + } + isPending && !item.isModified -> { + itemsPending.remove(item) + items.add(item) + } + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt b/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt index 210311a05..346efcc3f 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt +++ b/app/src/main/java/com/topjohnwu/magisk/utils/DataBindingAdapters.kt @@ -443,4 +443,11 @@ fun ProgressBar.setProgressAnimated(newProgress: Int) { addUpdateListener { progress = it.animatedValue as Int } tag = this }.start() +} + +@BindingAdapter("android:rotation") +fun View.setRotationNotAnimated(rotation: Int) { + if (animation != null) { + this.rotation = rotation.toFloat() + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_download_md2.xml b/app/src/main/res/drawable/ic_download_md2.xml new file mode 100644 index 000000000..5d3c38484 --- /dev/null +++ b/app/src/main/res/drawable/ic_download_md2.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_module_md2.xml b/app/src/main/res/layout/fragment_module_md2.xml index 36d00c488..35fecd63a 100644 --- a/app/src/main/res/layout/fragment_module_md2.xml +++ b/app/src/main/res/layout/fragment_module_md2.xml @@ -5,6 +5,8 @@ + + - + android:layout_height="wrap_content" + android:orientation="vertical"> + + + + + + + + + + + + + android:paddingStart="@dimen/l1" + android:paddingEnd="0dp" + app:layoutManager="androidx.recyclerview.widget.StaggeredGridLayoutManager" + app:layout_constraintTop_toBottomOf="@+id/module_notice" + app:spanCount="2" + tools:itemCount="3" + tools:listitem="@layout/item_module_md2" /> - + + + diff --git a/app/src/main/res/layout/item_module_md2.xml b/app/src/main/res/layout/item_module_md2.xml new file mode 100644 index 000000000..3e43f20e6 --- /dev/null +++ b/app/src/main/res/layout/item_module_md2.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_policy_md2.xml b/app/src/main/res/layout/item_policy_md2.xml index c330d9146..2cafbe1a2 100644 --- a/app/src/main/res/layout/item_policy_md2.xml +++ b/app/src/main/res/layout/item_policy_md2.xml @@ -151,7 +151,7 @@ isSelected="@{item.isExpanded}" android:layout_gravity="top|end" android:onClick="@{(view) -> item.toggle(view)}" - android:rotation="180" + android:rotation="@{item.isExpanded ? 225 : 180}" app:srcCompat="@drawable/ic_more_collapse" /> diff --git a/app/src/main/res/values/strings_md2.xml b/app/src/main/res/values/strings_md2.xml index 406a0cfbd..1c132269e 100644 --- a/app/src/main/res/values/strings_md2.xml +++ b/app/src/main/res/values/strings_md2.xml @@ -74,6 +74,7 @@ Let\'s go You\'re in safe mode. None of user modules will work.\nThis message will disappear once safe mode is disabled. + %1$s by %2$s Toggles logging Toggles “toast” notifications