Skip to content

Commit

Permalink
TagsSelector undo feature
Browse files Browse the repository at this point in the history
  • Loading branch information
mdrlzy committed Sep 27, 2021
1 parent 04d3888 commit c3f8f8c
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ import space.taran.arknavigator.mvp.model.UserPreferences
import space.taran.arknavigator.mvp.model.dao.ResourceId
import space.taran.arknavigator.mvp.model.repo.*
import space.taran.arknavigator.mvp.presenter.adapter.ResourcesGridPresenter
import space.taran.arknavigator.mvp.presenter.adapter.TagsSelectorPresenter
import space.taran.arknavigator.mvp.presenter.adapter.tagsselector.TagsSelectorPresenter
import space.taran.arknavigator.mvp.view.ResourcesView
import space.taran.arknavigator.ui.App
import space.taran.arknavigator.ui.fragments.utils.Notifications
import space.taran.arknavigator.utils.RESOURCES_SCREEN
import space.taran.arknavigator.utils.Tags
import java.nio.file.Path
import javax.inject.Inject

Expand Down Expand Up @@ -133,6 +132,12 @@ class ResourcesPresenter(
viewState.closeSortDialog()
}

fun onBackClick(): Boolean {
if (!tagsSelectorPresenter.onBackClick())
router.exit()
return true
}

private fun onSelectionChange(selection: Set<ResourceId>) {
viewState.notifyUser("${selection.size} resources selected")
gridPresenter.updateResources(selection.toList())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package space.taran.arknavigator.mvp.presenter.adapter.tagsselector

import space.taran.arknavigator.utils.Tag

sealed class TagsSelectorAction(val tag: Tag?)

class Include(tag: Tag): TagsSelectorAction(tag)
class Exclude(tag: Tag): TagsSelectorAction(tag)
class UncheckIncluded(tag: Tag): TagsSelectorAction(tag)
class UncheckExcluded(tag: Tag): TagsSelectorAction(tag)
class UncheckAndExclude(tag: Tag): TagsSelectorAction(tag)
class Clear(val included: Set<Tag>, val excluded: Set<Tag>): TagsSelectorAction(null)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package space.taran.arknavigator.mvp.presenter.adapter
package space.taran.arknavigator.mvp.presenter.adapter.tagsselector

import android.util.Log
import space.taran.arknavigator.mvp.model.dao.ResourceId
Expand All @@ -18,6 +18,7 @@ class TagsSelectorPresenter(
) {
private var index: ResourcesIndex? = null
private var storage: TagsStorage? = null
private val actions = ArrayDeque<TagsSelectorAction>()

var included = mutableSetOf<Tag>()
private set
Expand Down Expand Up @@ -59,7 +60,8 @@ class TagsSelectorPresenter(
}

fun onClearClick() {
(included + excluded).forEach { uncheckTag(it, needToCalculate = false) }
actions.addLast(Clear(included.toSet(), excluded.toSet()))
(included + excluded).forEach { uncheckTag(it, fromClearClick = true) }
calculateTagsAndSelection()
}

Expand Down Expand Up @@ -116,11 +118,66 @@ class TagsSelectorPresenter(
viewState.drawTags()
}

fun onBackClick(): Boolean {
verifyActions()

if (actions.isEmpty())
return false

when(val action = actions.last()) {
is Include -> {
included.remove(action.tag!!)
}
is Exclude -> {
excluded.remove(action.tag!!)
}
is UncheckIncluded -> {
included.add(action.tag!!)
}
is UncheckExcluded -> {
excluded.add(action.tag!!)
}
is UncheckAndExclude -> {
included.remove(action.tag!!)
excluded.add(action.tag)
}
is Clear -> {
included = action.included.toMutableSet()
excluded = action.excluded.toMutableSet()
}
}

actions.removeLast()

calculateTagsAndSelection()

return true
}

private fun verifyActions() {
if (storage == null || index == null)
return

val allTags = storage!!.getTags(index!!.listIds(prefix))
actions.toList().forEach { action ->
action.tag?.let { tag ->
if (!allTags.contains(tag))
actions.remove(action)
} ?: let {
action as Clear
if (action.excluded.intersect(allTags).isEmpty() &&
action.included.intersect(allTags).isEmpty())
actions.remove(action)
}
}
}

private fun includeTag(tag: Tag) {
Log.d(TAGS_SELECTOR, "including tag $tag")

included.add(tag)
excluded.remove(tag)
actions.addLast(Include(tag))

calculateTagsAndSelection()
}
Expand All @@ -130,11 +187,12 @@ class TagsSelectorPresenter(

excluded.add(tag)
included.remove(tag)
actions.addLast(Exclude(tag))

calculateTagsAndSelection()
}

private fun uncheckTag(tag: Tag, needToCalculate: Boolean = true) {
private fun uncheckTag(tag: Tag, fromClearClick: Boolean = false) {
Log.d(TAGS_SELECTOR, "un-checking tag $tag")

if (included.contains(tag) && excluded.contains(tag)) {
Expand All @@ -146,9 +204,12 @@ class TagsSelectorPresenter(

if (!included.remove(tag)) {
excluded.remove(tag)
if (!fromClearClick) actions.addLast(UncheckExcluded(tag))
} else {
if (!fromClearClick) actions.addLast(UncheckIncluded(tag))
}

if (needToCalculate)
if (!fromClearClick)
calculateTagsAndSelection()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import androidx.core.content.ContextCompat
import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup
import space.taran.arknavigator.R
import space.taran.arknavigator.mvp.presenter.adapter.TagsSelectorPresenter
import space.taran.arknavigator.mvp.presenter.adapter.tagsselector.TagsSelectorPresenter
import space.taran.arknavigator.utils.Tag

class TagsSelectorAdapter(val chipGroup: ChipGroup, val presenter: TagsSelectorPresenter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import kotlin.math.abs
//`path` is used for filtering resources' paths
// if it is `null`, then no filtering is performed
// (recommended instead of passing same value for `path` and `root)
class ResourcesFragment(val root: Path?, val path: Path?): MvpAppCompatFragment(), ResourcesView {
class ResourcesFragment(val root: Path?, val path: Path?): MvpAppCompatFragment(), ResourcesView, BackButtonListener {

private val presenter by moxyPresenter {
ResourcesPresenter(root, path).apply {
Expand Down Expand Up @@ -172,6 +172,10 @@ class ResourcesFragment(val root: Path?, val path: Path?): MvpAppCompatFragment(
sortByDialog?.dismiss()
}

override fun backClicked(): Boolean {
return presenter.onBackClick()
}

private fun showSortByDialog(sorting: Sorting, ascending: Boolean) {
Log.d(RESOURCES_SCREEN, "showing sort-by dialog in ResourcesFragment")
val dialogBinding = DialogSortBinding.inflate(LayoutInflater.from(requireContext()))
Expand Down

0 comments on commit c3f8f8c

Please sign in to comment.