anytype-kotlin-wild/app/src/main/java/com/anytypeio/anytype/ui/sets/modals/filter/CreateFilterFromSelectedValueFragment.kt
Evgenii Kozlov 36fe52e5ad
DROID-607 Relations & types and options | Refactoring | Everything-is-an-object refactoring (#2720)
* DROID-439 App | Relations refactoring, use SearchObjects for object types (#2592)
* DROID-446 Objects | Enhancement | Store relation links and process its updates (#2597)
* DROID-456 Tech | Remove deprecated API for creating object types (#2601)
* DROID-455 Object types | Enhancement Get object type list from ObjectSearch on Global search screen (#2602)
* DROID-459 Sets | Refactoring | Use relations links instead of relations for building search params to get data view data (#2603)
* DROID-458 Objects | Refactoring | Integrate new api for creating objets (#2604)
* DROID-464 Relations | Refactoring | New API for creating a relation from scratch - for data view or for an object (#2605)
* DROID-467 Relations | Refactoring | New API for creating options - for tags and statuses (#2607)
* DROID-470 Relations | Refactoring | New API for removing any relation from an object or from a data view (#2608)
* DROID-460 Tech | Object relations list (#2610)
* DROID-486 Sets | Refactoring | Displaying and controlling visibility of data view relations (#2611)
* DROID-500 Relations | Refactoring | Extend API of ObjectStore to be able to get a relation by its id (#2619)
* DROID-459 Sets | Fix | Get relations from store by id and not by key (#2618)
* DROID-489 Tech | Relations as object, add relationKey to relation connected screens (#2622)
* DROID-490 Sets | Refactoring | Displaying relation values for current object in bottom sheet cells (#2629)
* DROID-505 Relations | Refactoring | New interface for relations store (#2633)
* DROID-509 Relations | Refactoring | Bind new relations store with subscription container (#2635)
* DROID-507 Tech | MW , migration + relation links (#2636)
* DROID-507 Tech | MW , migration + relation links, fixes (#2637)
* DROID-517 Sets | Fix | Provide correct keys for data view search-and-subscribe query (#2641)
* DROID-409 Relations | Refactoring | Use relation key instead of id when creating new relation (#2642)
* DROID-521 Sets & Objects | Refactoring | Add relation to a data view or to an object from existing relations (#2644)
* DROID-522 Relations | Refactoring | Add objects to relations with object format (#2645)
* DROID-523 Object types | Refactoring | Implement global store for object types (#2646)
* DROID-527 Object types | Refactoring | Integrate global store for object types (#2647)
* DROID-531 Relations | Refactoring | Parse tag and status relations values (#2649)
* DROID-535 Tech | Integrate new MW lib with migration fixes (#2653)
* DROID-535 Tech | MW integration fixes (#2660)
* DROID-559 Relations | Refactoring | Parse tag and status values in editor (#2662)
* DROID-560 Relations | Refactoring | Integrate new lib with fixes (#2663)
* DROID-561 Relations | Refactoring | Parsing tag and status values in dv (#2665)
* DROID-562 Dashboard | Refactoring | Use store of object types as object type provider for favorites tab on dashboard (#2667)
* DROID-567 Relations | Refactoring | Suggest available options to populate a relation (#2671)
* DROID-604 Relations | Refactoring | Use details from Object.CreateRelation.Response to populate relation store (#2705)
* DROID-603 Relations | Refactoring | Creating relation options + Deleting relation from object (#2706)
* DROID-619 Relations | Refactoring | Migrate data view sorts and filters to the new relation-as-object paradigm (#2711)
* DROID-622 Relations | Tech | Update MW to 0.24.0-rc1 (#2714)
* DROID-598 Sets | Refactoring | Provide relation format for date filters (#2715)
* DROID-625 Protocol | Enhancement | Integrate v0.24.0-rc2 (#2718)
2022-11-24 18:11:19 +03:00

218 lines
8.8 KiB
Kotlin

package com.anytypeio.anytype.ui.sets.modals.filter
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import androidx.core.os.bundleOf
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_ui.extensions.relationIcon
import com.anytypeio.anytype.core_ui.features.sets.CreateFilterAdapter
import com.anytypeio.anytype.core_ui.reactive.clicks
import com.anytypeio.anytype.core_ui.reactive.textChanges
import com.anytypeio.anytype.core_utils.ext.arg
import com.anytypeio.anytype.core_utils.ext.drawable
import com.anytypeio.anytype.core_utils.ext.gone
import com.anytypeio.anytype.core_utils.ext.invisible
import com.anytypeio.anytype.core_utils.ext.subscribe
import com.anytypeio.anytype.core_utils.ext.visible
import com.anytypeio.anytype.core_utils.ext.withParent
import com.anytypeio.anytype.core_utils.ui.BaseFragment
import com.anytypeio.anytype.databinding.FragmentCreateOrUpdateFilterBinding
import com.anytypeio.anytype.di.common.componentManager
import com.anytypeio.anytype.presentation.sets.filter.FilterViewModel
import com.anytypeio.anytype.presentation.sets.model.Viewer
import com.anytypeio.anytype.ui.relations.RelationTextValueFragment
import com.anytypeio.anytype.ui.sets.modals.DatePickerFragment
import com.anytypeio.anytype.ui.sets.modals.DatePickerFragment.DatePickerReceiver
import com.anytypeio.anytype.ui.sets.modals.PickFilterConditionFragment
import com.anytypeio.anytype.ui.sets.modals.filter.CreateFilterFromInputFieldValueFragment.Companion.FILTER_INDEX_EMPTY
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.onStart
import javax.inject.Inject
open class CreateFilterFromSelectedValueFragment :
BaseFragment<FragmentCreateOrUpdateFilterBinding>(R.layout.fragment_create_or_update_filter),
UpdateConditionActionReceiver,
DatePickerReceiver,
RelationTextValueFragment.TextValueEditReceiver {
private val ctx: String get() = arg(CTX_KEY)
private val relation: String get() = arg(RELATION_KEY)
private val helper = FilterHelper()
private lateinit var searchRelationInput: EditText
lateinit var clearSearchText: View
@Inject
lateinit var factory: FilterViewModel.Factory
private val vm: FilterViewModel by viewModels { factory }
private val createFilterAdapter by lazy {
CreateFilterAdapter(
onItemClicked = vm::onFilterItemClicked
)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.btnBottomAction.setText(R.string.create)
searchRelationInput = binding.searchBar.root.findViewById(R.id.filterInputField)
searchRelationInput.apply {
hint = getString(R.string.choose_options)
}
clearSearchText = binding.searchBar.root.findViewById(R.id.clearSearchText)
clearSearchText.setOnClickListener {
searchRelationInput.setText("")
clearSearchText.invisible()
}
binding.rvViewerFilterRecycler.apply {
layoutManager = LinearLayoutManager(context)
adapter = createFilterAdapter
addItemDecoration(
DividerItemDecoration(context, DividerItemDecoration.VERTICAL).apply {
setDrawable(drawable(R.drawable.divider_filter_list))
}
)
}
with(lifecycleScope) {
subscribe(binding.tvFilterCondition.clicks()) {
vm.onConditionClicked()
}
subscribe(binding.btnBottomAction.clicks()) {
vm.onCreateFilterFromSelectedValueClicked(ctx = ctx, relation = relation)
}
subscribe(vm.relationState.filterNotNull()) {
binding.tvRelationName.text = it.title
binding.ivRelationIcon.setImageResource(it.format.relationIcon(true))
}
subscribe(vm.optionCountState) { binding.tvOptionCount.text = it.toString() }
subscribe(vm.isCompleted) { isCompleted ->
if (isCompleted) withParent<CreateFilterFlow> { onFilterCreated() }
}
subscribe(vm.conditionState) {
binding.tvFilterCondition.text = it?.condition?.title
}
subscribe(searchRelationInput.textChanges()) {
if (it.isEmpty()) {
clearSearchText.invisible()
} else {
clearSearchText.visible()
}
}
val queries = searchRelationInput.textChanges()
.onStart { emit(searchRelationInput.text.toString()) }
val views =
vm.filterValueListState.combine(queries) { views, query ->
if (views.isEmpty()) {
views
} else {
views.filter { it.text.contains(query, true) }
}
}
subscribe(views) { createFilterAdapter.update(it) }
subscribe(vm.commands) { observeCommands(it) }
}
}
override fun onTextValueChanged(ctx: Id, text: String, objectId: Id, relationKey: Key) {}
override fun onNumberValueChanged(ctx: Id, number: Double?, objectId: Id, relationKey: Key) {
helper.handleNumberValueChanged(this, number, vm)
}
override fun onStart() {
super.onStart()
vm.onStart(relationKey = relation, filterIndex = FILTER_INDEX_EMPTY)
}
override fun onStop() {
super.onStop()
vm.onStop()
}
private fun observeCommands(commands: FilterViewModel.Commands) {
when (commands) {
is FilterViewModel.Commands.OpenDatePicker -> {
DatePickerFragment.new(commands.timeInSeconds)
.show(childFragmentManager, null)
}
is FilterViewModel.Commands.OpenConditionPicker -> {
PickFilterConditionFragment.new(
ctx = ctx,
mode = PickFilterConditionFragment.MODE_CREATE,
type = commands.type,
index = commands.index
).show(childFragmentManager, null)
}
FilterViewModel.Commands.ShowCount -> binding.tvOptionCount.visible()
FilterViewModel.Commands.HideCount -> binding.tvOptionCount.gone()
FilterViewModel.Commands.ShowSearchbar -> binding.searchBar.root.visible()
FilterViewModel.Commands.HideSearchbar -> binding.searchBar.root.gone()
FilterViewModel.Commands.DateDivider -> setDivider(R.drawable.divider_relation_date)
FilterViewModel.Commands.ObjectDivider -> setDivider(R.drawable.divider_relation_object)
FilterViewModel.Commands.TagDivider -> setDivider(R.drawable.divider_relation_tag)
FilterViewModel.Commands.ShowInput -> {}
FilterViewModel.Commands.HideInput -> {}
is FilterViewModel.Commands.OpenNumberPicker -> {
helper.handleOpenNumberPicker(
fragment = this,
command = commands,
ctx = ctx
)
}
}
}
private fun setDivider(divider: Int) {
binding.rvViewerFilterRecycler.apply {
addItemDecoration(
DividerItemDecoration(context, DividerItemDecoration.VERTICAL).apply {
setDrawable(drawable(divider))
}
)
}
}
override fun update(condition: Viewer.Filter.Condition) {
vm.onConditionUpdate(condition)
}
override fun onPickDate(timeInSeconds: Long) {
vm.onExactDayPicked(timeInSeconds)
}
override fun injectDependencies() {
componentManager().createFilterComponent.get(ctx).inject(this)
}
override fun releaseDependencies() {
componentManager().createFilterComponent.release(ctx)
}
override fun inflateBinding(
inflater: LayoutInflater,
container: ViewGroup?
): FragmentCreateOrUpdateFilterBinding = FragmentCreateOrUpdateFilterBinding.inflate(
inflater, container, false
)
companion object {
fun new(ctx: Id, relation: Id): CreateFilterFromSelectedValueFragment = CreateFilterFromSelectedValueFragment().apply {
arguments = bundleOf(CTX_KEY to ctx, RELATION_KEY to relation)
}
const val CTX_KEY = "arg.create-filter-relation.ctx"
const val RELATION_KEY = "arg.create-filter-relation.relation"
}
}