1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-3240 Tech | Remove object relation links (#2000)

This commit is contained in:
Konstantin Ivanov 2025-01-16 15:35:08 +01:00 committed by GitHub
parent b3fdf89cbd
commit c4968c3e4f
Signed by: github
GPG key ID: B5690EEEBB952194
56 changed files with 304 additions and 1253 deletions

View file

@ -121,7 +121,6 @@ class MentionUpdateTesting : EditorTestSetup() {
context = root,
root = root,
details = customDetails,
relations = emptyList(),
blocks = document,
objectRestrictions = emptyList()
),

View file

@ -27,7 +27,6 @@ import com.anytypeio.anytype.domain.block.interactor.CreateBlock
import com.anytypeio.anytype.domain.block.interactor.DuplicateBlock
import com.anytypeio.anytype.domain.block.interactor.MergeBlocks
import com.anytypeio.anytype.domain.block.interactor.Move
import com.anytypeio.anytype.domain.block.interactor.MoveOld
import com.anytypeio.anytype.domain.block.interactor.RemoveLinkMark
import com.anytypeio.anytype.domain.block.interactor.ReplaceBlock
import com.anytypeio.anytype.domain.block.interactor.SetObjectType
@ -403,7 +402,7 @@ open class EditorTestSetup {
)
featureToggles = mock<DefaultFeatureToggles>()
addRelationToObject = AddRelationToObject(repo)
addRelationToObject = AddRelationToObject(repo, dispatchers)
interceptFileLimitEvents = InterceptFileLimitEvents(fileLimitsEventChannel, dispatchers)
@ -547,7 +546,6 @@ open class EditorTestSetup {
root = root,
details = details,
blocks = document,
relations = relations
)
)
)

View file

@ -1,714 +0,0 @@
package com.anytypeio.anytype.features.relations
import android.os.Bundle
import androidx.core.os.bundleOf
import androidx.fragment.app.testing.FragmentScenario
import androidx.fragment.app.testing.launchFragmentInContainer
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import com.anytypeio.anytype.R
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_ui.extensions.dark
import com.anytypeio.anytype.core_utils.const.DateConst
import com.anytypeio.anytype.core_utils.ext.toTimeSeconds
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.Gateway
import com.anytypeio.anytype.domain.debugging.Logger
import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.GetDateObjectByTimestamp
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.primitives.FieldParserImpl
import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.AddToFeaturedRelations
import com.anytypeio.anytype.domain.relations.DeleteRelationFromObject
import com.anytypeio.anytype.domain.relations.RemoveFromFeaturedRelations
import com.anytypeio.anytype.domain.resources.StringResourceProvider
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.Editor
import com.anytypeio.anytype.presentation.objects.LockedStateProvider
import com.anytypeio.anytype.presentation.relations.ObjectRelationListViewModelFactory
import com.anytypeio.anytype.presentation.relations.RelationListViewModel
import com.anytypeio.anytype.presentation.relations.providers.RelationListProvider
import com.anytypeio.anytype.presentation.util.Dispatcher
import com.anytypeio.anytype.test_utils.MockDataFactory
import com.anytypeio.anytype.test_utils.utils.checkHasText
import com.anytypeio.anytype.test_utils.utils.checkHasTextColor
import com.anytypeio.anytype.test_utils.utils.checkIsRecyclerSize
import com.anytypeio.anytype.test_utils.utils.onItemView
import com.anytypeio.anytype.test_utils.utils.rVMatcher
import com.anytypeio.anytype.test_utils.utils.resources
import com.anytypeio.anytype.ui.relations.ObjectRelationListFragment
import com.anytypeio.anytype.utils.CoroutinesTestRule
import com.bartoszlipinski.disableanimationsrule.DisableAnimationsRule
import java.text.SimpleDateFormat
import java.util.*
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@RunWith(AndroidJUnit4::class)
@LargeTest
class ObjectRelationListTest {
@get:Rule
val animationsRule = DisableAnimationsRule()
@get:Rule
val coroutineTestRule = CoroutinesTestRule()
private val spaceId = MockDataFactory.randomUuid()
@Mock
lateinit var gateway: Gateway
@Mock
lateinit var repo: BlockRepository
@Mock
lateinit var dispatcher: Dispatcher<Payload>
@Mock
lateinit var analytics: Analytics
@Mock
lateinit var storeOfRelations: StoreOfRelations
@Mock
lateinit var relationListProvider: RelationListProvider
@Mock
lateinit var addRelationToObject: AddRelationToObject
@Mock
lateinit var lockedStateProvider: LockedStateProvider
@Mock
lateinit var analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
private lateinit var updateDetail: UpdateDetail
private lateinit var addToFeaturedRelations: AddToFeaturedRelations
private lateinit var removeFromFeaturedRelations: RemoveFromFeaturedRelations
private lateinit var deleteRelationFromObject: DeleteRelationFromObject
private val ctx = MockDataFactory.randomUuid()
private val storage = Editor.Storage()
lateinit var urlBuilder: UrlBuilder
lateinit var fieldParser: FieldParser
@Mock
lateinit var logger: Logger
@Mock
lateinit var dateProvider: DateProvider
@Mock
lateinit var getDateObjectByTimestamp: GetDateObjectByTimestamp
@Mock
lateinit var stringResourceProvider: StringResourceProvider
@Before
fun setup() {
MockitoAnnotations.openMocks(this)
urlBuilder = UrlBuilder(gateway)
updateDetail = UpdateDetail(repo)
fieldParser = FieldParserImpl(
logger = logger,
dateProvider = dateProvider,
getDateObjectByTimestamp = getDateObjectByTimestamp,
stringResourceProvider = stringResourceProvider
)
addToFeaturedRelations = AddToFeaturedRelations(repo)
removeFromFeaturedRelations = RemoveFromFeaturedRelations(repo)
deleteRelationFromObject = DeleteRelationFromObject(repo)
TestObjectRelationListFragment.testVmFactory = ObjectRelationListViewModelFactory(
vmParams = RelationListViewModel.VmParams(
spaceId = SpaceId(spaceId)
),
lockedStateProvider = lockedStateProvider,
relationListProvider = relationListProvider,
urlBuilder = urlBuilder,
dispatcher = dispatcher,
updateDetail = updateDetail,
addToFeaturedRelations = addToFeaturedRelations,
removeFromFeaturedRelations = removeFromFeaturedRelations,
deleteRelationFromObject = deleteRelationFromObject,
analytics = analytics,
storeOfRelations = storeOfRelations,
addRelationToObject = addRelationToObject,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
fieldParser = fieldParser
)
}
@Test(expected = RuntimeException::class)
fun shouldThrowAnExceptionIfArgsNotProvided() {
launchFragment(bundleOf())
}
@Test
fun shouldDisplayOneRelationWithoutValueInsideOtherRelationsSection() {
// SETUP
val name = "Description"
val relation = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.LONG_TEXT,
source = Relation.Source.values().random(),
name = name
)
runBlocking {
storage.relations.update(
listOf(relation)
)
}
launchFragment(bundleOf(
ObjectRelationListFragment.ARG_CTX to ctx,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
))
// TESTING
with(R.id.recycler.rVMatcher()) {
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
onItemView(1, R.id.tvRelationTitle).checkHasText(name)
onItemView(1, R.id.tvRelationValue).checkHasText("")
checkIsRecyclerSize(2)
}
}
@Test
fun shouldDisplayOnlyFirstRelationBecauseSecondIsHiddenInsideOtherRelationsSection() {
// SETUP
val name1 = "Description"
val name2 = "Identifier"
val relation1 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.LONG_TEXT,
source = Relation.Source.values().random(),
isHidden = true,
name = name1
)
val relation2 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.LONG_TEXT,
source = Relation.Source.values().random(),
name = name2
)
runBlocking {
storage.relations.update(
listOf(relation1, relation2)
)
}
launchFragment(bundleOf(
ObjectRelationListFragment.ARG_CTX to ctx,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
))
// TESTING
with(R.id.recycler.rVMatcher()) {
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
onItemView(1, R.id.tvRelationTitle).checkHasText(name2)
onItemView(1, R.id.tvRelationValue).checkHasText("")
checkIsRecyclerSize(2)
}
}
@Test
fun shouldDisplayTwoRelationsWithoutValueInsideOtherRelationsSection() {
// SETUP
val name1 = "Description"
val name2 = "Comment"
val relation1 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.LONG_TEXT,
source = Relation.Source.values().random(),
name = name1
)
val relation2 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.LONG_TEXT,
source = Relation.Source.values().random(),
name = name2
)
runBlocking {
storage.relations.update(
listOf(relation1, relation2)
)
}
launchFragment(bundleOf(
ObjectRelationListFragment.ARG_CTX to ctx,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
))
// TESTING
with(R.id.recycler.rVMatcher()) {
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
onItemView(1, R.id.tvRelationTitle).checkHasText(name1)
onItemView(1, R.id.tvRelationValue).checkHasText("")
onItemView(2, R.id.tvRelationTitle).checkHasText(name2)
onItemView(2, R.id.tvRelationValue).checkHasText("")
checkIsRecyclerSize(3)
}
}
@Test
fun shouldDisplayTwoRelationsWithValuesInsideOtherRelationsSection() {
// SETUP
val name1 = "Description"
val name2 = "Comment"
val value1 = "A mountain is an elevated portion of the Earth's crust, generally with steep sides that show significant exposed bedrock."
val value2 = "We've never seen that mountain before."
val relation1 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.LONG_TEXT,
source = Relation.Source.values().random(),
name = name1
)
val relation2 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.LONG_TEXT,
source = Relation.Source.values().random(),
name = name2
)
val relations = listOf(relation1, relation2)
val details = Block.Details(
mapOf(
ctx to Block.Fields(
mapOf(
relation1.key to value1,
relation2.key to value2,
)
)
)
)
runBlocking {
storage.relations.update(relations)
storage.details.update(details)
}
launchFragment(
bundleOf(
ObjectRelationListFragment.ARG_CTX to ctx,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
)
)
// TESTING
with(R.id.recycler.rVMatcher()) {
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
onItemView(1, R.id.tvRelationTitle).checkHasText(name1)
onItemView(1, R.id.tvRelationValue).checkHasText(value1)
onItemView(2, R.id.tvRelationTitle).checkHasText(name2)
onItemView(2, R.id.tvRelationValue).checkHasText(value2)
checkIsRecyclerSize(3)
}
}
@Test
fun shouldDisplayTwoObjectRelationsWithNameAndAvatarInitialsInsideOtherRelationsSection() {
// SETUP
val name1 = "Assignee"
val target1: Id = MockDataFactory.randomUuid()
val username1 = "Konstantin"
val name2 = "Created by"
val target2: Id = MockDataFactory.randomUuid()
val username2 = "Roman"
val relation1 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.OBJECT,
source = Relation.Source.values().random(),
name = name1
)
val relation2 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.OBJECT,
source = Relation.Source.values().random(),
name = name2
)
val relations = listOf(relation1, relation2)
val details = Block.Details(
mapOf(
ctx to Block.Fields(
mapOf(
relation1.key to target1,
relation2.key to target2,
)
),
target1 to Block.Fields(
mapOf(
Block.Fields.NAME_KEY to username1
)
),
target2 to Block.Fields(
mapOf(
Block.Fields.NAME_KEY to username2
)
)
)
)
runBlocking {
storage.relations.update(relations)
storage.details.update(details)
}
launchFragment(bundleOf(
ObjectRelationListFragment.ARG_CTX to ctx,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
))
// TESTING
with(R.id.recycler.rVMatcher()) {
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
onItemView(1, R.id.tvRelationTitle).checkHasText(name1)
onItemView(1, R.id.obj0).check(matches(hasDescendant(withText(username1))))
onItemView(2, R.id.tvRelationTitle).checkHasText(name2)
onItemView(2, R.id.obj0).check(matches(hasDescendant(withText(username2))))
checkIsRecyclerSize(3)
}
}
@Test
fun shouldDisplayTwoDateRelationsInsideOtherRelationsSection() {
// SETUP
val format = SimpleDateFormat(DateConst.DEFAULT_DATE_FORMAT, Locale.getDefault())
val name1 = "Date of birth"
val date1 = System.currentTimeMillis()
val date1Screen = format.format(Date(date1))
val name2 = "Last modified at"
val date2 = System.currentTimeMillis()
val date2Screen = format.format(Date(date2))
val relation1 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.DATE,
source = Relation.Source.values().random(),
name = name1,
)
val relation2 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.DATE,
source = Relation.Source.values().random(),
name = name2
)
val relations = listOf(relation1, relation2)
val details = Block.Details(
mapOf(
ctx to Block.Fields(
mapOf(
relation1.key to date1.toTimeSeconds(),
relation2.key to date2.toTimeSeconds(),
)
)
)
)
runBlocking {
storage.relations.update(relations)
storage.details.update(details)
}
launchFragment(bundleOf(
ObjectRelationListFragment.ARG_CTX to ctx,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
))
// TESTING
with(R.id.recycler.rVMatcher()) {
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
onItemView(1, R.id.tvRelationTitle).checkHasText(name1)
onItemView(1, R.id.tvRelationValue).checkHasText(date1Screen)
onItemView(2, R.id.tvRelationTitle).checkHasText(name2)
onItemView(2, R.id.tvRelationValue).checkHasText(date2Screen)
checkIsRecyclerSize(3)
}
}
@Test
fun shouldDisplayTwoStatusRelationsInsideOtherRelationsSection() {
// SETUP
val color1 = ThemeColor.RED
val color2 = ThemeColor.TEAL
val option1 = Relation.Option(
id = MockDataFactory.randomUuid(),
text = "In progress",
color = color1.code
)
val option2 = Relation.Option(
id = MockDataFactory.randomUuid(),
text = "Done",
color = color2.code
)
val name1 = "Status 1"
val name2 = "Status 2"
val relation1 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.STATUS,
source = Relation.Source.values().random(),
name = name1,
selections = listOf(option1)
)
val relation2 = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.STATUS,
source = Relation.Source.values().random(),
name = name2,
selections = listOf(option2)
)
val relations = listOf(relation1, relation2)
val details = Block.Details(
mapOf(
ctx to Block.Fields(
mapOf(
relation1.key to option1.id,
relation2.key to option2.id,
)
)
)
)
runBlocking {
storage.relations.update(relations)
storage.details.update(details)
}
launchFragment(bundleOf(
ObjectRelationListFragment.ARG_CTX to ctx,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
))
// TESTING
with(R.id.recycler.rVMatcher()) {
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
onItemView(1, R.id.tvRelationTitle).checkHasText(name1)
onItemView(1, R.id.tvRelationValue).checkHasText(option1.text)
onItemView(1, R.id.tvRelationValue).checkHasTextColor(resources.dark(color1))
onItemView(2, R.id.tvRelationTitle).checkHasText(name2)
onItemView(2, R.id.tvRelationValue).checkHasText(option2.text)
onItemView(2, R.id.tvRelationValue).checkHasTextColor(resources.dark(color2))
checkIsRecyclerSize(3)
}
}
@Test
fun shouldDisplayFourTagRelationsInsideOtherRelationsSection() {
// SETUP
val color1 = ThemeColor.RED
val color2 = ThemeColor.TEAL
val color3 = ThemeColor.ICE
val color4 = ThemeColor.PURPLE
val name = "Role"
val option1 = Relation.Option(
id = MockDataFactory.randomUuid(),
text = "Essayist",
color = color1.code
)
val option2 = Relation.Option(
id = MockDataFactory.randomUuid(),
text = "Journalist",
color = color2.code
)
val option3 = Relation.Option(
id = MockDataFactory.randomUuid(),
text = "Politik",
color = color3.code
)
val option4 = Relation.Option(
id = MockDataFactory.randomUuid(),
text = "Critic",
color = color4.code
)
val relation = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.TAG,
source = Relation.Source.values().random(),
name = name,
selections = listOf(option1, option2, option3, option4)
)
val relations = listOf(relation)
val details = Block.Details(
mapOf(
ctx to Block.Fields(
mapOf(
relation.key to listOf(option1.id, option2.id, option3.id, option4.id)
)
)
)
)
runBlocking {
storage.relations.update(relations)
storage.details.update(details)
}
launchFragment(bundleOf(
ObjectRelationListFragment.ARG_CTX to ctx,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
))
// TESTING
with(R.id.recycler.rVMatcher()) {
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
onItemView(1, R.id.tvRelationTitle).checkHasText(name)
onItemView(1, R.id.tag0).check(matches((withText(option1.text))))
onItemView(1, R.id.tag1).check(matches((withText(option2.text))))
onItemView(1, R.id.tag2).check(matches((withText(option3.text))))
onItemView(1, R.id.tag3).check(matches((withText(option4.text))))
checkIsRecyclerSize(2)
}
}
@Test
fun shouldDisplayTwoFileRelationsInsideOtherRelationsSection() {
// SETUP
val name = "Attachement"
val relation = Relation(
key = MockDataFactory.randomUuid(),
format = Relation.Format.FILE,
source = Relation.Source.values().random(),
name = name,
selections = emptyList()
)
val relations = listOf(relation)
val file1 = MockDataFactory.randomUuid()
val file2 = MockDataFactory.randomUuid()
val details = Block.Details(
mapOf(
ctx to Block.Fields(
mapOf(
relation.key to listOf(file1, file2)
)
),
file1 to Block.Fields(
mapOf(
"name" to "Document",
"ext" to "pdf",
"mime" to "application/pdf"
)
),
file2 to Block.Fields(
mapOf(
"name" to "Image",
"ext" to "jpg",
"mime" to "image/jpeg"
)
)
)
)
runBlocking {
storage.relations.update(relations)
storage.details.update(details)
}
launchFragment(bundleOf(
ObjectRelationListFragment.ARG_CTX to ctx,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST
))
// TESTING
with(R.id.recycler.rVMatcher()) {
onItemView(0, R.id.tvSectionName).checkHasText(R.string.other_relations)
onItemView(1, R.id.tvRelationTitle).checkHasText(name)
onItemView(1, R.id.file0).check(matches(hasDescendant(withText("Document"))))
onItemView(1, R.id.file1).check(matches(hasDescendant(withText("Image"))))
checkIsRecyclerSize(2)
}
}
private fun launchFragment(args: Bundle): FragmentScenario<TestObjectRelationListFragment> {
return launchFragmentInContainer(
fragmentArgs = args,
themeResId = R.style.AppTheme
)
}
}

