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
|
@ -25,6 +25,7 @@ import com.anytypeio.anytype.domain.page.CloseBlock
|
|||
import com.anytypeio.anytype.domain.page.OpenPage
|
||||
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.templates.CreateTemplateFromObject
|
||||
import com.anytypeio.anytype.domain.widgets.CreateWidget
|
||||
|
@ -49,11 +50,12 @@ import com.anytypeio.anytype.ui.sets.ObjectSetMenuFragment
|
|||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.Subcomponent
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
|
||||
@Subcomponent(modules = [ObjectMenuModuleBase::class, ObjectMenuModule::class])
|
||||
|
@ -128,7 +130,9 @@ object ObjectMenuModule {
|
|||
getSpaceInviteLink: GetSpaceInviteLink,
|
||||
addToFeaturedRelations: AddToFeaturedRelations,
|
||||
removeFromFeaturedRelations: RemoveFromFeaturedRelations,
|
||||
userPermissionProvider: UserPermissionProvider
|
||||
userPermissionProvider: UserPermissionProvider,
|
||||
deleteRelationFromObject: DeleteRelationFromObject,
|
||||
objectMenuOptionsProvider: ObjectMenuOptionsProvider
|
||||
): ObjectMenuViewModel.Factory = ObjectMenuViewModel.Factory(
|
||||
setObjectIsArchived = setObjectIsArchived,
|
||||
duplicateObject = duplicateObject,
|
||||
|
@ -140,7 +144,7 @@ object ObjectMenuModule {
|
|||
dispatcher = dispatcher,
|
||||
updateFields = updateFields,
|
||||
delegator = delegator,
|
||||
menuOptionsProvider = createMenuOptionsProvider(storage),
|
||||
menuOptionsProvider = objectMenuOptionsProvider,
|
||||
addObjectToCollection = addObjectToCollection,
|
||||
createTemplateFromObject = createTemplateFromObject,
|
||||
setObjectDetails = setObjectDetails,
|
||||
|
@ -156,7 +160,19 @@ object ObjectMenuModule {
|
|||
spaceViewSubscriptionContainer = spaceViewSubscriptionContainer,
|
||||
addToFeaturedRelations = addToFeaturedRelations,
|
||||
removeFromFeaturedRelations = removeFromFeaturedRelations,
|
||||
userPermissionProvider = userPermissionProvider
|
||||
userPermissionProvider = userPermissionProvider,
|
||||
deleteRelationFromObject = deleteRelationFromObject
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
fun provideDeleteRelationFromObject(
|
||||
repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): DeleteRelationFromObject = DeleteRelationFromObject(
|
||||
repo = repo,
|
||||
dispatchers = dispatchers
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
@ -170,11 +186,15 @@ object ObjectMenuModule {
|
|||
dispatchers
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerDialog
|
||||
@JvmStatic
|
||||
private fun createMenuOptionsProvider(storage: Editor.Storage): ObjectMenuOptionsProvider =
|
||||
fun provideMenuOptionsProvider(
|
||||
storage: Editor.Storage
|
||||
): ObjectMenuOptionsProvider =
|
||||
ObjectMenuOptionsProviderImpl(
|
||||
objectViewDetailsFlow = storage.details.stream(),
|
||||
restrictions = storage.objectRestrictions.stream()
|
||||
hasObjectLayoutConflict = storage.hasLayoutOrRelationConflict.stream()
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
@ -240,6 +260,13 @@ object ObjectMenuModule {
|
|||
@Module
|
||||
object ObjectSetMenuModule {
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
fun provideUpdateFieldsUseCase(
|
||||
repo: BlockRepository
|
||||
): UpdateFields = UpdateFields(repo)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
|
@ -250,6 +277,7 @@ object ObjectSetMenuModule {
|
|||
urlBuilder: UrlBuilder,
|
||||
analytics: Analytics,
|
||||
state: MutableStateFlow<ObjectState>,
|
||||
updateFields: UpdateFields,
|
||||
featureToggles: FeatureToggles,
|
||||
dispatcher: Dispatcher<Payload>,
|
||||
addObjectToCollection: AddObjectToCollection,
|
||||
|
@ -266,7 +294,10 @@ object ObjectSetMenuModule {
|
|||
spaceViewSubscriptionContainer: SpaceViewSubscriptionContainer,
|
||||
addToFeaturedRelations: AddToFeaturedRelations,
|
||||
removeFromFeaturedRelations: RemoveFromFeaturedRelations,
|
||||
userPermissionProvider: UserPermissionProvider
|
||||
userPermissionProvider: UserPermissionProvider,
|
||||
deleteRelationFromObject: DeleteRelationFromObject,
|
||||
setObjectDetails: SetObjectDetails,
|
||||
objectMenuOptionsProvider: ObjectMenuOptionsProvider
|
||||
): ObjectSetMenuViewModel.Factory = ObjectSetMenuViewModel.Factory(
|
||||
setObjectListIsArchived = setObjectIsArchived,
|
||||
addBackLinkToObject = addBackLinkToObject,
|
||||
|
@ -276,7 +307,7 @@ object ObjectSetMenuModule {
|
|||
analytics = analytics,
|
||||
objectState = state,
|
||||
dispatcher = dispatcher,
|
||||
menuOptionsProvider = createMenuOptionsProvider(state),
|
||||
menuOptionsProvider = objectMenuOptionsProvider,
|
||||
addObjectToCollection = addObjectToCollection,
|
||||
debugGoroutinesShareDownloader = debugGoroutinesShareDownloader,
|
||||
createWidget = createWidget,
|
||||
|
@ -290,7 +321,21 @@ object ObjectSetMenuModule {
|
|||
spaceViewSubscriptionContainer = spaceViewSubscriptionContainer,
|
||||
addToFeaturedRelations = addToFeaturedRelations,
|
||||
removeFromFeaturedRelations = removeFromFeaturedRelations,
|
||||
userPermissionProvider = userPermissionProvider
|
||||
userPermissionProvider = userPermissionProvider,
|
||||
deleteRelationFromObject = deleteRelationFromObject,
|
||||
updateFields = updateFields,
|
||||
setObjectDetails = setObjectDetails
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
fun provideDeleteRelationFromObject(
|
||||
repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): DeleteRelationFromObject = DeleteRelationFromObject(
|
||||
repo = repo,
|
||||
dispatchers = dispatchers
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
@ -345,22 +390,50 @@ object ObjectSetMenuModule {
|
|||
dispatchers: AppCoroutineDispatchers
|
||||
): SetObjectListIsFavorite = SetObjectListIsFavorite(repo = repo, dispatchers = dispatchers)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@JvmStatic
|
||||
private fun createMenuOptionsProvider(
|
||||
state: StateFlow<ObjectState>,
|
||||
@Provides
|
||||
@PerDialog
|
||||
fun provideMenuOptionsProvider(
|
||||
state: MutableStateFlow<ObjectState>,
|
||||
): ObjectMenuOptionsProvider {
|
||||
return when (val currentState = state.value) {
|
||||
is ObjectState.DataView -> ObjectMenuOptionsProviderImpl(
|
||||
objectViewDetailsFlow = state.map { currentState.details }.distinctUntilChanged(),
|
||||
restrictions = state.map { currentState.objectRestrictions }.distinctUntilChanged(),
|
||||
)
|
||||
else -> ObjectMenuOptionsProviderImpl(
|
||||
objectViewDetailsFlow = emptyFlow(),
|
||||
restrictions = emptyFlow(),
|
||||
)
|
||||
}
|
||||
val objectViewDetailsFlow = state
|
||||
.flatMapLatest { currentState ->
|
||||
if (currentState is ObjectState.DataView) {
|
||||
flowOf(currentState.details)
|
||||
} else {
|
||||
emptyFlow()
|
||||
}
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
|
||||
val hasObjectLayoutConflictFlow = state
|
||||
.flatMapLatest { currentState ->
|
||||
if (currentState is ObjectState.DataView) {
|
||||
flowOf(currentState.hasObjectLayoutConflict)
|
||||
} else {
|
||||
emptyFlow()
|
||||
}
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
|
||||
return ObjectMenuOptionsProviderImpl(
|
||||
objectViewDetailsFlow = objectViewDetailsFlow,
|
||||
hasObjectLayoutConflict = hasObjectLayoutConflictFlow
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
fun provideSetObjectDetails(
|
||||
repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): SetObjectDetails = SetObjectDetails(
|
||||
repo,
|
||||
dispatchers
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
|
|
|
@ -106,8 +106,11 @@ object ObjectRelationListModule {
|
|||
@JvmStatic
|
||||
@Provides
|
||||
@PerModal
|
||||
fun deleteRelationFromObject(repo: BlockRepository): DeleteRelationFromObject =
|
||||
DeleteRelationFromObject(repo)
|
||||
fun deleteRelationFromObject(
|
||||
repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): DeleteRelationFromObject =
|
||||
DeleteRelationFromObject(repo, dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
|
|
|
@ -87,7 +87,12 @@ abstract class ObjectMenuBaseFragment :
|
|||
setContent {
|
||||
ConflictScreen(
|
||||
showScreen = vm.showLayoutConflictScreen.collectAsStateWithLifecycle().value,
|
||||
onResetClick = { },
|
||||
onResetClick = {
|
||||
vm.onResetToDefaultLayout(
|
||||
ctx = ctx,
|
||||
space = space
|
||||
)
|
||||
},
|
||||
onDismiss = { vm.onHideConflictScreen() }
|
||||
)
|
||||
}
|
||||
|
@ -133,6 +138,7 @@ abstract class ObjectMenuBaseFragment :
|
|||
val relationsVisibility = options.hasRelations.toVisibility()
|
||||
val historyVisibility = options.hasHistory.toVisibility()
|
||||
val objectDiagnosticsVisibility = options.hasDiagnosticsVisibility.toVisibility()
|
||||
val objectLayoutConflictVisibility = options.hasObjectLayoutConflict.toVisibility()
|
||||
|
||||
if (options.hasDescriptionShow) {
|
||||
binding.optionDescription.setAction(setAsHide = false)
|
||||
|
@ -150,6 +156,7 @@ abstract class ObjectMenuBaseFragment :
|
|||
binding.historyDivider.visibility = historyVisibility
|
||||
binding.objectDiagnostics.visibility = objectDiagnosticsVisibility
|
||||
binding.objectDiagnosticsDivider.visibility = objectDiagnosticsVisibility
|
||||
binding.objectLayoutConflict.visibility = objectLayoutConflictVisibility
|
||||
}
|
||||
|
||||
private fun execute(command: ObjectMenuViewModelBase.Command) {
|
||||
|
|
|
@ -173,7 +173,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/default_ripple"
|
||||
android:visibility="visible"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_attention_24"
|
||||
app:showArrow="false"
|
||||
app:title="@string/object_conflict_menu_item_title"
|
||||
|
|
|
@ -161,6 +161,9 @@
|
|||
android:id="@+id/actionExitToSpaceWidgets"
|
||||
app:popUpTo="@+id/homeScreen"
|
||||
app:popUpToInclusive="false" />
|
||||
<dialog android:id="@+id/objectTypeFieldsScreen"
|
||||
android:name="com.anytypeio.anytype.ui.primitives.ObjectTypeFieldsFragment"
|
||||
android:label="ObjectTypeFieldsScreen" />
|
||||
</navigation>
|
||||
|
||||
<fragment
|
||||
|
|
|
@ -306,6 +306,11 @@ sealed class Event {
|
|||
val defaultObjectTypeId: String?
|
||||
)
|
||||
}
|
||||
|
||||
data class UpdateConflictState(
|
||||
override val context: Id,
|
||||
val hasConflict: Boolean
|
||||
) : DataView()
|
||||
}
|
||||
|
||||
sealed class Chats : Command() {
|
||||
|
|
|
@ -103,6 +103,8 @@ object Relations {
|
|||
|
||||
const val SHARED_SPACES_LIMIT = "sharedSpacesLimit"
|
||||
|
||||
const val LAYOUT_ALIGN = "layoutAlign"
|
||||
|
||||
val systemRelationKeys = listOf(
|
||||
"id",
|
||||
"name",
|
||||
|
|
|
@ -467,8 +467,8 @@ class BlockDataRepository(
|
|||
ctx: Id, relation: Id
|
||||
): Payload? = remote.addRelationToObject(ctx, relation)
|
||||
|
||||
override suspend fun deleteRelationFromObject(ctx: Id, relation: Key): Payload {
|
||||
return remote.deleteRelationFromObject(ctx = ctx, relation = relation)
|
||||
override suspend fun deleteRelationFromObject(ctx: Id, relations: List<Key>): Payload {
|
||||
return remote.deleteRelationFromObject(ctx = ctx, relations = relations)
|
||||
}
|
||||
|
||||
override suspend fun debugSpace(space: SpaceId): String = remote.debugSpace(space)
|
||||
|
|
|
@ -192,7 +192,7 @@ interface BlockRemote {
|
|||
suspend fun cancelObjectSearchSubscription(subscriptions: List<Id>)
|
||||
|
||||
suspend fun addRelationToObject(ctx: Id, relation: Key): Payload?
|
||||
suspend fun deleteRelationFromObject(ctx: Id, relation: Key): Payload
|
||||
suspend fun deleteRelationFromObject(ctx: Id, relations: List<Key>): Payload
|
||||
|
||||
suspend fun debugSpace(space: SpaceId): String
|
||||
|
||||
|
|
|
@ -232,7 +232,7 @@ interface BlockRepository {
|
|||
suspend fun cancelObjectSearchSubscription(subscriptions: List<Id>)
|
||||
|
||||
suspend fun addRelationToObject(ctx: Id, relation: Key): Payload?
|
||||
suspend fun deleteRelationFromObject(ctx: Id, relation: Key): Payload
|
||||
suspend fun deleteRelationFromObject(ctx: Id, relations: List<Key>): Payload
|
||||
|
||||
suspend fun debugSpace(space: SpaceId): String
|
||||
|
||||
|
|
|
@ -3,29 +3,31 @@ package com.anytypeio.anytype.domain.relations
|
|||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.ResultInteractor
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
||||
/**
|
||||
* Use-case for deleting a relation from an object.
|
||||
*/
|
||||
class DeleteRelationFromObject(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Payload, DeleteRelationFromObject.Params>() {
|
||||
private val repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
) : ResultInteractor<DeleteRelationFromObject.Params, Payload>(dispatchers.io) {
|
||||
|
||||
override suspend fun run(params: Params) = safe {
|
||||
repo.deleteRelationFromObject(
|
||||
override suspend fun doWork(params: Params): Payload {
|
||||
return repo.deleteRelationFromObject(
|
||||
ctx = params.ctx,
|
||||
relation = params.relation
|
||||
relations = params.relations
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ctx id of the object
|
||||
* @param relation relation key
|
||||
* @param relations relation keys
|
||||
*/
|
||||
class Params(
|
||||
val ctx: Id,
|
||||
val relation: Key
|
||||
val relations: List<Key>
|
||||
)
|
||||
}
|
|
@ -420,10 +420,10 @@ class BlockMiddleware(
|
|||
|
||||
override suspend fun deleteRelationFromObject(
|
||||
ctx: Id,
|
||||
relation: Id
|
||||
relations: List<Key>
|
||||
): Payload = middleware.objectRelationDelete(
|
||||
ctx = ctx,
|
||||
relation = relation
|
||||
relations = relations
|
||||
)
|
||||
|
||||
override suspend fun debugSpace(space: SpaceId): String = middleware.debugSpaceSummary(space)
|
||||
|
|
|
@ -1171,10 +1171,10 @@ class Middleware @Inject constructor(
|
|||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun objectRelationDelete(ctx: Id, relation: Key): Payload {
|
||||
fun objectRelationDelete(ctx: Id, relations: List<Key>): Payload {
|
||||
val request = Rpc.ObjectRelation.Delete.Request(
|
||||
contextId = ctx,
|
||||
relationKeys = listOf(relation)
|
||||
relationKeys = relations
|
||||
)
|
||||
logRequestIfDebug(request)
|
||||
val (response, time) = measureTimedValue { service.objectRelationDelete(request) }
|
||||
|
|
|
@ -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