From 1ca1f32ebed4c3cce8cf4f181549afc49d6baf00 Mon Sep 17 00:00:00 2001 From: Evgenii Kozlov Date: Wed, 15 Mar 2023 15:23:57 +0100 Subject: [PATCH] DROID-326 Sets | Enhancement | Unblocking relations for Sets or Collections (#3012) --- .../features/editor/base/EditorTestSetup.kt | 4 +- .../emoji/DocumentEmojiPickerFragmentTest.kt | 6 +- .../relations/AddRelationStatusValueTest.kt | 5 +- .../relations/AddRelationTagValueTest.kt | 4 +- .../DisplayObjectRelationTextValueTest.kt | 2 +- .../DisplayRelationNumberValueTest.kt | 4 +- .../DisplayRelationObjectValueTest.kt | 4 +- .../DisplayRelationStatusValueTest.kt | 5 +- .../relations/DisplayRelationTagValueTest.kt | 4 +- .../relations/EditRelationTagValueTest.kt | 6 +- .../relations/ObjectRelationDateValueTest.kt | 4 +- .../relations/ObjectRelationListTest.kt | 5 - .../anytype/di/common/ComponentManager.kt | 8 + .../anytypeio/anytype/di/feature/EditorDI.kt | 15 +- .../di/feature/ObjectRelationListDI.kt | 3 - .../anytype/di/feature/ObjectSetDI.kt | 30 ++- .../anytype/di/feature/SelectDocCoverDI.kt | 3 - .../editor/sheets/ObjectMenuBaseFragment.kt | 18 +- .../relations/ObjectRelationListFragment.kt | 84 ++++++-- .../ui/relations/RelationDateValueFragment.kt | 9 +- .../relations/RelationStatusValueFragment.kt | 1 + .../ui/relations/RelationTextValueFragment.kt | 4 +- .../ui/relations/RelationValueBaseFragment.kt | 11 +- .../ui/relations/RelationValueDVFragment.kt | 7 +- .../relations/add/AddFileRelationFragment.kt | 6 +- .../add/AddObjectRelationFragment.kt | 7 +- .../add/AddOptionsRelationDVFragment.kt | 10 +- .../add/AddOptionsRelationFragment.kt | 2 + .../add/BaseAddOptionsRelationFragment.kt | 1 + .../anytype/ui/sets/ObjectSetFragment.kt | 5 +- .../anytype/core_models/ObjectWrapper.kt | 73 +++---- .../anytype/core_models/Relations.kt | 3 + .../anytype/core_models/inline/Ctx.kt | 4 + docs/screens.md | 12 ++ .../anytype/domain/object/UpdateDetail.kt | 4 +- .../presentation/editor/EditorViewModel.kt | 11 +- .../editor/EditorViewModelFactory.kt | 9 +- .../editor/cover/SelectCoverViewModel.kt | 31 --- .../editor/editor/DetailModificator.kt | 185 ------------------ .../objects/LockedStateProvider.kt | 4 + .../ObjectRelationListViewModelFactory.kt | 3 - .../relations/RelationListViewModel.kt | 13 +- .../relations/add/AddFileRelationViewModel.kt | 8 +- .../add/AddObjectRelationViewModel.kt | 9 +- .../add/AddOptionsRelationDVViewModel.kt | 4 + .../add/AddOptionsRelationViewModel.kt | 4 + .../add/BaseAddOptionsRelationViewModel.kt | 23 ++- .../providers/DataViewObjectValueProvider.kt | 42 +++- .../providers/DefaultObjectValueProvider.kt | 5 +- .../providers/ObjectValueProvider.kt | 5 +- .../providers/RelationListProvider.kt | 35 ++++ .../search/ObjectSearchConstants.kt | 5 +- .../sets/ObjectSetRecordViewModel.kt | 4 +- .../presentation/sets/ObjectSetViewModel.kt | 8 +- .../sets/RelationDateValueViewModel.kt | 11 +- .../sets/RelationTextValueViewModel.kt | 3 +- .../sets/RelationValueBaseViewModel.kt | 134 ++++++++++--- .../presentation/sets/SetsExtension.kt | 19 +- .../editor/EditorViewModelTest.kt | 4 +- .../editor/EditorPresentationTestSetup.kt | 3 +- .../BaseAddOptionsRelationViewModelTest.kt | 40 +++- .../providers/FakeObjectValueProvider.kt | 10 +- .../sets/ObjectSetRecordViewModelTest.kt | 8 +- 63 files changed, 534 insertions(+), 479 deletions(-) create mode 100644 core-models/src/main/java/com/anytypeio/anytype/core_models/inline/Ctx.kt create mode 100644 docs/screens.md delete mode 100644 presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/DetailModificator.kt 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 1473177fe1..788f24e195 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 @@ -59,9 +59,9 @@ import com.anytypeio.anytype.domain.icon.DocumentEmojiIconProvider import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon import com.anytypeio.anytype.domain.launch.GetDefaultPageType import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet import com.anytypeio.anytype.domain.`object`.UpdateDetail -import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes @@ -93,7 +93,6 @@ import com.anytypeio.anytype.presentation.editor.Editor import com.anytypeio.anytype.presentation.editor.EditorViewModelFactory import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider import com.anytypeio.anytype.presentation.editor.editor.Interactor -import com.anytypeio.anytype.presentation.editor.editor.InternalDetailModificationManager import com.anytypeio.anytype.presentation.editor.editor.Orchestrator import com.anytypeio.anytype.presentation.editor.editor.Proxy import com.anytypeio.anytype.presentation.editor.editor.pattern.DefaultPatternMatcher @@ -435,7 +434,6 @@ open class EditorTestSetup { interceptThreadStatus = interceptThreadStatus, analytics = analytics, dispatcher = Dispatcher.Default(), - detailModificationManager = InternalDetailModificationManager(stores.details), updateDetail = updateDetail, searchObjects = getSearchObjects, getDefaultPageType = getDefaultPageType, diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/emoji/DocumentEmojiPickerFragmentTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/emoji/DocumentEmojiPickerFragmentTest.kt index fbdfd40fd0..8420c043dd 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/emoji/DocumentEmojiPickerFragmentTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/emoji/DocumentEmojiPickerFragmentTest.kt @@ -27,11 +27,11 @@ import com.anytypeio.anytype.emojifier.data.Emoji import com.anytypeio.anytype.emojifier.data.EmojiProvider import com.anytypeio.anytype.emojifier.suggest.EmojiSuggester import com.anytypeio.anytype.emojifier.suggest.model.EmojiModel -import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager import com.anytypeio.anytype.presentation.editor.picker.ObjectIconPickerViewModelFactory import com.anytypeio.anytype.presentation.util.Dispatcher import com.anytypeio.anytype.test_utils.MockDataFactory import com.anytypeio.anytype.test_utils.utils.TestUtils.withRecyclerView +import kotlin.test.assertEquals import org.hamcrest.CoreMatchers.not import org.junit.Before import org.junit.Test @@ -43,15 +43,11 @@ import org.mockito.kotlin.doReturn import org.mockito.kotlin.stub import org.mockito.kotlin.times import org.mockito.kotlin.verifyBlocking -import kotlin.test.assertEquals @RunWith(AndroidJUnit4::class) @LargeTest class DocumentEmojiPickerFragmentTest { - @Mock - lateinit var detailModificationManager: DetailModificationManager - @Mock lateinit var suggester: EmojiSuggester diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/AddRelationStatusValueTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/AddRelationStatusValueTest.kt index fb593d6be5..0235d74185 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/AddRelationStatusValueTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/AddRelationStatusValueTest.kt @@ -16,10 +16,10 @@ import com.anytypeio.anytype.core_models.Relation import com.anytypeio.anytype.core_models.StubRelationOptionObject import com.anytypeio.anytype.core_models.ThemeColor import com.anytypeio.anytype.core_ui.extensions.dark -import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.block.repo.BlockRepository import com.anytypeio.anytype.domain.config.Gateway import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.DefaultObjectStore import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations import com.anytypeio.anytype.domain.objects.ObjectStore @@ -111,7 +111,8 @@ class AddRelationStatusValueTest { storeOfRelations = storeOfRelations ), values = DataViewObjectValueProvider( - db = db + db = db, + objectState = state ), dispatcher = dispatcher, optionsProvider = AddOptionsRelationProvider(), diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/AddRelationTagValueTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/AddRelationTagValueTest.kt index 96b210a3ef..b20e6057d8 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/AddRelationTagValueTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/AddRelationTagValueTest.kt @@ -15,10 +15,10 @@ import com.anytypeio.anytype.core_models.Relation import com.anytypeio.anytype.core_models.StubRelationOptionObject import com.anytypeio.anytype.core_models.ThemeColor import com.anytypeio.anytype.core_ui.extensions.dark -import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.block.repo.BlockRepository import com.anytypeio.anytype.domain.config.Gateway import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.DefaultObjectStore import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations import com.anytypeio.anytype.domain.objects.ObjectStore @@ -108,7 +108,7 @@ class AddRelationTagValueTest { objectState = state, storeOfRelations = storeOfRelations ), - values = DataViewObjectValueProvider(db = db), + values = DataViewObjectValueProvider(db = db, objectState = state), createRelationOption = createRelationOption, dispatcher = dispatcher, optionsProvider = AddOptionsRelationProvider(), diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayObjectRelationTextValueTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayObjectRelationTextValueTest.kt index fb31eb57c3..00114edb05 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayObjectRelationTextValueTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayObjectRelationTextValueTest.kt @@ -72,7 +72,7 @@ class DisplayObjectRelationTextValueTest { objectState = state, storeOfRelations = storeOfRelations ), - values = DataViewObjectValueProvider(db = db), + values = DataViewObjectValueProvider(db = db, objectState = state), reloadObject = reloadObject, analytics = analytics ) diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationNumberValueTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationNumberValueTest.kt index 890c7a9888..bfe8547bec 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationNumberValueTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationNumberValueTest.kt @@ -13,9 +13,9 @@ 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.Payload -import com.anytypeio.anytype.domain.`object`.ReloadObject import com.anytypeio.anytype.domain.block.repo.BlockRepository import com.anytypeio.anytype.domain.config.Gateway +import com.anytypeio.anytype.domain.`object`.ReloadObject import com.anytypeio.anytype.domain.objects.DefaultObjectStore import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations import com.anytypeio.anytype.domain.objects.ObjectStore @@ -79,7 +79,7 @@ class DisplayRelationNumberValueTest { objectState = state, storeOfRelations = storeOfRelations ), - values = DataViewObjectValueProvider(db = db), + values = DataViewObjectValueProvider(db = db, objectState = state), reloadObject = reloadObject, analytics = analytics ) diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationObjectValueTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationObjectValueTest.kt index f34412aeab..daecf0f99a 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationObjectValueTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationObjectValueTest.kt @@ -17,10 +17,10 @@ import com.anytypeio.anytype.core_models.Block import com.anytypeio.anytype.core_models.Id import com.anytypeio.anytype.core_models.ObjectType import com.anytypeio.anytype.core_models.Payload -import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.block.repo.BlockRepository import com.anytypeio.anytype.domain.config.Gateway import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.DefaultObjectStore import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations @@ -102,7 +102,7 @@ class DisplayRelationObjectValueTest { objectState = state, storeOfRelations = storeOfRelations ), - values = DataViewObjectValueProvider(db = db), + values = DataViewObjectValueProvider(db = db, objectState = state), details = object : ObjectDetailProvider { override fun provide(): Map = state.value.dataViewState()?.details.orEmpty() diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationStatusValueTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationStatusValueTest.kt index 1fb262b24e..7b636711ac 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationStatusValueTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationStatusValueTest.kt @@ -19,10 +19,10 @@ 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_ui.extensions.dark -import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.block.repo.BlockRepository import com.anytypeio.anytype.domain.config.Gateway import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.DefaultObjectStore import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations @@ -104,7 +104,8 @@ class DisplayRelationStatusValueTest { storeOfRelations = storeOfRelations ), values = DataViewObjectValueProvider( - db = db + db = db, + objectState = state ), details = object : ObjectDetailProvider { override fun provide(): Map = diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationTagValueTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationTagValueTest.kt index c9edc58a4f..e5565f9a66 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationTagValueTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/DisplayRelationTagValueTest.kt @@ -19,10 +19,10 @@ 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_ui.extensions.dark -import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.block.repo.BlockRepository import com.anytypeio.anytype.domain.config.Gateway import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.DefaultObjectStore import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations @@ -103,7 +103,7 @@ class DisplayRelationTagValueTest { objectState = state, storeOfRelations = storeOfRelations ), - values = DataViewObjectValueProvider(db = db), + values = DataViewObjectValueProvider(db = db, objectState = state), details = object : ObjectDetailProvider { override fun provide(): Map = state.value.dataViewState()?.details.orEmpty() diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/EditRelationTagValueTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/EditRelationTagValueTest.kt index 5989cf7142..844b0fd71c 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/EditRelationTagValueTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/EditRelationTagValueTest.kt @@ -14,10 +14,10 @@ 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_ui.extensions.dark -import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.block.repo.BlockRepository import com.anytypeio.anytype.domain.config.Gateway import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.DefaultObjectStore import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations @@ -105,7 +105,7 @@ class EditRelationTagValueTest { objectState = state, storeOfRelations = storeOfRelations ), - values = DataViewObjectValueProvider(db = db), + values = DataViewObjectValueProvider(db = db, objectState = state), details = object : ObjectDetailProvider { override fun provide(): Map = state.value.dataViewState()?.details.orEmpty() @@ -253,7 +253,7 @@ class EditRelationTagValueTest { launchFragment( bundleOf( RelationValueBaseFragment.CTX_KEY to ctx, - RelationValueBaseFragment.DATAVIEW_KEY to dv.id, + RelationValueBaseFragment.DV_KEY to dv.id, RelationValueBaseFragment.VIEWER_KEY to viewer.id, RelationValueBaseFragment.RELATION_KEY to relationKey, RelationValueBaseFragment.TARGET_KEY to target, diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/ObjectRelationDateValueTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/ObjectRelationDateValueTest.kt index 385f3c0627..b568ed4ea3 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/ObjectRelationDateValueTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/ObjectRelationDateValueTest.kt @@ -30,6 +30,7 @@ import com.anytypeio.anytype.test_utils.MockDataFactory import com.anytypeio.anytype.ui.relations.RelationDateValueFragment import com.anytypeio.anytype.utils.CoroutinesTestRule import com.bartoszlipinski.disableanimationsrule.DisableAnimationsRule +import java.util.* import kotlinx.coroutines.flow.MutableStateFlow import org.hamcrest.CoreMatchers.not import org.junit.Before @@ -37,7 +38,6 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.MockitoAnnotations -import java.util.* @RunWith(AndroidJUnit4::class) @LargeTest @@ -64,7 +64,7 @@ class ObjectRelationDateValueTest { objectState = state, storeOfRelations = storeOfRelations ), - values = DataViewObjectValueProvider(db = db) + values = DataViewObjectValueProvider(db = db, objectState = state) ) } 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 index cd2df93ab9..6adbac4b92 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/relations/ObjectRelationListTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/relations/ObjectRelationListTest.kt @@ -28,7 +28,6 @@ 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.presentation.editor.Editor -import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager import com.anytypeio.anytype.presentation.objects.LockedStateProvider import com.anytypeio.anytype.presentation.relations.ObjectRelationListViewModelFactory import com.anytypeio.anytype.presentation.relations.providers.RelationListProvider @@ -72,9 +71,6 @@ class ObjectRelationListTest { @Mock lateinit var dispatcher: Dispatcher - @Mock - lateinit var detailModificationManager: DetailModificationManager - @Mock lateinit var analytics: Analytics @@ -110,7 +106,6 @@ class ObjectRelationListTest { relationListProvider = relationListProvider, urlBuilder = urlBuilder, dispatcher = dispatcher, - detailModificationManager = detailModificationManager, updateDetail = updateDetail, addToFeaturedRelations = addToFeaturedRelations, removeFromFeaturedRelations = removeFromFeaturedRelations, 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 ac6e697fb9..be9e02081b 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 @@ -380,6 +380,14 @@ class ComponentManager( .build() } + val dataViewRelationListComponent = DependentComponentMap { id -> + objectSetComponent + .get(id) + .objectRelationListComponent() + .module(ObjectRelationListModule) + .build() + } + val relationTextValueDVComponent = DependentComponentMap { ctx -> objectSetComponent .get(ctx) 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 6f310c9564..0fc902fc91 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 @@ -53,8 +53,8 @@ import com.anytypeio.anytype.domain.event.interactor.InterceptEvents import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon import com.anytypeio.anytype.domain.launch.GetDefaultPageType import com.anytypeio.anytype.domain.misc.UrlBuilder -import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection +import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet import com.anytypeio.anytype.domain.`object`.DuplicateObject import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.SetObjectIsArchived @@ -101,9 +101,7 @@ import com.anytypeio.anytype.presentation.editor.DocumentExternalEventReducer import com.anytypeio.anytype.presentation.editor.Editor import com.anytypeio.anytype.presentation.editor.EditorViewModelFactory import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider -import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager import com.anytypeio.anytype.presentation.editor.editor.Interactor -import com.anytypeio.anytype.presentation.editor.editor.InternalDetailModificationManager import com.anytypeio.anytype.presentation.editor.editor.Orchestrator import com.anytypeio.anytype.presentation.editor.editor.pattern.DefaultPatternMatcher import com.anytypeio.anytype.presentation.editor.editor.table.DefaultEditorTableDelegate @@ -243,7 +241,6 @@ object EditorSessionModule { analytics: Analytics, dispatcher: Dispatcher, delegator: Delegator, - detailModificationManager: DetailModificationManager, updateDetail: UpdateDetail, searchObjects: SearchObjects, getDefaultPageType: GetDefaultPageType, @@ -278,7 +275,6 @@ object EditorSessionModule { analytics = analytics, dispatcher = dispatcher, delegator = delegator, - detailModificationManager = detailModificationManager, updateDetail = updateDetail, searchObjects = searchObjects, getDefaultPageType = getDefaultPageType, @@ -910,15 +906,6 @@ object EditorUseCaseModule { @PerScreen fun provideDelegator(): Delegator = Delegator.Default() - @JvmStatic - @Provides - @PerScreen - fun provideDetailManager( - storage: Editor.Storage - ): DetailModificationManager = InternalDetailModificationManager( - store = storage.details - ) - @JvmStatic @Provides @PerScreen diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectRelationListDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectRelationListDI.kt index 3e924f26df..875b4a6c49 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectRelationListDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectRelationListDI.kt @@ -10,7 +10,6 @@ import com.anytypeio.anytype.domain.objects.StoreOfRelations 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.presentation.editor.editor.DetailModificationManager import com.anytypeio.anytype.presentation.objects.LockedStateProvider import com.anytypeio.anytype.presentation.relations.ObjectRelationListViewModelFactory import com.anytypeio.anytype.presentation.relations.providers.RelationListProvider @@ -44,7 +43,6 @@ object ObjectRelationListModule { urlBuilder: UrlBuilder, dispatcher: Dispatcher, updateDetail: UpdateDetail, - detailModificationManager: DetailModificationManager, addToFeaturedRelations: AddToFeaturedRelations, removeFromFeaturedRelations: RemoveFromFeaturedRelations, deleteRelationFromObject: DeleteRelationFromObject, @@ -57,7 +55,6 @@ object ObjectRelationListModule { urlBuilder = urlBuilder, dispatcher = dispatcher, updateDetail = updateDetail, - detailModificationManager = detailModificationManager, addToFeaturedRelations = addToFeaturedRelations, removeFromFeaturedRelations = removeFromFeaturedRelations, deleteRelationFromObject = deleteRelationFromObject, 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 d39816487a..b1a8280f74 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 @@ -13,8 +13,6 @@ import com.anytypeio.anytype.di.feature.sets.ModifyFilterSubComponent import com.anytypeio.anytype.di.feature.sets.SelectFilterRelationSubComponent import com.anytypeio.anytype.di.feature.sets.viewer.ViewerCardSizeSelectSubcomponent import com.anytypeio.anytype.di.feature.sets.viewer.ViewerImagePreviewSelectSubcomponent -import com.anytypeio.anytype.domain.`object`.DuplicateObject -import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.auth.repo.AuthRepository import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers import com.anytypeio.anytype.domain.block.interactor.UpdateText @@ -30,6 +28,8 @@ import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon import com.anytypeio.anytype.domain.launch.GetDefaultPageType import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection +import com.anytypeio.anytype.domain.`object`.DuplicateObject +import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.DefaultObjectStore import com.anytypeio.anytype.domain.objects.ObjectStore import com.anytypeio.anytype.domain.objects.SetObjectIsArchived @@ -54,11 +54,13 @@ import com.anytypeio.anytype.domain.workspace.WorkspaceManager import com.anytypeio.anytype.presentation.common.Action import com.anytypeio.anytype.presentation.common.Delegator import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider +import com.anytypeio.anytype.presentation.objects.LockedStateProvider import com.anytypeio.anytype.presentation.relations.providers.DataViewObjectRelationProvider import com.anytypeio.anytype.presentation.relations.providers.DataViewObjectValueProvider import com.anytypeio.anytype.presentation.relations.providers.ObjectDetailProvider import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider +import com.anytypeio.anytype.presentation.relations.providers.RelationListProvider import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase import com.anytypeio.anytype.presentation.sets.ObjectSetPaginator import com.anytypeio.anytype.presentation.sets.ObjectSetSession @@ -75,8 +77,8 @@ import dagger.Binds import dagger.Module import dagger.Provides import dagger.Subcomponent -import kotlinx.coroutines.Dispatchers import javax.inject.Named +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow @Subcomponent(modules = [ObjectSetModule::class]) @@ -116,6 +118,8 @@ interface ObjectSetSubComponent { fun objectSetIconPickerComponent(): ObjectSetIconPickerComponent.Builder fun objectSetCoverComponent(): SelectCoverObjectSetSubComponent.Builder fun objectUnsplashComponent(): UnsplashSubComponent.Builder + + fun objectRelationListComponent(): ObjectRelationListComponent.Builder } @Module( @@ -354,9 +358,11 @@ object ObjectSetModule { @JvmStatic @Provides @PerScreen - fun provideDataViewObjectValueProvider( - db: ObjectSetDatabase + fun dataViewObjectValueProvider( + db: ObjectSetDatabase, + objectState: MutableStateFlow, ): ObjectValueProvider = DataViewObjectValueProvider( + objectState = objectState, db = db ) @@ -507,6 +513,20 @@ object ObjectSetModule { dispatchers = dispatchers ) + @JvmStatic + @Provides + @PerScreen + fun lockedStateProvider() : LockedStateProvider = LockedStateProvider.DataViewLockedStateProvider + + @JvmStatic + @Provides + @PerScreen + fun dataViewRelationListProvider( + objectStateFlow: MutableStateFlow + ) : RelationListProvider = RelationListProvider.DataViewRelationListProvider( + objectStates = objectStateFlow + ) + @Module interface Bindings { diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/SelectDocCoverDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/SelectDocCoverDI.kt index 4ad8f20d2d..128e726c68 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/SelectDocCoverDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/SelectDocCoverDI.kt @@ -12,7 +12,6 @@ import com.anytypeio.anytype.domain.cover.SetDocCoverGradient import com.anytypeio.anytype.domain.cover.SetDocCoverImage import com.anytypeio.anytype.presentation.editor.cover.SelectCoverObjectSetViewModel import com.anytypeio.anytype.presentation.editor.cover.SelectCoverObjectViewModel -import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager import com.anytypeio.anytype.presentation.util.Dispatcher import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectFragment import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectSetFragment @@ -65,7 +64,6 @@ object SelectCoverObjectModule { setCoverGradient: SetDocCoverGradient, removeCover: RemoveDocCover, dispatcher: Dispatcher, - details: DetailModificationManager, getCoverGradientCollection: GetCoverGradientCollection, analytics: Analytics ): SelectCoverObjectViewModel.Factory = SelectCoverObjectViewModel.Factory( @@ -74,7 +72,6 @@ object SelectCoverObjectModule { setCoverGradient = setCoverGradient, removeCover = removeCover, dispatcher = dispatcher, - details = details, getCoverGradientCollection = getCoverGradientCollection, analytics = analytics ) 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 79eb876915..465a8ed154 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 @@ -120,7 +120,7 @@ abstract class ObjectMenuBaseFragment : ObjectMenuViewModelBase.Command.OpenSetCover -> openSetCover() ObjectMenuViewModelBase.Command.OpenSetIcons -> openSetIcons() ObjectMenuViewModelBase.Command.OpenSetLayout -> toast(COMING_SOON_MSG) - ObjectMenuViewModelBase.Command.OpenSetRelations -> toast(COMING_SOON_MSG) + ObjectMenuViewModelBase.Command.OpenSetRelations -> openDataViewRelations() ObjectMenuViewModelBase.Command.OpenLinkToChooser -> openLinkChooser() is ObjectMenuViewModelBase.Command.OpenSnackbar -> openSnackbar(command) is ObjectMenuViewModelBase.Command.ShareDebugTree -> shareFile(command.uri) @@ -155,7 +155,21 @@ abstract class ObjectMenuBaseFragment : ObjectRelationListFragment.ARG_CTX to ctx, ObjectRelationListFragment.ARG_TARGET to null, ObjectRelationListFragment.ARG_LOCKED to isLocked, - ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST + ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST, + ObjectRelationListFragment.ARG_DATA_VIEW_FLOW to false + ) + ) + } + + private fun openDataViewRelations() { + findNavController().navigate( + R.id.objectRelationListScreen, + bundleOf( + ObjectRelationListFragment.ARG_CTX to ctx, + ObjectRelationListFragment.ARG_TARGET to null, + ObjectRelationListFragment.ARG_LOCKED to isLocked, + ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST, + ObjectRelationListFragment.ARG_DATA_VIEW_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 b6980407a2..65c4c2525a 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 @@ -53,6 +53,7 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment { - val fr = RelationValueFragment.new( - ctx = ctx, - target = command.target, - relationKey = command.relationKey, - targetObjectTypes = command.targetObjectTypes, - isLocked = command.isLocked - ) - fr.showChildFragment() + if (isDataViewFLow) { + val fr = RelationValueDVFragment().apply { + arguments = bundleOf( + RelationValueBaseFragment.CTX_KEY to command.ctx, + RelationValueBaseFragment.TARGET_KEY to command.target, + RelationValueBaseFragment.RELATION_KEY to command.relationKey, + RelationValueBaseFragment.TARGET_TYPES_KEY to command.targetObjectTypes, + RelationValueBaseFragment.IS_LOCKED_KEY to false + ) + } + fr.showChildFragment() + } else { + val fr = RelationValueFragment.new( + ctx = ctx, + target = command.target, + relationKey = command.relationKey, + targetObjectTypes = command.targetObjectTypes, + isLocked = command.isLocked + ) + fr.showChildFragment() + } } is Command.SetRelationKey -> { withParent { @@ -148,14 +166,27 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment { - val fr = RelationStatusValueFragment.new( - ctx = ctx, - target = command.target, - relationKey = command.relationKey, - targetObjectTypes = command.targetObjectTypes, - isLocked = command.isLocked - ) - fr.showChildFragment() + if (isDataViewFLow) { + val fr = RelationValueDVFragment().apply { + arguments = bundleOf( + RelationValueBaseFragment.CTX_KEY to command.ctx, + RelationValueBaseFragment.TARGET_KEY to command.target, + RelationValueBaseFragment.RELATION_KEY to command.relationKey, + RelationValueBaseFragment.TARGET_TYPES_KEY to command.targetObjectTypes, + RelationValueBaseFragment.IS_LOCKED_KEY to false + ) + } + fr.showChildFragment() + } else { + val fr = RelationStatusValueFragment.new( + ctx = ctx, + target = command.target, + relationKey = command.relationKey, + targetObjectTypes = command.targetObjectTypes, + isLocked = command.isLocked + ) + fr.showChildFragment() + } } } } @@ -240,11 +271,19 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment : BaseBottomSheetFragme protected val ctx get() = argString(CTX_KEY) protected val relationKey get() = argString(RELATION_KEY) protected val target get() = argString(TARGET_KEY) - protected val dataview get() = argString(DATAVIEW_KEY) + protected val dv get() = argString(DV_KEY) protected val viewer get() = argString(VIEWER_KEY) protected val types get() = arg>(TARGET_TYPES_KEY) protected val isLocked get() = arg(IS_LOCKED_KEY) @@ -114,6 +114,7 @@ abstract class RelationValueBaseFragment : BaseBottomSheetFragme onStatusClicked = onStatusClickedCallback, onRemoveStatusClicked = { status -> vm.onRemoveStatusFromObjectClicked( + ctx = ctx, target = target, relationKey = relationKey, status = status.id @@ -121,6 +122,7 @@ abstract class RelationValueBaseFragment : BaseBottomSheetFragme }, onRemoveTagClicked = { tag -> vm.onRemoveTagFromObjectClicked( + ctx = ctx, target = target, relationKey = relationKey, tag = tag.id @@ -142,6 +144,7 @@ abstract class RelationValueBaseFragment : BaseBottomSheetFragme }, onRemoveObjectClicked = { obj -> vm.onRemoveObjectFromObjectClicked( + ctx = ctx, target = target, relationKey = relationKey, objectId = obj @@ -150,6 +153,7 @@ abstract class RelationValueBaseFragment : BaseBottomSheetFragme onFileClicked = { o -> vm.onFileClicked(o.id) }, onRemoveFileClicked = { file -> vm.onRemoveFileFromObjectClicked( + ctx = ctx, target = target, relationKey = relationKey, fileId = file @@ -170,8 +174,9 @@ abstract class RelationValueBaseFragment : BaseBottomSheetFragme jobs += lifecycleScope.subscribe(vm.copyFileStatus) { command -> onCopyFileCommand(command) } super.onStart() vm.onStart( + ctx = ctx, relationKey = relationKey, - objectId = target + objectId = target, ) } @@ -442,7 +447,7 @@ abstract class RelationValueBaseFragment : BaseBottomSheetFragme const val IS_LOCKED_KEY = "arg.edit-cell-tag.locked" const val RELATION_KEY = "arg.edit-cell-tag.relation.key" const val TARGET_KEY = "arg.edit-cell-tag.target" - const val DATAVIEW_KEY = "arg.edit-cell-tag.dataview" + const val DV_KEY = "arg.edit-cell-tag.dataview" const val VIEWER_KEY = "arg.edit-cell-tag.viewer" const val TARGET_TYPES_KEY = "arg.relation-value.target-types" } diff --git a/app/src/main/java/com/anytypeio/anytype/ui/relations/RelationValueDVFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/relations/RelationValueDVFragment.kt index e7af07c2b9..7a884cf459 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/relations/RelationValueDVFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/relations/RelationValueDVFragment.kt @@ -28,7 +28,6 @@ import com.anytypeio.anytype.ui.relations.add.AddFileRelationFragment import com.anytypeio.anytype.ui.relations.add.AddObjectRelationFragment import com.anytypeio.anytype.ui.relations.add.AddOptionsRelationDVFragment import javax.inject.Inject -import timber.log.Timber open class RelationValueDVFragment : RelationValueBaseFragment(), FileActionsFragment.FileActionReceiver, @@ -82,6 +81,7 @@ open class RelationValueDVFragment : RelationValueBaseFragment ) { vm.onAddObjectsOrFilesValueToRecord( + ctx = ctx, record = objectId, relationKey = relationKey, ids = ids @@ -90,6 +90,7 @@ open class RelationValueDVFragment : RelationValueBaseFragment) { vm.onAddObjectsOrFilesValueToRecord( + ctx = ctx, record = objectId, relationKey = relationKey, ids = ids @@ -130,9 +131,7 @@ open class RelationValueDVFragment : RelationValueBaseFragment(R.layout.fragment_object_set), @@ -720,7 +719,7 @@ open class ObjectSetFragment : bundleOf( RelationValueBaseFragment.CTX_KEY to command.ctx, RelationValueBaseFragment.TARGET_KEY to command.target, - RelationValueBaseFragment.DATAVIEW_KEY to command.dataview, + RelationValueBaseFragment.DV_KEY to command.dataview, RelationValueBaseFragment.RELATION_KEY to command.relationKey, RelationValueBaseFragment.VIEWER_KEY to command.viewer, RelationValueBaseFragment.TARGET_TYPES_KEY to command.targetObjectTypes, diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/ObjectWrapper.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/ObjectWrapper.kt index 3c7adc0474..86ff6f2a95 100644 --- a/core-models/src/main/java/com/anytypeio/anytype/core_models/ObjectWrapper.kt +++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/ObjectWrapper.kt @@ -9,10 +9,12 @@ import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction */ sealed class ObjectWrapper { + abstract val map: Struct + /** * @property map [map] map with raw data containing relations. */ - data class Basic(val map: Map) : ObjectWrapper() { + data class Basic(override val map: Struct) : ObjectWrapper() { private val default = map.withDefault { null } @@ -36,19 +38,9 @@ sealed class ObjectWrapper { val isArchived: Boolean? by default val isDeleted: Boolean? by default - val type: List - get() = when (val value = map[Relations.TYPE]) { - is Id -> listOf(value) - is List<*> -> value.typeOf() - else -> emptyList() - } - - val setOf: List - get() = when (val value = map[Relations.SET_OF]) { - is Id -> listOf(value) - is List<*> -> value.typeOf() - else -> emptyList() - } + val type: List get() = getValues(Relations.TYPE) + val setOf: List get() = getValues(Relations.SET_OF) + val links: List get() = getValues(Relations.LINKS) val layout: ObjectType.Layout? get() = when (val value = map[Relations.LAYOUT]) { @@ -58,13 +50,6 @@ sealed class ObjectWrapper { else -> null } - val links: List - get() = when (val value = map[Relations.LINKS]) { - is Id -> listOf(value) - is List<*> -> value.typeOf() - else -> emptyList() - } - val id: Id by default val done: Boolean? by default @@ -75,14 +60,6 @@ sealed class ObjectWrapper { val fileMimeType: String? by default - inline fun getValue(relation: Id): T? { - val value = map.getOrDefault(relation, null) - return if (value is T) - value - else - null - } - val description: String? by default val url: String? by default @@ -129,7 +106,7 @@ sealed class ObjectWrapper { /** * Wrapper for bookmark objects */ - data class Bookmark(val map: Map) : ObjectWrapper() { + data class Bookmark(override val map: Struct) : ObjectWrapper() { private val default = map.withDefault { null } val name: String? by default val description: String? by default @@ -144,7 +121,7 @@ sealed class ObjectWrapper { /** * Wrapper for object types */ - data class Type(val map: Map) : ObjectWrapper() { + data class Type(override val map: Struct) : ObjectWrapper() { private val default = map.withDefault { null } val id: Id by default val name: String? by default @@ -165,7 +142,7 @@ sealed class ObjectWrapper { } } - data class Relation(val map: Struct) : ObjectWrapper() { + data class Relation(override val map: Struct) : ObjectWrapper() { private val default = map.withDefault { null } @@ -208,24 +185,14 @@ sealed class ObjectWrapper { else -> emptyList() } - val relationFormatObjectTypes - get() = when (val value = map[RELATION_FORMAT_OBJECT_TYPES]) { - is Id -> listOf(value) - is List<*> -> value.typeOf() - else -> emptyList() - } + val relationFormatObjectTypes get() = getValues(RELATION_FORMAT_OBJECT_TYPES) - val type: List - get() = when (val value = map[Relations.TYPE]) { - is Id -> listOf(value) - is List<*> -> value.typeOf() - else -> emptyList() - } + val type: List get() = getValues(Relations.TYPE) val isValid get() = map.containsKey(Relations.RELATION_KEY) && map.containsKey(Relations.ID) } - data class Option(val map: Struct) { + data class Option(override val map: Struct) : ObjectWrapper() { private val default = map.withDefault { null } private val relationOptionColor : String? by default @@ -233,4 +200,20 @@ sealed class ObjectWrapper { val name: String? by default val color: String = relationOptionColor.orEmpty() } + + inline fun getValue(relation: Key): T? { + val value = map.getOrDefault(relation, null) + return if (value is T) + value + else + null + } + + inline fun getValues(relation: Key): List { + return when (val value = map.getOrDefault(relation, emptyList())) { + is T -> listOf(value) + is List<*> -> value.typeOf() + else -> emptyList() + } + } } \ No newline at end of file diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/Relations.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/Relations.kt index 75171f0a5a..b86bf8f254 100644 --- a/core-models/src/main/java/com/anytypeio/anytype/core_models/Relations.kt +++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/Relations.kt @@ -49,6 +49,9 @@ object Relations { const val NUMBER_DEFAULT_VALUE = "0" const val RELATION_NAME_EMPTY = "Untitled" + const val FILE_EXT = "fileExt" + const val FILE_MIME_TYPE = "fileMimeType" + val systemRelationKeys = listOf( "id", "name", diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/inline/Ctx.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/inline/Ctx.kt new file mode 100644 index 0000000000..fdb479d54a --- /dev/null +++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/inline/Ctx.kt @@ -0,0 +1,4 @@ +package com.anytypeio.anytype.core_models.inline + +@JvmInline +value class Ctx(private val ctx: String) \ No newline at end of file diff --git a/docs/screens.md b/docs/screens.md new file mode 100644 index 0000000000..0f2dd16b0d --- /dev/null +++ b/docs/screens.md @@ -0,0 +1,12 @@ +### Object (aka Editor) + +[Main] + +### Set or Collection + +[Main] + - [ObjectSetMenuFragment] showing menu for a Set or Collection + - [ObjectRelationListFragment] displaying list of given object's relations + - [RelationTextValueFragment] + +// TODO diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/object/UpdateDetail.kt b/domain/src/main/java/com/anytypeio/anytype/domain/object/UpdateDetail.kt index a15c7f1f39..c73142ef0d 100644 --- a/domain/src/main/java/com/anytypeio/anytype/domain/object/UpdateDetail.kt +++ b/domain/src/main/java/com/anytypeio/anytype/domain/object/UpdateDetail.kt @@ -10,14 +10,14 @@ class UpdateDetail(private val repo: BlockRepository): BaseUseCase, private val delegator: Delegator, - private val detailModificationManager: DetailModificationManager, private val updateDetail: UpdateDetail, private val searchObjects: SearchObjects, private val getDefaultPageType: GetDefaultPageType, @@ -372,7 +370,6 @@ class EditorViewModel( startHandlingTextChanges() startProcessingFocusChanges() startProcessingControlPanelViewState() - startProcessingInternalDetailModifications() startObservingPayload() startObservingErrors() processRendering() @@ -462,10 +459,6 @@ class EditorViewModel( ) } - private fun startProcessingInternalDetailModifications() { - detailModificationManager.modifications.onEach { refresh() }.launchIn(viewModelScope) - } - private fun startProcessingFocusChanges() { viewModelScope.launch { orchestrator.stores.focus.stream().collect { focus -> @@ -4171,7 +4164,7 @@ class EditorViewModel( viewModelScope.launch { updateDetail( UpdateDetail.Params( - ctx = ctx, + target = ctx, key = key, value = value ) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModelFactory.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModelFactory.kt index efe5c1172f..f2ad648368 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModelFactory.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModelFactory.kt @@ -7,8 +7,6 @@ import com.anytypeio.anytype.core_models.Block import com.anytypeio.anytype.core_models.Event import com.anytypeio.anytype.core_models.Payload import com.anytypeio.anytype.core_utils.tools.FeatureToggles -import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet -import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.block.interactor.RemoveLinkMark import com.anytypeio.anytype.domain.block.interactor.UpdateLinkMarks import com.anytypeio.anytype.domain.block.interactor.sets.CreateObjectSet @@ -19,12 +17,14 @@ import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon import com.anytypeio.anytype.domain.launch.GetDefaultPageType import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection +import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet +import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfRelations import com.anytypeio.anytype.domain.page.CloseBlock -import com.anytypeio.anytype.domain.page.CreateObjectAsMentionOrLink import com.anytypeio.anytype.domain.page.CreateBlockLinkWithObject import com.anytypeio.anytype.domain.page.CreateObject +import com.anytypeio.anytype.domain.page.CreateObjectAsMentionOrLink import com.anytypeio.anytype.domain.page.OpenPage import com.anytypeio.anytype.domain.search.SearchObjects import com.anytypeio.anytype.domain.sets.FindObjectSetForType @@ -34,7 +34,6 @@ import com.anytypeio.anytype.domain.workspace.WorkspaceManager import com.anytypeio.anytype.presentation.common.Action import com.anytypeio.anytype.presentation.common.Delegator import com.anytypeio.anytype.presentation.common.StateReducer -import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager import com.anytypeio.anytype.presentation.editor.editor.Orchestrator import com.anytypeio.anytype.presentation.editor.editor.table.EditorTableDelegate import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer @@ -59,7 +58,6 @@ open class EditorViewModelFactory( private val analytics: Analytics, private val dispatcher: Dispatcher, private val delegator: Delegator, - private val detailModificationManager: DetailModificationManager, private val updateDetail: UpdateDetail, private val searchObjects: SearchObjects, private val getDefaultPageType: GetDefaultPageType, @@ -98,7 +96,6 @@ open class EditorViewModelFactory( analytics = analytics, dispatcher = dispatcher, delegator = delegator, - detailModificationManager = detailModificationManager, updateDetail = updateDetail, searchObjects = searchObjects, getDefaultPageType = getDefaultPageType, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/cover/SelectCoverViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/cover/SelectCoverViewModel.kt index 63f8c18121..981fea2798 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/cover/SelectCoverViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/cover/SelectCoverViewModel.kt @@ -12,8 +12,6 @@ import com.anytypeio.anytype.domain.cover.SetDocCoverColor import com.anytypeio.anytype.domain.cover.SetDocCoverGradient import com.anytypeio.anytype.domain.cover.SetDocCoverImage import com.anytypeio.anytype.presentation.common.BaseViewModel -import com.anytypeio.anytype.presentation.editor.EditorViewModel -import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager import com.anytypeio.anytype.presentation.extension.sendAnalyticsRemoveCoverEvent import com.anytypeio.anytype.presentation.extension.sendAnalyticsSetCoverEvent import com.anytypeio.anytype.presentation.util.Dispatcher @@ -137,7 +135,6 @@ abstract class SelectCoverViewModel( success = { sendAnalyticsSetCoverEvent(analytics) dispatcher.send(it) - onDetailsColor(ctx, color) isDismissed.emit(true) } ) @@ -159,15 +156,11 @@ abstract class SelectCoverViewModel( success = { sendAnalyticsSetCoverEvent(analytics) dispatcher.send(it) - onDetailsGradient(ctx, gradient) isDismissed.emit(true) } ) } } - - abstract fun onDetailsColor(ctx: Id, color: CoverColor) - abstract fun onDetailsGradient(ctx: Id, gradient: String) } class SelectCoverObjectViewModel( @@ -176,7 +169,6 @@ class SelectCoverObjectViewModel( private val setCoverGradient: SetDocCoverGradient, private val removeCover: RemoveDocCover, private val dispatcher: Dispatcher, - private val details: DetailModificationManager, private val getCoverGradientCollection: GetCoverGradientCollection, private val analytics: Analytics ) : SelectCoverViewModel( @@ -189,31 +181,12 @@ class SelectCoverObjectViewModel( analytics = analytics ) { - override fun onDetailsColor(ctx: Id, color: CoverColor) { - viewModelScope.launch { - details.setDocCoverColor( - target = ctx, - color = color.code - ) - } - } - - override fun onDetailsGradient(ctx: Id, gradient: String) { - viewModelScope.launch { - details.setDocCoverGradient( - target = ctx, - gradient = gradient - ) - } - } - class Factory( private val setCoverImage: SetDocCoverImage, private val setCoverColor: SetDocCoverColor, private val setCoverGradient: SetDocCoverGradient, private val removeCover: RemoveDocCover, private val dispatcher: Dispatcher, - private val details: DetailModificationManager, private val getCoverGradientCollection: GetCoverGradientCollection, private val analytics: Analytics ) : ViewModelProvider.Factory { @@ -226,7 +199,6 @@ class SelectCoverObjectViewModel( setCoverGradient = setCoverGradient, removeCover = removeCover, dispatcher = dispatcher, - details = details, getCoverGradientCollection = getCoverGradientCollection, analytics = analytics ) as T @@ -252,9 +224,6 @@ class SelectCoverObjectSetViewModel( analytics = analytics ) { - override fun onDetailsColor(ctx: Id, color: CoverColor) {} - override fun onDetailsGradient(ctx: Id, gradient: String) {} - class Factory( private val setCoverImage: SetDocCoverImage, private val setCoverColor: SetDocCoverColor, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/DetailModificator.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/DetailModificator.kt deleted file mode 100644 index 424b78f139..0000000000 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/DetailModificator.kt +++ /dev/null @@ -1,185 +0,0 @@ -package com.anytypeio.anytype.presentation.editor.editor - -import com.anytypeio.anytype.core_models.Block -import com.anytypeio.anytype.core_models.CoverType -import com.anytypeio.anytype.core_models.Hash -import com.anytypeio.anytype.core_models.Id -import com.anytypeio.anytype.core_utils.const.DetailsKeys -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow - -interface DetailModificationManager { - - val modifications: SharedFlow> - - suspend fun setEmojiIcon(target: Id, unicode: String) - suspend fun setImageIcon(target: Id, hash: Hash) - suspend fun removeIcon(target: Id) - - suspend fun setDocCoverColor(target: Id, color: String) - suspend fun setDocCoverGradient(target: Id, gradient: String) - suspend fun setDocCoverImage(target: Id, hash: Hash) - suspend fun removeDocCover(target: Id) - - suspend fun updateRelationValue(target: Id, key: String, value: Any?) -} - -class InternalDetailModificationManager(private val store: Store.Details) : DetailModificationManager { - - private val details: Block.Details get() = store.current() - private val _modifications = MutableSharedFlow>() - override val modifications: SharedFlow> = _modifications - - override suspend fun setEmojiIcon(target: Id, unicode: String) { - val detail = details.details[target] ?: return - val updated = detail.copy( - map = detail.map.toMutableMap().apply { - set(DetailsKeys.ICON_EMOJI, unicode) - set(DetailsKeys.ICON_IMAGE, null) - } - ) - store.update( - Block.Details( - details.details.toMutableMap().apply { - set(target, updated) - } - ) - ) - _modifications.emit(listOf(ICON_UPDATED)) - } - - override suspend fun setImageIcon(target: Id, hash: Hash) { - val detail = details.details[target] ?: return - val updated = detail.copy( - map = detail.map.toMutableMap().apply { - set(DetailsKeys.ICON_EMOJI, null) - set(DetailsKeys.ICON_IMAGE, hash) - } - ) - store.update( - Block.Details( - details.details.toMutableMap().apply { - set(target, updated) - } - ) - ) - _modifications.emit(listOf(ICON_UPDATED)) - } - - override suspend fun removeIcon(target: Id) { - val detail = details.details[target] ?: return - val updated = detail.copy( - map = detail.map.toMutableMap().apply { - set(DetailsKeys.ICON_EMOJI, null) - set(DetailsKeys.ICON_IMAGE, null) - } - ) - store.update( - Block.Details( - details.details.toMutableMap().apply { - set(target, updated) - } - ) - ) - _modifications.emit(listOf(ICON_CLEARED)) - } - - override suspend fun setDocCoverColor(target: Id, color: String) { - val detail = details.details[target] ?: return - val updated = detail.copy( - map = detail.map.toMutableMap().apply { - set(DetailsKeys.COVER_ID, color) - set(DetailsKeys.COVER_TYPE, CoverType.COLOR.code.toDouble()) - } - ) - store.update( - Block.Details( - details.details.toMutableMap().apply { - set(target, updated) - } - ) - ) - _modifications.emit(listOf(COVER_CHANGED)) - } - - override suspend fun setDocCoverGradient(target: Id, gradient: String) { - val detail = details.details[target] ?: return - val updated = detail.copy( - map = detail.map.toMutableMap().apply { - set(DetailsKeys.COVER_ID, gradient) - set(DetailsKeys.COVER_TYPE, CoverType.GRADIENT.code.toDouble()) - } - ) - store.update( - Block.Details( - details.details.toMutableMap().apply { - set(target, updated) - } - ) - ) - _modifications.emit(listOf(COVER_CHANGED)) - } - - override suspend fun setDocCoverImage(target: Id, hash: Hash) { - val detail = details.details[target] ?: return - val updated = detail.copy( - map = detail.map.toMutableMap().apply { - set(DetailsKeys.COVER_ID, hash) - set(DetailsKeys.COVER_TYPE, CoverType.UPLOADED_IMAGE.code.toDouble()) - } - ) - store.update( - Block.Details( - details.details.toMutableMap().apply { - set(target, updated) - } - ) - ) - _modifications.emit(listOf(COVER_CHANGED)) - } - - override suspend fun removeDocCover(target: Id) { - val detail = details.details[target] ?: return - val updated = detail.copy( - map = detail.map.toMutableMap().apply { - set(DetailsKeys.COVER_ID, null) - set(DetailsKeys.COVER_TYPE, CoverType.NONE.code.toDouble()) - } - ) - store.update( - Block.Details( - details.details.toMutableMap().apply { - set(target, updated) - } - ) - ) - _modifications.emit(listOf(COVER_CLEARED)) - } - - override suspend fun updateRelationValue(target: Id, key: String, value: Any?) { - val detail = details.details[target] ?: return - val updated = detail.copy( - map = detail.map.toMutableMap().apply { - set(key, value) - } - ) - store.update( - Block.Details( - details.details.toMutableMap().apply { - set(target, updated) - } - ) - ) - _modifications.emit(listOf(RELATION_VALUE_CHANGED)) - } - - companion object { - const val ICON_UPDATED = 1 - const val ICON_CLEARED = 2 - const val COVER_CHANGED = 3 - const val COVER_CLEARED = 4 - const val RELATION_VALUE_CHANGED = 5 - } -} - -typealias Modification = Int diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/LockedStateProvider.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/LockedStateProvider.kt index 191c2afe54..2174f2b914 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/LockedStateProvider.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/LockedStateProvider.kt @@ -13,4 +13,8 @@ interface LockedStateProvider { return doc?.fields?.isLocked ?: false } } + object DataViewLockedStateProvider : LockedStateProvider { + // Sets or Collections can't be locked currently. + override fun isLocked(ctx: Id): Boolean = false + } } \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/ObjectRelationListViewModelFactory.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/ObjectRelationListViewModelFactory.kt index 9836d63136..c855884df0 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/ObjectRelationListViewModelFactory.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/ObjectRelationListViewModelFactory.kt @@ -10,7 +10,6 @@ import com.anytypeio.anytype.domain.objects.StoreOfRelations 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.presentation.editor.editor.DetailModificationManager import com.anytypeio.anytype.presentation.objects.LockedStateProvider import com.anytypeio.anytype.presentation.relations.providers.RelationListProvider import com.anytypeio.anytype.presentation.util.Dispatcher @@ -21,7 +20,6 @@ class ObjectRelationListViewModelFactory( private val urlBuilder: UrlBuilder, private val dispatcher: Dispatcher, private val updateDetail: UpdateDetail, - private val detailModificationManager: DetailModificationManager, private val addToFeaturedRelations: AddToFeaturedRelations, private val removeFromFeaturedRelations: RemoveFromFeaturedRelations, private val deleteRelationFromObject: DeleteRelationFromObject, @@ -37,7 +35,6 @@ class ObjectRelationListViewModelFactory( urlBuilder = urlBuilder, dispatcher = dispatcher, updateDetail = updateDetail, - detailModificationManager = detailModificationManager, addToFeaturedRelations = addToFeaturedRelations, removeFromFeaturedRelations = removeFromFeaturedRelations, deleteRelationFromObject = deleteRelationFromObject, 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 ba39f4deb9..15a6b394fa 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 @@ -20,7 +20,6 @@ import com.anytypeio.anytype.domain.relations.DeleteRelationFromObject import com.anytypeio.anytype.domain.relations.RemoveFromFeaturedRelations import com.anytypeio.anytype.presentation.BuildConfig import com.anytypeio.anytype.presentation.common.BaseViewModel -import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager import com.anytypeio.anytype.presentation.extension.sendAnalyticsRelationDeleteEvent import com.anytypeio.anytype.presentation.extension.sendAnalyticsRelationValueEvent import com.anytypeio.anytype.presentation.objects.LockedStateProvider @@ -41,7 +40,6 @@ class RelationListViewModel( private val urlBuilder: UrlBuilder, private val dispatcher: Dispatcher, private val updateDetail: UpdateDetail, - private val detailModificationManager: DetailModificationManager, private val addToFeaturedRelations: AddToFeaturedRelations, private val removeFromFeaturedRelations: RemoveFromFeaturedRelations, private val deleteRelationFromObject: DeleteRelationFromObject, @@ -135,7 +133,7 @@ class RelationListViewModel( view: ObjectRelationView, ctx: Id ) { - val relationKey = view.key ?: return + val relationKey = view.key viewModelScope.launch { if (view.featured) { viewModelScope.launch { @@ -317,7 +315,7 @@ class RelationListViewModel( check(view is ObjectRelationView.Checkbox) updateDetail( UpdateDetail.Params( - ctx = ctx, + target = ctx, key = view.key, value = !view.isChecked ) @@ -352,18 +350,13 @@ class RelationListViewModel( viewModelScope.launch { updateDetail( UpdateDetail.Params( - ctx = ctx, + target = ctx, key = relationKey, value = value ) ).process( success = { payload -> if (payload.events.isNotEmpty()) dispatcher.send(payload) - detailModificationManager.updateRelationValue( - target = ctx, - key = relationKey, - value = value - ) sendAnalyticsRelationValueEvent(analytics) }, failure = { Timber.e(it, "Error while updating relation values") } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddFileRelationViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddFileRelationViewModel.kt index ffb72beee9..a5aea5619d 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddFileRelationViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddFileRelationViewModel.kt @@ -45,12 +45,16 @@ class AddFileRelationViewModel( val commands = MutableSharedFlow(0) val viewsFiltered: StateFlow = _viewsFiltered - fun onStart(relationKey: Key, objectId: String) { + fun onStart( + ctx: Id, + relationKey: Key, + objectId: String + ) { processingViewsSelectionsAndFilter() jobs += viewModelScope.launch { val pipeline = combine( relations.observe(relationKey), - values.subscribe(objectId) + values.subscribe(ctx = ctx, target = objectId) ) { relation, value -> when (val ids = value[relation.key]) { is List<*> -> { diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddObjectRelationViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddObjectRelationViewModel.kt index 51572a7c13..614b107741 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddObjectRelationViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddObjectRelationViewModel.kt @@ -47,13 +47,18 @@ class AddObjectRelationViewModel( val commands = MutableSharedFlow(0) val viewsFiltered: StateFlow = _viewsFiltered - fun onStart(relationKey: Key, objectId: String, targetTypes: List) { + fun onStart( + ctx: Id, + relationKey: Key, + objectId: String, + targetTypes: List + ) { Timber.d("key: $relationKey, object: ${objectId}, types: $targetTypes") processingViewsSelectionsAndFilter() jobs += viewModelScope.launch { val pipeline = combine( relations.observe(relationKey), - values.subscribe(objectId) + values.subscribe(ctx = ctx, target = objectId) ) { relation, value -> when (val ids = value[relation.key]) { is List<*> -> { diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddOptionsRelationDVViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddOptionsRelationDVViewModel.kt index 4d6883bb07..09a457bd58 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddOptionsRelationDVViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddOptionsRelationDVViewModel.kt @@ -42,6 +42,7 @@ class AddOptionsRelationDVViewModel( ) { fun onCreateDataViewRelationOptionClicked( + ctx: Id, relationKey: Key, target: Id, name: String @@ -59,6 +60,7 @@ class AddOptionsRelationDVViewModel( when (relations.get(relation = relationKey).format) { RelationFormat.TAG -> { proceedWithAddingTagToObject( + ctx = ctx, target = target, relationKey = relationKey, tags = listOf(option.id) @@ -92,6 +94,7 @@ class AddOptionsRelationDVViewModel( } fun onAddSelectedValuesToDataViewClicked( + ctx: Id, target: Id, relationKey: Key ) { @@ -102,6 +105,7 @@ class AddOptionsRelationDVViewModel( null } proceedWithAddingTagToObject( + ctx = ctx, relationKey = relationKey, tags = tags, target = target diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddOptionsRelationViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddOptionsRelationViewModel.kt index 39733c6b6b..5d87d24f34 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddOptionsRelationViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/AddOptionsRelationViewModel.kt @@ -52,6 +52,7 @@ class AddOptionsRelationViewModel( ) fun onAddSelectedValuesToObjectClicked( + ctx: Id, obj: Id, relationKey: Key, ) { @@ -62,6 +63,7 @@ class AddOptionsRelationViewModel( null } proceedWithAddingTagToObject( + ctx = ctx, target = obj, relationKey = relationKey, tags = tags @@ -69,6 +71,7 @@ class AddOptionsRelationViewModel( } fun onCreateObjectRelationOptionClicked( + ctx: Id, relationKey: Key, name: String, obj: Id @@ -85,6 +88,7 @@ class AddOptionsRelationViewModel( when (val format = relations.get(relationKey).format) { RelationFormat.TAG -> { proceedWithAddingTagToObject( + ctx = ctx, relationKey = relationKey, target = obj, tags = listOf(option.id) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/BaseAddOptionsRelationViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/BaseAddOptionsRelationViewModel.kt index 8e5364bb69..dc31b3145b 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/BaseAddOptionsRelationViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/add/BaseAddOptionsRelationViewModel.kt @@ -93,11 +93,15 @@ abstract class BaseAddOptionsRelationViewModel( } } - fun onStart(target: Id, relationKey: Key) { + fun onStart( + ctx: Id, + target: Id, + relationKey: Key + ) { jobs += viewModelScope.launch { combine( relations.observe(relationKey), - values.subscribe(target) + values.subscribe(ctx = ctx, target = target) ) { relation, record -> if (relation.format == Relation.Format.STATUS) { isAddButtonVisible.value = false @@ -134,10 +138,10 @@ abstract class BaseAddOptionsRelationViewModel( options: List ) { allRelationOptions.value = optionsProvider.provideOptions( - options = options, - relation = relation, - record = record, - relationKey = relationKey + options = options, + relation = relation, + record = record, + relationKey = relationKey ) } @@ -161,13 +165,14 @@ abstract class BaseAddOptionsRelationViewModel( } fun proceedWithAddingTagToObject( + ctx: Id, target: Id, relationKey: Key, tags: List ) { Timber.d("Relations | Adding tag to object with id: $target") viewModelScope.launch { - val obj = values.get(target = target) + val obj = values.get(target = target, ctx = ctx) val result = mutableListOf() val value = obj[relationKey] if (value is List<*>) { @@ -178,7 +183,7 @@ abstract class BaseAddOptionsRelationViewModel( result.addAll(tags) setObjectDetail( UpdateDetail.Params( - ctx = target, + target = target, key = relationKey, value = result ) @@ -202,7 +207,7 @@ abstract class BaseAddOptionsRelationViewModel( viewModelScope.launch { setObjectDetail( UpdateDetail.Params( - ctx = target, + target = target, key = relationKey, value = listOf(status) ) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DataViewObjectValueProvider.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DataViewObjectValueProvider.kt index 360da61466..009e28eb40 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DataViewObjectValueProvider.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DataViewObjectValueProvider.kt @@ -1,15 +1,51 @@ package com.anytypeio.anytype.presentation.relations.providers import com.anytypeio.anytype.core_models.Id +import com.anytypeio.anytype.core_models.Struct import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase +import com.anytypeio.anytype.presentation.sets.state.ObjectState +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map class DataViewObjectValueProvider( private val db: ObjectSetDatabase, + private val objectState: StateFlow ) : ObjectValueProvider { - override suspend fun get(target: Id): Map { - return db.store.get(target)?.map ?: emptyMap() + override suspend fun get(ctx: Id, target: Id): Struct { + return if (ctx == target) + parseIntrinsicObjectValues( + state = objectState.value, + target = target + ) + else + db.store.get(target)?.map ?: emptyMap() } - override suspend fun subscribe(target: Id) = db.observe(target).map { it.map } + override suspend fun subscribe(ctx: Id, target: Id): Flow { + return if (ctx == target) + objectState.map { state -> + parseIntrinsicObjectValues( + state = state, + target = target + ) + } + else + db.observe(target).map { it.map } + } + + /** + * Providing values for relations of a Set of objects or a Collection of objects. + * Set or Collection are both considered here as Objects, contrary to objects from database query. + * Objects corresponding to data view query should be taken from [db]. + */ + private fun parseIntrinsicObjectValues( + state: ObjectState, + target: Id + ) : Struct = when (state) { + is ObjectState.DataView.Collection -> state.details[target]?.map ?: emptyMap() + is ObjectState.DataView.Set -> state.details[target]?.map ?: emptyMap() + is ObjectState.ErrorLayout -> emptyMap() + is ObjectState.Init -> emptyMap() + } } \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DefaultObjectValueProvider.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DefaultObjectValueProvider.kt index 4ae821389c..2b8c9e5017 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DefaultObjectValueProvider.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/DefaultObjectValueProvider.kt @@ -2,6 +2,7 @@ package com.anytypeio.anytype.presentation.relations.providers import com.anytypeio.anytype.core_models.Block import com.anytypeio.anytype.core_models.Id +import com.anytypeio.anytype.core_models.Struct import com.anytypeio.anytype.presentation.editor.editor.Store import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -9,11 +10,11 @@ import kotlinx.coroutines.flow.map class DefaultObjectValueProvider( private val details: Store.Details ) : ObjectValueProvider { - override suspend fun get(target: Id): Map { + override suspend fun get(ctx: Id, target: Id): Struct { return details.current().details.getOrDefault(target, Block.Fields.empty()).map } - override suspend fun subscribe(target: Id): Flow> { + override suspend fun subscribe(ctx: Id, target: Id): Flow { return details.stream().map { details -> details.details.getOrDefault(target, Block.Fields.empty()).map } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/ObjectValueProvider.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/ObjectValueProvider.kt index 604cd244d4..95f3313b82 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/ObjectValueProvider.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/providers/ObjectValueProvider.kt @@ -1,9 +1,10 @@ package com.anytypeio.anytype.presentation.relations.providers import com.anytypeio.anytype.core_models.Id +import com.anytypeio.anytype.core_models.Struct import kotlinx.coroutines.flow.Flow interface ObjectValueProvider { - suspend fun get(target: Id): Map - suspend fun subscribe(target: Id) : Flow> + suspend fun get(ctx: Id, target: Id): Struct + suspend fun subscribe(ctx: Id, target: Id) : Flow } \ No newline at end of file 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 832c6d4b90..50474824da 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 @@ -2,8 +2,12 @@ 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.core_models.ext.content import com.anytypeio.anytype.presentation.editor.Editor +import com.anytypeio.anytype.presentation.sets.state.ObjectState import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map interface RelationListProvider { @@ -24,4 +28,35 @@ interface RelationListProvider { override fun getLinks() = storage.relationLinks.current() override fun getDetails() = storage.details.current() } + + class DataViewRelationListProvider( + 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) { + is ObjectState.DataView.Collection -> { + Block.Details(state.details) + } + is ObjectState.DataView.Set -> { + Block.Details(state.details) + } + else -> Block.Details(emptyMap()) + } + + private fun mapLinks(state: ObjectState) = when (state) { + is ObjectState.DataView.Collection -> { + state.dataViewBlock.content().relationLinks + } + is ObjectState.DataView.Set -> { + state.dataViewBlock.content().relationLinks + } + else -> emptyList() + } + } } \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/search/ObjectSearchConstants.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/search/ObjectSearchConstants.kt index 5b14ae03fa..0208211153 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/search/ObjectSearchConstants.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/search/ObjectSearchConstants.kt @@ -6,7 +6,6 @@ import com.anytypeio.anytype.core_models.DVFilterCondition import com.anytypeio.anytype.core_models.DVSort import com.anytypeio.anytype.core_models.DVSortType import com.anytypeio.anytype.core_models.Id -import com.anytypeio.anytype.core_models.Key import com.anytypeio.anytype.core_models.Marketplace.MARKETPLACE_ID import com.anytypeio.anytype.core_models.MarketplaceObjectTypeIds import com.anytypeio.anytype.core_models.ObjectTypeIds @@ -468,7 +467,9 @@ object ObjectSearchConstants { Relations.RELATION_OPTION_COLOR, Relations.COVER_TYPE, Relations.COVER_ID, - Relations.PAGE_COVER + Relations.PAGE_COVER, + Relations.FILE_EXT, + Relations.FILE_MIME_TYPE ) //endregion diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetRecordViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetRecordViewModel.kt index 19c532df87..e80d093dd9 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetRecordViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetRecordViewModel.kt @@ -20,7 +20,7 @@ class ObjectSetRecordViewModel( viewModelScope.launch { setObjectDetails( UpdateDetail.Params( - ctx = target, + target = target, key = Relations.NAME, value = input ) @@ -38,7 +38,7 @@ class ObjectSetRecordViewModel( } else { setObjectDetails( UpdateDetail.Params( - ctx = target, + target = target, key = Relations.NAME, value = input ) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetViewModel.kt index a728f2a111..561d9bffd5 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetViewModel.kt @@ -522,7 +522,7 @@ class ObjectSetViewModel( viewModelScope.launch { setObjectDetails( UpdateDetail.Params( - ctx = context, + target = context, key = Relations.NAME, value = txt ) @@ -632,7 +632,7 @@ class ObjectSetViewModel( is CellView.Checkbox -> { setObjectDetails( UpdateDetail.Params( - ctx = cell.id, + target = cell.id, key = cell.relationKey, value = !cell.isChecked ) @@ -689,7 +689,7 @@ class ObjectSetViewModel( if (obj != null) { setObjectDetails( UpdateDetail.Params( - ctx = target, + target = target, key = Relations.DONE, value = !(obj.done ?: false) ) @@ -717,7 +717,7 @@ class ObjectSetViewModel( viewModelScope.launch { setObjectDetails( UpdateDetail.Params( - ctx = objectId, + target = objectId, key = relationKey, value = value ) 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 98dbe7db09..8df9a22211 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 @@ -3,6 +3,7 @@ package com.anytypeio.anytype.presentation.sets import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope +import com.anytypeio.anytype.core_models.Id import com.anytypeio.anytype.core_models.Key import com.anytypeio.anytype.core_utils.const.DateConst.DEFAULT_DATE_FORMAT import com.anytypeio.anytype.core_utils.ext.cancel @@ -14,6 +15,7 @@ import com.anytypeio.anytype.core_utils.ext.isSameDay import com.anytypeio.anytype.presentation.relations.DateParser import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider +import java.util.* import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -21,7 +23,6 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch -import java.util.* class RelationDateValueViewModel( private val relations: ObjectRelationProvider, @@ -34,11 +35,15 @@ class RelationDateValueViewModel( private val jobs = mutableListOf() - fun onStart(relationKey: Key, objectId: String) { + fun onStart( + ctx: Id, + relationKey: Key, + objectId: String + ) { jobs += viewModelScope.launch { val pipeline = combine( relations.observe(relationKey), - values.subscribe(objectId) + values.subscribe(ctx = ctx, target = objectId) ) { relation, value -> setName(relation.name) setDate(timeInSeconds = DateParser.parse(value[relationKey])) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationTextValueViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationTextValueViewModel.kt index b2872585ab..04d75de60b 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationTextValueViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationTextValueViewModel.kt @@ -58,6 +58,7 @@ class RelationTextValueViewModel( } fun onStart( + ctx: Id, relationKey: Key, recordId: String, isLocked: Boolean = false @@ -65,7 +66,7 @@ class RelationTextValueViewModel( jobs += viewModelScope.launch { val pipeline = combine( relations.observe(relationKey), - values.subscribe(recordId) + values.subscribe(ctx = ctx, target = recordId) ) { relation, values -> val obj = ObjectWrapper.Basic(values) val value = values[relationKey]?.toString() diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationValueBaseViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationValueBaseViewModel.kt index c21af5d88a..349318a2fc 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationValueBaseViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/RelationValueBaseViewModel.kt @@ -66,14 +66,20 @@ abstract class RelationValueBaseViewModel( val commands = MutableSharedFlow(replay = 0) val isLoading = MutableStateFlow(false) - fun onStart(objectId: Id, relationKey: Key) { + fun onStart( + ctx: Id, + objectId: Id, + relationKey: Key + ) { Timber.d("onStart") jobs += viewModelScope.launch { combine( relations.observe(relationKey), - values.subscribe(objectId) + values.subscribe(ctx = ctx, target = objectId) ) { relation, record -> initViewState( + ctx = ctx, + target = objectId, relation = relation, record = record, relationKey = relationKey @@ -88,7 +94,9 @@ abstract class RelationValueBaseViewModel( } private suspend fun initViewState( + ctx: Id, relation: ObjectWrapper.Relation, + target: Id, record: Map, relationKey: Key ) { @@ -106,6 +114,8 @@ abstract class RelationValueBaseViewModel( } items.addAll( parseTagRelationValues( + ctx = ctx, + target = target, ids = ids, isRemovable = isRemovable, relationKey = relationKey @@ -121,6 +131,8 @@ abstract class RelationValueBaseViewModel( } items.addAll( parseStatusRelationValues( + ctx = ctx, + target = target, ids = ids, relationKey = relationKey ) @@ -130,9 +142,16 @@ abstract class RelationValueBaseViewModel( val isRemovable = isEditing.value relationFormat = Relation.Format.OBJECT val value = record.getOrDefault(relationKey, null) + // TODO remove code duplication below if (value is List<*>) { value.typeOf().forEach { id -> - val wrapper = resolveWrapperForObject(id) + val wrapper = if (ctx == target) { + ObjectWrapper.Basic( + details.provide()[id]?.map ?: emptyMap() + ) + } else { + resolveWrapperForObject(ctx = ctx, target = id) + } val type = wrapper.type.firstOrNull() val objectType = type?.let { storeOfObjectTypes.get(it) } if (wrapper.isDeleted == true) { @@ -161,7 +180,13 @@ abstract class RelationValueBaseViewModel( } } } else if (value is Id) { - val wrapper = resolveWrapperForObject(value) + val wrapper = if (ctx == target) { + ObjectWrapper.Basic( + details.provide()[value]?.map ?: emptyMap() + ) + } else { + resolveWrapperForObject(ctx = ctx, target = value) + } val type = wrapper.type.firstOrNull() val objectType = type?.let { storeOfObjectTypes.get(it) } if (wrapper.isDeleted == true) { @@ -202,14 +227,20 @@ abstract class RelationValueBaseViewModel( } } ids.forEach { id -> - val detail = details.provide()[id] + val wrapper = if (ctx == target) { + ObjectWrapper.Basic( + details.provide()[id]?.map ?: emptyMap() + ) + } else { + resolveWrapperForObject(ctx = ctx, target = id) + } items.add( RelationValueView.File( id = id, - name = detail?.name.orEmpty(), - mime = detail?.fileMimeType.orEmpty(), - ext = detail?.fileExt.orEmpty(), - image = detail?.iconImage, + name = wrapper.name.orEmpty(), + mime = wrapper.fileMimeType.orEmpty(), + ext = wrapper.fileExt.orEmpty(), + image = wrapper.iconImage, removable = isRemovable ) ) @@ -229,21 +260,37 @@ abstract class RelationValueBaseViewModel( name.value = relation.name.orEmpty() } + /** + * [ctx] operational context + * [target] targeted object + * [ids] status options ids + */ abstract suspend fun parseStatusRelationValues( + ctx: Id, + target: Id, ids: List, relationKey: Key ): List + /** + * [ctx] operational context + * [target] targeted object + * [ids] tags options ids + */ abstract suspend fun parseTagRelationValues( + ctx: Id, + target: Id, ids: List, isRemovable: Boolean, relationKey: Key ): List - open suspend fun resolveWrapperForObject(id: Id): ObjectWrapper.Basic { - val detail = details.provide()[id] + open suspend fun resolveWrapperForObject( + ctx: Id, target: Id + ): ObjectWrapper.Basic { + val detail = details.provide()[target] if (detail == null || detail.map.isEmpty()) { - Timber.w("Could not found data for object: $id") + Timber.w("Could not found data for object: $target") } return ObjectWrapper.Basic(detail?.map ?: emptyMap()) } @@ -294,16 +341,17 @@ abstract class RelationValueBaseViewModel( } fun onRemoveTagFromObjectClicked( + ctx: Id, target: Id, relationKey: Key, tag: Id ) { viewModelScope.launch { - val obj = values.get(target) + val obj = values.get(ctx = ctx, target = target) val remaining = obj[relationKey].filterIdsById(tag) setObjectDetails( UpdateDetail.Params( - ctx = target, + target = target, key = relationKey, value = remaining ) @@ -318,6 +366,7 @@ abstract class RelationValueBaseViewModel( } fun onRemoveStatusFromObjectClicked( + ctx: Id, target: Id, relationKey: Key, status: Id? = null @@ -326,11 +375,11 @@ abstract class RelationValueBaseViewModel( val statusId = status ?: ((views.value.first { it is RelationValueView.Option.Status }) as? RelationValueView.Option.Status)?.id ?: return@launch - val obj = values.get(target) + val obj = values.get(ctx = ctx, target = target) val remaining = obj[relationKey].filterIdsById(statusId) setObjectDetails( UpdateDetail.Params( - ctx = target, + target = target, key = relationKey, value = remaining ) @@ -345,16 +394,17 @@ abstract class RelationValueBaseViewModel( } fun onRemoveObjectFromObjectClicked( + ctx: Id, target: Id, relationKey: Key, objectId: Id ) { viewModelScope.launch { - val obj = values.get(target) + val obj = values.get(ctx = ctx, target = target) val remaining = obj[relationKey].filterIdsById(objectId) setObjectDetails( UpdateDetail.Params( - ctx = target, + target = target, key = relationKey, value = remaining ) @@ -369,16 +419,17 @@ abstract class RelationValueBaseViewModel( } fun onRemoveFileFromObjectClicked( + ctx: Id, target: Id, relationKey: Key, fileId: Id ) { viewModelScope.launch { - val obj = values.get(target) + val obj = values.get(ctx = ctx, target = target) val remaining = obj[relationKey].filterIdsById(fileId) setObjectDetails( UpdateDetail.Params( - ctx = target, + target = target, key = relationKey, value = remaining ) @@ -400,7 +451,7 @@ abstract class RelationValueBaseViewModel( viewModelScope.launch { setObjectDetails( UpdateDetail.Params( - ctx = target, + target = target, key = relationKey, value = order ) @@ -473,7 +524,7 @@ abstract class RelationValueBaseViewModel( ) { viewModelScope.launch { isLoading.emit(true) - val obj = values.get(target) + val obj = values.get(ctx = ctx, target = target) addFileToObject( params = AddFileToObject.Params( ctx = target, @@ -569,11 +620,13 @@ class RelationValueDVViewModel( ) { override suspend fun parseStatusRelationValues( + ctx: Id, + target: Id, ids: List, relationKey: Key ) = buildList { ids.forEach { id -> - val option = values.get(id) + val option = values.get(ctx = ctx, target = id) if (option.isNotEmpty()) { val wrapper = ObjectWrapper.Option(option) add( @@ -590,12 +643,20 @@ class RelationValueDVViewModel( } override suspend fun parseTagRelationValues( + ctx: Id, + target: Id, ids: List, isRemovable: Boolean, relationKey: Key ) = buildList { ids.forEach { id -> - val option = values.get(id) + val option = if (ctx == target) + details.provide()[id]?.map ?: emptyMap() + else + values.get( + ctx = ctx, + target = id + ) if (option.isNotEmpty()) { val wrapper = ObjectWrapper.Option(option) add( @@ -615,29 +676,36 @@ class RelationValueDVViewModel( } fun onAddObjectsOrFilesValueToRecord( + ctx: Id, record: Id, relationKey: Key, ids: List ) { viewModelScope.launch { - val rec = values.get(record) + val rec = if (ctx == record) + details.provide()[record]?.map ?: emptyMap() + else + values.get(ctx = ctx, target = record) val value = rec[relationKey].addIds(ids) setObjectDetails( UpdateDetail.Params( - ctx = record, + target = record, key = relationKey, value = value ) ).process( failure = { Timber.e(it, "Error while add objects or files value to record") }, - success = { Timber.d("Successfully add objects or files value to record") } + success = { dispatcher.send(it) } ) } } - override suspend fun resolveWrapperForObject(id: Id): ObjectWrapper.Basic { + override suspend fun resolveWrapperForObject( + ctx: Id, + target: Id + ): ObjectWrapper.Basic { // For sets, we need to take values from db / store, and not from details. - return ObjectWrapper.Basic(values.get(target = id)) + return ObjectWrapper.Basic(values.get(ctx = ctx, target = target)) } class Factory( @@ -693,6 +761,8 @@ class RelationValueViewModel( ) { override suspend fun parseStatusRelationValues( + ctx: Id, + target: Id, ids: List, relationKey: Key ) = buildList { @@ -714,6 +784,8 @@ class RelationValueViewModel( } override suspend fun parseTagRelationValues( + ctx: Id, + target: Id, ids: List, isRemovable: Boolean, relationKey: Key @@ -745,11 +817,11 @@ class RelationValueViewModel( ids: List ) { viewModelScope.launch { - val obj = values.get(target) + val obj = values.get(ctx = ctx, target = target) val remaining = obj[relationKey].addIds(ids) updateDetail( UpdateDetail.Params( - ctx = ctx, + target = ctx, key = relationKey, value = remaining ) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/SetsExtension.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/SetsExtension.kt index 82778feade..41a190863c 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/SetsExtension.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/SetsExtension.kt @@ -82,10 +82,21 @@ suspend fun List.buildGridRow( ) } ColumnView.Format.FILE -> { - val files = obj.map.buildFileViews( - relationKey = column.key, - details = details - ) + val files = buildList { + obj.getValues(column.key).forEach { id -> + val wrapper = store.get(id) + if (wrapper != null) { + add( + FileView( + id = id, + name = wrapper.name.orEmpty(), + mime = wrapper.fileMimeType.orEmpty(), + ext = wrapper.fileExt.orEmpty() + ) + ) + } + } + } CellView.File( id = obj.id, relationKey = column.key, 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 6c9b0b19f5..e1b6d1a00a 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 @@ -60,8 +60,8 @@ import com.anytypeio.anytype.domain.event.interactor.InterceptEvents import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon import com.anytypeio.anytype.domain.launch.GetDefaultPageType import com.anytypeio.anytype.domain.misc.UrlBuilder -import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection +import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations @@ -96,7 +96,6 @@ import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider import com.anytypeio.anytype.presentation.editor.editor.BlockDimensions import com.anytypeio.anytype.presentation.editor.editor.Command import com.anytypeio.anytype.presentation.editor.editor.Interactor -import com.anytypeio.anytype.presentation.editor.editor.InternalDetailModificationManager import com.anytypeio.anytype.presentation.editor.editor.Markup import com.anytypeio.anytype.presentation.editor.editor.Orchestrator import com.anytypeio.anytype.presentation.editor.editor.ViewState @@ -4024,7 +4023,6 @@ open class EditorViewModelTest { analytics = analytics, dispatcher = Dispatcher.Default(), delegator = delegator, - detailModificationManager = InternalDetailModificationManager(storage.details), updateDetail = updateDetail, searchObjects = searchObjects, getDefaultPageType = getDefaultPageType, 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 eebc82cb47..8bfd30665c 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 @@ -48,9 +48,9 @@ import com.anytypeio.anytype.domain.event.interactor.InterceptEvents import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon import com.anytypeio.anytype.domain.launch.GetDefaultPageType import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet import com.anytypeio.anytype.domain.`object`.UpdateDetail -import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes @@ -435,7 +435,6 @@ open class EditorPresentationTestSetup { analytics = analytics, dispatcher = dispatcher, delegator = delegator, - detailModificationManager = InternalDetailModificationManager(storage.details), updateDetail = updateDetail, searchObjects = searchObjects, getDefaultPageType = getDefaultPageType, diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/BaseAddOptionsRelationViewModelTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/BaseAddOptionsRelationViewModelTest.kt index 875e7acb2c..4d2fbd3e70 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/BaseAddOptionsRelationViewModelTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/BaseAddOptionsRelationViewModelTest.kt @@ -7,8 +7,8 @@ import com.anytypeio.anytype.core_models.Payload import com.anytypeio.anytype.core_models.Relation import com.anytypeio.anytype.core_models.StubRelationObject import com.anytypeio.anytype.core_models.StubRelationOptionObject -import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.base.Either +import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.options.GetOptions import com.anytypeio.anytype.presentation.relations.RelationValueView.Option.Tag import com.anytypeio.anytype.presentation.relations.add.AddOptionsRelationProvider @@ -19,6 +19,7 @@ import com.anytypeio.anytype.presentation.relations.providers.ObjectDetailProvid import com.anytypeio.anytype.presentation.util.CoroutinesTestRule import com.anytypeio.anytype.presentation.util.Dispatcher import com.anytypeio.anytype.test_utils.MockDataFactory +import kotlin.test.assertEquals import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.Before @@ -29,7 +30,6 @@ import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.doReturn import org.mockito.kotlin.stub -import kotlin.test.assertEquals @ExperimentalCoroutinesApi class BaseAddOptionsRelationViewModelTest { @@ -42,15 +42,17 @@ class BaseAddOptionsRelationViewModelTest { private val relation = StubRelationObject( format = Relation.Format.TAG ) - private val relationId = relation.key + private val relationKey = relation.key private val targetId = "stubTargetId" private val relationsProvider = FakeObjectRelationProvider() private val valuesProvider = FakeObjectValueProvider( mapOf( - targetId to mapOf(relationId to listOf(selectedOption.id)) + targetId to mapOf(relationKey to listOf(selectedOption.id)) ) ) + private val ctx = MockDataFactory.randomUuid() + @Mock lateinit var setObjectDetails: UpdateDetail @@ -91,7 +93,11 @@ class BaseAddOptionsRelationViewModelTest { // TESTING viewModel.ui.test { - viewModel.onStart(targetId, relationId) + viewModel.onStart( + ctx = ctx, + target = targetId, + relationKey = relationKey + ) // first item is emmit in constructor val actual = listOf(awaitItem(), awaitItem())[1] assertEquals( @@ -122,7 +128,11 @@ class BaseAddOptionsRelationViewModelTest { // TESTING viewModel.ui.test { - viewModel.onStart(targetId, relationId) + viewModel.onStart( + ctx = ctx, + target = targetId, + relationKey = relationKey + ) val query = MockDataFactory.randomString() + notSelectedOption.name.orEmpty() viewModel.onFilterInputChanged(query) // first item is emmit in constructor, second - at onStart @@ -157,7 +167,11 @@ class BaseAddOptionsRelationViewModelTest { // TESTING viewModel.ui.test { - viewModel.onStart(targetId, relationId) + viewModel.onStart( + ctx = ctx, + target = targetId, + relationKey = relationKey + ) val query = notSelectedOption.name.orEmpty().substring(1) viewModel.onFilterInputChanged(query) @@ -194,7 +208,11 @@ class BaseAddOptionsRelationViewModelTest { // TESTING viewModel.ui.test { - viewModel.onStart(targetId, relationId) + viewModel.onStart( + ctx = ctx, + target = targetId, + relationKey = relationKey + ) // first item is emmit in constructor, second - at onStart val actual = listOf(awaitItem(), awaitItem())[1] assertEquals( @@ -231,7 +249,11 @@ class BaseAddOptionsRelationViewModelTest { // TESTING viewModel.ui.test { - viewModel.onStart(targetId, relationId) + viewModel.onStart( + ctx = ctx, + target = targetId, + relationKey = relationKey + ) val actual = listOf(awaitItem(), awaitItem())[1] assertEquals( diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/providers/FakeObjectValueProvider.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/providers/FakeObjectValueProvider.kt index 07a7777782..15c5dd1252 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/providers/FakeObjectValueProvider.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/relations/providers/FakeObjectValueProvider.kt @@ -8,8 +8,12 @@ internal class FakeObjectValueProvider( var values: Map> = emptyMap() ) : ObjectValueProvider { - override suspend fun get(target: Id): Map = values[target] ?: emptyMap() + override suspend fun get(ctx: Id, target: Id): Map = values[target] ?: emptyMap() - override suspend fun subscribe(target: Id): Flow> = - flow { emit(get(target)) } + override suspend fun subscribe(ctx: Id, target: Id): Flow> = + flow { + emit( + get(ctx = ctx, target = target) + ) + } } \ No newline at end of file diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/ObjectSetRecordViewModelTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/ObjectSetRecordViewModelTest.kt index e23b68f3e5..86ffc1698a 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/ObjectSetRecordViewModelTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/ObjectSetRecordViewModelTest.kt @@ -9,6 +9,7 @@ import com.anytypeio.anytype.domain.base.Either import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.presentation.util.CoroutinesTestRule import com.anytypeio.anytype.test_utils.MockDataFactory +import kotlin.test.assertEquals import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Rule @@ -20,7 +21,6 @@ import org.mockito.kotlin.stub import org.mockito.kotlin.times import org.mockito.kotlin.verifyBlocking import org.mockito.kotlin.verifyNoInteractions -import kotlin.test.assertEquals class ObjectSetRecordViewModelTest { @@ -50,7 +50,7 @@ class ObjectSetRecordViewModelTest { val input = MockDataFactory.randomString() val params = UpdateDetail.Params( - ctx = obj.id, + target = obj.id, key = Relations.NAME, value = input ) @@ -77,7 +77,7 @@ class ObjectSetRecordViewModelTest { val input = MockDataFactory.randomString() val params = UpdateDetail.Params( - ctx = obj.id, + target = obj.id, key = Relations.NAME, value = input ) @@ -114,7 +114,7 @@ class ObjectSetRecordViewModelTest { val emptyInput = "" val params = UpdateDetail.Params( - ctx = obj.id, + target = obj.id, key = Relations.NAME, value = emptyInput )