View file

@ -360,7 +360,6 @@ abstract class TestObjectSetSetup {
root = ctx,
details = details,
blocks = set,
relations = relations
)
)
)
@ -383,7 +382,6 @@ abstract class TestObjectSetSetup {
root = ctx,
details = details,
blocks = set,
relations = relations,
)
)
)

View file

@ -116,6 +116,7 @@ import com.anytypeio.anytype.presentation.multiplayer.RequestJoinSpaceViewModel
import com.anytypeio.anytype.presentation.multiplayer.ShareSpaceViewModel
import com.anytypeio.anytype.presentation.multiplayer.SpaceJoinRequestViewModel
import com.anytypeio.anytype.presentation.objects.SelectObjectTypeViewModel
import com.anytypeio.anytype.presentation.relations.RelationAddViewModelBase
import com.anytypeio.anytype.presentation.relations.RelationListViewModel
import com.anytypeio.anytype.presentation.relations.option.CreateOrEditOptionViewModel
import com.anytypeio.anytype.presentation.relations.value.`object`.ObjectValueViewModel
@ -365,7 +366,12 @@ class ComponentManager(
editorComponent
.get(key = param.ctx, param = param)
.objectRelationListComponent()
.withVmParams(RelationListViewModel.VmParams(param.space))
.withVmParams(
RelationListViewModel.VmParams(
objectId = param.ctx,
spaceId = param.space
)
)
.module(ObjectRelationListModule)
.build()
}
@ -374,7 +380,12 @@ class ComponentManager(
objectSetComponent
.get(key = param.ctx, param = param)
.objectRelationListComponent()
.withVmParams(RelationListViewModel.VmParams(param.space))
.withVmParams(
RelationListViewModel.VmParams(
objectId = param.ctx,
spaceId = param.space
)
)
.module(ObjectRelationListModule)
.build()
}
@ -577,6 +588,12 @@ class ComponentManager(
editorComponent
.get(key = param.ctx, param = param)
.relationAddToObjectComponent()
.withVmParams(
vmParams = RelationAddViewModelBase.VmParams(
objectId = param.ctx,
space = param.space
)
)
.module(RelationAddToObjectModule)
.build()
}
@ -585,6 +602,12 @@ class ComponentManager(
objectSetComponent
.get(key = param.ctx, param = param)
.relationAddToObjectComponent()
.withVmParams(
vmParams = RelationAddViewModelBase.VmParams(
objectId = param.ctx,
space = param.space
)
)
.module(RelationAddToObjectModule)
.build()
}
@ -593,6 +616,12 @@ class ComponentManager(
objectSetComponent
.get(key = param.ctx, param = param)
.relationAddToDataViewComponent()
.withVmParams(
vmParams = RelationAddViewModelBase.VmParams(
objectId = param.ctx,
space = param.space
)
)
.module(RelationAddToDataViewModule)
.build()
}

View file

@ -1010,7 +1010,8 @@ object EditorUseCaseModule {
@JvmStatic
@Provides
@PerScreen
fun provideAddRelationToObject(repo: BlockRepository) = AddRelationToObject(repo)
fun provideAddRelationToObject(repo: BlockRepository, dispatchers: AppCoroutineDispatchers) =
AddRelationToObject(repo, dispatchers)
@JvmStatic
@Provides

View file

@ -579,7 +579,8 @@ object ObjectSetModule {
@JvmStatic
@Provides
@PerScreen
fun provideAddRelationToObject(repo: BlockRepository) = AddRelationToObject(repo)
fun provideAddRelationToObject(repo: BlockRepository, dispatchers: AppCoroutineDispatchers)
: AddRelationToObject = AddRelationToObject(repo, dispatchers)
@JvmStatic
@Provides

View file

@ -11,10 +11,10 @@ import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.GetRelations
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
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.providers.ObjectRelationProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider.Companion.DATA_VIEW_PROVIDER_TYPE
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider.Companion.INTRINSIC_PROVIDER_TYPE
@ -23,6 +23,7 @@ import com.anytypeio.anytype.presentation.util.Dispatcher
import com.anytypeio.anytype.ui.relations.RelationAddToDataViewFragment
import com.anytypeio.anytype.ui.relations.RelationAddToObjectBlockFragment
import com.anytypeio.anytype.ui.relations.RelationAddToObjectFragment
import dagger.BindsInstance
import dagger.Module
import dagger.Provides
import dagger.Subcomponent
@ -35,6 +36,8 @@ interface RelationAddToObjectSubComponent {
@Subcomponent.Builder
interface Builder {
@BindsInstance
fun withVmParams(vmParams: RelationAddViewModelBase.VmParams) : Builder
fun module(module: RelationAddToObjectModule): Builder
fun build(): RelationAddToObjectSubComponent
}
@ -49,6 +52,7 @@ object RelationAddToObjectModule {
@Provides
@PerDialog
fun provideViewModelFactory(
vmParams: RelationAddViewModelBase.VmParams,
addRelationToObject: AddRelationToObject,
storeOfRelations: StoreOfRelations,
dispatcher: Dispatcher<Payload>,
@ -57,9 +61,9 @@ object RelationAddToObjectModule {
getRelations: GetRelations,
appCoroutineDispatchers: AppCoroutineDispatchers,
addObjectToWorkspace: AddObjectToWorkspace,
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
): RelationAddToObjectViewModel.Factory = RelationAddToObjectViewModel.Factory(
vmParams = vmParams,
storeOfRelations = storeOfRelations,
addRelationToObject = addRelationToObject,
dispatcher = dispatcher,
@ -68,7 +72,6 @@ object RelationAddToObjectModule {
getRelations = getRelations,
appCoroutineDispatchers = appCoroutineDispatchers,
addObjectToWorkspace = addObjectToWorkspace,
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
)
@ -95,6 +98,8 @@ interface RelationAddToDataViewSubComponent {
@Subcomponent.Builder
interface Builder {
@BindsInstance
fun withVmParams(vmParams: RelationAddViewModelBase.VmParams) : Builder
fun module(module: RelationAddToDataViewModule): Builder
fun build(): RelationAddToDataViewSubComponent
}
@ -109,6 +114,7 @@ object RelationAddToDataViewModule {
@Provides
@PerDialog
fun provideViewModelFactory(
vmParams: RelationAddViewModelBase.VmParams,
addRelationToDataView: AddRelationToDataView,
dispatcher: Dispatcher<Payload>,
state: MutableStateFlow<ObjectState>,
@ -118,7 +124,6 @@ object RelationAddToDataViewModule {
appCoroutineDispatchers: AppCoroutineDispatchers,
getRelations: GetRelations,
addObjectToWorkspace: AddObjectToWorkspace,
spaceManager: SpaceManager,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
storeOfRelations: StoreOfRelations
): RelationAddToDataViewViewModel.Factory = RelationAddToDataViewViewModel.Factory(
@ -131,9 +136,9 @@ object RelationAddToDataViewModule {
appCoroutineDispatchers = appCoroutineDispatchers,
getRelations = getRelations,
addObjectToWorkspace = addObjectToWorkspace,
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
vmParams = vmParams
)
@JvmStatic

View file

@ -1069,17 +1069,6 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
SelectProgrammingLanguageFragment.new(command.target)
.showChildFragment()
}
is Command.OpenObjectRelationScreen.RelationAdd -> {
hideKeyboard()
ObjectRelationListFragment
.new(
ctx = command.ctx,
space = space,
target = command.target,
mode = ObjectRelationListFragment.MODE_ADD,
)
.showChildFragment()
}
is Command.OpenObjectRelationScreen.RelationList -> {
hideKeyboard()
findNavController().safeNavigate(
@ -1090,7 +1079,6 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
ObjectRelationListFragment.ARG_SPACE to space,
ObjectRelationListFragment.ARG_TARGET to command.target,
ObjectRelationListFragment.ARG_LOCKED to command.isLocked,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST,
)
)
}

View file

@ -229,7 +229,6 @@ abstract class ObjectMenuBaseFragment :
ObjectRelationListFragment.ARG_SPACE to space,
ObjectRelationListFragment.ARG_TARGET to null,
ObjectRelationListFragment.ARG_LOCKED to isLocked,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST,
ObjectRelationListFragment.ARG_SET_FLOW to false
)
)
@ -243,7 +242,6 @@ abstract class ObjectMenuBaseFragment :
ObjectRelationListFragment.ARG_SPACE to space,
ObjectRelationListFragment.ARG_TARGET to null,
ObjectRelationListFragment.ARG_LOCKED to isLocked,
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST,
ObjectRelationListFragment.ARG_SET_FLOW to true
)
)

View file

@ -16,9 +16,7 @@ import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.TimeInMillis
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_ui.features.relations.DocumentRelationAdapter
import com.anytypeio.anytype.core_ui.reactive.textChanges
import com.anytypeio.anytype.core_utils.ext.arg
import com.anytypeio.anytype.core_utils.ext.argInt
import com.anytypeio.anytype.core_utils.ext.argString
import com.anytypeio.anytype.core_utils.ext.argStringOrNull
import com.anytypeio.anytype.core_utils.ext.gone
@ -41,8 +39,6 @@ import com.anytypeio.anytype.ui.editor.OnFragmentInteractionListener
import com.anytypeio.anytype.ui.relations.value.ObjectValueFragment
import com.anytypeio.anytype.ui.relations.value.TagOrStatusValueFragment
import javax.inject.Inject
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.onStart
import timber.log.Timber
open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelationListBinding>(),
@ -60,7 +56,6 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
private val ctx: String get() = argString(ARG_CTX)
private val space: String get() = argString(ARG_SPACE)
private val target: String? get() = argStringOrNull(ARG_TARGET)
private val mode: Int get() = argInt(ARG_MODE)
private val isLocked: Boolean get() = arg(ARG_LOCKED)
private val isSetFlow: Boolean get() = arg(ARG_SET_FLOW)
@ -214,37 +209,10 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
binding.btnEditOrDone.setText(R.string.edit)
}
}
if (mode == MODE_ADD) {
binding.searchBar.root.visible()
val queries = searchRelationInput.textChanges()
.onStart { emit(searchRelationInput.text.toString()) }
val views = vm.views.combine(queries) { views, query ->
if (views.isEmpty()) {
views
} else {
views.filter { model ->
if (model is RelationListViewModel.Model.Item) {
model.view.name.contains(query, true)
} else {
true
}
}
}
}
jobs += lifecycleScope.subscribe(searchRelationInput.textChanges()) {
if (it.isEmpty()) clearSearchText.invisible() else clearSearchText.visible()
}
jobs += lifecycleScope.subscribe(views) { docRelationAdapter.update(it) }
} else {
binding.searchBar.root.gone()
jobs += lifecycleScope.subscribe(vm.views) { docRelationAdapter.update(it) }
}
binding.searchBar.root.gone()
jobs += lifecycleScope.subscribe(vm.views) { docRelationAdapter.update(it) }
super.onStart()
if (mode == MODE_LIST) {
vm.onStartListMode(ctx)
} else {
vm.onStartAddMode(ctx)
}
vm.onStartListMode(ctx)
}
override fun onStop() {
@ -325,7 +293,6 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
ctx: Id,
space: Id,
target: String?,
mode: Int,
locked: Boolean = false,
isSetFlow: Boolean = false,
) = ObjectRelationListFragment().apply {
@ -333,7 +300,6 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
ARG_CTX to ctx,
ARG_SPACE to space,
ARG_TARGET to target,
ARG_MODE to mode,
ARG_LOCKED to locked,
ARG_SET_FLOW to isSetFlow
)
@ -341,11 +307,8 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
const val ARG_CTX = "arg.document-relation.ctx"
const val ARG_SPACE = "arg.document-relation.space"
const val ARG_MODE = "arg.document-relation.mode"
const val ARG_TARGET = "arg.document-relation.target"
const val ARG_LOCKED = "arg.document-relation.locked"
const val MODE_ADD = 1
const val MODE_LIST = 2
const val ARG_SET_FLOW = "arg.document-relation.set-flow"
}
}

View file

@ -17,7 +17,6 @@ import com.anytypeio.anytype.R
import com.anytypeio.anytype.analytics.base.EventsDictionary
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_ui.features.relations.RelationAddAdapter
import com.anytypeio.anytype.core_ui.features.relations.RelationAddHeaderAdapter

View file

@ -24,8 +24,6 @@ sealed class Event {
val root: Id,
val details: Block.Details = Block.Details(emptyMap()),
val blocks: List<Block>,
val relations: List<Relation> = emptyList(),
val relationLinks: List<RelationLink> = emptyList(),
val objectRestrictions: List<ObjectRestriction> = emptyList(),
val dataViewRestrictions: List<DataViewRestrictions> = emptyList()
) : Command()
@ -193,32 +191,11 @@ sealed class Event {
val style: Block.Content.Divider.Style
) : Command()
sealed class ObjectRelationLinks : Command() {
data class Amend(
override val context: String,
val id: Id,
val relationLinks: List<RelationLink>
) : ObjectRelationLinks()
sealed class ObjectRelation : Command() {
data class Remove(
override val context: String,
val id: Id,
val keys: List<Key>
) : ObjectRelationLinks()
}
sealed class ObjectRelation : Command() {
data class Set(
override val context: String,
val id: Id,
val key: Id,
val relations: List<Relation>
) : ObjectRelation()
data class Remove(
override val context: String,
val id: Id,
val key: Id
) : ObjectRelation()
}

View file

@ -7,7 +7,6 @@ data class ObjectView(
val root: Id,
val blocks: List<Block>,
val details: Map<Id, Struct>,
val relations: List<RelationLink>,
val objectRestrictions: List<ObjectRestriction>,
val dataViewRestrictions: List<DataViewRestrictions>
)

View file

@ -1,17 +1,9 @@
package com.anytypeio.anytype.core_models.ext
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.RelationLink
fun List<RelationLink>.process(
event: Event.Command.ObjectRelationLinks
): List<RelationLink> = when (event) {
is Event.Command.ObjectRelationLinks.Amend -> amend(event.relationLinks)
is Event.Command.ObjectRelationLinks.Remove -> remove(event.keys)
}
fun List<RelationLink>.amend(relationLinks: List<RelationLink>): List<RelationLink> {
val map = this.associateBy { it.key }.toMutableMap()
relationLinks.forEach { relation ->

View file

@ -458,7 +458,7 @@ class BlockDataRepository(
override suspend fun addRelationToObject(
ctx: Id, relation: Id
): Payload = remote.addRelationToObject(ctx, relation)
): Payload? = remote.addRelationToObject(ctx, relation)
override suspend fun deleteRelationFromObject(ctx: Id, relation: Key): Payload {
return remote.deleteRelationFromObject(ctx = ctx, relation = relation)

View file

@ -189,7 +189,7 @@ interface BlockRemote {
suspend fun cancelObjectSearchSubscription(subscriptions: List<Id>)
suspend fun addRelationToObject(ctx: Id, relation: Key): Payload
suspend fun addRelationToObject(ctx: Id, relation: Key): Payload?
suspend fun deleteRelationFromObject(ctx: Id, relation: Key): Payload
suspend fun debugSpace(space: SpaceId): String

View file

@ -229,7 +229,7 @@ interface BlockRepository {
suspend fun cancelObjectSearchSubscription(subscriptions: List<Id>)
suspend fun addRelationToObject(ctx: Id, relation: Key): Payload
suspend fun addRelationToObject(ctx: Id, relation: Key): Payload?
suspend fun deleteRelationFromObject(ctx: Id, relation: Key): Payload
suspend fun debugSpace(space: SpaceId): String

View file

@ -3,18 +3,20 @@ package com.anytypeio.anytype.domain.relations
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.ResultInteractor
import com.anytypeio.anytype.domain.block.repo.BlockRepository
/**
* Use-case for adding a relation to an object.
*/
class AddRelationToObject(
private val repo: BlockRepository
) : BaseUseCase<Payload, AddRelationToObject.Params>() {
private val repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<AddRelationToObject.Params, Payload?>(dispatchers.io) {
override suspend fun run(params: Params) = safe {
repo.addRelationToObject(
override suspend fun doWork(params: Params): Payload? {
return repo.addRelationToObject(
ctx = params.ctx,
relation = params.relationKey
)

View file

@ -413,7 +413,7 @@ class BlockMiddleware(
override suspend fun addRelationToObject(
ctx: Id, relation: Key
): Payload = middleware.objectRelationAdd(ctx, relation)
): Payload? = middleware.objectRelationAdd(ctx, relation)
override suspend fun deleteRelationFromObject(
ctx: Id,

View file

@ -1122,7 +1122,7 @@ class Middleware @Inject constructor(
}
@Throws(Exception::class)
fun objectRelationAdd(ctx: Id, relation: Key): Payload {
fun objectRelationAdd(ctx: Id, relation: Key): Payload? {
val request = Rpc.ObjectRelation.Add.Request(
contextId = ctx,
relationKeys = listOf(relation)
@ -1130,7 +1130,7 @@ class Middleware @Inject constructor(
logRequestIfDebug(request)
val (response, time) = measureTimedValue { service.objectRelationAdd(request) }
logResponseIfDebug(response, time)
return response.event.toPayload()
return response.event?.toPayload()
}
@Throws(Exception::class)

View file

@ -237,19 +237,10 @@ fun anytype.Event.Message.toCoreModels(
key = event.key?.value_
)
}
objectRelationsAmend != null -> {
val event = objectRelationsAmend
checkNotNull(event)
Event.Command.ObjectRelationLinks.Amend(
context = context,
id = event.id,
relationLinks = event.relationLinks.map { it.toCoreModels() }
)
}
objectRelationsRemove != null -> {
val event = objectRelationsRemove
checkNotNull(event)
Event.Command.ObjectRelationLinks.Remove(
Event.Command.ObjectRelation.Remove(
context = context,
id = event.id,
keys = event.relationKeys

View file

@ -46,7 +46,6 @@ import com.anytypeio.anytype.core_models.RelationLink
import com.anytypeio.anytype.core_models.RelationListWithValueItem
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.SpaceUsage
import com.anytypeio.anytype.core_models.TimeInSeconds
import com.anytypeio.anytype.core_models.chats.Chat
import com.anytypeio.anytype.core_models.history.DiffVersionResponse
import com.anytypeio.anytype.core_models.history.ShowVersionResponse
@ -95,7 +94,6 @@ fun MObjectView.toPayload(): Payload {
details.id to details.details.toCoreModel()
}
),
relationLinks = relationLinks.map { it.toCoreModels() },
objectRestrictions = restrictions?.object_?.map { it.toCoreModel() }.orEmpty(),
dataViewRestrictions = restrictions?.dataview?.map { it.toCoreModel() }.orEmpty()
)
@ -108,7 +106,6 @@ fun MObjectView.toCore(): ObjectView {
root = rootId,
blocks = blocks.toCoreModels(),
details = details.associate { d -> d.id to d.details.orEmpty() },
relations = relationLinks.map { it.toCoreModels() },
objectRestrictions = restrictions?.object_?.map { it.toCoreModel() }.orEmpty(),
dataViewRestrictions = restrictions?.dataview?.map { it.toCoreModel() }.orEmpty(),
)

View file

@ -2,13 +2,10 @@ package com.anytypeio.anytype
import anytype.model.Block
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.RelationLink
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_utils.tools.FeatureToggles
import com.anytypeio.anytype.middleware.EventProxy
import com.anytypeio.anytype.middleware.interactor.MiddlewareEventChannel
import com.anytypeio.anytype.middleware.mappers.MRelationLink
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.runBlocking
@ -315,63 +312,6 @@ class MiddlewareEventChannelTest {
}
}
@Test
fun `should return amend relation links event`() {
val context = MockDataFactory.randomUuid()
val id = MockDataFactory.randomUuid()
val relationLink1 = MRelationLink(
key = MockDataFactory.randomUuid(),
format = anytype.model.RelationFormat.longtext
)
val relationLink2 = MRelationLink(
key = MockDataFactory.randomUuid(),
format = anytype.model.RelationFormat.longtext
)
val relationLink3 = MRelationLink(
key = MockDataFactory.randomUuid(),
format = anytype.model.RelationFormat.longtext
)
val msg = anytype.Event.Object.Relations.Amend(
id = id,
relationLinks = listOf(relationLink1, relationLink2, relationLink3)
)
val message = anytype.Event.Message(objectRelationsAmend = msg)
val event = anytype.Event(contextId = context, messages = listOf(message))
proxy.stub {
on { flow() } doReturn flowOf(event)
}
val expected = listOf(
Event.Command.ObjectRelationLinks.Amend(
context = context,
id = id,
relationLinks = listOf(
RelationLink(key = relationLink1.key, format = RelationFormat.LONG_TEXT),
RelationLink(key = relationLink2.key, format = RelationFormat.LONG_TEXT),
RelationLink(key = relationLink3.key, format = RelationFormat.LONG_TEXT)
)
)
)
runBlocking {
channel.observeEvents(context = context).collect { events ->
assertEquals(
expected = expected,
actual = events
)
}
}
}
@Test
fun `should return remove relation links event`() {
@ -397,7 +337,7 @@ class MiddlewareEventChannelTest {
}
val expected = listOf(
Event.Command.ObjectRelationLinks.Remove(
Event.Command.ObjectRelation.Remove(
context = context,
id = id,
keys = listOf(id1, id2, id3)

View file

@ -1,13 +1,11 @@
package com.anytypeio.anytype.presentation.editor
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Document
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.domain.editor.Editor
import com.anytypeio.anytype.domain.editor.Editor.Focus
import com.anytypeio.anytype.presentation.editor.editor.Proxy
import com.anytypeio.anytype.presentation.editor.editor.Store
import com.anytypeio.anytype.presentation.editor.editor.actions.ActionItemType
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.editor.selection.SelectionStateHolder
import kotlinx.coroutines.flow.Flow
@ -101,11 +99,8 @@ interface Editor {
val focus: Store<Focus> = Store.Focus()
val details: Store.Details = Store.Details()
@Deprecated("legacy")
val relations: Store.Relations = Store.Relations()
val textSelection: Store<Editor.TextSelection> = Store.TextSelection()
val objectRestrictions: Store.ObjectRestrictions = Store.ObjectRestrictions()
val relationLinks: Store.RelationLinks = Store.RelationLinks()
}
class Proxer(

View file

@ -599,15 +599,11 @@ class EditorViewModel(
when (event) {
is Event.Command.ShowObject -> {
orchestrator.stores.details.update(event.details)
orchestrator.stores.relationLinks.update(event.relationLinks)
orchestrator.stores.objectRestrictions.update(event.objectRestrictions)
}
is Event.Command.Details -> {
orchestrator.stores.details.apply { update(current().process(event)) }
}
is Event.Command.ObjectRelationLinks -> {
orchestrator.stores.relationLinks.apply { update(current().process(event)) }
}
else -> {
// do nothing
}
@ -792,7 +788,6 @@ class EditorViewModel(
anchor = context,
indent = INITIAL_INDENT,
details = details,
relationLinks = orchestrator.stores.relationLinks.current(),
restrictions = orchestrator.stores.objectRestrictions.current(),
selection = currentSelection()
) { onRenderFlagFound -> flags.add(onRenderFlagFound) }
@ -3994,12 +3989,9 @@ class EditorViewModel(
}
is ListenerType.Relation.Placeholder -> {
when (mode) {
EditorMode.Edit -> dispatch(
Command.OpenObjectRelationScreen.RelationAdd(
ctx = context,
target = clicked.target
)
)
EditorMode.Edit -> {
sendToast(NOT_ALLOWED_FOR_RELATION)
}
else -> onBlockMultiSelectClicked(clicked.target)
}
}
@ -5237,13 +5229,11 @@ class EditorViewModel(
val objectDetails = details.details[context]?.map ?: emptyMap()
val objectWrapper = ObjectWrapper.Basic(objectDetails)
val objectType = objectWrapper.getProperType()
val relationLinks = orchestrator.stores.relationLinks.current()
viewModelScope.launch {
val objectRelationViews = getObjectRelationsView(
ctx = context,
objectDetails = objectDetails,
relationLinks = relationLinks,
details = details,
objectWrapper = objectWrapper
)
@ -5251,7 +5241,6 @@ class EditorViewModel(
val recommendedRelationViews = getRecommendedRelations(
ctx = context,
objectDetails = objectDetails,
relationLinks = relationLinks,
objectTypeStruct = details.details[objectType]?.map,
details = details
)
@ -5265,14 +5254,13 @@ class EditorViewModel(
private suspend fun getObjectRelationsView(
ctx: Id,
objectDetails: Map<Key, Any?>,
relationLinks: List<RelationLink>,
details: Block.Details,
objectWrapper: ObjectWrapper.Basic
): List<ObjectRelationView> {
return getObjectRelations(
systemRelations = listOf(),
relationLinks = relationLinks,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
relationKeys = objectDetails.keys
).views(
context = ctx,
details = details,
@ -5286,16 +5274,15 @@ class EditorViewModel(
private suspend fun getRecommendedRelations(
ctx: Id,
objectDetails: Map<Key, Any?>,
relationLinks: List<RelationLink>,
objectTypeStruct: Struct?,
details: Block.Details
): List<ObjectRelationView> {
val objType = objectTypeStruct?.mapToObjectWrapperType()
val recommendedRelations = objType?.recommendedRelations ?: emptyList()
return getNotIncludedRecommendedRelations(
relationLinks = relationLinks,
recommendedRelations = recommendedRelations,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
relationKeys = objectDetails.keys
).views(
context = ctx,
details = details,
@ -7409,8 +7396,8 @@ class EditorViewModel(
private fun checkRelationIsInObject(
view: ObjectRelationView
): Boolean {
val relationLinks = orchestrator.stores.relationLinks.current()
return relationLinks.any { it.key == view.key }
val currentObjectDetails = orchestrator.stores.details.getAsObject(vmParams.ctx)
return currentObjectDetails?.map?.keys?.any { it == view.key } ?: false
}
private suspend fun proceedWithAddingRelationToObject(
@ -7422,10 +7409,10 @@ class EditorViewModel(
ctx = ctx,
relationKey = view.key
)
addRelationToObject.run(params).process(
failure = { Timber.e(it, "Error while adding relation to object") },
success = {
dispatcher.send(it)
addRelationToObject.async(params).fold(
onFailure = { e -> Timber.e(e, "Error while adding relation to object") },
onSuccess = { payload ->
if (payload != null) dispatcher.send(payload)
analytics.sendAnalyticsRelationEvent(
eventName = EventsDictionary.relationAdd,
storeOfRelations = storeOfRelations,

View file

@ -92,7 +92,6 @@ sealed class Command {
val isLocked: Boolean
) : OpenObjectRelationScreen()
data class RelationAdd(val ctx: String, val target: String) : OpenObjectRelationScreen()
sealed class Value : OpenObjectRelationScreen() {
abstract val isReadOnlyValue: Boolean
data class Text(

View file

@ -2,7 +2,6 @@ package com.anytypeio.anytype.presentation.editor.render
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.RelationLink
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
import com.anytypeio.anytype.domain.editor.Editor
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
@ -29,7 +28,6 @@ interface BlockViewRenderer {
anchor: Id,
indent: Int,
details: Block.Details = Block.Details(emptyMap()),
relationLinks: List<RelationLink>,
restrictions: List<ObjectRestriction>,
selection: Set<Id>,
count: Int = 0,

View file

@ -7,7 +7,6 @@ import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectTypeIds.BOOKMARK
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.RelationLink
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_models.ext.parseThemeTextColor
@ -65,7 +64,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor: Id,
indent: Int,
details: Block.Details,
relationLinks: List<RelationLink>,
restrictions: List<ObjectRestriction>,
selection: Set<Id>,
count: Int,
@ -128,7 +126,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent.inc(),
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
@ -174,7 +171,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent.inc(),
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
@ -212,7 +208,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent.inc(),
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
@ -253,7 +248,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent.inc(),
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
@ -294,7 +288,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent.inc(),
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
@ -335,7 +328,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent.inc(),
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
@ -379,7 +371,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent.inc(),
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
@ -416,7 +407,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent.inc(),
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
@ -475,7 +465,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent.inc(),
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
@ -515,7 +504,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent.inc(),
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
@ -560,7 +548,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent.inc(),
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
onRenderFlag = onRenderFlag,
@ -682,7 +669,6 @@ class DefaultBlockViewRenderer @Inject constructor(
anchor = block.id,
indent = indent,
details = details,
relationLinks = relationLinks,
restrictions = restrictions,
selection = selection,
count = mCounter,

View file

@ -536,7 +536,6 @@ class VersionHistoryViewModel(
anchor = vmParams.objectId,
indent = INITIAL_INDENT,
details = event.details,
relationLinks = event.relationLinks,
restrictions = event.objectRestrictions,
selection = emptySet()
).filterNot { it is BlockView.DataView }
@ -574,7 +573,6 @@ class VersionHistoryViewModel(
anchor = vmParams.objectId,
indent = INITIAL_INDENT,
details = event.details,
relationLinks = event.relationLinks,
restrictions = event.objectRestrictions,
selection = emptySet()
)

View file

@ -9,7 +9,6 @@ import com.anytypeio.anytype.core_models.DVViewerRelation
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.dataview.interactor.AddRelationToDataView
@ -17,7 +16,6 @@ import com.anytypeio.anytype.domain.dataview.interactor.UpdateDataViewViewer
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.relations.GetRelations
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.sendAnalyticsRelationEvent
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
@ -31,6 +29,7 @@ import timber.log.Timber
class RelationAddToDataViewViewModel(
relationsProvider: ObjectRelationProvider,
val vmParams: VmParams,
private val objectState: StateFlow<ObjectState>,
private val updateDataViewViewer: UpdateDataViewViewer,
private val addRelationToDataView: AddRelationToDataView,
@ -39,15 +38,14 @@ class RelationAddToDataViewViewModel(
private val analytics: Analytics,
private val addObjectToWorkspace: AddObjectToWorkspace,
private val appCoroutineDispatchers: AppCoroutineDispatchers,
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
private val storeOfRelations: StoreOfRelations
) : RelationAddViewModelBase(
vmParams = vmParams,
relationsProvider = relationsProvider,
appCoroutineDispatchers = appCoroutineDispatchers,
getRelations = getRelations,
addObjectToWorkspace = addObjectToWorkspace,
spaceManager = spaceManager
) {
fun onRelationSelected(
@ -78,7 +76,7 @@ class RelationAddToDataViewViewModel(
storeOfRelations = storeOfRelations,
relationKey = relation,
type = screenType,
spaceParams = analyticSpaceHelperDelegate.provideParams(spaceManager.get())
spaceParams = analyticSpaceHelperDelegate.provideParams(vmParams.space.id)
)
},
failure = {
@ -110,6 +108,7 @@ class RelationAddToDataViewViewModel(
}
class Factory(
private val vmParams: VmParams,
private val state: StateFlow<ObjectState>,
private val updateDataViewViewer: UpdateDataViewViewer,
private val addRelationToDataView: AddRelationToDataView,
@ -119,13 +118,13 @@ class RelationAddToDataViewViewModel(
private val appCoroutineDispatchers: AppCoroutineDispatchers,
private val getRelations: GetRelations,
private val addObjectToWorkspace: AddObjectToWorkspace,
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
private val storeOfRelations: StoreOfRelations
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return RelationAddToDataViewViewModel(
vmParams = vmParams,
addRelationToDataView = addRelationToDataView,
dispatcher = dispatcher,
updateDataViewViewer = updateDataViewViewer,
@ -135,7 +134,6 @@ class RelationAddToDataViewViewModel(
appCoroutineDispatchers = appCoroutineDispatchers,
getRelations = getRelations,
addObjectToWorkspace = addObjectToWorkspace,
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
storeOfRelations = storeOfRelations
) as T

View file

@ -8,14 +8,12 @@ import com.anytypeio.anytype.analytics.base.EventsDictionary
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.GetRelations
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.extension.sendAnalyticsRelationEvent
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
@ -26,6 +24,7 @@ import timber.log.Timber
class RelationAddToObjectViewModel(
relationsProvider: ObjectRelationProvider,
val vmParams: VmParams,
private val addRelationToObject: AddRelationToObject,
private val dispatcher: Dispatcher<Payload>,
private val analytics: Analytics,
@ -34,13 +33,12 @@ class RelationAddToObjectViewModel(
appCoroutineDispatchers: AppCoroutineDispatchers,
getRelations: GetRelations,
addObjectToWorkspace: AddObjectToWorkspace,
private val spaceManager: SpaceManager
) : RelationAddViewModelBase(
vmParams = vmParams,
relationsProvider = relationsProvider,
appCoroutineDispatchers = appCoroutineDispatchers,
getRelations = getRelations,
addObjectToWorkspace = addObjectToWorkspace,
spaceManager = spaceManager
), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
val commands = MutableSharedFlow<Command>(replay = 0)
@ -51,26 +49,24 @@ class RelationAddToObjectViewModel(
screenType: String
) {
viewModelScope.launch {
addRelationToObject(
AddRelationToObject.Params(
ctx = ctx,
relationKey = relation
)
).process(
success = {
dispatcher.send(it).also {
commands.emit(Command.OnRelationAdd(relation = relation))
analytics.sendAnalyticsRelationEvent(
eventName = EventsDictionary.relationAdd,
storeOfRelations = storeOfRelations,
relationKey = relation,
type = screenType,
spaceParams = provideParams(spaceManager.get())
)
isDismissed.value = true
}
val params = AddRelationToObject.Params(
ctx = ctx,
relationKey = relation
)
addRelationToObject.async(params).fold(
onSuccess = { payload ->
if (payload != null) dispatcher.send(payload)
commands.emit(Command.OnRelationAdd(relation = relation))
analytics.sendAnalyticsRelationEvent(
eventName = EventsDictionary.relationAdd,
storeOfRelations = storeOfRelations,
relationKey = relation,
type = screenType,
spaceParams = provideParams(vmParams.space.id)
)
isDismissed.value = true
},
failure = {
onFailure = {
Timber.e(it, ERROR_MESSAGE)
_toasts.emit("$ERROR_MESSAGE: ${it.localizedMessage}")
}
@ -79,6 +75,7 @@ class RelationAddToObjectViewModel(
}
class Factory(
private val vmParams: VmParams,
private val storeOfRelations: StoreOfRelations,
private val addRelationToObject: AddRelationToObject,
private val dispatcher: Dispatcher<Payload>,
@ -87,12 +84,12 @@ class RelationAddToObjectViewModel(
private val appCoroutineDispatchers: AppCoroutineDispatchers,
private val getRelations: GetRelations,
private val addObjectToWorkspace: AddObjectToWorkspace,
private val spaceManager: SpaceManager,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return RelationAddToObjectViewModel(
vmParams = vmParams,
relationsProvider = relationsProvider,
addRelationToObject = addRelationToObject,
storeOfRelations = storeOfRelations,
@ -101,7 +98,6 @@ class RelationAddToObjectViewModel(
appCoroutineDispatchers = appCoroutineDispatchers,
getRelations = getRelations,
addObjectToWorkspace = addObjectToWorkspace,
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}

View file

@ -7,14 +7,11 @@ import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.Marketplace.MARKETPLACE_SPACE_ID
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.primitives.RelationKey
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.relations.GetRelations
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.relations.model.RelationItemView
import com.anytypeio.anytype.presentation.relations.model.RelationView
@ -32,7 +29,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch
@ -43,10 +39,10 @@ import timber.log.Timber
*/
abstract class RelationAddViewModelBase(
relationsProvider: ObjectRelationProvider,
private val vmParams: VmParams,
private val getRelations: GetRelations,
private val appCoroutineDispatchers: AppCoroutineDispatchers,
private val addObjectToWorkspace: AddObjectToWorkspace,
private val spaceManager: SpaceManager
) : BaseViewModel() {
private val userInput = MutableStateFlow(DEFAULT_INPUT)
@ -59,11 +55,20 @@ abstract class RelationAddViewModelBase(
val isDismissed = MutableStateFlow(false)
val results = MutableStateFlow(emptyList<RelationItemView>())
private val objectRelationKeys = relationsProvider.observeAll().map { relations ->
relations.map { r -> r.key }
}
private val objectRelationKeys = MutableStateFlow<List<Key>>(emptyList())
init {
Timber.d("RelationAddViewModelBase init, objectId: ${vmParams.objectId}")
viewModelScope.launch {
relationsProvider.observeAll(id = vmParams.objectId)
.catch {
Timber.e(it, "Error while observing relations")
}
.collect { relations ->
Timber.d("Object all relations: ${relations.size}")
objectRelationKeys.value = relations.map { it.key }
}
}
viewModelScope.launch {
combine(
searchQuery,
@ -161,7 +166,7 @@ abstract class RelationAddViewModelBase(
): List<ObjectWrapper.Relation> {
val params = GetRelations.Params(
// TODO DROID-2916 Provide space id to vm params
space = SpaceId(spaceManager.get()),
space = vmParams.space,
sorts = defaultObjectSearchSorts(),
filters = buildList {
addAll(filterMyRelations())
@ -193,7 +198,7 @@ abstract class RelationAddViewModelBase(
addObjectToWorkspace(
AddObjectToWorkspace.Params(
objects = listOf(relation.id),
space = spaceManager.get()
space = vmParams.space.id
)
).proceed(
success = {
@ -236,6 +241,11 @@ abstract class RelationAddViewModelBase(
) : Command()
}
data class VmParams(
val objectId: Id,
val space: SpaceId
)
companion object {
const val ERROR_MESSAGE = "Error while adding relation to object"
const val DEBOUNCE_DURATION = 300L

View file

@ -6,7 +6,6 @@ import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.analytics.base.EventsDictionary
import com.anytypeio.anytype.core_models.*
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.dataview.interactor.AddRelationToDataView
import com.anytypeio.anytype.domain.dataview.interactor.UpdateDataViewViewer
@ -138,14 +137,14 @@ class RelationCreateFromScratchForObjectViewModel(
private fun proceedWithAddingRelationToObject(ctx: Id, relation: Key) {
viewModelScope.launch {
addRelationToObject(
AddRelationToObject.Params(
ctx = ctx,
relationKey = relation
)
).process(
success = { payload ->
dispatcher.send(payload).also { isDismissed.value = true }
val params = AddRelationToObject.Params(
ctx = ctx,
relationKey = relation
)
addRelationToObject.async(params).fold(
onSuccess = { payload ->
if (payload != null) dispatcher.send(payload)
isDismissed.value = true
analytics.sendAnalyticsRelationEvent(
eventName = EventsDictionary.relationAdd,
storeOfRelations = storeOfRelations,
@ -153,7 +152,7 @@ class RelationCreateFromScratchForObjectViewModel(
spaceParams = provideParams(spaceManager.get())
)
},
failure = {
onFailure = {
Timber.e(it, ACTION_FAILED_ERROR).also { _toasts.emit(ACTION_FAILED_ERROR) }
}
)
@ -244,14 +243,14 @@ class RelationCreateFromScratchForObjectBlockViewModel(
private fun proceedWithAddingRelationToObject(ctx: Id, relationKey: Id) {
viewModelScope.launch {
addRelationToObject(
AddRelationToObject.Params(
ctx = ctx,
relationKey = relationKey
)
).process(
success = { payload ->
dispatcher.send(payload).also { commands.emit(Command.OnSuccess(relationKey)) }
val params = AddRelationToObject.Params(
ctx = ctx,
relationKey = relationKey
)
addRelationToObject.async(params).fold(
onSuccess = { payload ->
if (payload != null) dispatcher.send(payload)
commands.emit(Command.OnSuccess(relationKey))
analytics.sendAnalyticsRelationEvent(
eventName = EventsDictionary.relationAdd,
storeOfRelations = storeOfRelations,
@ -259,7 +258,7 @@ class RelationCreateFromScratchForObjectBlockViewModel(
spaceParams = provideParams(spaceManager.get())
)
},
failure = {
onFailure = {
Timber.e(it, ACTION_FAILED_ERROR).also { _toasts.emit(ACTION_FAILED_ERROR) }
}
)

View file

@ -237,39 +237,38 @@ fun ColumnView.getDateRelationFormat(): String {
/**
* Retrieves a list of distinct [ObjectWrapper.Relation] relations of Object using the given relation links filtered by system relations.
*
* @param relationLinks The list of relation links (@see [RelationLink] class) used to identify the relations.
* @param relationKeys The list of object details keys
* @param systemRelations The list of keys of the system relations. Final list will be filtered by this list.
* @param storeOfRelations The store of relations to retrieve the relations from.
*
* @return A list of distinct [ObjectWrapper.Relation] object relations.
*/
suspend fun getObjectRelations(
relationLinks: List<RelationLink>,
relationKeys: Set<Key>,
systemRelations: List<Key>,
storeOfRelations: StoreOfRelations
): List<ObjectWrapper.Relation> {
val systemRelationKeys = systemRelations.toSet()
val objectRelationKeys = relationLinks.map { it.key }.filterNot { it in systemRelationKeys }
val objectRelationKeys = relationKeys.filterNot { it in systemRelationKeys }
return storeOfRelations.getByKeys(objectRelationKeys).distinctBy { it.key }
}
/**
* Retrieves a list of filtered [ObjectWrapper.Relation] recommended relations of Object.
*
* @param relationLinks The list of relation links (@see [RelationLink] class) used to identify the relations.
* @param relationKeys The list of object details keys
* @param recommendedRelations The list of ids of the recommended relations.
* @param storeOfRelations The store of relations to retrieve the relations from.
*
* @return A list of distinct [ObjectWrapper.Relation] object recommended relations.
*/
suspend fun getNotIncludedRecommendedRelations(
relationLinks: List<RelationLink>,
relationKeys: Set<Key>,
recommendedRelations: List<Id>,
storeOfRelations: StoreOfRelations
): List<ObjectWrapper.Relation> {
val relationLinkKeys = relationLinks.map { it.key }.toSet()
return storeOfRelations.getById(recommendedRelations)
.filterNot { recommended -> recommended.key in relationLinkKeys }
.filterNot { recommended -> recommended.key in relationKeys }
}
fun ObjectRelationView.getRelationFormat(): RelationFormat = when (this) {

View file

@ -13,11 +13,11 @@ import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.RelationLink
import com.anytypeio.anytype.core_models.TimeInMillis
import com.anytypeio.anytype.core_models.ext.mapToObjectWrapperType
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_utils.diff.DefaultObjectDiffIdentifier
import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.StoreOfRelations
@ -39,7 +39,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import timber.log.Timber
@ -64,7 +63,6 @@ class RelationListViewModel(
private val jobs = mutableListOf<Job>()
private val isInAddMode = MutableStateFlow(false)
val commands = MutableSharedFlow<Command>(replay = 0)
val views = MutableStateFlow<List<Model>>(emptyList())
@ -74,7 +72,6 @@ class RelationListViewModel(
fun onStartListMode(ctx: Id) {
Timber.d("onStartListMode, ctx: $ctx")
isInAddMode.value = false
viewModelScope.sendEvent(
analytics = analytics,
eventName = relationsScreenShow
@ -82,17 +79,15 @@ class RelationListViewModel(
jobs += viewModelScope.launch {
combine(
storeOfRelations.trackChanges(),
relationListProvider.links,
relationListProvider.details
) { _, relationLinks, details ->
constructViews(ctx, relationLinks, details)
) { _, details ->
constructViews(ctx, details)
}.collect { views.value = it }
}
}
private suspend fun constructViews(
ctx: Id,
relationLinks: List<RelationLink>,
details: Block.Details
): List<Model> {
@ -108,7 +103,6 @@ class RelationListViewModel(
val objectRelationViews = getObjectRelationsView(
ctx = ctx,
objectDetails = objectDetails,
relationLinks = relationLinks,
details = details,
objectWrapper = objectWrapper
)
@ -116,7 +110,6 @@ class RelationListViewModel(
val recommendedRelationViews = getRecommendedRelations(
ctx = ctx,
objectDetails = objectDetails,
relationLinks = relationLinks,
objectTypeWrapper = objectTypeWrapper,
details = details
)
@ -127,13 +120,12 @@ class RelationListViewModel(
private suspend fun getObjectRelationsView(
ctx: Id,
objectDetails: Map<Key, Any?>,
relationLinks: List<RelationLink>,
details: Block.Details,
objectWrapper: ObjectWrapper.Basic
): List<Model.Item> {
return getObjectRelations(
systemRelations = listOf(),
relationLinks = relationLinks,
relationKeys = objectDetails.keys,
storeOfRelations = storeOfRelations
).views(
context = ctx,
@ -153,12 +145,11 @@ class RelationListViewModel(
private suspend fun getRecommendedRelations(
ctx: Id,
objectDetails: Map<Key, Any?>,
relationLinks: List<RelationLink>,
objectTypeWrapper: ObjectWrapper.Type,
details: Block.Details
): List<Model.Item> {
return getNotIncludedRecommendedRelations(
relationLinks = relationLinks,
relationKeys = objectDetails.keys,
recommendedRelations = objectTypeWrapper.recommendedRelations,
storeOfRelations = storeOfRelations
).views(
@ -197,11 +188,6 @@ class RelationListViewModel(
}
}
fun onStartAddMode(ctx: Id) {
isInAddMode.value = true
getRelations(ctx)
}
fun onStop() {
jobs.apply {
forEach { it.cancel() }
@ -212,15 +198,11 @@ class RelationListViewModel(
fun onRelationClicked(ctx: Id, target: Id?, view: ObjectRelationView) {
Timber.d("onRelationClicked, ctx: $ctx, target: $target, view: $view")
viewModelScope.launch {
if (isInAddMode.value) {
onRelationClickedAddMode(target = target, view = view)
if (checkRelationIsInObject(view)) {
onRelationClickedListMode(ctx, view)
} else {
if (checkRelationIsInObject(view)) {
proceedWithAddingRelationToObject(ctx, view) {
onRelationClickedListMode(ctx, view)
} else {
proceedWithAddingRelationToObject(ctx, view) {
onRelationClickedListMode(ctx, view)
}
}
}
}
@ -244,9 +226,9 @@ class RelationListViewModel(
}
}
private suspend fun checkRelationIsInObject(view: ObjectRelationView): Boolean {
val relationLinks = relationListProvider.links.stateIn(viewModelScope).value
return relationLinks.any { it.key == view.key }
private fun checkRelationIsInObject(view: ObjectRelationView): Boolean {
val objectRelations = relationListProvider.getDetails().details[vmParams.objectId]?.map?.keys
return objectRelations?.any { it == view.key } == true
}
private suspend fun proceedWithAddingRelationToObject(
@ -258,10 +240,10 @@ class RelationListViewModel(
ctx = ctx,
relationKey = view.key
)
addRelationToObject.run(params).process(
failure = { Timber.e(it, "Error while adding relation to object") },
success = {
dispatcher.send(it)
addRelationToObject.async(params).fold(
onFailure = { Timber.e(it, "Error while adding relation to object") },
onSuccess = { payload ->
if (payload != null) dispatcher.send(payload)
analytics.sendAnalyticsRelationEvent(
eventName = EventsDictionary.relationAdd,
storeOfRelations = storeOfRelations,
@ -523,21 +505,6 @@ class RelationListViewModel(
}
}
private fun getRelations(ctx: Id) {
viewModelScope.launch {
val relations =
relationListProvider.getLinks().mapNotNull { storeOfRelations.getByKey(it.key) }
val details = relationListProvider.getDetails()
val values = details.details[ctx]?.map ?: emptyMap()
views.value = relations.views(
details = details,
values = values,
urlBuilder = urlBuilder,
fieldParser = fieldParser
).map { Model.Item(it) }
}
}
fun onRelationTextValueChanged(
ctx: Id,
value: Any?,
@ -653,6 +620,7 @@ class RelationListViewModel(
}
data class VmParams(
val objectId: Id,
val spaceId: SpaceId
)

View file

@ -5,47 +5,67 @@ import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.presentation.sets.state.ObjectState
import kotlin.collections.mapNotNull
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
class DataViewObjectRelationProvider(
private val objectState: StateFlow<ObjectState>,
private val storeOfRelations: StoreOfRelations
) : ObjectRelationProvider {
override suspend fun get(relation: Key): ObjectWrapper.Relation {
return storeOfRelations.getByKey(relation)
?: throw IllegalStateException("Could not found relation by key: $relation")
}
override suspend fun getOrNull(relation: Key): ObjectWrapper.Relation? {
return storeOfRelations.getByKey(relation)
}
override suspend fun getById(relation: Id): ObjectWrapper.Relation {
return storeOfRelations.getById(relation)
?: throw IllegalStateException("Could not find relation by id: $relation")
@OptIn(ExperimentalCoroutinesApi::class)
override suspend fun observeRelation(relation: Key): Flow<ObjectWrapper.Relation> {
return storeOfRelations.trackChanges()
.flatMapLatest { _ ->
val relation = storeOfRelations.getByKey(relation)
if (relation != null) {
flowOf(relation)
} else {
emptyFlow()
}
}
}
override fun observeAll(): Flow<List<ObjectWrapper.Relation>> {
return objectState.filterIsInstance<ObjectState.DataView>().map { set ->
set.dataViewContent.relationLinks.mapNotNull {
storeOfRelations.getByKey(it.key)
@OptIn(ExperimentalCoroutinesApi::class)
override suspend fun observeAll(id: Id): Flow<List<ObjectWrapper.Relation>> {
return combine(
storeOfRelations.trackChanges(),
objectState
) { _, state ->
state
}.flatMapLatest { state ->
when (state) {
is ObjectState.DataView.Collection -> {
val objectKeys = state.dataViewContent.relationLinks.map { it.key }
flow {
objectKeys.mapNotNull {
storeOfRelations.getByKey(it)
}
}
}
is ObjectState.DataView.Set -> {
val objectKeys = state.dataViewContent.relationLinks.map { it.key }
flow {
objectKeys.mapNotNull {
storeOfRelations.getByKey(it)
}
}
}
else -> emptyFlow()
}
}
}
override fun observe(relation: Key): Flow<ObjectWrapper.Relation> {
return objectState
.filterIsInstance<ObjectState.DataView>()
.map { it.dataViewContent.relationLinks }
.distinctUntilChanged()
.mapNotNull { storeOfRelations.getByKey(relation) }
}
}
class SetOrCollectionRelationProvider(
@ -53,43 +73,51 @@ class SetOrCollectionRelationProvider(
private val storeOfRelations: StoreOfRelations
) : ObjectRelationProvider {
override suspend fun get(relation: Key): ObjectWrapper.Relation {
return storeOfRelations.getByKey(relation)
?: throw IllegalStateException("Could not found relation by key: $relation")
}
override suspend fun getOrNull(relation: Key): ObjectWrapper.Relation? {
return storeOfRelations.getByKey(relation)
}
override suspend fun getById(relation: Id): ObjectWrapper.Relation {
return storeOfRelations.getById(relation)
?: throw IllegalStateException("Could not find relation by id: $relation")
}
override fun observeAll(): Flow<List<ObjectWrapper.Relation>> {
return objectState.map { set ->
when (set) {
@OptIn(ExperimentalCoroutinesApi::class)
override suspend fun observeAll(id: Id): Flow<List<ObjectWrapper.Relation>> {
return combine(
storeOfRelations.trackChanges(),
objectState
) { _, state ->
state
}.flatMapLatest { state ->
when (state) {
is ObjectState.DataView.Collection -> {
set.objectRelationLinks.mapNotNull {
storeOfRelations.getByKey(it.key)
val objectKeys = state.details[id]?.map?.keys.orEmpty()
flow {
objectKeys.mapNotNull {
storeOfRelations.getByKey(it)
}
}
}
is ObjectState.DataView.Set ->
set.objectRelationLinks.mapNotNull {
storeOfRelations.getByKey(it.key)
is ObjectState.DataView.Set -> {
val objectKeys = state.details[id]?.map?.keys.orEmpty()
flow {
objectKeys.mapNotNull {
storeOfRelations.getByKey(it)
}
}
ObjectState.ErrorLayout -> emptyList()
ObjectState.Init -> emptyList()
}
else -> emptyFlow()
}
}
}
override fun observe(relation: Key): Flow<ObjectWrapper.Relation> {
return objectState
.filterIsInstance<ObjectState.DataView>()
.map { it.dataViewContent.relationLinks }
.distinctUntilChanged()
.mapNotNull { storeOfRelations.getByKey(relation) }
@OptIn(ExperimentalCoroutinesApi::class)
override suspend fun observeRelation(relation: Key): Flow<ObjectWrapper.Relation> {
return storeOfRelations.trackChanges()
.flatMapLatest { _ ->
val relation = storeOfRelations.getByKey(relation)
if (relation != null) {
flowOf(relation)
} else {
emptyFlow()
}
}
}
}

View file

@ -5,38 +5,49 @@ import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.presentation.editor.Editor
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
class DefaultObjectRelationProvider(
private val storeOfRelations: StoreOfRelations,
private val storage: Editor.Storage
) : ObjectRelationProvider {
override suspend fun getById(relation: Id): ObjectWrapper.Relation {
return storeOfRelations.getById(relation) ?: throw IllegalStateException("Could not find relation by id: $relation")
}
override suspend fun get(relation: Key): ObjectWrapper.Relation {
return storeOfRelations.getByKey(relation) ?: throw IllegalStateException("Could not find relation by key: $relation")
}
override suspend fun getOrNull(relation: Key): ObjectWrapper.Relation? {
return storeOfRelations.getByKey(relation)
}
override fun observeAll(): Flow<List<ObjectWrapper.Relation>> {
return storage.relationLinks.stream().map { links ->
links.mapNotNull { relationLink ->
storeOfRelations.getByKey(relationLink.key)
@OptIn(ExperimentalCoroutinesApi::class)
override suspend fun observeAll(id: Id): Flow<List<ObjectWrapper.Relation>> =
combine(
storeOfRelations.trackChanges(),
storage.details.stream()
) { _, details ->
details
}.flatMapLatest { details ->
val objectKeys = details.details[id]?.map?.keys ?: emptyList()
flow {
objectKeys.mapNotNull {
storeOfRelations.getByKey(it)
}
}
}
}
override fun observe(relation: Key): Flow<ObjectWrapper.Relation> {
return observeAll().mapNotNull { relations ->
relations.find { it.key == relation }
}
@OptIn(ExperimentalCoroutinesApi::class)
override suspend fun observeRelation(relation: Key): Flow<ObjectWrapper.Relation> {
return storeOfRelations.trackChanges()
.flatMapLatest { _ ->
val relation = storeOfRelations.getByKey(relation)
if (relation != null) {
flowOf(relation)
} else {
emptyFlow()
}
}
}
}

View file

@ -6,11 +6,9 @@ import com.anytypeio.anytype.core_models.ObjectWrapper
import kotlinx.coroutines.flow.Flow
interface ObjectRelationProvider {
suspend fun get(relation: Key): ObjectWrapper.Relation
suspend fun getOrNull(relation: Key): ObjectWrapper.Relation?
suspend fun getById(relation: Id) : ObjectWrapper.Relation
fun observe(relation: Key): Flow<ObjectWrapper.Relation>
fun observeAll(): Flow<List<ObjectWrapper.Relation>>
suspend fun observeRelation(relation: Key): Flow<ObjectWrapper.Relation>
suspend fun observeAll(id: Id): Flow<List<ObjectWrapper.Relation>>
companion object {
/**

View file

@ -1,7 +1,6 @@
package com.anytypeio.anytype.presentation.relations.providers
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.RelationLink
import com.anytypeio.anytype.presentation.editor.Editor
import com.anytypeio.anytype.presentation.sets.state.ObjectState
import kotlinx.coroutines.flow.Flow
@ -10,21 +9,16 @@ import kotlinx.coroutines.flow.map
interface RelationListProvider {
val links: Flow<List<RelationLink>>
val details: Flow<Block.Details>
fun getLinks() : List<RelationLink>
fun getDetails(): Block.Details
class EditorRelationListProvider(
private val storage: Editor.Storage
) : RelationListProvider {
override val links: Flow<List<RelationLink>>
get() = storage.relationLinks.stream()
override val details: Flow<Block.Details>
get() = storage.details.stream()
override fun getLinks() = storage.relationLinks.current()
override fun getDetails() = storage.details.current()
}
@ -32,10 +26,8 @@ interface RelationListProvider {
private val objectStates: StateFlow<ObjectState>
) : RelationListProvider {
override val links = objectStates.map { state -> mapLinks(state) }
override val details = objectStates.map { state -> mapDetails(state) }
override fun getLinks(): List<RelationLink> = mapLinks(objectStates.value)
override fun getDetails(): Block.Details = mapDetails(objectStates.value)
private fun mapDetails(state: ObjectState) = when (state) {
@ -50,10 +42,10 @@ interface RelationListProvider {
private fun mapLinks(state: ObjectState) = when (state) {
is ObjectState.DataView.Collection -> {
state.objectRelationLinks
state.details.keys
}
is ObjectState.DataView.Set -> {
state.objectRelationLinks
state.details.keys
}
else -> emptyList()
}

View file

@ -53,7 +53,7 @@ class ObjectSetCreateBookmarkRecordViewModel(
val prefilled = viewer.prefillNewObjectDetails(
dateProvider = dateProvider,
storeOfRelations = storeOfRelations,
dataViewRelationLinks = state.objectRelationLinks
dataViewRelationLinks = state.dataViewContent.relationLinks
)
createBookmark(
input = input,
@ -70,7 +70,7 @@ class ObjectSetCreateBookmarkRecordViewModel(
val viewer = state.viewerByIdOrFirst(session.currentViewerId.value) ?: return
val details = viewer.resolveSetByRelationPrefilledObjectData(
objSetByRelation = sourceObject,
dataViewRelationLinks = state.objectRelationLinks,
dataViewRelationLinks = state.dataViewContent.relationLinks,
dateProvider = dateProvider,
storeOfRelations = storeOfRelations
)
@ -84,7 +84,7 @@ class ObjectSetCreateBookmarkRecordViewModel(
val prefilled = viewer.prefillNewObjectDetails(
dateProvider = dateProvider,
storeOfRelations = storeOfRelations,
dataViewRelationLinks = state.objectRelationLinks
dataViewRelationLinks = state.dataViewContent.relationLinks
)
createBookmark(
input = input,

View file

@ -636,7 +636,11 @@ suspend fun DVViewer.resolveSetByRelationPrefilledObjectData(
val defaultValue = resolveDefaultValueByFormat(relationFormat)
put(objSetByRelation.key, defaultValue)
}
val prefillNewObjectDetails = prefillNewObjectDetails(storeOfRelations, dateProvider, dataViewRelationLinks)
val prefillNewObjectDetails = prefillNewObjectDetails(
storeOfRelations = storeOfRelations,
dateProvider = dateProvider,
dataViewRelationLinks = dataViewRelationLinks
)
return prefillWithSetOf + prefillNewObjectDetails
}

View file

@ -43,7 +43,7 @@ class RelationDateValueViewModel(
Timber.d("onStart: ctx:[$ctx], relationKey:[$relationKey], objectId:[$objectId]")
jobs += viewModelScope.launch {
val pipeline = combine(
relations.observe(relationKey),
relations.observeRelation(relationKey),
values.subscribe(ctx = ctx, target = objectId)
) { relation, value ->
setupIsRelationNotEditable(isLocked, relation)

View file

@ -7,7 +7,6 @@ import com.anytypeio.anytype.core_models.Event.Command
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ext.amend
import com.anytypeio.anytype.core_models.ext.remove
import com.anytypeio.anytype.core_models.ext.unset
import com.anytypeio.anytype.core_utils.ext.replace
import com.anytypeio.anytype.presentation.sets.updateFields
@ -61,12 +60,6 @@ class DefaultObjectStateReducer : ObjectStateReducer {
is Command.ShowObject -> {
handleShowObject(event)
}
is Command.ObjectRelationLinks.Amend -> {
amendObjectRelationLinks(state, event)
}
is Command.ObjectRelationLinks.Remove -> {
removeObjectRelationLinks(state, event)
}
is Command.DataView.SetView -> {
handleSetView(state, event)
}
@ -118,49 +111,6 @@ class DefaultObjectStateReducer : ObjectStateReducer {
)
}
private fun removeObjectRelationLinks(
state: ObjectState,
event: Command.ObjectRelationLinks.Remove
) = when (state) {
is ObjectState.DataView.Collection -> {
state.copy(
objectRelationLinks = state.objectRelationLinks.remove(
event.keys
)
)
}
is ObjectState.DataView.Set -> {
state.copy(
objectRelationLinks = state.objectRelationLinks.remove(
event.keys
)
)
}
else -> state
}
private fun amendObjectRelationLinks(
state: ObjectState,
event: Command.ObjectRelationLinks.Amend
) = when (state) {
is ObjectState.DataView.Collection -> {
state.copy(
objectRelationLinks = state.objectRelationLinks.amend(
event.relationLinks
)
)
}
is ObjectState.DataView.Set -> {
state.copy(
objectRelationLinks = state.objectRelationLinks.amend(
event.relationLinks
)
)
}
else -> state
}
//region EVENTS
/**
* @see Command.ShowObject
@ -171,17 +121,13 @@ class DefaultObjectStateReducer : ObjectStateReducer {
root = event.root,
blocks = event.blocks,
details = event.details.details,
objectRestrictions = event.objectRestrictions,
dataViewRestrictions = event.dataViewRestrictions,
objectRelationLinks = event.relationLinks
dataViewRestrictions = event.dataViewRestrictions
)
ObjectType.Layout.SET.code -> ObjectState.DataView.Set(
root = event.root,
blocks = event.blocks,
details = event.details.details,
objectRestrictions = event.objectRestrictions,
dataViewRestrictions = event.dataViewRestrictions,
objectRelationLinks = event.relationLinks
dataViewRestrictions = event.dataViewRestrictions
)
else -> {
Timber.e("Wrong layout type: $layout")
@ -368,8 +314,7 @@ class DefaultObjectStateReducer : ObjectStateReducer {
blocks = blocks,
details = state.details,
objectRestrictions = state.objectRestrictions,
dataViewRestrictions = state.dataViewRestrictions,
objectRelationLinks = state.objectRelationLinks
dataViewRestrictions = state.dataViewRestrictions
)
}
else -> state

View file

@ -6,7 +6,6 @@ import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.DVViewerType
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectTypeIds
import com.anytypeio.anytype.core_models.RelationLink
import com.anytypeio.anytype.core_models.restrictions.DataViewRestrictions
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
@ -22,8 +21,6 @@ sealed class ObjectState {
abstract val objectRestrictions: List<ObjectRestriction>
abstract val dataViewRestrictions: List<DataViewRestrictions>
abstract val objectRelationLinks: List<RelationLink>
abstract val dataViewContent: DV
abstract val dataViewBlock: Block
abstract val viewers: List<DVViewer>
@ -34,7 +31,6 @@ sealed class ObjectState {
override val details: Map<Id, Block.Fields> = emptyMap(),
override val objectRestrictions: List<ObjectRestriction> = emptyList(),
override val dataViewRestrictions: List<DataViewRestrictions> = emptyList(),
override val objectRelationLinks: List<RelationLink> = emptyList(),
) : DataView() {
override val isInitialized get() = blocks.any { it.content is DV }
@ -49,7 +45,6 @@ sealed class ObjectState {
override val details: Map<Id, Block.Fields> = emptyMap(),
override val objectRestrictions: List<ObjectRestriction> = emptyList(),
override val dataViewRestrictions: List<DataViewRestrictions> = emptyList(),
override val objectRelationLinks: List<RelationLink> = emptyList()
) : DataView() {
override val isInitialized get() = blocks.any { it.content is DV }

View file

@ -101,7 +101,6 @@ class TemplateBlankViewModel(
anchor = page.first().id,
indent = EditorViewModel.INITIAL_INDENT,
details = customDetails,
relationLinks = emptyList(),
restrictions = emptyList(),
selection = emptySet()
)

View file

@ -82,7 +82,6 @@ class DefaultBlockViewRendererTest {
anchor = anchor,
indent = indent,
details = details,
relationLinks = emptyList(),
restrictions = restrictions,
selection = emptySet(),
parentScheme = schema

View file

@ -3605,7 +3605,6 @@ open class EditorViewModelTest {
context = root,
root = root,
details = details,
relations = relations,
blocks = document,
objectRestrictions = objectRestrictions
)
@ -3818,7 +3817,7 @@ open class EditorViewModelTest {
val memory = Editor.Memory(
selections = SelectionStateHolder.Default()
)
addRelationToObject = AddRelationToObject(repo)
addRelationToObject = AddRelationToObject(repo, dispatchers)
objectToSet = ConvertObjectToSet(repo, dispatchers)
updateDetail = UpdateDetail(repo)
setDocCoverImage = SetDocCoverImage(repo)

View file

@ -845,7 +845,6 @@ class EditorMentionTest : EditorPresentationTestSetup() {
context = root,
root = root,
details = Block.Details(),
relations = emptyList(),
blocks = document,
objectRestrictions = emptyList()
),
@ -1004,7 +1003,6 @@ class EditorMentionTest : EditorPresentationTestSetup() {
context = root,
root = root,
details = Block.Details(detailsAmend),
relations = emptyList(),
blocks = document,
objectRestrictions = emptyList()
),
@ -1291,7 +1289,6 @@ class EditorMentionTest : EditorPresentationTestSetup() {
context = root,
root = root,
details = Block.Details(detailsAmend),
relations = emptyList(),
blocks = document,
objectRestrictions = emptyList()
),
@ -1450,7 +1447,6 @@ class EditorMentionTest : EditorPresentationTestSetup() {
context = root,
root = root,
details = Block.Details(detailsAmend),
relations = emptyList(),
blocks = document,
objectRestrictions = emptyList()
),

View file

@ -561,8 +561,6 @@ open class EditorPresentationTestSetup {
context = root,
root = root,
details = details,
relations = relations,
relationLinks = relationLinks,
blocks = document,
objectRestrictions = objectRestrictions
)

View file

@ -61,7 +61,6 @@ class TableBlockRendererTest {
focus = focus,
indent = indent,
details = details,
relationLinks = emptyList(),
restrictions = restrictions,
selection = selections
)

View file

@ -300,6 +300,9 @@ class RelationAddViewModelBaseTest {
repo = repo,
dispatchers = appCoroutineDispatchers
),
spaceManager = spaceManager
vmParams = VmParams(
objectId = MockDataFactory.randomUuid(),
space = SpaceId(spaceId)
)
) {}
}

View file

@ -42,9 +42,9 @@ class RelationExtensionsTest {
// When
val result = getNotIncludedRecommendedRelations(
relationLinks = relationLinks,
recommendedRelations = recommendedRelations,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
relationKeys = relationLinks.map { it.key }.toSet()
)
// Then

View file

@ -22,27 +22,19 @@ internal class FakeObjectRelationProvider : ObjectRelationProvider {
constructor(relation: ObjectWrapper.Relation = StubRelationObject()) : this(listOf(relation))
override suspend fun get(relation: Key): ObjectWrapper.Relation {
return relations.first { it.key == relation }
}
override suspend fun getOrNull(relation: Key): ObjectWrapper.Relation? {
return relations.find { it.key == relation }
}
override suspend fun getById(relation: Id): ObjectWrapper.Relation {
return relations.first { it.id == relation }
}
override fun observe(relation: Key): Flow<ObjectWrapper.Relation> {
return flow {
emit(get(relation))
}
}
override fun observeAll(): Flow<List<ObjectWrapper.Relation>> {
override suspend fun observeAll(id: Id): Flow<List<ObjectWrapper.Relation>> {
return flow {
emit(relations)
}
}
override suspend fun observeRelation(relation: Key): Flow<ObjectWrapper.Relation> {
return flow {
emit(this@FakeObjectRelationProvider.relation)
}
}
}

View file

@ -358,7 +358,6 @@ open class ObjectSetViewModelTestSetup {
root = root,
blocks = doc,
details = details,
relations = relations,
dataViewRestrictions = dataViewRestrictions
)
) + additionalEvents

View file

@ -80,14 +80,12 @@ fun StubObjectView(
root: Id,
blocks: List<Block> = emptyList(),
details: Map<Id, Struct> = emptyMap(),
relations: List<RelationLink> = emptyList(),
objectRestrictions: List<ObjectRestriction> = emptyList(),
dataViewRestrictions: List<DataViewRestrictions> = emptyList()
): ObjectView = ObjectView(
root = root,
blocks = blocks,
details = details,
relations = relations,
objectRestrictions = objectRestrictions,
dataViewRestrictions = dataViewRestrictions
)