1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-3466 Primitives | Property, format object relation (#2183)

This commit is contained in:
Konstantin Ivanov 2025-03-25 18:02:06 +01:00 committed by GitHub
parent 6ad8e54721
commit 546ab62b6c
Signed by: github
GPG key ID: B5690EEEBB952194
23 changed files with 821 additions and 154 deletions

View file

@ -1,6 +1,7 @@
package com.anytypeio.anytype.feature_object_type.fields
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.feature_properties.add.UiEditTypePropertiesEvent
sealed class FieldEvent {
@ -30,5 +31,7 @@ sealed class FieldEvent {
sealed class EditProperty : FieldEvent() {
data class OnPropertyNameUpdate(val name: String) : EditProperty()
data object OnSaveButtonClicked : EditProperty()
data object OnLimitTypesClick : EditProperty()
data object OnLimitTypesDismiss : EditProperty()
}
}

View file

@ -43,7 +43,7 @@ sealed class UiFieldsListItem {
abstract val fieldKey: Key
abstract val fieldTitle: String
abstract val format: RelationFormat
abstract val limitObjectTypes: List<UiPropertyLimitTypeItem>
abstract val limitObjectTypes: List<Id>
abstract val isPossibleToUnlinkFromType: Boolean
abstract val isEditableField: Boolean
@ -52,7 +52,7 @@ sealed class UiFieldsListItem {
override val fieldKey: Key,
override val fieldTitle: String,
override val format: RelationFormat,
override val limitObjectTypes: List<UiPropertyLimitTypeItem> = emptyList(),
override val limitObjectTypes: List<Id>,
override val isPossibleToUnlinkFromType: Boolean,
override val isEditableField: Boolean
) : Item()
@ -62,7 +62,7 @@ sealed class UiFieldsListItem {
override val fieldKey: Key,
override val fieldTitle: String,
override val format: RelationFormat,
override val limitObjectTypes: List<UiPropertyLimitTypeItem> = emptyList(),
override val limitObjectTypes: List<Id>,
override val isPossibleToUnlinkFromType: Boolean = false,
override val isEditableField: Boolean
) : Item()

View file

@ -62,6 +62,8 @@ import com.anytypeio.anytype.core_utils.insets.EDGE_TO_EDGE_MIN_SDK
import com.anytypeio.anytype.feature_object_type.R
import com.anytypeio.anytype.feature_object_type.fields.FieldEvent
import com.anytypeio.anytype.feature_object_type.fields.FieldEvent.*
import com.anytypeio.anytype.feature_object_type.fields.FieldEvent.EditProperty.OnLimitTypesClick
import com.anytypeio.anytype.feature_object_type.fields.FieldEvent.EditProperty.OnLimitTypesDismiss
import com.anytypeio.anytype.feature_object_type.fields.FieldEvent.FieldItemMenu.*
import com.anytypeio.anytype.feature_object_type.fields.UiFieldsListItem
import com.anytypeio.anytype.feature_object_type.fields.UiFieldsListItem.Section
@ -69,6 +71,7 @@ import com.anytypeio.anytype.feature_object_type.fields.UiFieldsListState
import com.anytypeio.anytype.feature_object_type.fields.UiLocalsFieldsInfoState
import com.anytypeio.anytype.feature_object_type.ui.UiIconState
import com.anytypeio.anytype.feature_object_type.ui.UiTitleState
import com.anytypeio.anytype.feature_properties.add.UiEditTypePropertiesEvent
import com.anytypeio.anytype.feature_properties.edit.UiEditPropertyState
import com.anytypeio.anytype.feature_properties.edit.ui.PropertyScreen
import com.anytypeio.anytype.presentation.objects.ObjectIcon
@ -226,12 +229,12 @@ fun FieldsMainScreen(
uiState = uiEditPropertyState,
onDismissRequest = { fieldEvent(OnEditPropertyScreenDismiss) },
onFormatClick = {},
onLimitTypesClick = {},
onSaveButtonClicked = { fieldEvent(EditProperty.OnSaveButtonClicked) },
onCreateNewButtonClicked = {},
onPropertyNameUpdate = { fieldEvent(EditProperty.OnPropertyNameUpdate(it)) },
onMenuUnlinkClick = { fieldEvent(OnDeleteFromTypeClick(it)) }
onMenuUnlinkClick = { fieldEvent(OnDeleteFromTypeClick(it)) },
onLimitTypesClick = { fieldEvent(OnLimitTypesClick) },
onDismissLimitTypes = { fieldEvent(OnLimitTypesDismiss) },
)
}
@ -681,7 +684,8 @@ fun PreviewTypeFieldsMainScreen() {
fieldTitle = "Status",
format = RelationFormat.STATUS,
isPossibleToUnlinkFromType = true,
isEditableField = true
isEditableField = true,
limitObjectTypes = listOf()
),
UiFieldsListItem.Item.Draggable(
id = "id2",
@ -689,7 +693,8 @@ fun PreviewTypeFieldsMainScreen() {
fieldTitle = "Very long field title, just to test how it looks",
format = RelationFormat.LONG_TEXT,
isPossibleToUnlinkFromType = true,
isEditableField = true
isEditableField = true,
limitObjectTypes = listOf()
),
UiFieldsListItem.Section.SideBar(
canAdd = true
@ -700,7 +705,8 @@ fun PreviewTypeFieldsMainScreen() {
fieldTitle = "Links",
format = RelationFormat.URL,
isEditableField = true,
isPossibleToUnlinkFromType = true
isPossibleToUnlinkFromType = true,
limitObjectTypes = listOf()
),
UiFieldsListItem.Item.Draggable(
id = "id4",
@ -708,7 +714,8 @@ fun PreviewTypeFieldsMainScreen() {
fieldTitle = "Very long field title, just to test how it looks",
format = RelationFormat.DATE,
isEditableField = true,
isPossibleToUnlinkFromType = true
isPossibleToUnlinkFromType = true,
limitObjectTypes = listOf()
),
UiFieldsListItem.Section.Hidden(),
UiFieldsListItem.Item.Draggable(
@ -717,7 +724,8 @@ fun PreviewTypeFieldsMainScreen() {
fieldTitle = "Hidden field",
format = RelationFormat.LONG_TEXT,
isEditableField = true,
isPossibleToUnlinkFromType = true
isPossibleToUnlinkFromType = true,
limitObjectTypes = listOf()
),
UiFieldsListItem.Section.Local(),
UiFieldsListItem.Item.Local(
@ -725,14 +733,16 @@ fun PreviewTypeFieldsMainScreen() {
fieldKey = "key5",
fieldTitle = "Local field",
format = RelationFormat.LONG_TEXT,
isEditableField = true
isEditableField = true,
limitObjectTypes = listOf()
),
UiFieldsListItem.Item.Local(
id = "id6",
fieldKey = "key6",
fieldTitle = "Local Very long field title, just to test how it looks",
format = RelationFormat.LONG_TEXT,
isEditableField = true
isEditableField = true,
limitObjectTypes = listOf()
)
)
),

View file

@ -66,7 +66,6 @@ suspend fun buildUiFieldsList(
objType: ObjectWrapper.Type,
stringResourceProvider: StringResourceProvider,
fieldParser: FieldParser,
urlBuilder: UrlBuilder,
storeOfObjectTypes: StoreOfObjectTypes,
storeOfRelations: StoreOfRelations,
objTypeConflictingFields: List<Id>,
@ -85,7 +84,6 @@ suspend fun buildUiFieldsList(
field = it,
stringResourceProvider = stringResourceProvider,
fieldParser = fieldParser,
urlBuilder = urlBuilder,
storeOfObjectTypes = storeOfObjectTypes
)
}
@ -94,7 +92,6 @@ suspend fun buildUiFieldsList(
field = it,
stringResourceProvider = stringResourceProvider,
fieldParser = fieldParser,
urlBuilder = urlBuilder,
storeOfObjectTypes = storeOfObjectTypes
)
}
@ -103,7 +100,6 @@ suspend fun buildUiFieldsList(
field = it,
stringResourceProvider = stringResourceProvider,
fieldParser = fieldParser,
urlBuilder = urlBuilder,
storeOfObjectTypes = storeOfObjectTypes
)
}
@ -112,7 +108,6 @@ suspend fun buildUiFieldsList(
field = it,
stringResourceProvider = stringResourceProvider,
fieldParser = fieldParser,
urlBuilder = urlBuilder,
storeOfObjectTypes = storeOfObjectTypes
)
}
@ -123,7 +118,6 @@ suspend fun buildUiFieldsList(
field = it,
stringResourceProvider = stringResourceProvider,
fieldParser = fieldParser,
urlBuilder = urlBuilder,
storeOfObjectTypes = storeOfObjectTypes
)
}
@ -133,7 +127,6 @@ suspend fun buildUiFieldsList(
field = it,
stringResourceProvider = stringResourceProvider,
fieldParser = fieldParser,
urlBuilder = urlBuilder,
storeOfObjectTypes = storeOfObjectTypes
)
}
@ -169,19 +162,16 @@ suspend fun buildUiFieldsList(
*/
private suspend fun mapLimitObjectTypes(
relation: ObjectWrapper.Relation,
storeOfObjectTypes: StoreOfObjectTypes,
fieldParser: FieldParser,
urlBuilder: UrlBuilder
): List<UiPropertyLimitTypeItem> {
storeOfObjectTypes: StoreOfObjectTypes
): List<Id> {
return if (relation.format == RelationFormat.OBJECT && relation.relationFormatObjectTypes.isNotEmpty()) {
relation.relationFormatObjectTypes.mapNotNull { key ->
storeOfObjectTypes.getByKey(key)?.let { objType ->
UiPropertyLimitTypeItem(
id = objType.id,
key = objType.uniqueKey,
title = fieldParser.getObjectName(objType),
icon = objType.objectIcon()
)
relation.relationFormatObjectTypes.mapNotNull { id ->
storeOfObjectTypes.get(id)?.let { objType ->
if (objType.isValid) {
objType.id
} else {
null
}
}
}
} else {
@ -197,18 +187,16 @@ private suspend fun mapToUiFieldsDraggableListItem(
field: ObjectWrapper.Relation,
stringResourceProvider: StringResourceProvider,
storeOfObjectTypes: StoreOfObjectTypes,
fieldParser: FieldParser,
urlBuilder: UrlBuilder
fieldParser: FieldParser
): UiFieldsListItem? {
if (field.key == Relations.DESCRIPTION) return null
val limitObjectTypes = mapLimitObjectTypes(field, storeOfObjectTypes, fieldParser, urlBuilder)
return Item.Draggable(
id = field.id,
fieldKey = field.key,
fieldTitle = field.getName(stringResourceProvider),
format = field.format,
limitObjectTypes = limitObjectTypes,
limitObjectTypes = mapLimitObjectTypes(field, storeOfObjectTypes),
isEditableField = fieldParser.isFieldEditable(field),
isPossibleToUnlinkFromType = fieldParser.isFieldCanBeDeletedFromType(field)
)
@ -223,17 +211,15 @@ private suspend fun mapToUiFieldsLocalListItem(
stringResourceProvider: StringResourceProvider,
storeOfObjectTypes: StoreOfObjectTypes,
fieldParser: FieldParser,
urlBuilder: UrlBuilder
): UiFieldsListItem? {
if (field.key == Relations.DESCRIPTION) return null
val limitObjectTypes = mapLimitObjectTypes(field, storeOfObjectTypes, fieldParser, urlBuilder)
return Item.Local(
id = field.id,
fieldKey = field.key,
fieldTitle = field.getName(stringResourceProvider),
format = field.format,
limitObjectTypes = limitObjectTypes,
limitObjectTypes = mapLimitObjectTypes(field, storeOfObjectTypes),
isEditableField = fieldParser.isFieldEditable(field)
)
}

View file

@ -37,6 +37,8 @@ import com.anytypeio.anytype.feature_object_type.ui.TypeEvent
import com.anytypeio.anytype.feature_object_type.ui.UiDeleteAlertState
import com.anytypeio.anytype.feature_object_type.ui.UiEditButton
import com.anytypeio.anytype.feature_object_type.ui.UiErrorState
import com.anytypeio.anytype.feature_object_type.ui.UiErrorState.*
import com.anytypeio.anytype.feature_object_type.ui.UiErrorState.Reason.*
import com.anytypeio.anytype.feature_object_type.ui.UiFieldsButtonState
import com.anytypeio.anytype.feature_object_type.ui.UiIconsPickerState
import com.anytypeio.anytype.feature_object_type.ui.UiIconState
@ -51,6 +53,7 @@ import com.anytypeio.anytype.feature_object_type.ui.buildUiFieldsList
import com.anytypeio.anytype.feature_object_type.ui.toTemplateView
import com.anytypeio.anytype.feature_properties.edit.UiEditPropertyState
import com.anytypeio.anytype.feature_properties.edit.UiEditPropertyState.Visible.View
import com.anytypeio.anytype.feature_properties.edit.UiPropertyLimitTypeItem
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
import com.anytypeio.anytype.presentation.extension.sendAnalyticsScreenObjectType
@ -119,7 +122,7 @@ class ObjectTypeViewModel(
MutableStateFlow<UiTemplatesButtonState>(UiTemplatesButtonState.Hidden)
//type layouts
val uiTypeLayoutsState = MutableStateFlow<UiLayoutTypeState>(Hidden)
val uiTypeLayoutsState = MutableStateFlow<UiLayoutTypeState>(UiLayoutTypeState.Hidden)
//templates modal list state
val uiTemplatesModalListState =
@ -328,7 +331,6 @@ class ObjectTypeViewModel(
val items = buildUiFieldsList(
objType = objType,
stringResourceProvider = stringResourceProvider,
urlBuilder = urlBuilder,
fieldParser = fieldParser,
storeOfObjectTypes = storeOfObjectTypes,
storeOfRelations = storeOfRelations,
@ -373,29 +375,47 @@ class ObjectTypeViewModel(
}
fun setupUiEditPropertyScreen(item: UiFieldsListItem.Item) {
val permissions = _objectTypePermissionsState.value
if (permissions?.participantCanEdit == true && item.isEditableField) {
uiEditPropertyScreen.value = UiEditPropertyState.Visible.Edit(
id = item.id,
key = item.fieldKey,
name = item.fieldTitle,
formatName = stringResourceProvider.getPropertiesFormatPrettyString(item.format),
formatIcon = item.format.simpleIcon(),
format = item.format,
limitObjectTypes = item.limitObjectTypes,
isPossibleToUnlinkFromType = item.isPossibleToUnlinkFromType
)
} else {
uiEditPropertyScreen.value = UiEditPropertyState.Visible.View(
id = item.id,
key = item.fieldKey,
name = item.fieldTitle,
formatName = stringResourceProvider.getPropertiesFormatPrettyString(item.format),
formatIcon = item.format.simpleIcon(),
format = item.format,
limitObjectTypes = item.limitObjectTypes,
isPossibleToUnlinkFromType = item.isPossibleToUnlinkFromType
)
viewModelScope.launch {
val permissions = _objectTypePermissionsState.value
val computedLimitTypes = item.limitObjectTypes.mapNotNull { id ->
storeOfObjectTypes.get(id = id)?.let { objType ->
UiPropertyLimitTypeItem(
id = objType.id,
name = fieldParser.getObjectName(objectWrapper = objType),
icon = objType.objectIcon(),
uniqueKey = objType.uniqueKey
)
}
}
val formatName = stringResourceProvider.getPropertiesFormatPrettyString(item.format)
val formatIcon = item.format.simpleIcon()
uiEditPropertyScreen.value = if (permissions?.participantCanEdit == true && item.isEditableField) {
UiEditPropertyState.Visible.Edit(
id = item.id,
key = item.fieldKey,
name = item.fieldTitle,
formatName = formatName,
formatIcon = formatIcon,
format = item.format,
limitObjectTypes = computedLimitTypes,
isPossibleToUnlinkFromType = item.isPossibleToUnlinkFromType,
showLimitTypes = false
)
} else {
UiEditPropertyState.Visible.View(
id = item.id,
key = item.fieldKey,
name = item.fieldTitle,
formatName = formatName,
formatIcon = formatIcon,
format = item.format,
limitObjectTypes = computedLimitTypes,
isPossibleToUnlinkFromType = item.isPossibleToUnlinkFromType,
showLimitTypes = false
)
}
}
}
//endregion
@ -461,7 +481,7 @@ class ObjectTypeViewModel(
}
TypeEvent.OnLayoutTypeDismiss -> {
uiTypeLayoutsState.value = Hidden
uiTypeLayoutsState.value = UiLayoutTypeState.Hidden
}
is TypeEvent.OnLayoutTypeItemClick -> {
@ -811,13 +831,30 @@ class ObjectTypeViewModel(
},
onFailure = { error ->
Timber.e(error, "Failed to update relation")
errorState.value = UiErrorState.Show(
reason = UiErrorState.Reason.Other(error.message ?: "")
errorState.value = Show(
reason = Other(error.message ?: "")
)
}
)
}
}
FieldEvent.EditProperty.OnLimitTypesClick -> {
uiEditPropertyScreen.value = when (val state = uiEditPropertyScreen.value) {
is UiEditPropertyState.Visible.Edit -> state.copy(showLimitTypes = true)
is UiEditPropertyState.Visible.New -> state.copy(showLimitTypes = true)
is View -> state.copy(showLimitTypes = true)
else -> state
}
}
FieldEvent.EditProperty.OnLimitTypesDismiss -> {
uiEditPropertyScreen.value = when (val state = uiEditPropertyScreen.value) {
is UiEditPropertyState.Visible.Edit -> state.copy(showLimitTypes = false)
is UiEditPropertyState.Visible.New -> state.copy(showLimitTypes = false)
is View -> state.copy(showLimitTypes = false)
else -> state
}
}
}
}
//endregion