mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Editor | Feature | Link to (#1746)
* move to redesign * design fixes * design fixes * fixes * fix * move to fixes * fixes * fix * ci * link to screen * fixes * delete link to object use case * link to object * fixes * fix * fix * Update check.yml
This commit is contained in:
parent
219fbdb83a
commit
7a054b2d9d
23 changed files with 316 additions and 563 deletions
|
@ -1,12 +1,12 @@
|
|||
package com.anytypeio.anytype.di.feature
|
||||
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
|
||||
import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider
|
||||
import com.anytypeio.anytype.domain.block.interactor.CreateLinkToObject
|
||||
import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.domain.config.GetConfig
|
||||
import com.anytypeio.anytype.domain.config.GetFlavourConfig
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.page.navigation.GetObjectInfoWithLinks
|
||||
import com.anytypeio.anytype.presentation.linking.LinkToObjectViewModelFactory
|
||||
import com.anytypeio.anytype.ui.linking.LinkToObjectFragment
|
||||
import dagger.Module
|
||||
|
@ -31,41 +31,30 @@ interface LinkToObjectSubComponent {
|
|||
@Module
|
||||
object LinkToObjectModule {
|
||||
|
||||
@JvmStatic
|
||||
@PerScreen
|
||||
@Provides
|
||||
fun provideGetPageInfoWithLinks(
|
||||
repo: BlockRepository
|
||||
): GetObjectInfoWithLinks = GetObjectInfoWithLinks(repo = repo)
|
||||
|
||||
@JvmStatic
|
||||
@PerScreen
|
||||
@Provides
|
||||
fun provideLinkToObjectViewModelFactory(
|
||||
urlBuilder: UrlBuilder,
|
||||
getObjectInfoWithLinks: GetObjectInfoWithLinks,
|
||||
createLinkToObject: CreateLinkToObject,
|
||||
getConfig: GetConfig,
|
||||
objectTypesProvider: ObjectTypesProvider
|
||||
getObjectTypes: GetObjectTypes,
|
||||
searchObjects: SearchObjects,
|
||||
getFlavourConfig: GetFlavourConfig,
|
||||
analytics: Analytics
|
||||
): LinkToObjectViewModelFactory = LinkToObjectViewModelFactory(
|
||||
urlBuilder = urlBuilder,
|
||||
getObjectInfoWithLinks = getObjectInfoWithLinks,
|
||||
createLinkToObject = createLinkToObject,
|
||||
getConfig = getConfig,
|
||||
objectTypesProvider = objectTypesProvider
|
||||
getObjectTypes = getObjectTypes,
|
||||
searchObjects = searchObjects,
|
||||
analytics = analytics,
|
||||
getFlavourConfig = getFlavourConfig
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@PerScreen
|
||||
@Provides
|
||||
fun provideCreateLinkToObjectUseCase(
|
||||
repo: BlockRepository
|
||||
): CreateLinkToObject = CreateLinkToObject(repo)
|
||||
fun getObjectTypes(repo: BlockRepository): GetObjectTypes = GetObjectTypes(repo = repo)
|
||||
|
||||
@JvmStatic
|
||||
@PerScreen
|
||||
@Provides
|
||||
fun provideGetConfigUseCase(
|
||||
repo: BlockRepository
|
||||
): GetConfig = GetConfig(repo)
|
||||
fun searchObjects(repo: BlockRepository): SearchObjects = SearchObjects(repo = repo)
|
||||
}
|
|
@ -6,15 +6,12 @@ import androidx.navigation.NavController
|
|||
import androidx.navigation.navOptions
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Position
|
||||
import com.anytypeio.anytype.presentation.navigation.AppNavigation
|
||||
import com.anytypeio.anytype.presentation.settings.EditorSettings
|
||||
import com.anytypeio.anytype.ui.archive.ArchiveFragment
|
||||
import com.anytypeio.anytype.ui.auth.Keys
|
||||
import com.anytypeio.anytype.ui.auth.account.CreateAccountFragment.Companion.ARGS_CODE
|
||||
import com.anytypeio.anytype.ui.editor.EditorFragment
|
||||
import com.anytypeio.anytype.ui.linking.LinkToObjectFragment
|
||||
import com.anytypeio.anytype.ui.moving.MoveToFragment
|
||||
import com.anytypeio.anytype.ui.navigation.PageNavigationFragment
|
||||
import com.anytypeio.anytype.ui.sets.CreateObjectSetFragment
|
||||
import com.anytypeio.anytype.ui.sets.ObjectSetFragment
|
||||
|
@ -168,16 +165,6 @@ class Navigator : AppNavigation {
|
|||
navController?.navigate(R.id.pageNavigationFragment, bundle)
|
||||
}
|
||||
|
||||
override fun openLinkTo(target: String, context: String, replace: Boolean, position: Position) {
|
||||
val bundle = bundleOf(
|
||||
LinkToObjectFragment.TARGET_ID_KEY to target,
|
||||
LinkToObjectFragment.CONTEXT_ID_KEY to context,
|
||||
LinkToObjectFragment.REPLACE_KEY to replace,
|
||||
LinkToObjectFragment.POSITION_KEY to position.name
|
||||
)
|
||||
navController?.navigate(R.id.linkToFragment, bundle)
|
||||
}
|
||||
|
||||
override fun openPageSearch() {
|
||||
navController?.navigate(R.id.pageSearchFragment)
|
||||
}
|
||||
|
|
|
@ -52,12 +52,6 @@ abstract class NavigationFragment(
|
|||
is Command.ExitToDesktop -> navigation.exitToDesktop()
|
||||
is Command.OpenDebugSettingsScreen -> navigation.openDebugSettings()
|
||||
is Command.OpenPageNavigationScreen -> navigation.openPageNavigation(command.target)
|
||||
is Command.OpenLinkToScreen -> navigation.openLinkTo(
|
||||
command.target,
|
||||
command.context,
|
||||
command.replace,
|
||||
command.position
|
||||
)
|
||||
is Command.ExitToDesktopAndOpenPage -> navigation.exitToDesktopAndOpenPage(command.pageId)
|
||||
is Command.OpenPageSearch -> navigation.openPageSearch()
|
||||
is Command.OpenCreateSetScreen -> navigation.openCreateSetScreen(command.ctx)
|
||||
|
|
|
@ -39,8 +39,6 @@ import androidx.transition.TransitionManager
|
|||
import androidx.transition.TransitionSet
|
||||
import com.anytypeio.anytype.BuildConfig
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Block.Content.Text
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.SyncStatus
|
||||
|
@ -82,6 +80,8 @@ import com.anytypeio.anytype.ui.editor.modals.*
|
|||
import com.anytypeio.anytype.ui.editor.modals.actions.BlockActionToolbarFactory
|
||||
import com.anytypeio.anytype.ui.editor.sheets.ObjectMenuBaseFragment.DocumentMenuActionReceiver
|
||||
import com.anytypeio.anytype.ui.editor.sheets.ObjectMenuFragment
|
||||
import com.anytypeio.anytype.ui.linking.LinkToObjectFragment
|
||||
import com.anytypeio.anytype.ui.linking.OnLinkToAction
|
||||
import com.anytypeio.anytype.ui.moving.MoveToFragment
|
||||
import com.anytypeio.anytype.ui.moving.OnMoveToAction
|
||||
import com.anytypeio.anytype.ui.objects.ObjectTypeChangeFragment
|
||||
|
@ -107,7 +107,6 @@ const val REQUEST_FILE_CODE = 745
|
|||
@RuntimePermissions
|
||||
open class EditorFragment : NavigationFragment(R.layout.fragment_editor),
|
||||
OnFragmentInteractionListener,
|
||||
AddBlockFragment.AddBlockActionReceiver,
|
||||
TurnIntoActionReceiver,
|
||||
SelectProgrammingLanguageReceiver,
|
||||
RelationTextValueFragment.TextValueEditReceiver,
|
||||
|
@ -116,6 +115,7 @@ open class EditorFragment : NavigationFragment(R.layout.fragment_editor),
|
|||
ClipboardInterceptor,
|
||||
DocCoverAction,
|
||||
OnMoveToAction,
|
||||
OnLinkToAction,
|
||||
PickiTCallbacks {
|
||||
|
||||
private val ctx get() = arg<Id>(ID_KEY)
|
||||
|
@ -302,13 +302,6 @@ open class EditorFragment : NavigationFragment(R.layout.fragment_editor),
|
|||
}
|
||||
}
|
||||
|
||||
override fun onAddObjectClicked(url: String, layout: ObjectType.Layout) {
|
||||
vm.onAddNewObjectClicked(
|
||||
type = url,
|
||||
layout = layout
|
||||
)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
when (requestCode) {
|
||||
|
@ -634,31 +627,6 @@ open class EditorFragment : NavigationFragment(R.layout.fragment_editor),
|
|||
vm.onAddBookmarkUrl(target = target, url = url)
|
||||
}
|
||||
|
||||
override fun onAddBlockClicked(block: UiBlock) {
|
||||
when (block) {
|
||||
UiBlock.TEXT -> vm.onAddTextBlockClicked(Text.Style.P)
|
||||
UiBlock.HEADER_ONE -> vm.onAddTextBlockClicked(Text.Style.H1)
|
||||
UiBlock.HEADER_TWO -> vm.onAddTextBlockClicked(Text.Style.H2)
|
||||
UiBlock.HEADER_THREE -> vm.onAddTextBlockClicked(Text.Style.H3)
|
||||
UiBlock.HIGHLIGHTED -> vm.onAddTextBlockClicked(Text.Style.QUOTE)
|
||||
UiBlock.CHECKBOX -> vm.onAddTextBlockClicked(Text.Style.CHECKBOX)
|
||||
UiBlock.BULLETED -> vm.onAddTextBlockClicked(Text.Style.BULLET)
|
||||
UiBlock.NUMBERED -> vm.onAddTextBlockClicked(Text.Style.NUMBERED)
|
||||
UiBlock.TOGGLE -> vm.onAddTextBlockClicked(Text.Style.TOGGLE)
|
||||
UiBlock.CODE -> vm.onAddTextBlockClicked(Text.Style.CODE_SNIPPET)
|
||||
UiBlock.PAGE -> vm.onAddNewPageClicked()
|
||||
UiBlock.FILE -> vm.onAddFileBlockClicked(Block.Content.File.Type.FILE)
|
||||
UiBlock.IMAGE -> vm.onAddFileBlockClicked(Block.Content.File.Type.IMAGE)
|
||||
UiBlock.VIDEO -> vm.onAddFileBlockClicked(Block.Content.File.Type.VIDEO)
|
||||
UiBlock.BOOKMARK -> vm.onAddBookmarkBlockClicked()
|
||||
UiBlock.LINE_DIVIDER -> vm.onAddDividerBlockClicked(Block.Content.Divider.Style.LINE)
|
||||
UiBlock.THREE_DOTS -> vm.onAddDividerBlockClicked(Block.Content.Divider.Style.DOTS)
|
||||
UiBlock.LINK_TO_OBJECT -> vm.onAddLinkToObjectClicked()
|
||||
UiBlock.RELATION -> vm.onAddRelationBlockClicked()
|
||||
else -> toast(NOT_IMPLEMENTED_MESSAGE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTurnIntoBlockClicked(target: String, uiBlock: UiBlock) {
|
||||
vm.onTurnIntoBlockClicked(target, uiBlock)
|
||||
}
|
||||
|
@ -991,6 +959,16 @@ open class EditorFragment : NavigationFragment(R.layout.fragment_editor),
|
|||
fr.show(childFragmentManager, null)
|
||||
}
|
||||
}
|
||||
is Command.OpenLinkToScreen -> {
|
||||
lifecycleScope.launch {
|
||||
hideSoftInput()
|
||||
delay(DEFAULT_ANIM_DURATION)
|
||||
val fr = LinkToObjectFragment.new(
|
||||
target = command.target
|
||||
)
|
||||
fr.show(childFragmentManager, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1733,6 +1711,13 @@ open class EditorFragment : NavigationFragment(R.layout.fragment_editor),
|
|||
)
|
||||
}
|
||||
|
||||
override fun onLinkTo(link: Id, target: Id) {
|
||||
vm.proceedWithLinkToAction(
|
||||
link = link,
|
||||
target = target
|
||||
)
|
||||
}
|
||||
|
||||
//------------ End of Anytype Custom Context Menu ------------
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -27,6 +27,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
|
|||
import kotlinx.android.synthetic.main.fragment_add_block.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@Deprecated("To be deleted")
|
||||
class AddBlockFragment : BaseBottomSheetFragment() {
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -1,219 +1,194 @@
|
|||
package com.anytypeio.anytype.ui.linking
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.core.view.minusAssign
|
||||
import androidx.core.view.plusAssign
|
||||
import android.view.ViewGroup
|
||||
import android.widget.EditText
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.widget.doAfterTextChanged
|
||||
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_ui.features.navigation.FilterView
|
||||
import com.anytypeio.anytype.core_ui.features.navigation.PageNavigationAdapter
|
||||
import com.anytypeio.anytype.core_ui.layout.AppBarLayoutStateChangeListener
|
||||
import com.anytypeio.anytype.core_ui.layout.State
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_ui.features.navigation.DefaultObjectViewAdapter
|
||||
import com.anytypeio.anytype.core_utils.ext.*
|
||||
import com.anytypeio.anytype.core_utils.ui.ViewState
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetFragment
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.core_models.Position
|
||||
import com.anytypeio.anytype.emojifier.Emojifier
|
||||
import com.anytypeio.anytype.presentation.linking.LinkToObjectViewModel
|
||||
import com.anytypeio.anytype.presentation.linking.LinkToObjectViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.navigation.PageNavigationView
|
||||
import com.anytypeio.anytype.ui.base.ViewStateFragment
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import kotlinx.android.synthetic.main.fragment_link_to_object.*
|
||||
import kotlinx.android.synthetic.main.view_link_to_object_bottom.*
|
||||
import kotlinx.android.synthetic.main.view_link_to_object_preview.*
|
||||
import kotlinx.android.synthetic.main.view_page_navigation_open_bottom.avatarSmall
|
||||
import kotlinx.android.synthetic.main.view_page_navigation_open_bottom.pageTitleSmall
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchView
|
||||
import com.anytypeio.anytype.ui.search.ObjectSearchFragment
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import kotlinx.android.synthetic.main.fragment_link_to_object.progressBar
|
||||
import kotlinx.android.synthetic.main.fragment_object_search.*
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class LinkToObjectFragment :
|
||||
ViewStateFragment<ViewState<PageNavigationView>>(R.layout.fragment_link_to_object) {
|
||||
|
||||
private val position: Position
|
||||
get() {
|
||||
val args = requireArguments()
|
||||
val value = args.getString(POSITION_KEY)
|
||||
checkNotNull(value)
|
||||
return Position.valueOf(value)
|
||||
}
|
||||
|
||||
private val replace: Boolean
|
||||
get() = arguments?.getBoolean(REPLACE_KEY) ?: false
|
||||
|
||||
private val target: String
|
||||
get() = arguments?.getString(TARGET_ID_KEY) ?: throw IllegalStateException("Missing target")
|
||||
|
||||
private val targetContext: String
|
||||
get() = arguments?.getString(CONTEXT_ID_KEY)
|
||||
?: throw IllegalStateException("Missing target")
|
||||
class LinkToObjectFragment : BaseBottomSheetFragment() {
|
||||
|
||||
private val vm by viewModels<LinkToObjectViewModel> { factory }
|
||||
|
||||
@Inject
|
||||
lateinit var factory: LinkToObjectViewModelFactory
|
||||
|
||||
private lateinit var clearSearchText: View
|
||||
private lateinit var filterInputField: EditText
|
||||
|
||||
private val target get() = arg<Id>(ARG_TARGET)
|
||||
|
||||
private val moveToAdapter by lazy {
|
||||
DefaultObjectViewAdapter(
|
||||
onClick = vm::onObjectClicked
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? = inflater.inflate(R.layout.fragment_object_search, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
vm.state.observe(viewLifecycleOwner, this)
|
||||
vm.navigation.observe(viewLifecycleOwner, navObserver)
|
||||
observeLinkingButtonState()
|
||||
vm.onViewCreated()
|
||||
}
|
||||
|
||||
private fun observeLinkingButtonState() {
|
||||
lifecycleScope.launch {
|
||||
vm.isLinkingDisabled.collect { isDisabled ->
|
||||
if (isDisabled)
|
||||
disableLinking()
|
||||
else
|
||||
enableLinking()
|
||||
}
|
||||
setupFullHeight()
|
||||
setTransparent()
|
||||
BottomSheetBehavior.from(sheet).apply {
|
||||
state = BottomSheetBehavior.STATE_EXPANDED
|
||||
isHideable = true
|
||||
addBottomSheetCallback(
|
||||
object : BottomSheetBehavior.BottomSheetCallback() {
|
||||
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
|
||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
|
||||
vm.onBottomSheetHidden()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
vm.state.observe(viewLifecycleOwner, { observe(it) })
|
||||
clearSearchText = searchView.findViewById(R.id.clearSearchText)
|
||||
filterInputField = searchView.findViewById(R.id.filterInputField)
|
||||
filterInputField.setHint(R.string.search)
|
||||
initialize()
|
||||
}
|
||||
|
||||
private fun enableLinking() {
|
||||
btnLinkToThisObject.isEnabled = true
|
||||
btnLinkToObjectSmall.isEnabled = true
|
||||
btnLinkToThisObject.alpha = 1f
|
||||
btnLinkToObjectSmall.alpha = 1f
|
||||
override fun onStart() {
|
||||
lifecycleScope.launch {
|
||||
jobs += subscribe(vm.commands) { execute(it) }
|
||||
}
|
||||
super.onStart()
|
||||
vm.onStart()
|
||||
expand()
|
||||
}
|
||||
|
||||
private fun disableLinking() {
|
||||
btnLinkToThisObject.isEnabled = false
|
||||
btnLinkToObjectSmall.isEnabled = false
|
||||
btnLinkToThisObject.alpha = 0.2f
|
||||
btnLinkToObjectSmall.alpha = 0.2f
|
||||
}
|
||||
|
||||
override fun render(state: ViewState<PageNavigationView>) {
|
||||
private fun observe(state: ObjectSearchView) {
|
||||
when (state) {
|
||||
ViewState.Init -> {
|
||||
appBarLayout.addOnOffsetChangedListener(
|
||||
object : AppBarLayoutStateChangeListener() {
|
||||
override fun onStateChanged(state: State) {
|
||||
if (state == State.COLLAPSED) {
|
||||
pagePreviewSmall.visible()
|
||||
} else {
|
||||
pagePreviewSmall.gone()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
viewPager.adapter = PageNavigationAdapter(
|
||||
onClick = { vm.onLinkClicked(it, targetContext) }
|
||||
) { links ->
|
||||
filterContainer.plusAssign(
|
||||
FilterView(requireContext()).apply {
|
||||
cancelClicked = { closeFilterView() }
|
||||
pageClicked = {
|
||||
closeFilterView()
|
||||
vm.onLinkClicked(it, targetContext)
|
||||
}
|
||||
bind(links)
|
||||
}
|
||||
)
|
||||
}
|
||||
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
|
||||
when (position) {
|
||||
POSITION_FROM -> tab.text = getString(R.string.page_nav_link_from)
|
||||
POSITION_TO -> tab.text = getString(R.string.page_nav_links_to)
|
||||
}
|
||||
}.attach()
|
||||
btnLinkToThisObject.setOnClickListener {
|
||||
vm.onLinkToObjectClicked(
|
||||
context = targetContext,
|
||||
target = target,
|
||||
replace = replace,
|
||||
position = position
|
||||
)
|
||||
}
|
||||
btnLinkToObjectSmall.setOnClickListener {
|
||||
vm.onLinkToObjectClicked(
|
||||
context = targetContext,
|
||||
target = target,
|
||||
replace = replace,
|
||||
position = position
|
||||
)
|
||||
}
|
||||
vm.onStart(targetContext)
|
||||
}
|
||||
ViewState.Loading -> {
|
||||
ObjectSearchView.Loading -> {
|
||||
recyclerView.invisible()
|
||||
tvScreenStateMessage.invisible()
|
||||
tvScreenStateSubMessage.invisible()
|
||||
progressBar.visible()
|
||||
}
|
||||
is ViewState.Success -> {
|
||||
is ObjectSearchView.Success -> {
|
||||
progressBar.invisible()
|
||||
state.data.title.let { title ->
|
||||
pageTitleSmall.text =
|
||||
if (title.isEmpty()) getString(R.string.untitled) else title
|
||||
tvPageTitle.text =
|
||||
if (title.isEmpty()) getString(R.string.untitled) else title
|
||||
}
|
||||
if (state.data.subtitle.isNotEmpty()) {
|
||||
tvPageSubtitle.visible()
|
||||
tvPageSubtitle.text = state.data.subtitle
|
||||
} else {
|
||||
tvPageSubtitle.text = null
|
||||
tvPageSubtitle.gone()
|
||||
}
|
||||
|
||||
imageIcon.setImageDrawable(null)
|
||||
avatarSmall.setImageDrawable(null)
|
||||
emojiIcon.setImageDrawable(null)
|
||||
|
||||
state.data.image?.let { url ->
|
||||
Glide
|
||||
.with(imageIcon)
|
||||
.load(url)
|
||||
.centerInside()
|
||||
.circleCrop()
|
||||
.into(imageIcon)
|
||||
Glide
|
||||
.with(avatarSmall)
|
||||
.load(url)
|
||||
.centerInside()
|
||||
.circleCrop()
|
||||
.into(avatarSmall)
|
||||
}
|
||||
|
||||
state.data.emoji?.let { emoji ->
|
||||
try {
|
||||
Glide
|
||||
.with(emojiIcon)
|
||||
.load(Emojifier.uri(emoji))
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.into(emojiIcon)
|
||||
Glide
|
||||
.with(avatarSmall)
|
||||
.load(Emojifier.uri(emoji))
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.into(avatarSmall)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error while setting emoji icon for: $emoji")
|
||||
}
|
||||
}
|
||||
|
||||
(viewPager.adapter as? PageNavigationAdapter)?.setPageLinks(
|
||||
inbound = state.data.inbound,
|
||||
outbound = state.data.outbound
|
||||
)
|
||||
tvScreenStateMessage.invisible()
|
||||
tvScreenStateSubMessage.invisible()
|
||||
recyclerView.visible()
|
||||
moveToAdapter.submitList(state.objects)
|
||||
}
|
||||
is ViewState.Error -> {
|
||||
ObjectSearchView.EmptyPages -> {
|
||||
progressBar.invisible()
|
||||
coordinatorLayout.showSnackbar(state.error)
|
||||
recyclerView.invisible()
|
||||
tvScreenStateMessage.visible()
|
||||
tvScreenStateMessage.text = getString(R.string.search_empty_pages)
|
||||
tvScreenStateSubMessage.invisible()
|
||||
}
|
||||
is ObjectSearchView.NoResults -> {
|
||||
progressBar.invisible()
|
||||
recyclerView.invisible()
|
||||
tvScreenStateMessage.visible()
|
||||
tvScreenStateMessage.text = getString(R.string.search_no_results, state.searchText)
|
||||
tvScreenStateSubMessage.visible()
|
||||
}
|
||||
is ObjectSearchView.Error -> {
|
||||
progressBar.invisible()
|
||||
recyclerView.invisible()
|
||||
tvScreenStateMessage.visible()
|
||||
tvScreenStateMessage.text = state.error
|
||||
tvScreenStateSubMessage.invisible()
|
||||
}
|
||||
else -> Timber.d("Skipping state: $state")
|
||||
}
|
||||
}
|
||||
|
||||
private fun execute(command: LinkToObjectViewModel.Command) {
|
||||
when (command) {
|
||||
LinkToObjectViewModel.Command.Exit -> dismiss()
|
||||
is LinkToObjectViewModel.Command.Link -> {
|
||||
withParent<OnLinkToAction> {
|
||||
onLinkTo(
|
||||
link = command.link,
|
||||
target = target
|
||||
)
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun closeFilterView() {
|
||||
filterContainer.getChildAt(0)?.let { filterContainer.minusAssign(it) }
|
||||
requireActivity().hideSoftInput()
|
||||
private fun initialize() {
|
||||
with(tvScreenTitle) {
|
||||
text = getString(R.string.link_to)
|
||||
visible()
|
||||
}
|
||||
recyclerView.invisible()
|
||||
tvScreenStateMessage.invisible()
|
||||
progressBar.invisible()
|
||||
clearSearchText.setOnClickListener {
|
||||
filterInputField.setText(ObjectSearchFragment.EMPTY_FILTER_TEXT)
|
||||
clearSearchText.invisible()
|
||||
}
|
||||
filterInputField.doAfterTextChanged { newText ->
|
||||
if (newText != null) {
|
||||
vm.onSearchTextChanged(newText.toString())
|
||||
}
|
||||
if (newText.isNullOrEmpty()) {
|
||||
clearSearchText.invisible()
|
||||
} else {
|
||||
clearSearchText.visible()
|
||||
}
|
||||
}
|
||||
with(recyclerView) {
|
||||
layoutManager = LinearLayoutManager(requireContext())
|
||||
adapter = moveToAdapter
|
||||
addItemDecoration(
|
||||
DividerItemDecoration(context, DividerItemDecoration.VERTICAL).apply {
|
||||
setDrawable(drawable(R.drawable.divider_object_search))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupFullHeight() {
|
||||
val lp = (root.layoutParams as FrameLayout.LayoutParams)
|
||||
lp.height =
|
||||
Resources.getSystem().displayMetrics.heightPixels - requireActivity().statusBarHeight
|
||||
root.layoutParams = lp
|
||||
}
|
||||
|
||||
private fun setTransparent() {
|
||||
with(root) {
|
||||
background = null
|
||||
(parent as? View)?.setBackgroundColor(Color.TRANSPARENT)
|
||||
}
|
||||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
|
@ -225,11 +200,16 @@ class LinkToObjectFragment :
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val TARGET_ID_KEY = "arg.link_to.target"
|
||||
const val REPLACE_KEY = "arg.link_to.replace"
|
||||
const val POSITION_KEY = "arg.link_to.position"
|
||||
const val CONTEXT_ID_KEY = "arg.link_to.context"
|
||||
const val POSITION_FROM = 0
|
||||
const val POSITION_TO = 1
|
||||
const val ARG_TARGET = "arg.link_to.target"
|
||||
|
||||
fun new(target: Id) = LinkToObjectFragment().apply {
|
||||
arguments = bundleOf(
|
||||
ARG_TARGET to target
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface OnLinkToAction {
|
||||
fun onLinkTo(link: Id, target: Id)
|
||||
}
|
|
@ -358,11 +358,6 @@
|
|||
android:defaultValue='""'
|
||||
app:argType="string" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/linkToFragment"
|
||||
android:name="com.anytypeio.anytype.ui.linking.LinkToObjectFragment"
|
||||
android:label="LinkToFragment"
|
||||
tools:layout="@layout/fragment_link_to_object" />
|
||||
<fragment
|
||||
android:id="@+id/pageSearchFragment"
|
||||
android:name="com.anytypeio.anytype.ui.search.ObjectSearchFragment"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
package com.anytypeio.anytype.core_models
|
||||
|
||||
enum class Position { NONE, TOP, BOTTOM, LEFT, RIGHT, INNER }
|
||||
enum class Position { NONE, TOP, BOTTOM, LEFT, RIGHT, INNER, REPLACE }
|
|
@ -247,6 +247,7 @@
|
|||
<string name="content_desc_object_icon">Object image or emoji</string>
|
||||
<string name="move">Move</string>
|
||||
<string name="move_to">Move to</string>
|
||||
<string name="link_to">Link to</string>
|
||||
<string name="mention_suggester_new_page">Create new object</string>
|
||||
<string name="widget_archive_select_pages">Select pages</string>
|
||||
<string name="your_search_query">Search</string>
|
||||
|
|
|
@ -207,20 +207,6 @@ class BlockDataRepository(
|
|||
|
||||
override suspend fun getListPages(): List<DocumentInfo> = factory.remote.getListPages()
|
||||
|
||||
override suspend fun linkToObject(
|
||||
context: Id,
|
||||
target: Id,
|
||||
block: Id,
|
||||
replace: Boolean,
|
||||
position: Position
|
||||
): Payload = factory.remote.linkToObject(
|
||||
context = context,
|
||||
target = target,
|
||||
block = block,
|
||||
replace = replace,
|
||||
position = position
|
||||
)
|
||||
|
||||
override suspend fun setRelationKey(command: Command.SetRelationKey): Payload =
|
||||
factory.remote.setRelationKey(command)
|
||||
|
||||
|
|
|
@ -54,14 +54,6 @@ interface BlockDataStore {
|
|||
|
||||
suspend fun getListPages(): List<DocumentInfo>
|
||||
|
||||
suspend fun linkToObject(
|
||||
context: String,
|
||||
target: String,
|
||||
block: String,
|
||||
replace: Boolean,
|
||||
position: Position
|
||||
): Payload
|
||||
|
||||
suspend fun updateDivider(command: Command.UpdateDivider): Payload
|
||||
|
||||
suspend fun setFields(command: Command.SetFields): Payload
|
||||
|
|
|
@ -53,14 +53,6 @@ interface BlockRemote {
|
|||
|
||||
suspend fun getListPages(): List<DocumentInfo>
|
||||
|
||||
suspend fun linkToObject(
|
||||
context: String,
|
||||
target: String,
|
||||
block: String,
|
||||
replace: Boolean,
|
||||
position: Position
|
||||
): Payload
|
||||
|
||||
suspend fun setRelationKey(command: Command.SetRelationKey): Payload
|
||||
|
||||
suspend fun updateDivider(command: Command.UpdateDivider): Payload
|
||||
|
|
|
@ -160,20 +160,6 @@ class BlockRemoteDataStore(private val remote: BlockRemote) : BlockDataStore {
|
|||
|
||||
override suspend fun getListPages(): List<DocumentInfo> = remote.getListPages()
|
||||
|
||||
override suspend fun linkToObject(
|
||||
context: String,
|
||||
target: String,
|
||||
block: String,
|
||||
replace: Boolean,
|
||||
position: Position
|
||||
): Payload = remote.linkToObject(
|
||||
context = context,
|
||||
target = target,
|
||||
block = block,
|
||||
replace = replace,
|
||||
position = position
|
||||
)
|
||||
|
||||
override suspend fun setRelationKey(command: Command.SetRelationKey): Payload =
|
||||
remote.setRelationKey(command)
|
||||
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
package com.anytypeio.anytype.domain.block.interactor
|
||||
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
import com.anytypeio.anytype.domain.block.interactor.CreateLinkToObject.Params
|
||||
import com.anytypeio.anytype.core_models.Position
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
|
||||
/**
|
||||
* Use-case for creating a link to existing object.
|
||||
* @see [Params] for details.
|
||||
*/
|
||||
class CreateLinkToObject(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Payload, Params>() {
|
||||
|
||||
override suspend fun run(params: Params) = safe {
|
||||
repo.linkToObject(
|
||||
context = params.context,
|
||||
target = params.target,
|
||||
block = params.block,
|
||||
replace = params.replace,
|
||||
position = params.position
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Params for creating a link to existing object
|
||||
* @property [target] represents blocks, relative to which a link will be inserted.
|
||||
* @property [context] operation's context
|
||||
* @property [block] id of the block being inserted
|
||||
* @property [replace] if true, a link will replace [target] block, if false, a link will be inserted below [target]
|
||||
*/
|
||||
data class Params(
|
||||
val context: Id,
|
||||
val block: Id,
|
||||
val target: Id,
|
||||
val replace: Boolean,
|
||||
val position: Position
|
||||
)
|
||||
}
|
|
@ -107,14 +107,6 @@ interface BlockRepository {
|
|||
suspend fun getObjectInfoWithLinks(pageId: String): ObjectInfoWithLinks
|
||||
suspend fun getListPages(): List<DocumentInfo>
|
||||
|
||||
suspend fun linkToObject(
|
||||
context: Id,
|
||||
target: Id,
|
||||
block: Id,
|
||||
replace: Boolean,
|
||||
position: Position
|
||||
): Payload
|
||||
|
||||
suspend fun updateDivider(command: Command.UpdateDivider): Payload
|
||||
|
||||
suspend fun setFields(command: Command.SetFields): Payload
|
||||
|
|
|
@ -189,14 +189,6 @@ class BlockMiddleware(
|
|||
return middleware.setRelationKey(command)
|
||||
}
|
||||
|
||||
override suspend fun linkToObject(
|
||||
context: String,
|
||||
target: String,
|
||||
block: String,
|
||||
replace: Boolean,
|
||||
position: Position
|
||||
): Payload = middleware.linkToObject(context, target, block, replace, position)
|
||||
|
||||
override suspend fun updateDivider(
|
||||
command: Command.UpdateDivider
|
||||
): Payload = middleware.updateDividerStyle(command)
|
||||
|
|
|
@ -891,41 +891,6 @@ class Middleware(
|
|||
return response.objects
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun linkToObject(
|
||||
contextId: String,
|
||||
targetId: String,
|
||||
blockId: String,
|
||||
replace: Boolean,
|
||||
positionCore: Position
|
||||
): Payload {
|
||||
|
||||
val position: Block.Position = if (replace) {
|
||||
Block.Position.Replace
|
||||
} else {
|
||||
positionCore.toMiddlewareModel()
|
||||
}
|
||||
|
||||
val link = Block.Content.Link(targetBlockId = blockId)
|
||||
|
||||
val model = Block(link = link)
|
||||
|
||||
val request: Rpc.Block.Create.Request = Rpc.Block.Create.Request(
|
||||
contextId = contextId,
|
||||
targetId = targetId,
|
||||
position = position,
|
||||
block = model
|
||||
)
|
||||
|
||||
if (BuildConfig.DEBUG) logRequest(request)
|
||||
|
||||
val response = service.blockCreate(request)
|
||||
|
||||
if (BuildConfig.DEBUG) logResponse(response)
|
||||
|
||||
return response.event.toPayload()
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun updateDividerStyle(command: Command.UpdateDivider): Payload {
|
||||
val style = command.style.toMiddlewareModel()
|
||||
|
|
|
@ -204,6 +204,7 @@ fun Position.toMiddlewareModel(): MBPosition = when (this) {
|
|||
Position.LEFT -> MBPosition.Left
|
||||
Position.RIGHT -> MBPosition.Right
|
||||
Position.INNER -> MBPosition.Inner
|
||||
Position.REPLACE -> MBPosition.Replace
|
||||
}
|
||||
|
||||
fun BlockSplitMode.toMiddlewareModel() = when (this) {
|
||||
|
|
|
@ -1827,48 +1827,6 @@ class EditorViewModel(
|
|||
dispatch(Command.OpenGallery(mediaType = MIME_IMAGE_ALL))
|
||||
}
|
||||
|
||||
fun onAddLinkToObjectClicked() {
|
||||
|
||||
Timber.d("onAddLinkToObjectClicked, ")
|
||||
|
||||
val focused = blocks.first { it.id == orchestrator.stores.focus.current().id }
|
||||
|
||||
val content = focused.content
|
||||
|
||||
val replace = content is Content.Text && content.text.isEmpty()
|
||||
|
||||
var position: Position = Position.BOTTOM
|
||||
|
||||
var target: Id = focused.id
|
||||
|
||||
if (!replace && focused.id == context) {
|
||||
if (focused.children.isEmpty()) {
|
||||
position = Position.INNER
|
||||
} else {
|
||||
position = Position.TOP
|
||||
target = focused.children.first()
|
||||
}
|
||||
}
|
||||
|
||||
proceedWithClearingFocus()
|
||||
|
||||
viewModelScope.sendEvent(
|
||||
analytics = analytics,
|
||||
eventName = EventsDictionary.SCREEN_LINK_TO
|
||||
)
|
||||
|
||||
navigate(
|
||||
EventWrapper(
|
||||
AppNavigation.Command.OpenLinkToScreen(
|
||||
target = target,
|
||||
context = context,
|
||||
replace = replace,
|
||||
position = position
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun onAddRelationBlockClicked() {
|
||||
|
||||
Timber.d("onAddRelationBlockClicked, ")
|
||||
|
@ -2238,6 +2196,7 @@ class EditorViewModel(
|
|||
onBlockLongPressedClicked(target, dimensions)
|
||||
}
|
||||
|
||||
@Deprecated("To be deleted")
|
||||
fun onAddBlockToolbarClicked() {
|
||||
Timber.d("onAddBlockToolbarClicked, ")
|
||||
|
||||
|
@ -4691,7 +4650,8 @@ class EditorViewModel(
|
|||
proceedWithMoveToButtonClicked(targetId)
|
||||
}
|
||||
SlashItem.Actions.LinkTo -> {
|
||||
onAddLinkToObjectClicked()
|
||||
onHideKeyboardClicked()
|
||||
proceedWithLinkToButtonClicked(targetId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4920,4 +4880,39 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region LINK TO
|
||||
private fun proceedWithLinkToButtonClicked(block: Id) {
|
||||
viewModelScope.sendEvent(
|
||||
analytics = analytics,
|
||||
eventName = EventsDictionary.SCREEN_LINK_TO
|
||||
)
|
||||
dispatch(Command.OpenLinkToScreen(target = block))
|
||||
}
|
||||
|
||||
fun proceedWithLinkToAction(link: Id, target: Id) {
|
||||
val targetBlock = blocks.firstOrNull { it.id == target }
|
||||
if (targetBlock != null) {
|
||||
val targetContent = targetBlock.content
|
||||
val position = if (targetContent is Content.Text && targetContent.text.isEmpty()) {
|
||||
Position.REPLACE
|
||||
} else {
|
||||
Position.BOTTOM
|
||||
}
|
||||
viewModelScope.launch {
|
||||
orchestrator.proxies.intents.send(
|
||||
Intent.CRUD.Create(
|
||||
context = context,
|
||||
target = target,
|
||||
position = position,
|
||||
prototype = Prototype.Link(target = link)
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Timber.e("Can't find target block for link")
|
||||
_toasts.offer("Error while creating link")
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
|
@ -34,6 +34,7 @@ sealed class Command {
|
|||
val context: String
|
||||
) : Command()
|
||||
|
||||
@Deprecated("To be deleted")
|
||||
data class OpenAddBlockPanel(val ctx: Id) : Command()
|
||||
|
||||
data class Measure(val target: Id) : Command()
|
||||
|
@ -103,4 +104,6 @@ sealed class Command {
|
|||
data class OpenChangeObjectTypeScreen(val ctx: Id, val smartBlockType: SmartBlockType): Command()
|
||||
|
||||
data class OpenMoveToScreen(val block: Id): Command()
|
||||
|
||||
data class OpenLinkToScreen(val target: Id): Command()
|
||||
}
|
|
@ -1,117 +1,84 @@
|
|||
package com.anytypeio.anytype.presentation.linking
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Position
|
||||
import com.anytypeio.anytype.core_utils.common.EventWrapper
|
||||
import com.anytypeio.anytype.core_utils.ext.timber
|
||||
import com.anytypeio.anytype.core_utils.ui.ViewState
|
||||
import com.anytypeio.anytype.core_utils.ui.ViewStateViewModel
|
||||
import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider
|
||||
import com.anytypeio.anytype.domain.block.interactor.CreateLinkToObject
|
||||
import com.anytypeio.anytype.domain.config.GetConfig
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_models.*
|
||||
import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
|
||||
import com.anytypeio.anytype.domain.config.GetFlavourConfig
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.page.navigation.GetObjectInfoWithLinks
|
||||
import com.anytypeio.anytype.presentation.mapper.getEmojiPath
|
||||
import com.anytypeio.anytype.presentation.mapper.getImagePath
|
||||
import com.anytypeio.anytype.presentation.mapper.toView
|
||||
import com.anytypeio.anytype.presentation.navigation.AppNavigation
|
||||
import com.anytypeio.anytype.presentation.navigation.PageNavigationView
|
||||
import com.anytypeio.anytype.presentation.navigation.SupportNavigation
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchViewModel
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
class LinkToObjectViewModel(
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val getObjectInfoWithLinks: GetObjectInfoWithLinks,
|
||||
private val createLinkToObject: CreateLinkToObject,
|
||||
private val getConfig: GetConfig,
|
||||
private val objectTypesProvider: ObjectTypesProvider
|
||||
) : ViewStateViewModel<ViewState<PageNavigationView>>(),
|
||||
SupportNavigation<EventWrapper<AppNavigation.Command>> {
|
||||
urlBuilder: UrlBuilder,
|
||||
searchObjects: SearchObjects,
|
||||
getObjectTypes: GetObjectTypes,
|
||||
analytics: Analytics,
|
||||
private val getFlavourConfig: GetFlavourConfig
|
||||
) : ObjectSearchViewModel(
|
||||
urlBuilder = urlBuilder,
|
||||
getObjectTypes = getObjectTypes,
|
||||
searchObjects = searchObjects,
|
||||
analytics = analytics,
|
||||
getFlavourConfig = getFlavourConfig,
|
||||
) {
|
||||
|
||||
private var pageId: String = ""
|
||||
private var home: Id = ""
|
||||
val commands = MutableSharedFlow<Command>(replay = 0)
|
||||
|
||||
val isLinkingDisabled: MutableStateFlow<Boolean> = MutableStateFlow(true)
|
||||
override fun getSearchObjectsParams(): SearchObjects.Params {
|
||||
|
||||
override val navigation: MutableLiveData<EventWrapper<AppNavigation.Command>> =
|
||||
MutableLiveData()
|
||||
val filteredTypes = if (getFlavourConfig.isDataViewEnabled()) {
|
||||
types.value.map { objectType -> objectType.url }
|
||||
} else {
|
||||
listOf(ObjectTypeConst.PAGE)
|
||||
}
|
||||
|
||||
fun onViewCreated() {
|
||||
stateData.postValue(ViewState.Init)
|
||||
val filters = listOf(
|
||||
DVFilter(
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = false,
|
||||
relationKey = Relations.IS_ARCHIVED,
|
||||
operator = DVFilterOperator.AND
|
||||
),
|
||||
DVFilter(
|
||||
relationKey = Relations.IS_HIDDEN,
|
||||
condition = DVFilterCondition.NOT_EQUAL,
|
||||
value = true
|
||||
)
|
||||
)
|
||||
|
||||
val sorts = listOf(
|
||||
DVSort(
|
||||
relationKey = Relations.LAST_OPENED_DATE,
|
||||
type = DVSortType.DESC
|
||||
)
|
||||
)
|
||||
|
||||
return SearchObjects.Params(
|
||||
limit = SEARCH_LIMIT,
|
||||
objectTypeFilter = filteredTypes,
|
||||
filters = filters,
|
||||
sorts = sorts,
|
||||
fulltext = EMPTY_QUERY
|
||||
)
|
||||
}
|
||||
|
||||
fun onStart(initialTarget: Id) {
|
||||
override fun onObjectClicked(target: Id, layout: ObjectType.Layout?) {
|
||||
viewModelScope.launch {
|
||||
getConfig(Unit).proceed(
|
||||
failure = { Timber.e(it, "Error while getting config") },
|
||||
success = { config ->
|
||||
home = config.home
|
||||
proceedWithGettingDocumentLinks(initialTarget)
|
||||
}
|
||||
)
|
||||
commands.emit(Command.Link(link = target))
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithGettingDocumentLinks(target: String) {
|
||||
stateData.postValue(ViewState.Loading)
|
||||
override fun onBottomSheetHidden() {
|
||||
viewModelScope.launch {
|
||||
getObjectInfoWithLinks.invoke(GetObjectInfoWithLinks.Params(pageId = target)).proceed(
|
||||
failure = { error ->
|
||||
error.timber()
|
||||
stateData.postValue(ViewState.Error(error.message ?: "Unknown error"))
|
||||
},
|
||||
success = { response ->
|
||||
with(response.pageInfoWithLinks) {
|
||||
pageId = this.id
|
||||
stateData.postValue(
|
||||
ViewState.Success(
|
||||
PageNavigationView(
|
||||
title = documentInfo.obj.name.orEmpty(),
|
||||
subtitle = documentInfo.snippet.orEmpty(),
|
||||
image = documentInfo.obj.getImagePath(urlBuilder),
|
||||
emoji = documentInfo.obj.getEmojiPath(),
|
||||
inbound = links.inbound.map { it.toView(urlBuilder, objectTypesProvider.get()) },
|
||||
outbound = links.outbound.map { it.toView(urlBuilder, objectTypesProvider.get()) }
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
commands.emit(Command.Exit)
|
||||
}
|
||||
}
|
||||
|
||||
fun onLinkClicked(
|
||||
target: Id,
|
||||
context: Id
|
||||
) {
|
||||
isLinkingDisabled.value = (target == context || target == home)
|
||||
proceedWithGettingDocumentLinks(target)
|
||||
}
|
||||
|
||||
fun onLinkToObjectClicked(
|
||||
context: Id,
|
||||
target: Id,
|
||||
replace: Boolean,
|
||||
position: Position
|
||||
) {
|
||||
viewModelScope.launch {
|
||||
createLinkToObject(
|
||||
CreateLinkToObject.Params(
|
||||
context = context,
|
||||
target = target,
|
||||
block = pageId,
|
||||
replace = replace,
|
||||
position = position
|
||||
)
|
||||
).proceed(
|
||||
failure = { Timber.e(it, "Error while creating link to object") },
|
||||
success = { navigate(EventWrapper(AppNavigation.Command.Exit)) }
|
||||
)
|
||||
}
|
||||
sealed class Command {
|
||||
object Exit : Command()
|
||||
data class Link(val link: Id) : Command()
|
||||
}
|
||||
}
|
|
@ -2,28 +2,28 @@ package com.anytypeio.anytype.presentation.linking
|
|||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.anytypeio.anytype.domain.`object`.ObjectTypesProvider
|
||||
import com.anytypeio.anytype.domain.block.interactor.CreateLinkToObject
|
||||
import com.anytypeio.anytype.domain.config.GetConfig
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
|
||||
import com.anytypeio.anytype.domain.config.GetFlavourConfig
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.page.navigation.GetObjectInfoWithLinks
|
||||
|
||||
class LinkToObjectViewModelFactory(
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val getObjectInfoWithLinks: GetObjectInfoWithLinks,
|
||||
private val createLinkToObject: CreateLinkToObject,
|
||||
private val getConfig: GetConfig,
|
||||
private val objectTypesProvider: ObjectTypesProvider
|
||||
private val getObjectTypes: GetObjectTypes,
|
||||
private val searchObjects: SearchObjects,
|
||||
private val analytics: Analytics,
|
||||
private val getFlavourConfig: GetFlavourConfig
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||
return LinkToObjectViewModel(
|
||||
urlBuilder = urlBuilder,
|
||||
getObjectInfoWithLinks = getObjectInfoWithLinks,
|
||||
createLinkToObject = createLinkToObject,
|
||||
getConfig = getConfig,
|
||||
objectTypesProvider = objectTypesProvider
|
||||
getObjectTypes = getObjectTypes,
|
||||
searchObjects = searchObjects,
|
||||
analytics = analytics,
|
||||
getFlavourConfig = getFlavourConfig
|
||||
) as T
|
||||
}
|
||||
}
|
|
@ -40,7 +40,6 @@ interface AppNavigation {
|
|||
fun exitToDesktop()
|
||||
fun openDebugSettings()
|
||||
fun openPageNavigation(target: String)
|
||||
fun openLinkTo(target: String, context: String, replace: Boolean, position: Position)
|
||||
fun openPageSearch()
|
||||
fun exitToDesktopAndOpenPage(pageId: String)
|
||||
fun exitToInvitationCodeScreen()
|
||||
|
@ -82,13 +81,6 @@ interface AppNavigation {
|
|||
|
||||
data class OpenPageNavigationScreen(val target: String) : Command()
|
||||
|
||||
data class OpenLinkToScreen(
|
||||
val context: String,
|
||||
val target: String,
|
||||
val replace: Boolean,
|
||||
val position: Position
|
||||
) : Command()
|
||||
|
||||
data class ExitToDesktopAndOpenPage(val pageId: String) : Command()
|
||||
object OpenPageSearch : Command()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue