From c4968c3e4fed3fa0f35a9b325acba0b20ec2b02d Mon Sep 17 00:00:00 2001 From: Konstantin Ivanov <54908981+konstantiniiv@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:35:08 +0100 Subject: [PATCH] DROID-3240 Tech | Remove object relation links (#2000) --- .../features/editor/MentionUpdateTesting.kt | 1 - .../features/editor/base/EditorTestSetup.kt | 4 +- .../relations/ObjectRelationListTest.kt | 714 ------------------ .../features/sets/dv/TestObjectSetSetup.kt | 2 - .../anytype/di/common/ComponentManager.kt | 33 +- .../anytypeio/anytype/di/feature/EditorDI.kt | 3 +- .../anytype/di/feature/ObjectSetDI.kt | 3 +- .../di/feature/relations/RelationAddDI.kt | 17 +- .../anytype/ui/editor/EditorFragment.kt | 12 - .../editor/sheets/ObjectMenuBaseFragment.kt | 2 - .../relations/ObjectRelationListFragment.kt | 43 +- .../ui/relations/RelationAddBaseFragment.kt | 1 - .../anytypeio/anytype/core_models/Event.kt | 25 +- .../anytype/core_models/ObjectView.kt | 1 - .../anytype/core_models/ext/RelationExt.kt | 8 - .../auth/repo/block/BlockDataRepository.kt | 2 +- .../data/auth/repo/block/BlockRemote.kt | 2 +- .../domain/block/repo/BlockRepository.kt | 2 +- .../domain/relations/AddRelationToObject.kt | 12 +- .../middleware/block/BlockMiddleware.kt | 2 +- .../middleware/interactor/Middleware.kt | 4 +- .../interactor/MiddlewareEventMapper.kt | 11 +- .../middleware/mappers/ToCoreModelMappers.kt | 3 - .../anytype/MiddlewareEventChannelTest.kt | 62 +- .../anytype/presentation/editor/Editor.kt | 5 - .../presentation/editor/EditorViewModel.kt | 39 +- .../presentation/editor/editor/Command.kt | 1 - .../editor/render/BlockViewRenderer.kt | 2 - .../editor/render/DefaultBlockViewRenderer.kt | 14 - .../history/VersionHistoryViewModel.kt | 2 - .../RelationAddToDataViewViewModel.kt | 12 +- .../relations/RelationAddToObjectViewModel.kt | 48 +- .../relations/RelationAddViewModelBase.kt | 30 +- .../RelationCreateFromScratchBaseViewModel.kt | 37 +- .../relations/RelationExtensions.kt | 13 +- .../relations/RelationListViewModel.kt | 64 +- .../DataViewObjectRelationProvider.kt | 128 ++-- .../DefaultObjectRelationProvider.kt | 49 +- .../providers/ObjectRelationProvider.kt | 6 +- .../providers/RelationListProvider.kt | 12 +- .../ObjectSetCreateBookmarkRecordViewModel.kt | 6 +- .../presentation/sets/ObjectSetExtension.kt | 6 +- .../sets/RelationDateValueViewModel.kt | 2 +- .../sets/state/DefaultObjectStateReducer.kt | 61 +- .../presentation/sets/state/ObjectState.kt | 5 - .../templates/TemplateBlankViewModel.kt | 1 - .../editor/DefaultBlockViewRendererTest.kt | 1 - .../editor/EditorViewModelTest.kt | 3 +- .../editor/editor/EditorMentionTest.kt | 4 - .../editor/EditorPresentationTestSetup.kt | 2 - .../editor/table/TableBlockRendererTest.kt | 1 - .../relations/RelationAddViewModelBaseTest.kt | 5 +- .../relations/RelationExtensionsTest.kt | 4 +- .../providers/FakeObjectRelationProvider.kt | 22 +- .../sets/main/ObjectSetViewModelTestSetup.kt | 1 - .../anytypeio/anytype/core_models/Object.kt | 2 - 56 files changed, 304 insertions(+), 1253 deletions(-) delete mode 100644 app/src/androidTest/java/com/anytypeio/anytype/features/relations/ObjectRelationListTest.kt diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/editor/MentionUpdateTesting.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/editor/MentionUpdateTesting.kt index 9e8769922a..692f660ce9 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/editor/MentionUpdateTesting.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/editor/MentionUpdateTesting.kt @@ -121,7 +121,6 @@ class MentionUpdateTesting : EditorTestSetup() { context = root, root = root, details = customDetails, - relations = emptyList(), blocks = document, objectRestrictions = emptyList() ), diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/editor/base/EditorTestSetup.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/editor/base/EditorTestSetup.kt index 0ce008e78c..f6494157f3 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/editor/base/EditorTestSetup.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/editor/base/EditorTestSetup.kt @@ -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() - 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 ) ) ) diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/ObjectRelationListTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/ObjectRelationListTest.kt deleted file mode 100644 index 4e7a09e464..0000000000 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/ObjectRelationListTest.kt +++ /dev/null @@ -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 - - @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 { - return launchFragmentInContainer( - fragmentArgs = args, - themeResId = R.style.AppTheme - ) - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/sets/dv/TestObjectSetSetup.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/sets/dv/TestObjectSetSetup.kt index a28eb53189..bc70801e56 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/sets/dv/TestObjectSetSetup.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/sets/dv/TestObjectSetSetup.kt @@ -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, ) ) ) diff --git a/app/src/main/java/com/anytypeio/anytype/di/common/ComponentManager.kt b/app/src/main/java/com/anytypeio/anytype/di/common/ComponentManager.kt index add16e9516..8e1a16cacd 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/common/ComponentManager.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/common/ComponentManager.kt @@ -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() } diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/EditorDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/EditorDI.kt index e7c32cd1e7..74e0007279 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/EditorDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/EditorDI.kt @@ -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 diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectSetDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectSetDI.kt index 41960e9634..19d2b76e1d 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectSetDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectSetDI.kt @@ -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 diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/relations/RelationAddDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/relations/RelationAddDI.kt index 8b4a525128..7200388a32 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/relations/RelationAddDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/relations/RelationAddDI.kt @@ -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, @@ -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, state: MutableStateFlow, @@ -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 diff --git a/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt index 927b0df03f..31393dfc52 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt @@ -1069,17 +1069,6 @@ open class EditorFragment : NavigationFragment(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(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, ) ) } diff --git a/app/src/main/java/com/anytypeio/anytype/ui/editor/sheets/ObjectMenuBaseFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/editor/sheets/ObjectMenuBaseFragment.kt index 0d601a2531..ca982daba6 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/editor/sheets/ObjectMenuBaseFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/editor/sheets/ObjectMenuBaseFragment.kt @@ -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 ) ) diff --git a/app/src/main/java/com/anytypeio/anytype/ui/relations/ObjectRelationListFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/relations/ObjectRelationListFragment.kt index 10f820bc68..58e47b4c06 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/relations/ObjectRelationListFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/relations/ObjectRelationListFragment.kt @@ -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(), @@ -60,7 +56,6 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment - 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, - val relations: List = emptyList(), - val relationLinks: List = emptyList(), val objectRestrictions: List = emptyList(), val dataViewRestrictions: List = 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 - ) : ObjectRelationLinks() - + sealed class ObjectRelation : Command() { data class Remove( override val context: String, val id: Id, val keys: List - ) : ObjectRelationLinks() - } - - sealed class ObjectRelation : Command() { - data class Set( - override val context: String, - val id: Id, - val key: Id, - val relations: List - ) : ObjectRelation() - - data class Remove( - override val context: String, - val id: Id, - val key: Id ) : ObjectRelation() } diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/ObjectView.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/ObjectView.kt index dc2c457a7b..f4f3ad60d9 100644 --- a/core-models/src/main/java/com/anytypeio/anytype/core_models/ObjectView.kt +++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/ObjectView.kt @@ -7,7 +7,6 @@ data class ObjectView( val root: Id, val blocks: List, val details: Map, - val relations: List, val objectRestrictions: List, val dataViewRestrictions: List ) \ No newline at end of file diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/ext/RelationExt.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/ext/RelationExt.kt index dff5352830..8c2d771c6e 100644 --- a/core-models/src/main/java/com/anytypeio/anytype/core_models/ext/RelationExt.kt +++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/ext/RelationExt.kt @@ -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.process( - event: Event.Command.ObjectRelationLinks -): List = when (event) { - is Event.Command.ObjectRelationLinks.Amend -> amend(event.relationLinks) - is Event.Command.ObjectRelationLinks.Remove -> remove(event.keys) -} - fun List.amend(relationLinks: List): List { val map = this.associateBy { it.key }.toMutableMap() relationLinks.forEach { relation -> diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt index 2149419c09..419f8b73fc 100644 --- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt +++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt @@ -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) diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt index c6bcba866d..1e7b874c28 100644 --- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt +++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt @@ -189,7 +189,7 @@ interface BlockRemote { suspend fun cancelObjectSearchSubscription(subscriptions: List) - 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 diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt b/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt index ca76f96195..46d43d1538 100644 --- a/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt +++ b/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt @@ -229,7 +229,7 @@ interface BlockRepository { suspend fun cancelObjectSearchSubscription(subscriptions: List) - 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 diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/relations/AddRelationToObject.kt b/domain/src/main/java/com/anytypeio/anytype/domain/relations/AddRelationToObject.kt index ceae57b690..a351c3f004 100644 --- a/domain/src/main/java/com/anytypeio/anytype/domain/relations/AddRelationToObject.kt +++ b/domain/src/main/java/com/anytypeio/anytype/domain/relations/AddRelationToObject.kt @@ -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() { + private val repo: BlockRepository, + dispatchers: AppCoroutineDispatchers +) : ResultInteractor(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 ) diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt index 25e9ddc1e2..34fdc27095 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt @@ -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, diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt index 1c13a7093e..00fbc09c60 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt @@ -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) diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/MiddlewareEventMapper.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/MiddlewareEventMapper.kt index dfeea90bee..c90f031d60 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/MiddlewareEventMapper.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/MiddlewareEventMapper.kt @@ -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 diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/mappers/ToCoreModelMappers.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/mappers/ToCoreModelMappers.kt index 5f426fef8c..701a2a35cf 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/mappers/ToCoreModelMappers.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/mappers/ToCoreModelMappers.kt @@ -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(), ) diff --git a/middleware/src/test/java/com/anytypeio/anytype/MiddlewareEventChannelTest.kt b/middleware/src/test/java/com/anytypeio/anytype/MiddlewareEventChannelTest.kt index 962bb96de6..d7b5d6d3d7 100644 --- a/middleware/src/test/java/com/anytypeio/anytype/MiddlewareEventChannelTest.kt +++ b/middleware/src/test/java/com/anytypeio/anytype/MiddlewareEventChannelTest.kt @@ -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) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/Editor.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/Editor.kt index f4351c3193..faa249e69b 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/Editor.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/Editor.kt @@ -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 = Store.Focus() val details: Store.Details = Store.Details() - @Deprecated("legacy") - val relations: Store.Relations = Store.Relations() val textSelection: Store = Store.TextSelection() val objectRestrictions: Store.ObjectRestrictions = Store.ObjectRestrictions() - val relationLinks: Store.RelationLinks = Store.RelationLinks() } class Proxer( diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt index ec6eecea03..f485902d9b 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt @@ -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, - relationLinks: List, details: Block.Details, objectWrapper: ObjectWrapper.Basic ): List { 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, - relationLinks: List, objectTypeStruct: Struct?, details: Block.Details ): List { 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, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/Command.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/Command.kt index 16348bc2f0..e1b0ab1432 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/Command.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/Command.kt @@ -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( diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/BlockViewRenderer.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/BlockViewRenderer.kt index 3def4602fa..e463ee71e4 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/BlockViewRenderer.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/BlockViewRenderer.kt @@ -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, restrictions: List, selection: Set, count: Int = 0, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/DefaultBlockViewRenderer.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/DefaultBlockViewRenderer.kt index 5be545e17a..7e894ec801 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/DefaultBlockViewRenderer.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/DefaultBlockViewRenderer.kt @@ -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, restrictions: List, selection: Set, 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, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/history/VersionHistoryViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/history/VersionHistoryViewModel.kt index c05a74a52c..bd60bd8877 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/history/VersionHistoryViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/history/VersionHistoryViewModel.kt @@ -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() ) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddToDataViewViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddToDataViewViewModel.kt index 25a0a6f226..f3750981e7 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddToDataViewViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddToDataViewViewModel.kt @@ -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, 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, 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 create(modelClass: Class): 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 diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddToObjectViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddToObjectViewModel.kt index eafb7175e4..d89d39ce4e 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddToObjectViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddToObjectViewModel.kt @@ -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, 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(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, @@ -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 create(modelClass: Class): 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 } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddViewModelBase.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddViewModelBase.kt index 3ce9ce704d..ccc6f97060 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddViewModelBase.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationAddViewModelBase.kt @@ -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()) - private val objectRelationKeys = relationsProvider.observeAll().map { relations -> - relations.map { r -> r.key } - } + private val objectRelationKeys = MutableStateFlow>(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 { 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 diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationCreateFromScratchBaseViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationCreateFromScratchBaseViewModel.kt index 6e79d5a113..37f381a7ee 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationCreateFromScratchBaseViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationCreateFromScratchBaseViewModel.kt @@ -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) } } ) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationExtensions.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationExtensions.kt index a5d0803190..61477f6c55 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationExtensions.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationExtensions.kt @@ -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, + relationKeys: Set, systemRelations: List, storeOfRelations: StoreOfRelations ): List { 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, + relationKeys: Set, recommendedRelations: List, storeOfRelations: StoreOfRelations ): List { - 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) { diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationListViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationListViewModel.kt index 1866bf26c4..625bdaf7fe 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationListViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/RelationListViewModel.kt @@ -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() - private val isInAddMode = MutableStateFlow(false) val commands = MutableSharedFlow(replay = 0) val views = MutableStateFlow>(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, details: Block.Details ): List { @@ -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, - relationLinks: List, details: Block.Details, objectWrapper: ObjectWrapper.Basic ): List { 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, - relationLinks: List, objectTypeWrapper: ObjectWrapper.Type, details: Block.Details ): List { 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 ) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DataViewObjectRelationProvider.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DataViewObjectRelationProvider.kt index bc550384e5..7eb6ab3536 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DataViewObjectRelationProvider.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DataViewObjectRelationProvider.kt @@ -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, 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 { + return storeOfRelations.trackChanges() + .flatMapLatest { _ -> + val relation = storeOfRelations.getByKey(relation) + if (relation != null) { + flowOf(relation) + } else { + emptyFlow() + } + } } - override fun observeAll(): Flow> { - return objectState.filterIsInstance().map { set -> - set.dataViewContent.relationLinks.mapNotNull { - storeOfRelations.getByKey(it.key) + @OptIn(ExperimentalCoroutinesApi::class) + override suspend fun observeAll(id: Id): Flow> { + 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 { - return objectState - .filterIsInstance() - .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> { - return objectState.map { set -> - when (set) { + @OptIn(ExperimentalCoroutinesApi::class) + override suspend fun observeAll(id: Id): Flow> { + 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 { - return objectState - .filterIsInstance() - .map { it.dataViewContent.relationLinks } - .distinctUntilChanged() - .mapNotNull { storeOfRelations.getByKey(relation) } + @OptIn(ExperimentalCoroutinesApi::class) + override suspend fun observeRelation(relation: Key): Flow { + return storeOfRelations.trackChanges() + .flatMapLatest { _ -> + val relation = storeOfRelations.getByKey(relation) + if (relation != null) { + flowOf(relation) + } else { + emptyFlow() + } + } } + } \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DefaultObjectRelationProvider.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DefaultObjectRelationProvider.kt index 6232db94d4..a96f4001f4 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DefaultObjectRelationProvider.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DefaultObjectRelationProvider.kt @@ -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> { - return storage.relationLinks.stream().map { links -> - links.mapNotNull { relationLink -> - storeOfRelations.getByKey(relationLink.key) + @OptIn(ExperimentalCoroutinesApi::class) + override suspend fun observeAll(id: Id): Flow> = + 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 { - return observeAll().mapNotNull { relations -> - relations.find { it.key == relation } - } + @OptIn(ExperimentalCoroutinesApi::class) + override suspend fun observeRelation(relation: Key): Flow { + return storeOfRelations.trackChanges() + .flatMapLatest { _ -> + val relation = storeOfRelations.getByKey(relation) + if (relation != null) { + flowOf(relation) + } else { + emptyFlow() + } + } } } \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/ObjectRelationProvider.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/ObjectRelationProvider.kt index f151a41939..b4996b06a3 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/ObjectRelationProvider.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/ObjectRelationProvider.kt @@ -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 - fun observeAll(): Flow> + suspend fun observeRelation(relation: Key): Flow + suspend fun observeAll(id: Id): Flow> companion object { /** diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/RelationListProvider.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/RelationListProvider.kt index e718dc1a4e..c7072083b0 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/RelationListProvider.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/RelationListProvider.kt @@ -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> val details: Flow - fun getLinks() : List fun getDetails(): Block.Details class EditorRelationListProvider( private val storage: Editor.Storage ) : RelationListProvider { - override val links: Flow> - get() = storage.relationLinks.stream() override val details: Flow 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 ) : RelationListProvider { - override val links = objectStates.map { state -> mapLinks(state) } override val details = objectStates.map { state -> mapDetails(state) } - override fun getLinks(): List = 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() } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetCreateBookmarkRecordViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetCreateBookmarkRecordViewModel.kt index 6799426fd4..082ea3b483 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetCreateBookmarkRecordViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetCreateBookmarkRecordViewModel.kt @@ -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, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetExtension.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetExtension.kt index e6d62f4d02..3926467ab5 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetExtension.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetExtension.kt @@ -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 } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationDateValueViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationDateValueViewModel.kt index f05ecc18fc..e55cd2628b 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationDateValueViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationDateValueViewModel.kt @@ -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) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/state/DefaultObjectStateReducer.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/state/DefaultObjectStateReducer.kt index 369c204344..37fe500d2d 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/state/DefaultObjectStateReducer.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/state/DefaultObjectStateReducer.kt @@ -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 diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/state/ObjectState.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/state/ObjectState.kt index 3e0944636b..b32b26b899 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/state/ObjectState.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/state/ObjectState.kt @@ -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 abstract val dataViewRestrictions: List - abstract val objectRelationLinks: List - abstract val dataViewContent: DV abstract val dataViewBlock: Block abstract val viewers: List @@ -34,7 +31,6 @@ sealed class ObjectState { override val details: Map = emptyMap(), override val objectRestrictions: List = emptyList(), override val dataViewRestrictions: List = emptyList(), - override val objectRelationLinks: List = emptyList(), ) : DataView() { override val isInitialized get() = blocks.any { it.content is DV } @@ -49,7 +45,6 @@ sealed class ObjectState { override val details: Map = emptyMap(), override val objectRestrictions: List = emptyList(), override val dataViewRestrictions: List = emptyList(), - override val objectRelationLinks: List = emptyList() ) : DataView() { override val isInitialized get() = blocks.any { it.content is DV } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/templates/TemplateBlankViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/templates/TemplateBlankViewModel.kt index 9c96408b70..0bd8ab1d4a 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/templates/TemplateBlankViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/templates/TemplateBlankViewModel.kt @@ -101,7 +101,6 @@ class TemplateBlankViewModel( anchor = page.first().id, indent = EditorViewModel.INITIAL_INDENT, details = customDetails, - relationLinks = emptyList(), restrictions = emptyList(), selection = emptySet() ) diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/DefaultBlockViewRendererTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/DefaultBlockViewRendererTest.kt index 318df39ecc..5fbfcd76e0 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/DefaultBlockViewRendererTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/DefaultBlockViewRendererTest.kt @@ -82,7 +82,6 @@ class DefaultBlockViewRendererTest { anchor = anchor, indent = indent, details = details, - relationLinks = emptyList(), restrictions = restrictions, selection = emptySet(), parentScheme = schema diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt index 7e114c9ca8..8a228f01b8 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt @@ -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) diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorMentionTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorMentionTest.kt index a09742ac45..8edcde6da3 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorMentionTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorMentionTest.kt @@ -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() ), diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorPresentationTestSetup.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorPresentationTestSetup.kt index ed70640531..ce80493a66 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorPresentationTestSetup.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorPresentationTestSetup.kt @@ -561,8 +561,6 @@ open class EditorPresentationTestSetup { context = root, root = root, details = details, - relations = relations, - relationLinks = relationLinks, blocks = document, objectRestrictions = objectRestrictions ) diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/table/TableBlockRendererTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/table/TableBlockRendererTest.kt index ccbacf5e19..f0059acaa5 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/table/TableBlockRendererTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/table/TableBlockRendererTest.kt @@ -61,7 +61,6 @@ class TableBlockRendererTest { focus = focus, indent = indent, details = details, - relationLinks = emptyList(), restrictions = restrictions, selection = selections ) diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/RelationAddViewModelBaseTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/RelationAddViewModelBaseTest.kt index d3d32cff90..fbab7367a6 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/RelationAddViewModelBaseTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/RelationAddViewModelBaseTest.kt @@ -300,6 +300,9 @@ class RelationAddViewModelBaseTest { repo = repo, dispatchers = appCoroutineDispatchers ), - spaceManager = spaceManager + vmParams = VmParams( + objectId = MockDataFactory.randomUuid(), + space = SpaceId(spaceId) + ) ) {} } \ No newline at end of file diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/RelationExtensionsTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/RelationExtensionsTest.kt index aea40f50ad..04af868b33 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/RelationExtensionsTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/RelationExtensionsTest.kt @@ -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 diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/providers/FakeObjectRelationProvider.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/providers/FakeObjectRelationProvider.kt index 467204a7ff..89759b490a 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/providers/FakeObjectRelationProvider.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/providers/FakeObjectRelationProvider.kt @@ -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 { - return flow { - emit(get(relation)) - } - } - - override fun observeAll(): Flow> { + override suspend fun observeAll(id: Id): Flow> { return flow { emit(relations) } } + + override suspend fun observeRelation(relation: Key): Flow { + return flow { + emit(this@FakeObjectRelationProvider.relation) + } + } } \ No newline at end of file diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/main/ObjectSetViewModelTestSetup.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/main/ObjectSetViewModelTestSetup.kt index a5acd81996..46d3bfb2d9 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/main/ObjectSetViewModelTestSetup.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/main/ObjectSetViewModelTestSetup.kt @@ -358,7 +358,6 @@ open class ObjectSetViewModelTestSetup { root = root, blocks = doc, details = details, - relations = relations, dataViewRestrictions = dataViewRestrictions ) ) + additionalEvents diff --git a/test/core-models-stub/src/main/java/com/anytypeio/anytype/core_models/Object.kt b/test/core-models-stub/src/main/java/com/anytypeio/anytype/core_models/Object.kt index a4feed51cc..34b79cf637 100644 --- a/test/core-models-stub/src/main/java/com/anytypeio/anytype/core_models/Object.kt +++ b/test/core-models-stub/src/main/java/com/anytypeio/anytype/core_models/Object.kt @@ -80,14 +80,12 @@ fun StubObjectView( root: Id, blocks: List = emptyList(), details: Map = emptyMap(), - relations: List = emptyList(), objectRestrictions: List = emptyList(), dataViewRestrictions: List = emptyList() ): ObjectView = ObjectView( root = root, blocks = blocks, details = details, - relations = relations, objectRestrictions = objectRestrictions, dataViewRestrictions = dataViewRestrictions )