diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/CreateSelectedFilterTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/CreateSelectedFilterTest.kt index 96ebae7829..084e1f53c2 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/CreateSelectedFilterTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/CreateSelectedFilterTest.kt @@ -24,6 +24,7 @@ import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations import com.anytypeio.anytype.domain.objects.ObjectStore import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfRelations +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.options.GetOptions import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects @@ -77,6 +78,9 @@ class CreateSelectedFilterTest { @Mock lateinit var fieldParser: FieldParser + @Mock + lateinit var spaceViews: SpaceViewSubscriptionContainer + private lateinit var updateDataViewViewer: UpdateDataViewViewer private lateinit var searchObjects: SearchObjects private lateinit var getOptions: GetOptions @@ -109,7 +113,8 @@ class CreateSelectedFilterTest { objectSetDatabase = db, getOptions = getOptions, spaceManager = spaceManager, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyInputValueFilterTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyInputValueFilterTest.kt index 39d8ded654..76b7640180 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyInputValueFilterTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyInputValueFilterTest.kt @@ -32,6 +32,7 @@ import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations import com.anytypeio.anytype.domain.objects.ObjectStore import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfRelations +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.options.GetOptions import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects @@ -82,6 +83,9 @@ class ModifyInputValueFilterTest { @Mock lateinit var fieldParser: FieldParser + @Mock + lateinit var spaceViews: SpaceViewSubscriptionContainer + private lateinit var updateDataViewViewer: UpdateDataViewViewer private lateinit var searchObjects: SearchObjects private lateinit var getOptions: GetOptions @@ -113,7 +117,8 @@ class ModifyInputValueFilterTest { objectSetDatabase = db, getOptions = getOptions, spaceManager = spaceManager, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyStatusFilterTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyStatusFilterTest.kt index 006f507e5b..50c6d62067 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyStatusFilterTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyStatusFilterTest.kt @@ -30,6 +30,7 @@ import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations import com.anytypeio.anytype.domain.objects.ObjectStore import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfRelations +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.options.GetOptions import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects @@ -81,6 +82,9 @@ class ModifyStatusFilterTest { @Mock lateinit var spaceManager: SpaceManager + @Mock + lateinit var spaceViews: SpaceViewSubscriptionContainer + private lateinit var updateDataViewViewer: UpdateDataViewViewer private lateinit var searchObjects: SearchObjects private lateinit var getOptions: GetOptions @@ -113,7 +117,8 @@ class ModifyStatusFilterTest { storeOfRelations = storeOfRelations, objectSetDatabase = db, spaceManager = spaceManager, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } diff --git a/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyTagFilterTest.kt b/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyTagFilterTest.kt index 9c6a64505a..2d136d86e5 100644 --- a/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyTagFilterTest.kt +++ b/app/src/androidTest/java/com/anytypeio/anytype/features/sets/filter/ModifyTagFilterTest.kt @@ -30,6 +30,7 @@ import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations import com.anytypeio.anytype.domain.objects.ObjectStore import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfRelations +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.options.GetOptions import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects @@ -80,6 +81,9 @@ class ModifyTagFilterTest { @Mock lateinit var fieldParser: FieldParser + @Mock + lateinit var spaceViews: SpaceViewSubscriptionContainer + private lateinit var updateDataViewViewer: UpdateDataViewViewer private lateinit var searchObjects: SearchObjects private lateinit var getOptions: GetOptions @@ -112,7 +116,8 @@ class ModifyTagFilterTest { objectSetDatabase = db, getOptions = getOptions, spaceManager = spaceManager, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/LinkToObjectDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/LinkToObjectDI.kt index b3be74b6ae..9a808b90ca 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/LinkToObjectDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/LinkToObjectDI.kt @@ -6,6 +6,7 @@ import com.anytypeio.anytype.di.common.ComponentDependencies import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes import com.anytypeio.anytype.domain.misc.DateProvider import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects @@ -46,7 +47,7 @@ interface LinkToObjectDependencies: ComponentDependencies { fun dateProvider(): DateProvider fun fieldParser(): FieldParser fun storeOfObjectTypes(): StoreOfObjectTypes - + fun spaceViews(): SpaceViewSubscriptionContainer } @Module @@ -63,7 +64,8 @@ object LinkToObjectModule { analytics: Analytics, analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, fieldParser: FieldParser, - storeOfObjectTypes: StoreOfObjectTypes + storeOfObjectTypes: StoreOfObjectTypes, + spaceViews: SpaceViewSubscriptionContainer ): LinkToObjectViewModelFactory = LinkToObjectViewModelFactory( vmParams = vmParams, urlBuilder = urlBuilder, @@ -72,6 +74,7 @@ object LinkToObjectModule { analytics = analytics, analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, fieldParser = fieldParser, - storeOfObjectTypes = storeOfObjectTypes + storeOfObjectTypes = storeOfObjectTypes, + spaceViews = spaceViews ) -} \ No newline at end of file +} diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/LinkToObjectOrWebDi.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/LinkToObjectOrWebDi.kt index 586fd220e4..6941d284a2 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/LinkToObjectOrWebDi.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/LinkToObjectOrWebDi.kt @@ -4,6 +4,7 @@ import com.anytypeio.anytype.analytics.base.Analytics import com.anytypeio.anytype.core_utils.di.scope.PerModal import com.anytypeio.anytype.core_utils.tools.UrlValidator import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects @@ -49,7 +50,8 @@ object LinkToObjectOrWebModule { stores: Editor.Storage, urlValidator: UrlValidator, analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, - fieldParser: FieldParser + fieldParser: FieldParser, + spaceViews: SpaceViewSubscriptionContainer ): LinkToObjectOrWebViewModelFactory = LinkToObjectOrWebViewModelFactory( vmParams = vmParams, urlBuilder = urlBuilder, @@ -59,6 +61,7 @@ object LinkToObjectOrWebModule { stores = stores, urlValidator = urlValidator, analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } \ No newline at end of file diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectValueDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectValueDI.kt index b180cafea9..04c6e70642 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectValueDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectValueDI.kt @@ -6,6 +6,7 @@ import com.anytypeio.anytype.core_utils.di.scope.PerModal import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers import com.anytypeio.anytype.domain.block.repo.BlockRepository import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.`object`.DuplicateObject import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived @@ -74,6 +75,7 @@ object ObjectValueObjectModule { analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, storeOfRelations: StoreOfRelations, fieldParser: FieldParser, + spaceViews: SpaceViewSubscriptionContainer ): ObjectValueViewModelFactory = ObjectValueViewModelFactory( params = params, values = values, @@ -89,7 +91,8 @@ object ObjectValueObjectModule { duplicateObject = duplicateObject, analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, storeOfRelations = storeOfRelations, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } //endregion @@ -132,7 +135,8 @@ object ObjectValueSetModule { duplicateObject: DuplicateObject, analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, storeOfRelations: StoreOfRelations, - fieldParser: FieldParser + fieldParser: FieldParser, + spaceViews: SpaceViewSubscriptionContainer ): ObjectValueViewModelFactory = ObjectValueViewModelFactory( params = params, values = values, @@ -148,7 +152,8 @@ object ObjectValueSetModule { duplicateObject = duplicateObject, analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, storeOfRelations = storeOfRelations, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } //endregion @@ -191,7 +196,8 @@ object ObjectValueDataViewModule { duplicateObject: DuplicateObject, analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, storeOfRelations: StoreOfRelations, - fieldParser: FieldParser + fieldParser: FieldParser, + spaceViews: SpaceViewSubscriptionContainer ): ObjectValueViewModelFactory = ObjectValueViewModelFactory( params = params, values = values, @@ -207,7 +213,8 @@ object ObjectValueDataViewModule { duplicateObject = duplicateObject, analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, storeOfRelations = storeOfRelations, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } //endregion \ No newline at end of file diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/objects/SelectObjectTypeDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/objects/SelectObjectTypeDI.kt index 7b13a2872c..0ecf21d4a1 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/objects/SelectObjectTypeDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/objects/SelectObjectTypeDI.kt @@ -9,6 +9,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository import com.anytypeio.anytype.domain.config.ConfigStorage import com.anytypeio.anytype.domain.config.UserSettingsRepository import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.workspace.SpaceManager import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate import com.anytypeio.anytype.presentation.objects.SelectObjectTypeViewModel @@ -56,4 +57,5 @@ interface SelectObjectTypeDependencies : ComponentDependencies { fun userSettingsRepository(): UserSettingsRepository fun provideSpaceManger(): SpaceManager fun provideUrlBuilder(): UrlBuilder -} \ No newline at end of file + fun spaceViews(): SpaceViewSubscriptionContainer +} diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/sets/CreateFilter.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/sets/CreateFilter.kt index ae1d8b453f..e650d9a671 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/sets/CreateFilter.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/sets/CreateFilter.kt @@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfRelations import com.anytypeio.anytype.domain.objects.options.GetOptions +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects import com.anytypeio.anytype.domain.workspace.SpaceManager @@ -54,7 +55,8 @@ object CreateFilterModule { analytics: Analytics, getOptions: GetOptions, spaceManager: SpaceManager, - fieldParser: FieldParser + fieldParser: FieldParser, + spaceViews: SpaceViewSubscriptionContainer ): FilterViewModel.Factory = FilterViewModel.Factory( objectState = state, dispatcher = dispatcher, @@ -67,6 +69,7 @@ object CreateFilterModule { analytics = analytics, getOptions = getOptions, spaceManager = spaceManager, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/sets/ModifyFilter.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/sets/ModifyFilter.kt index e59025290c..0fad63e263 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/sets/ModifyFilter.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/sets/ModifyFilter.kt @@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfRelations import com.anytypeio.anytype.domain.objects.options.GetOptions +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects import com.anytypeio.anytype.domain.workspace.SpaceManager @@ -54,7 +55,8 @@ object ModifyFilterModule { getOptions: GetOptions, storeOfRelations: StoreOfRelations, spaceManager: SpaceManager, - fieldParser: FieldParser + fieldParser: FieldParser, + spaceViews: SpaceViewSubscriptionContainer ): FilterViewModel.Factory = FilterViewModel.Factory( objectState = state, dispatcher = dispatcher, @@ -67,6 +69,7 @@ object ModifyFilterModule { analytics = analytics, getOptions = getOptions, spaceManager = spaceManager, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/SupportedLayouts.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/SupportedLayouts.kt index 9f5155a8fa..8f39f0d53f 100644 --- a/core-models/src/main/java/com/anytypeio/anytype/core_models/SupportedLayouts.kt +++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/SupportedLayouts.kt @@ -1,7 +1,13 @@ package com.anytypeio.anytype.core_models +import com.anytypeio.anytype.core_models.multiplayer.SpaceUxType + object SupportedLayouts { - val layouts = listOf( + + /** + * Base supported layouts (without CHAT_DERIVED) + */ + private val baseLayouts = listOf( ObjectType.Layout.BASIC, ObjectType.Layout.FILE, ObjectType.Layout.IMAGE, @@ -15,9 +21,15 @@ object SupportedLayouts { ObjectType.Layout.BOOKMARK, ObjectType.Layout.AUDIO, ObjectType.Layout.PDF, - ObjectType.Layout.OBJECT_TYPE, - ObjectType.Layout.CHAT_DERIVED + ObjectType.Layout.OBJECT_TYPE ) + + /** + * Default layouts list (includes CHAT_DERIVED for data spaces). + * For space-aware behavior, use [getLayouts] instead. + */ + private val layouts = baseLayouts + listOf(ObjectType.Layout.CHAT_DERIVED) + val editorLayouts = listOf( ObjectType.Layout.BASIC, ObjectType.Layout.PROFILE, @@ -34,7 +46,11 @@ object SupportedLayouts { ObjectType.Layout.PDF ) - val systemLayouts = listOf( + /** + * System layouts that should not be shown in general object lists. + * Note: CHAT_DERIVED is context-dependent - see [getSystemLayouts] + */ + private val baseSystemLayouts = listOf( ObjectType.Layout.RELATION, ObjectType.Layout.RELATION_OPTION, ObjectType.Layout.DASHBOARD, @@ -43,7 +59,17 @@ object SupportedLayouts { ObjectType.Layout.TAG ) - val createObjectLayouts = listOf( + /** + * Default system layouts (without CHAT_DERIVED). + * For space-aware behavior, use [getSystemLayouts] instead. + */ + val systemLayouts = baseSystemLayouts + + /** + * Layouts that can be created through the "New Object" flow. + * Note: CHAT_DERIVED is context-dependent - see [getCreateObjectLayouts] + */ + private val baseCreateObjectLayouts = listOf( ObjectType.Layout.BASIC, ObjectType.Layout.PROFILE, ObjectType.Layout.PARTICIPANT, @@ -51,10 +77,21 @@ object SupportedLayouts { ObjectType.Layout.COLLECTION, ObjectType.Layout.TODO, ObjectType.Layout.NOTE, - ObjectType.Layout.BOOKMARK, - ObjectType.Layout.CHAT_DERIVED + ObjectType.Layout.BOOKMARK ) + /** + * Default create object layouts (includes CHAT_DERIVED for data spaces). + * For space-aware behavior, use [getCreateObjectLayouts] instead. + */ + val createObjectLayouts = baseCreateObjectLayouts + listOf(ObjectType.Layout.CHAT_DERIVED) + + /** + * Handling create-object layouts for editor. Converting an object to a chat is not currently supported. + */ + val editorCreateObjectLayouts = baseCreateObjectLayouts + + val dateLayouts = listOf( ObjectType.Layout.DATE ) @@ -85,4 +122,52 @@ object SupportedLayouts { fun isFileLayout(layout: ObjectType.Layout?) : Boolean { return fileLayouts.contains(layout) } -} \ No newline at end of file + + /** + * Get system layouts for a specific space context. + * + * In chat spaces (UX type == CHAT), CHAT_DERIVED is a system layout. + * In data spaces, CHAT_DERIVED should be treated as a regular object type. + * + * @param spaceUxType The UX type of the current space + * @return List of layouts that should be filtered out as system layouts + */ + fun getSystemLayouts(spaceUxType: SpaceUxType?): List { + return when (spaceUxType) { + SpaceUxType.CHAT -> baseSystemLayouts + listOf(ObjectType.Layout.CHAT_DERIVED) + else -> baseSystemLayouts + } + } + + /** + * Get create object layouts for a specific space context. + * + * In data spaces, users should be able to create CHAT_DERIVED objects. + * In chat spaces (UX type == CHAT), CHAT_DERIVED creation is handled separately. + * + * @param spaceUxType The UX type of the current space + * @return List of layouts that can be created in the "New Object" flow + */ + fun getCreateObjectLayouts(spaceUxType: SpaceUxType?): List { + return when (spaceUxType) { + SpaceUxType.CHAT -> baseCreateObjectLayouts + else -> baseCreateObjectLayouts + listOf(ObjectType.Layout.CHAT_DERIVED) + } + } + + /** + * Get supported layouts for a specific space context. + * + * In data spaces, CHAT_DERIVED objects should be visible and manageable. + * In chat spaces (UX type == CHAT), CHAT_DERIVED is handled through special UI. + * + * @param spaceUxType The UX type of the current space + * @return List of layouts that are supported for display/interaction + */ + fun getLayouts(spaceUxType: SpaceUxType? = null): List { + return when (spaceUxType) { + SpaceUxType.CHAT -> baseLayouts + else -> baseLayouts + listOf(ObjectType.Layout.CHAT_DERIVED) + } + } +} diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt index 3d52f0b962..62c0d33660 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt @@ -6668,7 +6668,7 @@ class EditorViewModel( val params = GetObjectTypes.Params( sorts = emptyList(), filters = ObjectSearchConstants.filterTypes( - recommendedLayouts = SupportedLayouts.createObjectLayouts + recommendedLayouts = SupportedLayouts.editorCreateObjectLayouts ), keys = ObjectSearchConstants.defaultKeysObjectType, space = vmParams.space diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectOrWebViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectOrWebViewModel.kt index 2883367d98..da6effd947 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectOrWebViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectOrWebViewModel.kt @@ -11,6 +11,7 @@ import com.anytypeio.anytype.core_models.ext.rangeIntersection import com.anytypeio.anytype.core_models.primitives.SpaceId import com.anytypeio.anytype.core_utils.tools.UrlValidator import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects @@ -42,7 +43,8 @@ class LinkToObjectOrWebViewModel( private val stores: Editor.Storage, private val urlValidator: UrlValidator, private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val spaceViews: SpaceViewSubscriptionContainer ) : ViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate { val viewState = MutableStateFlow(ViewState.Init) @@ -127,9 +129,11 @@ class LinkToObjectOrWebViewModel( } } else -> { + val spaceUxType = spaceViews.get(vmParams.space)?.spaceUxType + val supportedLayouts = SupportedLayouts.getLayouts(spaceUxType) val filteredSearchResponse = searchResponse - .filter { SupportedLayouts.layouts.contains(it.layout) } + .filter { supportedLayouts.contains(it.layout) } val objectViews = filteredSearchResponse.toLinkToView( urlBuilder = urlBuilder, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectViewModel.kt index 5e2707d96d..5ac243a8f1 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectViewModel.kt @@ -8,6 +8,7 @@ import com.anytypeio.anytype.core_models.ObjectWrapper import com.anytypeio.anytype.domain.base.Resultat import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate @@ -29,6 +30,7 @@ class LinkToObjectViewModel( analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, fieldParser: FieldParser, storeOfObjectTypes: StoreOfObjectTypes, + private val spaceViews: SpaceViewSubscriptionContainer ) : ObjectSearchViewModel( vmParams = vmParams, urlBuilder = urlBuilder, @@ -76,9 +78,11 @@ class LinkToObjectViewModel( } override suspend fun setObjects(data: List) { + val spaceUxType = spaceViews.get(vmParams.space)?.spaceUxType + val supportedLayouts = SupportedLayouts.getLayouts(spaceUxType) objects.emit( Resultat.success(data.filter { - SupportedLayouts.layouts.contains(it.layout) + supportedLayouts.contains(it.layout) }) ) } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectViewModelFactory.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectViewModelFactory.kt index a4bd2b22fc..d707dc13e1 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectViewModelFactory.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/linking/LinkToObjectViewModelFactory.kt @@ -6,6 +6,7 @@ import com.anytypeio.anytype.analytics.base.Analytics import com.anytypeio.anytype.core_utils.tools.UrlValidator import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects @@ -22,7 +23,8 @@ class LinkToObjectViewModelFactory( private val analytics: Analytics, private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, private val fieldParser: FieldParser, - private val storeOfObjectTypes: StoreOfObjectTypes + private val storeOfObjectTypes: StoreOfObjectTypes, + private val spaceViews: SpaceViewSubscriptionContainer ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") @@ -35,7 +37,8 @@ class LinkToObjectViewModelFactory( analytics = analytics, analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, fieldParser = fieldParser, - storeOfObjectTypes = storeOfObjectTypes + storeOfObjectTypes = storeOfObjectTypes, + spaceViews = spaceViews ) as T } } @@ -49,7 +52,8 @@ class LinkToObjectOrWebViewModelFactory( private val stores: Editor.Storage, private val urlValidator: UrlValidator, private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val spaceViews: SpaceViewSubscriptionContainer ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") @@ -63,7 +67,8 @@ class LinkToObjectOrWebViewModelFactory( stores = stores, urlValidator = urlValidator, analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) as T } } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/ObjectTypeExtensions.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/ObjectTypeExtensions.kt index e27156eb68..5a44b674b9 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/ObjectTypeExtensions.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/ObjectTypeExtensions.kt @@ -18,6 +18,8 @@ import com.anytypeio.anytype.core_models.SupportedLayouts.editorLayouts import com.anytypeio.anytype.core_models.SupportedLayouts.fileLayouts import com.anytypeio.anytype.core_models.SupportedLayouts.systemLayouts import com.anytypeio.anytype.core_models.SupportedLayouts.createObjectLayouts +import com.anytypeio.anytype.core_models.SupportedLayouts.getCreateObjectLayouts +import com.anytypeio.anytype.core_models.multiplayer.SpaceUxType import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.presentation.sets.state.ObjectState @@ -95,6 +97,21 @@ fun canCreateObjectOfType(objectType: ObjectWrapper.Type?): Boolean { return createObjectLayouts.contains(objectType?.recommendedLayout) } +/** + * Determines if objects of the given type can be created based on the object type's layout, + * taking into account the space context. + * + * @param objectType The object type to check for creation eligibility + * @param spaceUxType The UX type of the current space + * @return true if objects of this type can be created, false otherwise + */ +fun canCreateObjectOfType(objectType: ObjectWrapper.Type?, spaceUxType: SpaceUxType?): Boolean { + if (objectType?.uniqueKey == ObjectTypeIds.TEMPLATE) { + return false + } + return getCreateObjectLayouts(spaceUxType).contains(objectType?.recommendedLayout) +} + fun ObjectState.DataView.isCreateObjectAllowed(objectType: ObjectWrapper.Type? = null): Boolean { val dataViewRestrictions = dataViewRestrictions.firstOrNull()?.restrictions if (dataViewRestrictions?.contains(DataViewRestriction.CREATE_OBJECT) == true) { diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/SelectObjectTypeViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/SelectObjectTypeViewModel.kt index e76c707210..4b91e15ac4 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/SelectObjectTypeViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/SelectObjectTypeViewModel.kt @@ -14,6 +14,7 @@ import com.anytypeio.anytype.core_models.ObjectTypeUniqueKeys import com.anytypeio.anytype.core_models.ObjectWrapper import com.anytypeio.anytype.core_models.Relations import com.anytypeio.anytype.core_models.SupportedLayouts +import com.anytypeio.anytype.core_models.SupportedLayouts.getCreateObjectLayouts import com.anytypeio.anytype.core_models.Url import com.anytypeio.anytype.core_models.ext.mapToObjectWrapperType import com.anytypeio.anytype.core_models.primitives.SpaceId @@ -27,6 +28,7 @@ import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes import com.anytypeio.anytype.domain.launch.GetDefaultObjectType import com.anytypeio.anytype.domain.launch.SetDefaultObjectType import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.CreateBookmarkObject import com.anytypeio.anytype.domain.objects.CreatePrefilledNote import com.anytypeio.anytype.domain.spaces.AddObjectToSpace @@ -60,7 +62,8 @@ class SelectObjectTypeViewModel( private val createPrefilledNote: CreatePrefilledNote, private val analytics: Analytics, private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, - private val urlBuilder: UrlBuilder + private val urlBuilder: UrlBuilder, + private val spaceViews: SpaceViewSubscriptionContainer ) : BaseViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate { val viewState = MutableStateFlow(SelectTypeViewState.Loading) @@ -84,13 +87,18 @@ class SelectObjectTypeViewModel( } viewModelScope.launch { query.onStart { emit(EMPTY_QUERY) }.flatMapLatest { query -> + // Get space UX type for context-aware filtering + val spaceView = spaceViews.get(vmParams.space) + val spaceUxType = spaceView?.spaceUxType + val createLayouts = getCreateObjectLayouts(spaceUxType) + val types = getObjectTypes.stream( GetObjectTypes.Params( // TODO DROID-2916 Merge with marketplace object types query results space = vmParams.space, sorts = ObjectSearchConstants.defaultObjectTypeSearchSorts(), filters = ObjectSearchConstants.filterTypes( - recommendedLayouts = SupportedLayouts.createObjectLayouts, + recommendedLayouts = createLayouts, excludedTypeKeys = vmParams.excludedTypeKeys ), keys = ObjectSearchConstants.defaultKeysObjectType, @@ -468,7 +476,8 @@ class SelectObjectTypeViewModel( private val createPrefilledNote: CreatePrefilledNote, private val analytics: Analytics, private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, - private val urlBuilder: UrlBuilder + private val urlBuilder: UrlBuilder, + private val spaceViews: SpaceViewSubscriptionContainer ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create( @@ -485,7 +494,8 @@ class SelectObjectTypeViewModel( createPrefilledNote = createPrefilledNote, analytics = analytics, analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, - urlBuilder = urlBuilder + urlBuilder = urlBuilder, + spaceViews = spaceViews ) as T } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/value/object/ObjectValueViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/value/object/ObjectValueViewModel.kt index e19853947a..feb02a9315 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/value/object/ObjectValueViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/value/object/ObjectValueViewModel.kt @@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.ObjectTypeIds import com.anytypeio.anytype.core_models.ObjectWrapper import com.anytypeio.anytype.core_models.Payload import com.anytypeio.anytype.core_models.Relation.Format.FILE +import com.anytypeio.anytype.core_models.multiplayer.SpaceUxType import com.anytypeio.anytype.core_models.primitives.SpaceId import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction import com.anytypeio.anytype.core_utils.ext.typeOf @@ -19,6 +20,7 @@ import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfRelations +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects import com.anytypeio.anytype.domain.workspace.SpaceManager @@ -60,7 +62,8 @@ class ObjectValueViewModel( private val duplicateObject: DuplicateObject, private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, private val storeOfRelations: StoreOfRelations, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val spaceViews: SpaceViewSubscriptionContainer ) : BaseViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate { val viewState = MutableStateFlow(ObjectValueViewState.Loading()) @@ -137,9 +140,11 @@ class ObjectValueViewModel( } else -> { if (isEditableRelation) { + val spaceUxType = spaceViews.get(viewModelParams.space)?.spaceUxType ObjectSearchConstants.filterAddObjectToRelation( space = viewModelParams.space.id, - targetTypes = relation.relationFormatObjectTypes + targetTypes = relation.relationFormatObjectTypes, + spaceUxType = spaceUxType ) } else { ObjectSearchConstants.filterObjectsByIds( diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/value/object/ObjectValueViewModelFactory.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/value/object/ObjectValueViewModelFactory.kt index 0388849841..4bec7cc78c 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/value/object/ObjectValueViewModelFactory.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/relations/value/object/ObjectValueViewModelFactory.kt @@ -10,6 +10,7 @@ import com.anytypeio.anytype.domain.`object`.UpdateDetail import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfRelations +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects import com.anytypeio.anytype.domain.workspace.SpaceManager @@ -34,7 +35,8 @@ class ObjectValueViewModelFactory @Inject constructor( private val duplicateObject: DuplicateObject, private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, private val storeOfRelations: StoreOfRelations, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val spaceViews: SpaceViewSubscriptionContainer ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create( @@ -54,6 +56,7 @@ class ObjectValueViewModelFactory @Inject constructor( duplicateObject = duplicateObject, analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, storeOfRelations = storeOfRelations, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) as T } \ 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 338924b783..9d73a116c5 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 @@ -11,6 +11,7 @@ import com.anytypeio.anytype.core_models.ObjectType import com.anytypeio.anytype.core_models.ObjectTypeUniqueKeys import com.anytypeio.anytype.core_models.RelationFormat import com.anytypeio.anytype.core_models.Relations +import com.anytypeio.anytype.core_models.multiplayer.SpaceUxType import com.anytypeio.anytype.core_models.primitives.SpaceId import com.anytypeio.anytype.core_models.primitives.TypeKey import com.anytypeio.anytype.domain.library.StoreSearchParams @@ -198,7 +199,11 @@ object ObjectSearchConstants { //endregion //region ADD OBJECT TO RELATION VALUE - fun filterAddObjectToRelation(space: Id, targetTypes: List) = buildList { + fun filterAddObjectToRelation( + space: Id, + targetTypes: List, + spaceUxType: SpaceUxType? = null + ) = buildList { addAll( listOf( DVFilter( @@ -238,7 +243,7 @@ object ObjectSearchConstants { DVFilter( relation = Relations.LAYOUT, condition = DVFilterCondition.IN, - value = SupportedLayouts.layouts.map { it.code.toDouble() } + value = SupportedLayouts.getLayouts(spaceUxType).map { it.code.toDouble() } ) ) } else { @@ -255,7 +260,8 @@ object ObjectSearchConstants { //region ADD OBJECT TO FILTER fun filterAddObjectToFilter( - limitObjectTypes: List + limitObjectTypes: List, + spaceUxType: SpaceUxType? = null ) = buildList { add( DVFilter( @@ -292,13 +298,12 @@ object ObjectSearchConstants { value = ObjectTypeUniqueKeys.TEMPLATE ) ) - // TODO check these filters if (limitObjectTypes.isEmpty()) { add( DVFilter( relation = Relations.LAYOUT, condition = DVFilterCondition.IN, - value = SupportedLayouts.layouts.map { it.code.toDouble() } + value = SupportedLayouts.getLayouts(spaceUxType).map { it.code.toDouble() } ) ) } else { 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 b7cade4b79..2794eaa1e1 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 @@ -22,6 +22,7 @@ import com.anytypeio.anytype.core_models.Payload import com.anytypeio.anytype.core_models.RelationFormat import com.anytypeio.anytype.core_models.Relations import com.anytypeio.anytype.core_models.SupportedLayouts +import com.anytypeio.anytype.core_models.SupportedLayouts.getCreateObjectLayouts import com.anytypeio.anytype.core_models.TimeInMillis import com.anytypeio.anytype.core_models.isDataView import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions @@ -2388,8 +2389,13 @@ class ObjectSetViewModel( } private suspend fun fetchAndProcessObjectTypes(selectedType: Id, widgetState: TypeTemplatesWidgetUI.Data) { + // Get space UX type for context-aware filtering + val spaceView = spaceViews.get(vmParams.space) + val spaceUxType = spaceView?.spaceUxType + val createLayouts = getCreateObjectLayouts(spaceUxType) + val filters = ObjectSearchConstants.filterTypes( - recommendedLayouts = SupportedLayouts.createObjectLayouts + recommendedLayouts = createLayouts ) val params = GetObjectTypes.Params( space = vmParams.space, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModel.kt index 66067eafe6..a62507d083 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModel.kt @@ -24,6 +24,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfRelations import com.anytypeio.anytype.domain.objects.options.GetOptions +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects import com.anytypeio.anytype.domain.workspace.SpaceManager @@ -75,7 +76,8 @@ open class FilterViewModel( private val analytics: Analytics, private val getOptions: GetOptions, private val spaceManager: SpaceManager, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val spaceViews: SpaceViewSubscriptionContainer ) : ViewModel() { val commands = MutableSharedFlow() @@ -394,13 +396,16 @@ open class FilterViewModel( limitObjectTypes: List = emptyList() ) { viewModelScope.launch { + val spaceId = SpaceId(spaceManager.get()) + val spaceUxType = spaceViews.get(spaceId)?.spaceUxType searchObjects( SearchObjects.Params( // TODO DROID-2916 Provide space id to vm params - space = SpaceId(spaceManager.get()), + space = spaceId, sorts = ObjectSearchConstants.sortAddObjectToFilter, filters = ObjectSearchConstants.filterAddObjectToFilter( - limitObjectTypes = limitObjectTypes + limitObjectTypes = limitObjectTypes, + spaceUxType = spaceUxType ), fulltext = SearchObjects.EMPTY_TEXT, offset = SearchObjects.INIT_OFFSET, @@ -948,7 +953,8 @@ open class FilterViewModel( private val getOptions: GetOptions, private val analytics: Analytics, private val spaceManager: SpaceManager, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val spaceViews: SpaceViewSubscriptionContainer ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T { @@ -964,7 +970,8 @@ open class FilterViewModel( getOptions = getOptions, analytics = analytics, spaceManager = spaceManager, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) as T } } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/Widget.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/Widget.kt index 033143ed2e..8120a1b4c3 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/Widget.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/Widget.kt @@ -11,6 +11,7 @@ import com.anytypeio.anytype.core_models.Relations import com.anytypeio.anytype.core_models.Struct import com.anytypeio.anytype.core_models.SupportedLayouts import com.anytypeio.anytype.core_models.SupportedLayouts.createObjectLayouts +import com.anytypeio.anytype.core_models.SupportedLayouts.getSystemLayouts import com.anytypeio.anytype.core_models.ext.asMap import com.anytypeio.anytype.core_models.multiplayer.SpaceUxType import com.anytypeio.anytype.presentation.objects.canCreateObjectOfType @@ -508,11 +509,12 @@ private suspend fun buildTypeSection( val sectionStateDesc = if (isObjectTypeSectionCollapsed) "collapsed" else "expanded" if (!isObjectTypeSectionCollapsed) { + val spaceUxType = if (isChatSpace) SpaceUxType.CHAT else null val types = mapSpaceTypesToWidgets( isOwnerOrEditor = params.isOwnerOrEditor, config = state.config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = isChatSpace + spaceUxType = spaceUxType ) addAll(types) Timber.d("ObjectType section: $sectionStateDesc, widgets added: ${types.size}") @@ -541,13 +543,21 @@ internal suspend fun mapSpaceTypesToWidgets( isOwnerOrEditor: Boolean, config: Config, storeOfObjectTypes: StoreOfObjectTypes, - isChatSpace: Boolean + spaceUxType: SpaceUxType? ): List { val allTypes = storeOfObjectTypes.getAll() + + // Get system layouts based on space context + val systemLayoutsForSpace = getSystemLayouts(spaceUxType) + val excludedLayouts = systemLayoutsForSpace + SupportedLayouts.dateLayouts + listOf( + ObjectType.Layout.OBJECT_TYPE, + ObjectType.Layout.PARTICIPANT + ) + val filteredObjectTypes = allTypes .mapNotNull { objectType -> if (!objectType.isValid || - SupportedLayouts.excludedSpaceTypeLayouts.contains(objectType.recommendedLayout) || + excludedLayouts.contains(objectType.recommendedLayout) || objectType.isArchived == true || objectType.isDeleted == true || objectType.uniqueKey == ObjectTypeIds.TEMPLATE @@ -561,6 +571,7 @@ internal suspend fun mapSpaceTypesToWidgets( Timber.d("Refreshing system types, isOwnerOrEditor = $isOwnerOrEditor, allTypes = ${allTypes.size}, types = ${filteredObjectTypes.size}") // Define custom sort order based on uniqueKey + val isChatSpace = spaceUxType == SpaceUxType.CHAT val customUniqueKeyOrder = if (!isChatSpace) { listOf( ObjectTypeIds.PAGE, diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/linking/LinkToObjectOrWebViewModelTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/linking/LinkToObjectOrWebViewModelTest.kt index d0b9facdc2..cbb9348703 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/linking/LinkToObjectOrWebViewModelTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/linking/LinkToObjectOrWebViewModelTest.kt @@ -10,6 +10,7 @@ import com.anytypeio.anytype.core_utils.tools.UrlValidator import com.anytypeio.anytype.domain.base.Either import com.anytypeio.anytype.domain.config.Gateway import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.primitives.FieldParser @@ -306,6 +307,9 @@ open class LinkToObjectOrWebViewModelTest { @Mock lateinit var fieldParser: FieldParser + @Mock + lateinit var spaceViews: SpaceViewSubscriptionContainer + private fun givenViewModel() = LinkToObjectOrWebViewModel( searchObjects = searchObjects, analytics = analytics, @@ -315,7 +319,8 @@ open class LinkToObjectOrWebViewModelTest { storeOfObjectTypes = storeOfObjectTypes, analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, vmParams = vmParams, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) fun stubSpaceManager() { diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModelInputFieldValueCreateTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModelInputFieldValueCreateTest.kt index 4b7f556a98..13e11c6b2a 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModelInputFieldValueCreateTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModelInputFieldValueCreateTest.kt @@ -16,6 +16,7 @@ import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations import com.anytypeio.anytype.domain.objects.ObjectStore import com.anytypeio.anytype.domain.objects.StoreOfRelations +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.options.GetOptions import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects @@ -70,6 +71,9 @@ class FilterViewModelInputFieldValueCreateTest { @Mock lateinit var fieldParser: FieldParser + @Mock + lateinit var spaceViews: SpaceViewSubscriptionContainer + private lateinit var viewModel: FilterViewModel private lateinit var urlBuilder: UrlBuilder private val root = MockDataFactory.randomUuid() @@ -196,7 +200,8 @@ class FilterViewModelInputFieldValueCreateTest { objectSetDatabase = db, getOptions = getOptions, spaceManager = spaceManager, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModelInputFieldValueModifyTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModelInputFieldValueModifyTest.kt index 55e9d11fb7..1792453980 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModelInputFieldValueModifyTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/filter/FilterViewModelInputFieldValueModifyTest.kt @@ -17,6 +17,7 @@ import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations import com.anytypeio.anytype.domain.objects.ObjectStore import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.objects.StoreOfRelations +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.objects.options.GetOptions import com.anytypeio.anytype.domain.primitives.FieldParser import com.anytypeio.anytype.domain.search.SearchObjects @@ -72,6 +73,9 @@ class FilterViewModelInputFieldValueModifyTest { @Mock lateinit var fieldParser: FieldParser + @Mock + lateinit var spaceViews: SpaceViewSubscriptionContainer + private lateinit var viewModel: FilterViewModel private lateinit var urlBuilder: UrlBuilder private val root = MockDataFactory.randomUuid() @@ -203,7 +207,8 @@ class FilterViewModelInputFieldValueModifyTest { objectSetDatabase = db, getOptions = getOptions, spaceManager = spaceManager, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViews = spaceViews ) } diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/main/ObjectSetNavigationTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/main/ObjectSetNavigationTest.kt index fa75519ead..f1020ec848 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/main/ObjectSetNavigationTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/sets/main/ObjectSetNavigationTest.kt @@ -141,7 +141,7 @@ class ObjectSetNavigationTest : ObjectSetViewModelTestSetup() { mapOf( Relations.ID to targetObjectId, Relations.SPACE_ID to mockObjectSet.spaceId, - Relations.LAYOUT to SupportedLayouts.layouts.random().code.toDouble() + Relations.LAYOUT to SupportedLayouts.getLayouts(null).random().code.toDouble() ) ) diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/widgets/WidgetTypeSortingTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/widgets/WidgetTypeSortingTest.kt index 8728fbf559..7126836934 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/widgets/WidgetTypeSortingTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/widgets/WidgetTypeSortingTest.kt @@ -4,6 +4,7 @@ import com.anytypeio.anytype.core_models.Config import com.anytypeio.anytype.core_models.ObjectTypeIds import com.anytypeio.anytype.core_models.StubObjectType import com.anytypeio.anytype.core_models.StubConfig +import com.anytypeio.anytype.core_models.multiplayer.SpaceUxType import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals @@ -57,7 +58,7 @@ class WidgetTypeSortingTest { isOwnerOrEditor = true, config = config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = false + spaceUxType = null ) // Then: Should be sorted by orderId ascending @@ -96,7 +97,7 @@ class WidgetTypeSortingTest { isOwnerOrEditor = true, config = config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = false + spaceUxType = null ) // Then: Type with orderId should come first @@ -140,7 +141,7 @@ class WidgetTypeSortingTest { isOwnerOrEditor = true, config = config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = false + spaceUxType = null ) // Then: Should follow custom order: Page, Note, Task, Collection @@ -181,7 +182,7 @@ class WidgetTypeSortingTest { isOwnerOrEditor = true, config = config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = true + spaceUxType = SpaceUxType.CHAT ) // Then: Should follow chat order: Image, Bookmark, Page @@ -220,7 +221,7 @@ class WidgetTypeSortingTest { isOwnerOrEditor = true, config = config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = false + spaceUxType = null ) // Then: Should be alphabetically sorted by name @@ -253,7 +254,7 @@ class WidgetTypeSortingTest { isOwnerOrEditor = true, config = config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = false + spaceUxType = null ) // Then: Should be sorted alphabetically @@ -314,7 +315,7 @@ class WidgetTypeSortingTest { isOwnerOrEditor = true, config = config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = false + spaceUxType = null ) // Then: Should be sorted by: @@ -363,7 +364,7 @@ class WidgetTypeSortingTest { isOwnerOrEditor = true, config = config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = false + spaceUxType = null ) // Then: Only valid type should be returned @@ -381,7 +382,7 @@ class WidgetTypeSortingTest { isOwnerOrEditor = true, config = config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = false + spaceUxType = null ) // Then: Should return empty list @@ -417,7 +418,7 @@ class WidgetTypeSortingTest { isOwnerOrEditor = true, config = config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = false + spaceUxType = null ) // Then: Should be sorted case-insensitively @@ -450,7 +451,7 @@ class WidgetTypeSortingTest { isOwnerOrEditor = true, config = config, storeOfObjectTypes = storeOfObjectTypes, - isChatSpace = false + spaceUxType = null ) // Then: Should maintain stable order