* 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)
283 lines
10 KiB
Kotlin
283 lines
10 KiB
Kotlin
package com.anytypeio.anytype.ui.relations
|
|
|
|
import android.content.res.Resources
|
|
import android.os.Bundle
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import android.view.ViewGroup
|
|
import android.widget.EditText
|
|
import android.widget.FrameLayout
|
|
import androidx.core.os.bundleOf
|
|
import androidx.fragment.app.viewModels
|
|
import androidx.lifecycle.lifecycleScope
|
|
import androidx.navigation.fragment.findNavController
|
|
import androidx.recyclerview.widget.ConcatAdapter
|
|
import androidx.recyclerview.widget.DividerItemDecoration
|
|
import androidx.recyclerview.widget.LinearLayoutManager
|
|
import com.anytypeio.anytype.R
|
|
import com.anytypeio.anytype.analytics.base.EventsDictionary
|
|
import com.anytypeio.anytype.core_models.Id
|
|
import com.anytypeio.anytype.core_ui.features.relations.RelationAddAdapter
|
|
import com.anytypeio.anytype.core_ui.features.relations.RelationAddHeaderAdapter
|
|
import com.anytypeio.anytype.core_ui.reactive.focusChanges
|
|
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.invisible
|
|
import com.anytypeio.anytype.core_utils.ext.statusBarHeight
|
|
import com.anytypeio.anytype.core_utils.ext.subscribe
|
|
import com.anytypeio.anytype.core_utils.ext.toast
|
|
import com.anytypeio.anytype.core_utils.ext.visible
|
|
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetTextInputFragment
|
|
import com.anytypeio.anytype.databinding.FragmentRelationAddBinding
|
|
import com.anytypeio.anytype.di.common.componentManager
|
|
import com.anytypeio.anytype.presentation.relations.RelationAddToDataViewViewModel
|
|
import com.anytypeio.anytype.presentation.relations.RelationAddToObjectViewModel
|
|
import com.anytypeio.anytype.presentation.relations.RelationAddViewModelBase
|
|
import com.anytypeio.anytype.presentation.relations.model.RelationView
|
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
import java.io.Serializable
|
|
import javax.inject.Inject
|
|
|
|
|
|
abstract class RelationAddBaseFragment : BaseBottomSheetTextInputFragment<FragmentRelationAddBinding>() {
|
|
|
|
abstract val vm: RelationAddViewModelBase
|
|
|
|
override val textInput: EditText get() = binding.searchBar.root.findViewById(R.id.filterInputField)
|
|
|
|
abstract val ctx: String
|
|
|
|
private lateinit var searchRelationInput: EditText
|
|
lateinit var clearSearchText: View
|
|
|
|
protected val createFromScratchAdapter = RelationAddHeaderAdapter {
|
|
onCreateFromScratchClicked()
|
|
}
|
|
|
|
private val relationAdapter = RelationAddAdapter { relation ->
|
|
onRelationSelected(ctx = ctx, relation = relation)
|
|
}
|
|
|
|
private val concatAdapter = ConcatAdapter(createFromScratchAdapter, relationAdapter)
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
super.onViewCreated(view, savedInstanceState)
|
|
searchRelationInput = binding.searchBar.root.findViewById(R.id.filterInputField)
|
|
searchRelationInput.apply {
|
|
hint = getString(R.string.find_a_relation)
|
|
}
|
|
clearSearchText = binding.searchBar.root.findViewById(R.id.clearSearchText)
|
|
clearSearchText.setOnClickListener {
|
|
searchRelationInput.setText("")
|
|
clearSearchText.invisible()
|
|
}
|
|
setupFullHeight()
|
|
binding.relationAddRecycler.apply {
|
|
layoutManager = LinearLayoutManager(context)
|
|
adapter = concatAdapter
|
|
addItemDecoration(
|
|
DividerItemDecoration(context, DividerItemDecoration.VERTICAL).apply {
|
|
setDrawable(drawable(R.drawable.divider_relations_with_padding))
|
|
}
|
|
)
|
|
}
|
|
with(lifecycleScope) {
|
|
subscribe(searchRelationInput.focusChanges()) { hasFocus -> if (hasFocus) expand(view) }
|
|
subscribe(searchRelationInput.textChanges()) {
|
|
createFromScratchAdapter.query = it.toString()
|
|
vm.onQueryChanged(it.toString())
|
|
}
|
|
subscribe(vm.results) { relationAdapter.submitList(it) }
|
|
subscribe(vm.isDismissed) { isDismissed -> if (isDismissed) dismiss() }
|
|
subscribe(vm.toasts) { toast(it) }
|
|
subscribe(searchRelationInput.textChanges()) {
|
|
if (it.isEmpty()) clearSearchText.invisible() else clearSearchText.visible()
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun setupFullHeight() {
|
|
val lp = (binding.root.layoutParams as FrameLayout.LayoutParams)
|
|
lp.height =
|
|
Resources.getSystem().displayMetrics.heightPixels - requireActivity().statusBarHeight
|
|
binding.root.layoutParams = lp
|
|
}
|
|
|
|
private fun expand(root: View) {
|
|
BottomSheetBehavior.from(root.parent as View).state = BottomSheetBehavior.STATE_EXPANDED
|
|
}
|
|
|
|
override fun onStart() {
|
|
super.onStart()
|
|
vm.onStart()
|
|
}
|
|
|
|
abstract fun onRelationSelected(ctx: Id, relation: RelationView.Existing)
|
|
abstract fun onCreateFromScratchClicked()
|
|
|
|
override fun inflateBinding(
|
|
inflater: LayoutInflater,
|
|
container: ViewGroup?
|
|
): FragmentRelationAddBinding = FragmentRelationAddBinding.inflate(
|
|
inflater, container, false
|
|
)
|
|
|
|
companion object {
|
|
const val CTX_KEY = "arg.relation-add.ctx"
|
|
}
|
|
}
|
|
|
|
class RelationAddToObjectFragment : RelationAddBaseFragment() {
|
|
|
|
override val ctx get() = arg<Id>(CTX_KEY)
|
|
|
|
@Inject
|
|
lateinit var factory: RelationAddToObjectViewModel.Factory
|
|
override val vm: RelationAddToObjectViewModel by viewModels { factory }
|
|
|
|
override fun onRelationSelected(ctx: Id, relation: RelationView.Existing) {
|
|
vm.onRelationSelected(
|
|
ctx = ctx,
|
|
relation = relation,
|
|
screenType = EventsDictionary.Type.menu
|
|
)
|
|
}
|
|
|
|
override fun onCreateFromScratchClicked() {
|
|
RelationCreateFromScratchForObjectFragment
|
|
.new(
|
|
ctx = ctx,
|
|
query = createFromScratchAdapter.query
|
|
)
|
|
.show(childFragmentManager, null)
|
|
}
|
|
|
|
override fun injectDependencies() {
|
|
componentManager().relationAddToObjectComponent.get(ctx).inject(this)
|
|
}
|
|
|
|
override fun releaseDependencies() {
|
|
componentManager().relationAddToObjectComponent.release(ctx)
|
|
}
|
|
|
|
companion object {
|
|
fun new(ctx: Id) = RelationAddToObjectFragment().apply {
|
|
arguments = bundleOf(CTX_KEY to ctx)
|
|
}
|
|
}
|
|
}
|
|
|
|
class RelationAddToDataViewFragment : RelationAddBaseFragment() {
|
|
|
|
private val dv get() = arg<Id>(DV_KEY)
|
|
override val ctx get() = arg<Id>(CTX_KEY)
|
|
|
|
@Inject
|
|
lateinit var factory: RelationAddToDataViewViewModel.Factory
|
|
override val vm: RelationAddToDataViewViewModel by viewModels { factory }
|
|
|
|
override fun onRelationSelected(ctx: Id, relation: RelationView.Existing) {
|
|
vm.onRelationSelected(
|
|
ctx = ctx,
|
|
relation = relation,
|
|
dv = dv,
|
|
screenType = EventsDictionary.Type.dataView
|
|
)
|
|
}
|
|
|
|
override fun onCreateFromScratchClicked() {
|
|
RelationCreateFromScratchForDataViewFragment
|
|
.new(
|
|
ctx = ctx,
|
|
dv = dv,
|
|
query = createFromScratchAdapter.query
|
|
)
|
|
.show(childFragmentManager, null)
|
|
}
|
|
|
|
override fun injectDependencies() {
|
|
componentManager().relationAddToDataViewComponent.get(ctx).inject(this)
|
|
}
|
|
|
|
override fun releaseDependencies() {
|
|
componentManager().relationAddToDataViewComponent.release(ctx)
|
|
}
|
|
|
|
companion object {
|
|
fun new(ctx: Id, dv: Id, viewer: Id): RelationAddToDataViewFragment =
|
|
RelationAddToDataViewFragment().apply {
|
|
arguments = bundleOf(
|
|
CTX_KEY to ctx,
|
|
DV_KEY to dv,
|
|
VIEWER_KEY to viewer
|
|
)
|
|
}
|
|
|
|
private const val DV_KEY = "arg.relation-add-to-data-view.dv"
|
|
private const val VIEWER_KEY = "arg.relation-add-to-data-view.viewer"
|
|
}
|
|
}
|
|
|
|
class RelationAddToObjectBlockFragment : RelationAddBaseFragment() {
|
|
|
|
override val ctx get() = arg<Id>(CTX_KEY)
|
|
private val target get() = arg<Id>(TARGET_KEY)
|
|
|
|
@Inject
|
|
lateinit var factory: RelationAddToObjectViewModel.Factory
|
|
override val vm: RelationAddToObjectViewModel by viewModels { factory }
|
|
|
|
override fun onStart() {
|
|
with(lifecycleScope) {
|
|
jobs += subscribe(vm.commands) { execute(it) }
|
|
}
|
|
super.onStart()
|
|
}
|
|
|
|
override fun onRelationSelected(ctx: Id, relation: RelationView.Existing) {
|
|
vm.onRelationSelected(
|
|
ctx = ctx,
|
|
relation = relation,
|
|
screenType = EventsDictionary.Type.block
|
|
)
|
|
}
|
|
|
|
private fun execute(command: RelationAddToObjectViewModel.Command) {
|
|
when (command) {
|
|
is RelationAddToObjectViewModel.Command.OnRelationAdd -> {
|
|
findNavController().run {
|
|
val result = RelationAddResult(target = target, relation = command.relation)
|
|
previousBackStackEntry?.savedStateHandle?.set(RELATION_ADD_RESULT_KEY, result)
|
|
popBackStack()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
override fun onCreateFromScratchClicked() {
|
|
findNavController().navigate(
|
|
R.id.action_relationAddToObjectBlockFragment_to_relationCreateFromScratchForObjectBlockFragment,
|
|
bundleOf(
|
|
RelationCreateFromScratchBaseFragment.CTX_KEY to ctx,
|
|
RelationCreateFromScratchBaseFragment.QUERY_KEY to createFromScratchAdapter.query,
|
|
RelationCreateFromScratchForObjectBlockFragment.TARGET_KEY to target
|
|
)
|
|
)
|
|
}
|
|
|
|
override fun injectDependencies() {
|
|
componentManager().relationAddToObjectComponent.get(ctx).inject(this)
|
|
}
|
|
|
|
override fun releaseDependencies() {
|
|
componentManager().relationAddToObjectComponent.release(ctx)
|
|
}
|
|
|
|
companion object {
|
|
const val TARGET_KEY = "arg.relation-add-to-object-block.target"
|
|
const val RELATION_ADD_RESULT_KEY = "arg.relation-add-to-object-block.result"
|
|
}
|
|
}
|
|
|
|
data class RelationAddResult(val target: String, val relation: String) : Serializable |