mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3409 Primitives | Reset layout conflict (#2217)
This commit is contained in:
parent
7bec1556cb
commit
eb0f7e16a9
25 changed files with 405 additions and 99 deletions
|
@ -270,6 +270,7 @@ import com.anytypeio.anytype.presentation.navigation.leftButtonClickAnalytics
|
|||
import com.anytypeio.anytype.presentation.objects.getCreateObjectParams
|
||||
import com.anytypeio.anytype.presentation.objects.getObjectTypeViewsForSBPage
|
||||
import com.anytypeio.anytype.presentation.objects.getProperType
|
||||
import com.anytypeio.anytype.presentation.objects.hasLayoutConflict
|
||||
import com.anytypeio.anytype.presentation.objects.isTemplatesAllowed
|
||||
import com.anytypeio.anytype.presentation.objects.toViews
|
||||
import com.anytypeio.anytype.presentation.relations.ObjectRelationView
|
||||
|
@ -837,24 +838,13 @@ class EditorViewModel(
|
|||
newBlocks: List<BlockView>
|
||||
) {
|
||||
|
||||
if (currentObject == null) {
|
||||
orchestrator.stores.hasLayoutOrRelationConflict.update(false)
|
||||
return
|
||||
}
|
||||
|
||||
val featuredBlock = newBlocks.firstOrNull { it is BlockView.FeaturedRelation }
|
||||
val hasFeaturedPropertiesConflict =
|
||||
(featuredBlock as? BlockView.FeaturedRelation)?.hasFeaturePropertiesConflict == true
|
||||
val currentObjectType = storeOfObjectTypes.getTypeOfObject(currentObject)
|
||||
|
||||
val objectLayout = currentObject.layout
|
||||
val hasObjectLayoutConflict = objectLayout != null
|
||||
&& objectLayout != currentObjectType?.recommendedLayout
|
||||
|
||||
orchestrator.stores.hasLayoutOrRelationConflict.update(
|
||||
hasObjectLayoutConflict
|
||||
|| hasFeaturedPropertiesConflict
|
||||
val hasConflict = hasLayoutConflict(
|
||||
currentObject = currentObject,
|
||||
blocks = newBlocks,
|
||||
storeOfObjectTypes = storeOfObjectTypes
|
||||
)
|
||||
|
||||
orchestrator.stores.hasLayoutOrRelationConflict.update(hasConflict)
|
||||
}
|
||||
|
||||
private fun refreshTableToolbar() {
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.anytypeio.anytype.core_models.permissions.toObjectPermissionsForTypes
|
|||
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.getTypeOfObject
|
||||
import com.anytypeio.anytype.domain.primitives.FieldParser
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.extension.getObject
|
||||
|
@ -265,4 +266,28 @@ private suspend fun ObjectWrapper.Relation.toView(
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun hasLayoutConflict(
|
||||
blocks: List<BlockView>,
|
||||
currentObject: ObjectWrapper.Basic?,
|
||||
storeOfObjectTypes: StoreOfObjectTypes,
|
||||
): Boolean {
|
||||
|
||||
val featuredBlock = blocks.firstOrNull { it is BlockView.FeaturedRelation }
|
||||
|
||||
if (currentObject == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
val hasFeaturedPropertiesConflict =
|
||||
(featuredBlock as? BlockView.FeaturedRelation)?.hasFeaturePropertiesConflict == true
|
||||
val currentObjectType = storeOfObjectTypes.getTypeOfObject(currentObject)
|
||||
|
||||
val objectLayout = currentObject.layout
|
||||
val hasObjectLayoutConflict =
|
||||
objectLayout != null && currentObjectType != null && currentObjectType.isValid
|
||||
&& objectLayout != currentObjectType.recommendedLayout
|
||||
|
||||
return hasObjectLayoutConflict || hasFeaturedPropertiesConflict
|
||||
}
|
|
@ -11,7 +11,8 @@ interface ObjectMenuOptionsProvider {
|
|||
val hasRelations: Boolean,
|
||||
val hasDiagnosticsVisibility: Boolean,
|
||||
val hasHistory: Boolean,
|
||||
val hasDescriptionShow: Boolean
|
||||
val hasDescriptionShow: Boolean,
|
||||
val hasObjectLayoutConflict: Boolean
|
||||
) {
|
||||
companion object {
|
||||
val ALL = Options(
|
||||
|
@ -20,7 +21,8 @@ interface ObjectMenuOptionsProvider {
|
|||
hasRelations = true,
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasHistory = true,
|
||||
hasDescriptionShow = true
|
||||
hasDescriptionShow = true,
|
||||
hasObjectLayoutConflict = false
|
||||
)
|
||||
val NONE = Options(
|
||||
hasIcon = false,
|
||||
|
@ -28,7 +30,8 @@ interface ObjectMenuOptionsProvider {
|
|||
hasRelations = false,
|
||||
hasDiagnosticsVisibility = false,
|
||||
hasHistory = false,
|
||||
hasDescriptionShow = false
|
||||
hasDescriptionShow = false,
|
||||
hasObjectLayoutConflict = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,9 @@ package com.anytypeio.anytype.presentation.objects.menu
|
|||
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.SupportedLayouts
|
||||
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
|
||||
import com.anytypeio.anytype.core_models.ObjectViewDetails
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.SupportedLayouts
|
||||
import com.anytypeio.anytype.presentation.extension.getObject
|
||||
import com.anytypeio.anytype.presentation.objects.menu.ObjectMenuOptionsProvider.Options
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -16,7 +15,7 @@ import timber.log.Timber
|
|||
|
||||
class ObjectMenuOptionsProviderImpl(
|
||||
private val objectViewDetailsFlow: Flow<ObjectViewDetails>,
|
||||
private val restrictions: Flow<List<ObjectRestriction>>
|
||||
private val hasObjectLayoutConflict: Flow<Boolean>
|
||||
) : ObjectMenuOptionsProvider {
|
||||
|
||||
private fun observeLayout(ctx: Id): Flow<ObjectType.Layout?> = objectViewDetailsFlow
|
||||
|
@ -41,16 +40,20 @@ class ObjectMenuOptionsProviderImpl(
|
|||
return@map featuredRelations?.any { it == Relations.DESCRIPTION } == true
|
||||
}
|
||||
|
||||
private fun observeHasObjectLayoutConflict(): Flow<Boolean> = hasObjectLayoutConflict
|
||||
|
||||
override fun provide(ctx: Id, isLocked: Boolean, isReadOnly: Boolean): Flow<Options> {
|
||||
return combine(
|
||||
observeLayout(ctx),
|
||||
observeFeatureFieldsContainsDescription(ctx)
|
||||
) { layout, featuredContainsDescription ->
|
||||
observeFeatureFieldsContainsDescription(ctx),
|
||||
observeHasObjectLayoutConflict()
|
||||
) { layout, featuredContainsDescription, hasObjectLayoutConflict ->
|
||||
createOptions(
|
||||
layout = layout,
|
||||
isLocked = isLocked,
|
||||
isReadOnly = isReadOnly,
|
||||
featuredContainsDescription = featuredContainsDescription
|
||||
featuredContainsDescription = featuredContainsDescription,
|
||||
hasObjectLayoutConflict = hasObjectLayoutConflict
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +62,8 @@ class ObjectMenuOptionsProviderImpl(
|
|||
layout: ObjectType.Layout?,
|
||||
isLocked: Boolean,
|
||||
isReadOnly: Boolean,
|
||||
featuredContainsDescription: Boolean
|
||||
featuredContainsDescription: Boolean,
|
||||
hasObjectLayoutConflict: Boolean
|
||||
): Options {
|
||||
val hasIcon = !isLocked && !isReadOnly
|
||||
val hasCover = !isLocked && !isReadOnly
|
||||
|
@ -71,7 +75,8 @@ class ObjectMenuOptionsProviderImpl(
|
|||
hasDiagnosticsVisibility = true,
|
||||
hasHistory = false,
|
||||
hasRelations = false,
|
||||
hasDescriptionShow = !featuredContainsDescription
|
||||
hasDescriptionShow = !featuredContainsDescription,
|
||||
hasObjectLayoutConflict = hasObjectLayoutConflict
|
||||
)
|
||||
|
||||
in SupportedLayouts.systemLayouts -> Options.NONE
|
||||
|
@ -81,7 +86,8 @@ class ObjectMenuOptionsProviderImpl(
|
|||
hasCover = false,
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasHistory = false,
|
||||
hasDescriptionShow = !featuredContainsDescription
|
||||
hasDescriptionShow = !featuredContainsDescription,
|
||||
hasObjectLayoutConflict = hasObjectLayoutConflict
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -92,7 +98,8 @@ class ObjectMenuOptionsProviderImpl(
|
|||
hasCover = hasCover,
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasHistory = !isLocked && !isReadOnly,
|
||||
hasDescriptionShow = !featuredContainsDescription
|
||||
hasDescriptionShow = !featuredContainsDescription,
|
||||
hasObjectLayoutConflict = hasObjectLayoutConflict
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -103,7 +110,8 @@ class ObjectMenuOptionsProviderImpl(
|
|||
hasCover = hasCover,
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasHistory = !isLocked && !isReadOnly,
|
||||
hasDescriptionShow = !featuredContainsDescription
|
||||
hasDescriptionShow = !featuredContainsDescription,
|
||||
hasObjectLayoutConflict = hasObjectLayoutConflict
|
||||
)
|
||||
|
||||
ObjectType.Layout.TODO -> Options(
|
||||
|
@ -112,7 +120,8 @@ class ObjectMenuOptionsProviderImpl(
|
|||
hasRelations = true,
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasHistory = !isLocked && !isReadOnly,
|
||||
hasDescriptionShow = !featuredContainsDescription
|
||||
hasDescriptionShow = !featuredContainsDescription,
|
||||
hasObjectLayoutConflict = hasObjectLayoutConflict
|
||||
)
|
||||
|
||||
ObjectType.Layout.NOTE -> Options(
|
||||
|
@ -121,17 +130,20 @@ class ObjectMenuOptionsProviderImpl(
|
|||
hasRelations = true,
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasHistory = !isLocked && !isReadOnly,
|
||||
hasDescriptionShow = !featuredContainsDescription
|
||||
hasDescriptionShow = !featuredContainsDescription,
|
||||
hasObjectLayoutConflict = hasObjectLayoutConflict
|
||||
)
|
||||
|
||||
else -> Options.NONE.copy(
|
||||
hasDiagnosticsVisibility = true
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasObjectLayoutConflict = hasObjectLayoutConflict
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// unknown layout
|
||||
Options.NONE.copy(
|
||||
hasDiagnosticsVisibility = true
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasObjectLayoutConflict = hasObjectLayoutConflict
|
||||
)
|
||||
}
|
||||
return options
|
||||
|
|
|
@ -40,6 +40,7 @@ import com.anytypeio.anytype.domain.multiplayer.GetSpaceInviteLink
|
|||
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
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.extension.getObject
|
||||
import com.anytypeio.anytype.presentation.extension.getTypeObject
|
||||
|
@ -80,7 +81,8 @@ class ObjectMenuViewModel(
|
|||
private val getSpaceInviteLink: GetSpaceInviteLink,
|
||||
private val addToFeaturedRelations: AddToFeaturedRelations,
|
||||
private val removeFromFeaturedRelations: RemoveFromFeaturedRelations,
|
||||
private val userPermissionProvider: UserPermissionProvider
|
||||
private val userPermissionProvider: UserPermissionProvider,
|
||||
private val deleteRelationFromObject: DeleteRelationFromObject
|
||||
) : ObjectMenuViewModelBase(
|
||||
setObjectIsArchived = setObjectIsArchived,
|
||||
addBackLinkToObject = addBackLinkToObject,
|
||||
|
@ -521,6 +523,79 @@ class ObjectMenuViewModel(
|
|||
return doc.fields.isLocked ?: false
|
||||
}
|
||||
|
||||
override fun onResetToDefaultLayout(
|
||||
ctx: Id,
|
||||
space: Id
|
||||
) {
|
||||
|
||||
showLayoutConflictScreen.value = false
|
||||
|
||||
val currentObject = storage.details.current().getObject(ctx)
|
||||
val featuredRelations = currentObject?.featuredRelations ?: emptyList()
|
||||
|
||||
viewModelScope.launch {
|
||||
val params = DeleteRelationFromObject.Params(
|
||||
ctx = ctx,
|
||||
relations = listOf(
|
||||
Relations.LEGACY_LAYOUT,
|
||||
Relations.LAYOUT_ALIGN
|
||||
)
|
||||
)
|
||||
deleteRelationFromObject.async(
|
||||
params = params
|
||||
).fold(
|
||||
onSuccess = { payload ->
|
||||
dispatcher.send(payload)
|
||||
},
|
||||
onFailure = {
|
||||
Timber.e(it, "Error while resetting layout to default")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
viewModelScope.launch{
|
||||
|
||||
val rootBlockFields = storage.document.get().find { it.id == ctx }?.fields
|
||||
|
||||
val params = UpdateFields.Params(
|
||||
context = ctx,
|
||||
fields = listOf(Pair(ctx, rootBlockFields?.copy(
|
||||
map = rootBlockFields.map.toMutableMap().apply {
|
||||
put("width", null)
|
||||
}
|
||||
) ?: Block.Fields.empty()))
|
||||
)
|
||||
updateFields(params = params
|
||||
).process(
|
||||
success = { payload ->
|
||||
dispatcher.send(payload)
|
||||
},
|
||||
failure = {
|
||||
Timber.e(it, "Error while resetting layout to default")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
val params = SetObjectDetails.Params(
|
||||
ctx = ctx,
|
||||
details = mapOf(
|
||||
Relations.FEATURED_RELATIONS to featuredRelations.filter {
|
||||
it == Relations.DESCRIPTION
|
||||
}.map { it }
|
||||
)
|
||||
)
|
||||
setObjectDetails.async(params).fold(
|
||||
onSuccess = {
|
||||
dispatcher.send(it)
|
||||
},
|
||||
onFailure = {
|
||||
Timber.e(it, "Error while resetting layout to default")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class Factory @Inject constructor(
|
||||
private val duplicateObject: DuplicateObject,
|
||||
|
@ -549,7 +624,8 @@ class ObjectMenuViewModel(
|
|||
private val spaceViewSubscriptionContainer: SpaceViewSubscriptionContainer,
|
||||
private val addToFeaturedRelations: AddToFeaturedRelations,
|
||||
private val removeFromFeaturedRelations: RemoveFromFeaturedRelations,
|
||||
private val userPermissionProvider: UserPermissionProvider
|
||||
private val userPermissionProvider: UserPermissionProvider,
|
||||
private val deleteRelationFromObject: DeleteRelationFromObject
|
||||
) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return ObjectMenuViewModel(
|
||||
|
@ -579,7 +655,8 @@ class ObjectMenuViewModel(
|
|||
spaceViewSubscriptionContainer = spaceViewSubscriptionContainer,
|
||||
addToFeaturedRelations = addToFeaturedRelations,
|
||||
removeFromFeaturedRelations = removeFromFeaturedRelations,
|
||||
userPermissionProvider = userPermissionProvider
|
||||
userPermissionProvider = userPermissionProvider,
|
||||
deleteRelationFromObject = deleteRelationFromObject
|
||||
) as T
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,8 @@ abstract class ObjectMenuViewModelBase(
|
|||
hasRelations = false,
|
||||
hasDiagnosticsVisibility = false,
|
||||
hasHistory = false,
|
||||
hasDescriptionShow = false
|
||||
hasDescriptionShow = false,
|
||||
hasObjectLayoutConflict = false
|
||||
)
|
||||
)
|
||||
val options: Flow<ObjectMenuOptionsProvider.Options> = _options
|
||||
|
@ -95,6 +96,7 @@ abstract class ObjectMenuViewModelBase(
|
|||
abstract fun onCoverClicked(ctx: Id, space: Id)
|
||||
abstract fun onDescriptionClicked(ctx: Id, space: Id)
|
||||
abstract fun onRelationsClicked()
|
||||
abstract fun onResetToDefaultLayout(ctx: Id, space: Id)
|
||||
|
||||
val showLayoutConflictScreen = MutableStateFlow(false)
|
||||
|
||||
|
|
|
@ -4,11 +4,14 @@ import androidx.lifecycle.ViewModel
|
|||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.block.interactor.UpdateFields
|
||||
import com.anytypeio.anytype.domain.collections.AddObjectToCollection
|
||||
import com.anytypeio.anytype.domain.dashboard.interactor.SetObjectListIsFavorite
|
||||
import com.anytypeio.anytype.domain.misc.DeepLinkResolver
|
||||
|
@ -17,10 +20,12 @@ import com.anytypeio.anytype.domain.multiplayer.GetSpaceInviteLink
|
|||
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.`object`.DuplicateObject
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
|
||||
import com.anytypeio.anytype.domain.page.AddBackLinkToObject
|
||||
import com.anytypeio.anytype.domain.primitives.FieldParser
|
||||
import com.anytypeio.anytype.domain.relations.AddToFeaturedRelations
|
||||
import com.anytypeio.anytype.domain.relations.DeleteRelationFromObject
|
||||
import com.anytypeio.anytype.domain.relations.RemoveFromFeaturedRelations
|
||||
import com.anytypeio.anytype.domain.widgets.CreateWidget
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
|
@ -62,7 +67,10 @@ class ObjectSetMenuViewModel(
|
|||
getSpaceInviteLink: GetSpaceInviteLink,
|
||||
private val addToFeaturedRelations: AddToFeaturedRelations,
|
||||
private val removeFromFeaturedRelations: RemoveFromFeaturedRelations,
|
||||
private val userPermissionProvider: UserPermissionProvider
|
||||
private val userPermissionProvider: UserPermissionProvider,
|
||||
private val deleteRelationFromObject: DeleteRelationFromObject,
|
||||
private val updateFields: UpdateFields,
|
||||
private val setObjectDetails: SetObjectDetails
|
||||
) : ObjectMenuViewModelBase(
|
||||
setObjectIsArchived = setObjectIsArchived,
|
||||
addBackLinkToObject = addBackLinkToObject,
|
||||
|
@ -113,7 +121,10 @@ class ObjectSetMenuViewModel(
|
|||
private val getSpaceInviteLink: GetSpaceInviteLink,
|
||||
private val addToFeaturedRelations: AddToFeaturedRelations,
|
||||
private val removeFromFeaturedRelations: RemoveFromFeaturedRelations,
|
||||
private val userPermissionProvider: UserPermissionProvider
|
||||
private val userPermissionProvider: UserPermissionProvider,
|
||||
private val deleteRelationFromObject: DeleteRelationFromObject,
|
||||
private val updateFields: UpdateFields,
|
||||
private val setObjectDetails: SetObjectDetails
|
||||
) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return ObjectSetMenuViewModel(
|
||||
|
@ -139,7 +150,10 @@ class ObjectSetMenuViewModel(
|
|||
getSpaceInviteLink = getSpaceInviteLink,
|
||||
addToFeaturedRelations = addToFeaturedRelations,
|
||||
removeFromFeaturedRelations = removeFromFeaturedRelations,
|
||||
userPermissionProvider = userPermissionProvider
|
||||
userPermissionProvider = userPermissionProvider,
|
||||
deleteRelationFromObject = deleteRelationFromObject,
|
||||
updateFields = updateFields,
|
||||
setObjectDetails = setObjectDetails
|
||||
) as T
|
||||
}
|
||||
}
|
||||
|
@ -308,4 +322,32 @@ class ObjectSetMenuViewModel(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResetToDefaultLayout(
|
||||
ctx: Id,
|
||||
space: Id
|
||||
) {
|
||||
showLayoutConflictScreen.value = false
|
||||
|
||||
val state = objectState.value.dataViewState() ?: return
|
||||
|
||||
val currentObject = state.details.getObject(ctx)
|
||||
val featuredRelations = currentObject?.featuredRelations ?: emptyList()
|
||||
|
||||
viewModelScope.launch {
|
||||
val featuredWithoutConflict = featuredRelations.filter { key -> key == Relations.DESCRIPTION }
|
||||
val params = SetObjectDetails.Params(
|
||||
ctx = ctx,
|
||||
details = mapOf(Relations.FEATURED_RELATIONS to featuredWithoutConflict)
|
||||
)
|
||||
setObjectDetails.async(params).fold(
|
||||
onSuccess = {
|
||||
dispatcher.send(it)
|
||||
},
|
||||
onFailure = {
|
||||
Timber.e(it, "Error while resetting layout to default")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -475,14 +475,13 @@ class RelationListViewModel(
|
|||
|
||||
fun onDeleteClicked(ctx: Id, view: ObjectRelationView) {
|
||||
viewModelScope.launch {
|
||||
deleteRelationFromObject(
|
||||
DeleteRelationFromObject.Params(
|
||||
ctx = ctx,
|
||||
relation = view.key
|
||||
)
|
||||
).process(
|
||||
failure = { Timber.e(it, "Error while deleting relation") },
|
||||
success = {
|
||||
val params = DeleteRelationFromObject.Params(
|
||||
ctx = ctx,
|
||||
relations = listOf(view.key)
|
||||
)
|
||||
deleteRelationFromObject.async(params).fold(
|
||||
onFailure = { Timber.e(it, "Error while deleting relation") },
|
||||
onSuccess = {
|
||||
dispatcher.send(it)
|
||||
analytics.sendAnalyticsRelationEvent(
|
||||
eventName = EventsDictionary.relationDelete,
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.anytypeio.anytype.analytics.props.Props.Companion.OBJ_TYPE_CUSTOM
|
|||
import com.anytypeio.anytype.core_models.DVViewer
|
||||
import com.anytypeio.anytype.core_models.DVViewerCardSize
|
||||
import com.anytypeio.anytype.core_models.DVViewerType
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
|
@ -80,6 +81,7 @@ import com.anytypeio.anytype.presentation.extension.getObject
|
|||
import com.anytypeio.anytype.presentation.navigation.NavPanelState
|
||||
import com.anytypeio.anytype.presentation.navigation.leftButtonClickAnalytics
|
||||
import com.anytypeio.anytype.presentation.objects.getCreateObjectParams
|
||||
import com.anytypeio.anytype.presentation.objects.hasLayoutConflict
|
||||
import com.anytypeio.anytype.presentation.objects.isCreateObjectAllowed
|
||||
import com.anytypeio.anytype.presentation.objects.isTemplatesAllowed
|
||||
import com.anytypeio.anytype.presentation.objects.toFeaturedPropertiesViews
|
||||
|
@ -245,7 +247,7 @@ class ObjectSetViewModel(
|
|||
state to permission
|
||||
}
|
||||
.collectLatest { (state, permission) ->
|
||||
featured.value = toFeaturedPropertiesViews(
|
||||
val featuredBlock = toFeaturedPropertiesViews(
|
||||
objectId = vmParams.ctx,
|
||||
urlBuilder = urlBuilder,
|
||||
fieldParser = fieldParser,
|
||||
|
@ -255,12 +257,14 @@ class ObjectSetViewModel(
|
|||
details = state.details,
|
||||
participantCanEdit = permission?.isOwnerOrEditor() == true
|
||||
)
|
||||
featured.value = featuredBlock
|
||||
_header.value = state.header(
|
||||
ctx = vmParams.ctx,
|
||||
urlBuilder = urlBuilder,
|
||||
coverImageHashProvider = coverImageHashProvider,
|
||||
isReadOnlyMode = permission == SpaceMemberPermissions.NO_PERMISSIONS || permission == SpaceMemberPermissions.READER
|
||||
)
|
||||
updateLayoutConflictState(featuredBlock = featuredBlock)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,6 +422,33 @@ class ObjectSetViewModel(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun updateLayoutConflictState(
|
||||
featuredBlock: BlockView.FeaturedRelation?,
|
||||
) {
|
||||
val state = stateReducer.state.value.dataViewState() ?: return
|
||||
val objectWrapper = state.details.getObject(vmParams.ctx)
|
||||
|
||||
val blocks = featuredBlock?.let { listOf(it) } ?: emptyList()
|
||||
|
||||
val hasConflict = hasLayoutConflict(
|
||||
currentObject = objectWrapper,
|
||||
blocks = blocks,
|
||||
storeOfObjectTypes = storeOfObjectTypes
|
||||
)
|
||||
|
||||
dispatcher.send(
|
||||
Payload(
|
||||
context = vmParams.ctx,
|
||||
events = listOf(
|
||||
Event.Command.DataView.UpdateConflictState(
|
||||
context = vmParams.ctx,
|
||||
hasConflict = hasConflict
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun onStart(view: Id? = null) {
|
||||
Timber.d("onStart, ctx:[${vmParams.ctx}], space:[${vmParams.space}], view:[$view]")
|
||||
if (view != null) {
|
||||
|
|
|
@ -102,6 +102,9 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
is Command.AddBlock -> {
|
||||
handleAddBlock(state, event)
|
||||
}
|
||||
is Command.DataView.UpdateConflictState -> {
|
||||
handleUpdateConflictState(state, event)
|
||||
}
|
||||
|
||||
else -> {
|
||||
Timber.d("Ignoring event: $event")
|
||||
|
@ -551,6 +554,24 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
ObjectState.ErrorLayout -> state
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleUpdateConflictState(
|
||||
state: ObjectState,
|
||||
event: Command.DataView.UpdateConflictState
|
||||
): ObjectState {
|
||||
return when (state) {
|
||||
is ObjectState.DataView.Collection -> state.copy(
|
||||
hasObjectLayoutConflict = event.hasConflict
|
||||
)
|
||||
is ObjectState.DataView.Set -> state.copy(
|
||||
hasObjectLayoutConflict = event.hasConflict
|
||||
)
|
||||
is ObjectState.DataView.TypeSet -> state.copy(
|
||||
hasObjectLayoutConflict = event.hasConflict
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
private inline fun ObjectState.DataView.updateBlockContent(
|
||||
|
|
|
@ -26,12 +26,15 @@ sealed class ObjectState {
|
|||
abstract val dataViewBlock: Block
|
||||
abstract val viewers: List<DVViewer>
|
||||
|
||||
abstract val hasObjectLayoutConflict: Boolean
|
||||
|
||||
data class Set(
|
||||
override val root: Id,
|
||||
override val blocks: List<Block> = emptyList(),
|
||||
override val details: ObjectViewDetails = ObjectViewDetails.EMPTY,
|
||||
override val objectRestrictions: List<ObjectRestriction> = emptyList(),
|
||||
override val dataViewRestrictions: List<DataViewRestrictions> = emptyList(),
|
||||
override val hasObjectLayoutConflict: Boolean = false,
|
||||
) : DataView() {
|
||||
|
||||
override val isInitialized get() = blocks.any { it.content is DV }
|
||||
|
@ -46,6 +49,7 @@ sealed class ObjectState {
|
|||
override val details: ObjectViewDetails = ObjectViewDetails.EMPTY,
|
||||
override val objectRestrictions: List<ObjectRestriction> = emptyList(),
|
||||
override val dataViewRestrictions: List<DataViewRestrictions> = emptyList(),
|
||||
override val hasObjectLayoutConflict: Boolean = false,
|
||||
) : DataView() {
|
||||
|
||||
override val isInitialized get() = blocks.any { it.content is DV }
|
||||
|
@ -60,6 +64,7 @@ sealed class ObjectState {
|
|||
override val details: ObjectViewDetails = ObjectViewDetails.EMPTY,
|
||||
override val objectRestrictions: List<ObjectRestriction> = emptyList(),
|
||||
override val dataViewRestrictions: List<DataViewRestrictions> = emptyList(),
|
||||
override val hasObjectLayoutConflict: Boolean = false,
|
||||
) : DataView() {
|
||||
|
||||
override val isInitialized get() = blocks.any { it.content is DV }
|
||||
|
|
|
@ -16,8 +16,8 @@ class ObjectMenuOptionsProviderImplTest {
|
|||
|
||||
private val objectId: String = "objectId"
|
||||
private val details = MutableStateFlow<ObjectViewDetails>(ObjectViewDetails.EMPTY)
|
||||
private val restrictions = MutableStateFlow<List<ObjectRestriction>>(emptyList())
|
||||
private val provider = ObjectMenuOptionsProviderImpl(details, restrictions)
|
||||
private val hasObjectLayoutConflict = MutableStateFlow(false)
|
||||
private val provider = ObjectMenuOptionsProviderImpl(details, hasObjectLayoutConflict)
|
||||
|
||||
@Test
|
||||
fun `when layout note - options are layout, relations, history`() {
|
||||
|
@ -35,7 +35,8 @@ class ObjectMenuOptionsProviderImplTest {
|
|||
hasDescriptionShow = true,
|
||||
hasRelations = true,
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasHistory = true
|
||||
hasHistory = true,
|
||||
hasObjectLayoutConflict = false
|
||||
)
|
||||
|
||||
assertOptions(
|
||||
|
@ -59,7 +60,8 @@ class ObjectMenuOptionsProviderImplTest {
|
|||
hasRelations = true,
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasHistory = true,
|
||||
hasDescriptionShow = true
|
||||
hasDescriptionShow = true,
|
||||
hasObjectLayoutConflict = false
|
||||
)
|
||||
|
||||
assertOptions(
|
||||
|
@ -118,7 +120,8 @@ class ObjectMenuOptionsProviderImplTest {
|
|||
hasRelations = true,
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasHistory = false,
|
||||
hasDescriptionShow = true
|
||||
hasDescriptionShow = true,
|
||||
hasObjectLayoutConflict = false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -143,7 +146,8 @@ class ObjectMenuOptionsProviderImplTest {
|
|||
hasRelations = true,
|
||||
hasDiagnosticsVisibility = true,
|
||||
hasHistory = false,
|
||||
hasDescriptionShow = false
|
||||
hasDescriptionShow = false,
|
||||
hasObjectLayoutConflict = false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue