Updated hide fragment with more robust filtering UI

This commit is contained in:
Viktor De Pasquale
2019-11-02 18:12:22 +01:00
parent d48e9d5d72
commit dad52724db
9 changed files with 242 additions and 40 deletions

View File

@@ -2,9 +2,8 @@ package com.topjohnwu.magisk.redesign.hide
import android.content.Context
import android.graphics.Insets
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.os.Bundle
import android.view.View
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.FragmentHideMd2Binding
import com.topjohnwu.magisk.redesign.compat.CompatFragment
@@ -20,16 +19,14 @@ class HideFragment : CompatFragment<HideViewModel, FragmentHideMd2Binding>() {
override fun onAttach(context: Context) {
super.onAttach(context)
activity.setTitle(R.string.magiskhide)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_hide_md2, menu)
menu.findItem(R.id.action_show_system)?.isChecked = viewModel.isShowSystem
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return viewModel.menuItemPressed(item)
binding.hideActionScrollUp.setOnClickListener {
binding.hideScrollContainer.fullScroll(View.FOCUS_UP)
}
}
}

View File

@@ -1,12 +1,14 @@
package com.topjohnwu.magisk.redesign.hide
import android.content.pm.ApplicationInfo
import android.view.MenuItem
import android.os.Handler
import android.os.Looper
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.data.repository.MagiskRepository
import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.extensions.toggle
import com.topjohnwu.magisk.model.entity.HideAppInfo
import com.topjohnwu.magisk.model.entity.HideTarget
import com.topjohnwu.magisk.model.entity.ProcessHideApp
@@ -19,18 +21,31 @@ import com.topjohnwu.magisk.utils.DiffObservableList
import com.topjohnwu.magisk.utils.FilterableDiffObservableList
import com.topjohnwu.magisk.utils.KObservableField
import com.topjohnwu.magisk.utils.currentLocale
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
class HideViewModel(
private val magiskRepo: MagiskRepository
) : CompatViewModel() {
private val queryHandler = Handler(Looper.getMainLooper())
private val queryRunnable = Runnable { query() }
var isShowSystem = false
@Bindable get
set(value) {
field = value
notifyPropertyChanged(BR.showSystem)
query()
}
val query = KObservableField("")
var query = ""
@Bindable get
set(value) {
field = value
notifyPropertyChanged(BR.query)
submitQuery()
}
val items = filterableListOf<HideItem>()
val itemBinding = itemBindingOf<HideItem> {
it.bindExtra(BR.viewModel, this)
@@ -39,6 +54,8 @@ class HideViewModel(
it.bindExtra(BR.viewModel, this)
}
val isFilterExpanded = KObservableField(false)
override fun refresh() = magiskRepo.fetchApps()
.map { it to magiskRepo.fetchHideTargets().blockingGet() }
.map { pair -> pair.first.map { mergeAppTargets(it, pair.second) } }
@@ -70,8 +87,13 @@ class HideViewModel(
// ---
private fun submitQuery() {
queryHandler.removeCallbacks(queryRunnable)
queryHandler.postDelayed(queryRunnable, 1000)
}
private fun query(
query: String = this.query.value,
query: String = this.query,
showSystem: Boolean = isShowSystem
) = items.filter {
fun filterSystem(): Boolean {
@@ -90,18 +112,22 @@ class HideViewModel(
// ---
fun menuItemPressed(menuItem: MenuItem) = when (menuItem.itemId) {
R.id.action_show_system -> isShowSystem = (!menuItem.isChecked)
.also { menuItem.isChecked = it }
else -> null
}?.let { true } ?: false
fun toggleItem(item: HideProcessItem) = magiskRepo
.toggleHide(item.isHidden.value, item.item.packageName, item.item.name)
// might wanna reorder the list to display the item at the top
.subscribeK()
.add()
fun toggle(item: KObservableField<Boolean>) = item.toggle()
fun resetQuery() {
query = ""
}
fun hideFilter() {
isFilterExpanded.value = false
}
}
inline fun <T : ComparableRvItem<T>> filterableListOf(

View File

@@ -15,6 +15,7 @@ import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.Toolbar
import androidx.core.animation.doOnEnd
import androidx.core.view.*
import androidx.core.widget.NestedScrollView
import androidx.databinding.BindingAdapter
import androidx.databinding.InverseBindingAdapter
import androidx.databinding.InverseBindingListener
@@ -26,6 +27,7 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView
import com.google.android.material.chip.Chip
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.navigation.NavigationView
import com.google.android.material.textfield.TextInputLayout
@@ -410,4 +412,21 @@ fun Toolbar.setOnMenuClickListener(listener: Toolbar.OnMenuItemClickListener) {
@BindingAdapter("tooltipText")
fun View.setTooltipTextCompat(text: String) {
ViewCompat.setTooltipText(this, text)
}
@BindingAdapter("onCloseClicked")
fun Chip.setOnCloseClickedListenerBinding(listener: View.OnClickListener) {
setOnCloseIconClickListener(listener)
}
@BindingAdapter("onScrollStateChanged")
fun NestedScrollView.setOnScrollStateChangeListener(listener: Runnable) {
setOnScrollChangeListener { _: NestedScrollView?, _: Int, _: Int, _: Int, _: Int ->
if (!handler.hasCallbacks(listener)) {
listener.run()
} else {
handler.removeCallbacksAndMessages(null)
}
handler.postDelayed(listener, 1000)
}
}