diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/AllContentDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/AllContentDI.kt index 97bb6225b4..6b2464cc2d 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/AllContentDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/AllContentDI.kt @@ -15,6 +15,7 @@ import com.anytypeio.anytype.domain.launch.GetDefaultObjectType import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer import com.anytypeio.anytype.domain.misc.LocaleProvider import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider import com.anytypeio.anytype.domain.`object`.SetObjectDetails import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes @@ -180,4 +181,5 @@ interface AllContentDependencies : ComponentDependencies { fun localeProvider(): LocaleProvider fun spaceManager(): SpaceManager fun config(): ConfigStorage + fun userPermissionProvider(): UserPermissionProvider } \ No newline at end of file diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/foundation/DismissBackground.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/foundation/DismissBackground.kt index e6ffa7c8c4..cb79b176e8 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/foundation/DismissBackground.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/foundation/DismissBackground.kt @@ -3,7 +3,6 @@ package com.anytypeio.anytype.core_ui.foundation import androidx.compose.animation.animateColorAsState import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.SwipeToDismissBoxState diff --git a/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/models/AllContentModels.kt b/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/models/AllContentModels.kt index de74fbaa0f..49d4bf546e 100644 --- a/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/models/AllContentModels.kt +++ b/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/models/AllContentModels.kt @@ -126,7 +126,8 @@ sealed class UiContentItem { val layout: ObjectType.Layout? = null, val icon: ObjectIcon = ObjectIcon.None, val lastModifiedDate: Long = 0L, - val createdDate: Long = 0L + val createdDate: Long = 0L, + val isPossibleToDelete: Boolean = false ) : UiContentItem() data class Type( @@ -199,15 +200,17 @@ fun Key?.mapRelationKeyToSort(): AllContentSort { fun List.toUiContentItems( space: SpaceId, urlBuilder: UrlBuilder, - objectTypes: List + objectTypes: List, + isOwnerOrEditor: Boolean ): List { - return map { it.toAllContentItem(space, urlBuilder, objectTypes) } + return map { it.toAllContentItem(space, urlBuilder, objectTypes, isOwnerOrEditor) } } fun ObjectWrapper.Basic.toAllContentItem( space: SpaceId, urlBuilder: UrlBuilder, - objectTypes: List + objectTypes: List, + isOwnerOrEditor: Boolean ): UiContentItem.Item { val obj = this val typeUrl = obj.getProperType() @@ -233,18 +236,21 @@ fun ObjectWrapper.Basic.toAllContentItem( builder = urlBuilder ), lastModifiedDate = DateParser.parse(obj.getValue(Relations.LAST_MODIFIED_DATE)) ?: 0L, - createdDate = DateParser.parse(obj.getValue(Relations.CREATED_DATE)) ?: 0L + createdDate = DateParser.parse(obj.getValue(Relations.CREATED_DATE)) ?: 0L, + isPossibleToDelete = isOwnerOrEditor ) } fun List.toUiContentTypes( - urlBuilder: UrlBuilder + urlBuilder: UrlBuilder, + isOwnerOrEditor: Boolean ): List { - return map { it.toAllContentType(urlBuilder) } + return map { it.toAllContentType(urlBuilder, isOwnerOrEditor) } } fun ObjectWrapper.Basic.toAllContentType( urlBuilder: UrlBuilder, + isOwnerOrEditor: Boolean ): UiContentItem.Type { val obj = this val layout = layout ?: ObjectType.Layout.BASIC @@ -258,16 +264,18 @@ fun ObjectWrapper.Basic.toAllContentType( ), sourceObject = obj.map[SOURCE_OBJECT]?.toString(), uniqueKey = obj.uniqueKey, - readOnly = obj.restrictions.contains(ObjectRestriction.DELETE), + readOnly = obj.restrictions.contains(ObjectRestriction.DELETE) || !isOwnerOrEditor, editable = !obj.restrictions.contains(ObjectRestriction.DETAILS) ) } -fun List.toUiContentRelations(): List { - return map { it.toAllContentRelation() } +fun List.toUiContentRelations(isOwnerOrEditor: Boolean): List { + return map { it.toAllContentRelation(isOwnerOrEditor) } } -fun ObjectWrapper.Basic.toAllContentRelation(): UiContentItem.Relation { +fun ObjectWrapper.Basic.toAllContentRelation( + isOwnerOrEditor: Boolean +): UiContentItem.Relation { val relation = ObjectWrapper.Relation(map) val obj = this return UiContentItem.Relation( @@ -275,7 +283,7 @@ fun ObjectWrapper.Basic.toAllContentRelation(): UiContentItem.Relation { name = obj.name.orEmpty(), format = relation.format, sourceObject = map[SOURCE_OBJECT]?.toString(), - readOnly = obj.restrictions.contains(ObjectRestriction.DELETE), + readOnly = obj.restrictions.contains(ObjectRestriction.DELETE) || !isOwnerOrEditor, editable = !obj.restrictions.contains(ObjectRestriction.DETAILS) ) } diff --git a/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/presentation/AllContentViewModel.kt b/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/presentation/AllContentViewModel.kt index afcbc4bd66..cb70263ac1 100644 --- a/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/presentation/AllContentViewModel.kt +++ b/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/presentation/AllContentViewModel.kt @@ -17,6 +17,7 @@ import com.anytypeio.anytype.domain.base.fold import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer import com.anytypeio.anytype.domain.misc.LocaleProvider import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider import com.anytypeio.anytype.domain.`object`.SetObjectDetails import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes @@ -75,6 +76,7 @@ import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.take import kotlinx.coroutines.launch import timber.log.Timber @@ -100,7 +102,8 @@ class AllContentViewModel( private val createObject: CreateObject, private val setObjectListIsArchived: SetObjectListIsArchived, private val setObjectDetails: SetObjectDetails, - private val removeObjectsFromWorkspace: RemoveObjectsFromWorkspace + private val removeObjectsFromWorkspace: RemoveObjectsFromWorkspace, + private val userPermissionProvider: UserPermissionProvider ) : ViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate { private val searchResultIds = MutableStateFlow>(emptyList()) @@ -135,11 +138,24 @@ class AllContentViewModel( private var shouldScrollToTopItems = false + private val permission = MutableStateFlow(userPermissionProvider.get(vmParams.spaceId)) + init { Timber.d("AllContentViewModel init, spaceId:[${vmParams.spaceId.id}]") setupInitialStateParams() setupSearchStateFlow() setupMenuFlow() + proceedWithObservingPermissions() + } + + private fun proceedWithObservingPermissions() { + viewModelScope.launch { + userPermissionProvider + .observe(space = vmParams.spaceId) + .collect { + permission.value = it + } + } } private fun setupInitialStateParams() { @@ -263,13 +279,16 @@ class AllContentViewModel( return when (activeTab) { AllContentTab.TYPES -> { val items = objectWrappers.toUiContentTypes( - urlBuilder = urlBuilder + urlBuilder = urlBuilder, + isOwnerOrEditor = permission.value?.isOwnerOrEditor() == true ) items } AllContentTab.RELATIONS -> { - val items = objectWrappers.toUiContentRelations() + val items = objectWrappers.toUiContentRelations( + isOwnerOrEditor = permission.value?.isOwnerOrEditor() == true + ) items } @@ -277,7 +296,8 @@ class AllContentViewModel( val items = objectWrappers.toUiContentItems( space = vmParams.spaceId, urlBuilder = urlBuilder, - objectTypes = storeOfObjectTypes.getAll() + objectTypes = storeOfObjectTypes.getAll(), + isOwnerOrEditor = permission.value?.isOwnerOrEditor() == true ) val result = when (activeSort) { is AllContentSort.ByDateCreated -> { diff --git a/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/presentation/AllContentViewModelFactory.kt b/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/presentation/AllContentViewModelFactory.kt index d1235918c9..98ea554e30 100644 --- a/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/presentation/AllContentViewModelFactory.kt +++ b/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/presentation/AllContentViewModelFactory.kt @@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.all_content.UpdateAllContentState import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer import com.anytypeio.anytype.domain.misc.LocaleProvider import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider import com.anytypeio.anytype.domain.`object`.SetObjectDetails import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes @@ -33,6 +34,7 @@ class AllContentViewModelFactory @Inject constructor( private val setObjectListIsArchived: SetObjectListIsArchived, private val setObjectDetails: SetObjectDetails, private val removeObjectsFromWorkspace: RemoveObjectsFromWorkspace, + private val userPermissionProvider: UserPermissionProvider ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = @@ -51,5 +53,6 @@ class AllContentViewModelFactory @Inject constructor( setObjectListIsArchived = setObjectListIsArchived, setObjectDetails = setObjectDetails, removeObjectsFromWorkspace = removeObjectsFromWorkspace, + userPermissionProvider = userPermissionProvider ) as T } \ No newline at end of file diff --git a/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/ui/AllContentScreen.kt b/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/ui/AllContentScreen.kt index d9d39e94e7..c99d82e3ee 100644 --- a/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/ui/AllContentScreen.kt +++ b/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/ui/AllContentScreen.kt @@ -793,6 +793,7 @@ fun SwipeToDismissListItems( SwipeToDismissBox( modifier = modifier, state = dismissState, + enableDismissFromEndToStart = item.isPossibleToDelete, enableDismissFromStartToEnd = false, backgroundContent = { DismissBackground(