mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3435 Primitives | Type page as Set (#2134)
This commit is contained in:
parent
51ffabc160
commit
f179d64231
23 changed files with 582 additions and 62 deletions
|
@ -28,13 +28,12 @@ import com.anytypeio.anytype.core_utils.ext.subscribe
|
|||
import com.anytypeio.anytype.core_utils.ext.toast
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseComposeFragment
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.feature_object_type.ui.ObjectTypeMainScreen
|
||||
import com.anytypeio.anytype.feature_object_type.viewmodel.ObjectTypeVMFactory
|
||||
import com.anytypeio.anytype.feature_object_type.viewmodel.ObjectTypeViewModel
|
||||
import com.anytypeio.anytype.feature_object_type.ui.ObjectTypeVmParams
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiErrorState
|
||||
import com.anytypeio.anytype.feature_object_type.fields.ui.FieldsMainScreen
|
||||
import com.anytypeio.anytype.feature_object_type.ui.ObjectTypeCommand
|
||||
import com.anytypeio.anytype.feature_object_type.ui.ObjectTypeVmParams
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiErrorState
|
||||
import com.anytypeio.anytype.feature_object_type.viewmodel.ObjectTypeVMFactory
|
||||
import com.anytypeio.anytype.feature_object_type.viewmodel.ObjectTypeViewModel
|
||||
import com.anytypeio.anytype.presentation.home.OpenObjectNavigation
|
||||
import com.anytypeio.anytype.ui.chats.ChatFragment
|
||||
import com.anytypeio.anytype.ui.date.DateObjectFragment
|
||||
|
@ -153,16 +152,20 @@ class ObjectTypeFragment : BaseComposeFragment() {
|
|||
startDestination = OBJ_TYPE_MAIN
|
||||
) {
|
||||
composable(route = OBJ_TYPE_MAIN) {
|
||||
ObjectTypeMainScreen(
|
||||
WithSetScreen(
|
||||
uiEditButtonState = vm.uiEditButtonState.collectAsStateWithLifecycle().value,
|
||||
uiSyncStatusBadgeState = vm.uiSyncStatusBadgeState.collectAsStateWithLifecycle().value,
|
||||
uiSyncStatusState = vm.uiSyncStatusWidgetState.collectAsStateWithLifecycle().value,
|
||||
uiTitleState = vm.uiTitleState.collectAsStateWithLifecycle().value,
|
||||
uiIconState = vm.uiIconState.collectAsStateWithLifecycle().value,
|
||||
uiTitleState = vm.uiTitleState.collectAsStateWithLifecycle().value,
|
||||
uiFieldsButtonState = vm.uiFieldsButtonState.collectAsStateWithLifecycle().value,
|
||||
uiLayoutButtonState = vm.uiLayoutButtonState.collectAsStateWithLifecycle().value,
|
||||
uiDeleteAlertState = vm.uiAlertState.collectAsStateWithLifecycle().value,
|
||||
uiEditButtonState = vm.uiEditButtonState.collectAsStateWithLifecycle().value,
|
||||
uiTemplatesButtonState = vm.uiTemplatesButtonState.collectAsStateWithLifecycle().value,
|
||||
uiTemplatesModalListState = vm.uiTemplatesModalListState.collectAsStateWithLifecycle().value,
|
||||
uiLayoutTypeState = vm.uiTypeLayoutsState.collectAsStateWithLifecycle().value,
|
||||
uiSyncStatusState = vm.uiSyncStatusWidgetState.collectAsStateWithLifecycle().value,
|
||||
uiDeleteAlertState = vm.uiAlertState.collectAsStateWithLifecycle().value,
|
||||
objectId = objectId,
|
||||
space = space,
|
||||
onTypeEvent = vm::onTypeEvent
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package com.anytypeio.anytype.ui.primitives
|
||||
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
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.UiFieldsButtonState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiIconState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiLayoutButtonState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiLayoutTypeState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiSyncStatusBadgeState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiTemplatesButtonState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiTemplatesModalListState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiTitleState
|
||||
import com.anytypeio.anytype.presentation.sync.SyncStatusWidgetState
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun WithSetScreen(
|
||||
//top bar
|
||||
uiEditButtonState: UiEditButton,
|
||||
uiSyncStatusBadgeState: UiSyncStatusBadgeState,
|
||||
uiSyncStatusState: SyncStatusWidgetState,
|
||||
//header
|
||||
uiIconState: UiIconState,
|
||||
uiTitleState: UiTitleState,
|
||||
//layout and fields buttons
|
||||
uiFieldsButtonState: UiFieldsButtonState,
|
||||
uiLayoutButtonState: UiLayoutButtonState,
|
||||
uiLayoutTypeState: UiLayoutTypeState,
|
||||
uiTemplatesButtonState: UiTemplatesButtonState,
|
||||
//templates modal list
|
||||
uiTemplatesModalListState: UiTemplatesModalListState,
|
||||
//delete alert
|
||||
uiDeleteAlertState: UiDeleteAlertState,
|
||||
//events
|
||||
onTypeEvent: (TypeEvent) -> Unit,
|
||||
objectId: String,
|
||||
space: String,
|
||||
) {
|
||||
//next PR
|
||||
}
|
|
@ -705,6 +705,57 @@ open class ObjectSetFragment :
|
|||
dataViewInfo.hide()
|
||||
setViewer(viewer = null)
|
||||
}
|
||||
is DataViewViewState.TypeSet.Default -> {
|
||||
topToolbarThreeDotsButton.gone()
|
||||
topToolbarStatusContainer.gone()
|
||||
topBackButton.gone()
|
||||
initView.gone()
|
||||
header.gone()
|
||||
dataViewHeader.visible()
|
||||
viewerTitle.isEnabled = true
|
||||
setupNewButtonsForTypeSet(state.isCreateObjectAllowed)
|
||||
if (state.isEditingViewAllowed) {
|
||||
customizeViewButton.visible()
|
||||
} else {
|
||||
customizeViewButton.invisible()
|
||||
}
|
||||
customizeViewButton.isEnabled = true
|
||||
setCurrentViewerName(state.viewer?.title)
|
||||
setViewer(viewer = state.viewer)
|
||||
dataViewInfo.hide()
|
||||
}
|
||||
is DataViewViewState.TypeSet.NoItems -> {
|
||||
topToolbarThreeDotsButton.gone()
|
||||
topToolbarStatusContainer.gone()
|
||||
topBackButton.gone()
|
||||
initView.gone()
|
||||
header.gone()
|
||||
dataViewHeader.visible()
|
||||
viewerTitle.isEnabled = true
|
||||
setupNewButtonsForTypeSet(state.isCreateObjectAllowed)
|
||||
if (state.isEditingViewAllowed) {
|
||||
customizeViewButton.visible()
|
||||
} else {
|
||||
customizeViewButton.invisible()
|
||||
}
|
||||
customizeViewButton.isEnabled = true
|
||||
setCurrentViewerName(state.title)
|
||||
dataViewInfo.show(
|
||||
type = DataViewInfo.TYPE.SET_NO_ITEMS,
|
||||
isReadOnlyAccess = !state.isCreateObjectAllowed
|
||||
)
|
||||
setViewer(viewer = null)
|
||||
}
|
||||
|
||||
is DataViewViewState.TypeSet.Error -> {
|
||||
topToolbarThreeDotsButton.gone()
|
||||
topToolbarStatusContainer.gone()
|
||||
topBackButton.gone()
|
||||
initView.gone()
|
||||
header.gone()
|
||||
dataViewHeader.visible()
|
||||
setViewer(viewer = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -726,6 +777,16 @@ open class ObjectSetFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupNewButtonsForTypeSet(isCreateObjectAllowed: Boolean) {
|
||||
if (isCreateObjectAllowed) {
|
||||
addNewButton.visible()
|
||||
addNewIconButton.gone()
|
||||
} else {
|
||||
addNewButton.gone()
|
||||
addNewIconButton.gone()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setViewer(viewer: Viewer?) {
|
||||
when (viewer) {
|
||||
is Viewer.GridView -> {
|
||||
|
|
|
@ -36,6 +36,7 @@ dependencies {
|
|||
|
||||
implementation libs.appcompat
|
||||
implementation libs.compose
|
||||
implementation libs.fragmentCompose
|
||||
implementation libs.composeFoundation
|
||||
implementation libs.composeToolingPreview
|
||||
implementation libs.composeMaterial3
|
||||
|
|
|
@ -168,7 +168,7 @@ private fun MainContent(
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun TopBarContent(
|
||||
fun TopBarContent(
|
||||
uiSyncStatusBadgeState: UiSyncStatusBadgeState,
|
||||
uiEditButtonState: UiEditButton,
|
||||
uiTitleState: UiTitleState,
|
||||
|
@ -199,7 +199,7 @@ private fun TopBarContent(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun BottomSyncStatus(
|
||||
fun BottomSyncStatus(
|
||||
uiSyncStatusState: SyncStatusWidgetState,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
|
|
|
@ -21,6 +21,7 @@ sealed class TypeEvent {
|
|||
//endregion
|
||||
|
||||
//region Templates
|
||||
data object OnTemplatesModalListDismiss : TypeEvent()
|
||||
data object OnTemplatesAddIconClick : TypeEvent()
|
||||
data class OnTemplateItemClick(val item: TemplateView) : TypeEvent()
|
||||
sealed class OnTemplateMenuClick : TypeEvent() {
|
||||
|
@ -29,6 +30,7 @@ sealed class TypeEvent {
|
|||
data class Duplicate(val item: TemplateView) : OnTemplateMenuClick()
|
||||
data class Delete(val item: TemplateView) : OnTemplateMenuClick()
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
//region Layout type
|
||||
|
@ -39,4 +41,5 @@ sealed class TypeEvent {
|
|||
|
||||
data object OnLayoutButtonClick : TypeEvent()
|
||||
data object OnFieldsButtonClick : TypeEvent()
|
||||
data object OnTemplatesButtonClick : TypeEvent()
|
||||
}
|
|
@ -33,7 +33,8 @@ sealed class ObjectTypeCommand {
|
|||
|
||||
data object OpenFieldsScreen : ObjectTypeCommand()
|
||||
|
||||
data class OpenAddFieldScreen(val typeId: Id, val space: Id, val isSet: Boolean = false) : ObjectTypeCommand()
|
||||
data class OpenAddFieldScreen(val typeId: Id, val space: Id, val isSet: Boolean = false) :
|
||||
ObjectTypeCommand()
|
||||
}
|
||||
|
||||
//region OBJECT TYPE HEADER (title + icon)
|
||||
|
@ -71,6 +72,11 @@ sealed class UiFieldsButtonState {
|
|||
|
||||
}
|
||||
|
||||
sealed class UiTemplatesButtonState {
|
||||
data object Hidden : UiTemplatesButtonState()
|
||||
data class Visible(val count: Int) : UiTemplatesButtonState()
|
||||
}
|
||||
|
||||
//region MENU
|
||||
@Immutable
|
||||
sealed class UiMenuSetItem {
|
||||
|
@ -153,6 +159,24 @@ data class UiTemplatesListState(
|
|||
val EMPTY = UiTemplatesListState(items = emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
sealed class UiTemplatesModalListState {
|
||||
abstract val items: List<TemplateView>
|
||||
|
||||
data class Hidden(
|
||||
override val items: List<TemplateView>,
|
||||
) : UiTemplatesModalListState() {
|
||||
companion object {
|
||||
val EMPTY = Hidden(items = emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
data class Visible(
|
||||
override val items: List<TemplateView>,
|
||||
val showAddIcon: Boolean
|
||||
) :
|
||||
UiTemplatesModalListState()
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region OBJECTS HEADER
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.anytypeio.anytype.feature_object_type.ui.header
|
||||
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
@ -8,6 +9,7 @@ import androidx.compose.foundation.layout.height
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
@ -21,21 +23,26 @@ import androidx.compose.ui.unit.dp
|
|||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
|
||||
import com.anytypeio.anytype.core_ui.common.OldDevicesPreview
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
|
||||
import com.anytypeio.anytype.core_ui.views.PreviewTitle2Medium
|
||||
import com.anytypeio.anytype.feature_object_type.ui.TypeEvent
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiFieldsButtonState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiLayoutButtonState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiTemplatesButtonState
|
||||
|
||||
@Composable
|
||||
fun HorizontalButtons(
|
||||
modifier: Modifier,
|
||||
uiLayoutButtonState: UiLayoutButtonState,
|
||||
uiFieldsButtonState: UiFieldsButtonState,
|
||||
uiTemplatesButtonState: UiTemplatesButtonState = UiTemplatesButtonState.Hidden,
|
||||
onTypeEvent: (TypeEvent) -> Unit
|
||||
) {
|
||||
val horizontalScrollState = rememberScrollState()
|
||||
|
||||
Row(
|
||||
modifier = modifier,
|
||||
modifier = modifier.horizontalScroll(state = horizontalScrollState),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
val modifierButton = Modifier
|
||||
|
@ -99,6 +106,32 @@ fun HorizontalButtons(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (uiTemplatesButtonState is UiTemplatesButtonState.Visible) {
|
||||
Row(
|
||||
modifier = modifierButton.noRippleThrottledClickable {
|
||||
onTypeEvent(TypeEvent.OnTemplatesButtonClick)
|
||||
},
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.wrapContentSize()
|
||||
.padding(start = 12.dp),
|
||||
text = stringResource(R.string.button_templates),
|
||||
style = PreviewTitle2Medium,
|
||||
color = colorResource(R.color.text_primary)
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.wrapContentSize()
|
||||
.padding(start = 6.dp, end = 12.dp),
|
||||
text = uiTemplatesButtonState.count.toString(),
|
||||
style = PreviewTitle2Medium,
|
||||
color = colorResource(R.color.glyph_active)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,6 +145,7 @@ fun HorizontalButtonsPreview() {
|
|||
.padding(start = 20.dp),
|
||||
uiLayoutButtonState = UiLayoutButtonState.Visible(ObjectType.Layout.BASIC),
|
||||
uiFieldsButtonState = UiFieldsButtonState.Visible(3),
|
||||
uiTemplatesButtonState = UiTemplatesButtonState.Visible(2),
|
||||
onTypeEvent = {}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ fun TypeLayoutsScreen(
|
|||
modifier = Modifier,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
TemplateItemContent(
|
||||
LayoutItemContent(
|
||||
modifier = Modifier
|
||||
.width(120.dp)
|
||||
.height(224.dp)
|
||||
|
@ -147,7 +147,7 @@ fun TypeLayoutsScreen(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun TemplateItemContent(
|
||||
private fun LayoutItemContent(
|
||||
modifier: Modifier,
|
||||
item: ObjectType.Layout
|
||||
) {
|
||||
|
|
|
@ -10,8 +10,6 @@ import com.anytypeio.anytype.core_models.ObjectWrapper
|
|||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.permissions.ObjectPermissions
|
||||
import com.anytypeio.anytype.core_models.permissions.toObjectPermissionsForTypes
|
||||
import com.anytypeio.anytype.core_models.primitives.TypeId
|
||||
import com.anytypeio.anytype.core_models.primitives.TypeKey
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.block.interactor.sets.CreateObjectSet
|
||||
import com.anytypeio.anytype.domain.event.interactor.SpaceSyncAndP2PStatusProvider
|
||||
|
@ -53,7 +51,8 @@ import com.anytypeio.anytype.feature_object_type.ui.UiLayoutTypeState
|
|||
import com.anytypeio.anytype.feature_object_type.ui.UiLayoutTypeState.*
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiSyncStatusBadgeState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiTemplatesAddIconState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiTemplatesHeaderState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiTemplatesButtonState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiTemplatesModalListState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiTitleState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.buildUiFieldsList
|
||||
import com.anytypeio.anytype.feature_object_type.ui.mapToUiAddFieldListItem
|
||||
|
@ -97,7 +96,7 @@ import timber.log.Timber
|
|||
* Models: @see [ObjectViewState]
|
||||
*/
|
||||
class ObjectTypeViewModel(
|
||||
private val vmParams: ObjectTypeVmParams,
|
||||
val vmParams: ObjectTypeVmParams,
|
||||
private val analytics: Analytics,
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
|
@ -132,18 +131,17 @@ class ObjectTypeViewModel(
|
|||
val uiTitleState = MutableStateFlow<UiTitleState>(UiTitleState.Companion.EMPTY)
|
||||
val uiIconState = MutableStateFlow<UiIconState>(UiIconState.Companion.EMPTY)
|
||||
|
||||
//layout and fields buttons
|
||||
//layout, fields and templates buttons
|
||||
val uiFieldsButtonState = MutableStateFlow<UiFieldsButtonState>(UiFieldsButtonState.Hidden)
|
||||
val uiLayoutButtonState = MutableStateFlow<UiLayoutButtonState>(UiLayoutButtonState.Hidden)
|
||||
val uiTemplatesButtonState = MutableStateFlow<UiTemplatesButtonState>(UiTemplatesButtonState.Hidden)
|
||||
|
||||
//type layouts
|
||||
val uiTypeLayoutsState = MutableStateFlow<UiLayoutTypeState>(Hidden)
|
||||
|
||||
//templates header
|
||||
val uiTemplatesHeaderState =
|
||||
MutableStateFlow<UiTemplatesHeaderState>(UiTemplatesHeaderState.Hidden)
|
||||
val uiTemplatesAddIconState =
|
||||
MutableStateFlow<UiTemplatesAddIconState>(UiTemplatesAddIconState.Hidden)
|
||||
//templates modal list state
|
||||
val uiTemplatesModalListState =
|
||||
MutableStateFlow<UiTemplatesModalListState>(UiTemplatesModalListState.Hidden.EMPTY)
|
||||
|
||||
//alerts
|
||||
val uiAlertState = MutableStateFlow<UiDeleteAlertState>(UiDeleteAlertState.Hidden)
|
||||
|
@ -326,10 +324,6 @@ class ObjectTypeViewModel(
|
|||
_objTypeState.value = objType
|
||||
_objectTypePermissionsState.value = objectPermissions
|
||||
|
||||
if (!objectPermissions.canCreateTemplatesForThisType) {
|
||||
uiTemplatesHeaderState.value = UiTemplatesHeaderState.Hidden
|
||||
uiTemplatesAddIconState.value = UiTemplatesAddIconState.Hidden
|
||||
}
|
||||
uiTitleState.value = UiTitleState(
|
||||
title = objType.name.orEmpty(),
|
||||
isEditable = objectPermissions.canEditDetails
|
||||
|
@ -368,31 +362,25 @@ class ObjectTypeViewModel(
|
|||
templates: List<TemplateView>,
|
||||
permissions: ObjectPermissions
|
||||
) {
|
||||
uiTemplatesHeaderState.value = UiTemplatesHeaderState.Visible(count = "${templates.size}")
|
||||
uiTemplatesButtonState.value = UiTemplatesButtonState.Visible(count = templates.size)
|
||||
|
||||
// Update each template view regarding default selection.
|
||||
val updatedTemplates = templates.map { template ->
|
||||
when (template) {
|
||||
is TemplateView.Blank -> template
|
||||
is TemplateView.New -> template
|
||||
is TemplateView.Template -> template.copy(
|
||||
val updatedTemplates = templates.mapNotNull { template ->
|
||||
if (template is TemplateView.Template) {
|
||||
template.copy(
|
||||
isDefault = template.id == objType.defaultTemplateId
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
// Build final list with an extra "new template" item if allowed.
|
||||
val finalTemplates = buildList<TemplateView> {
|
||||
addAll(updatedTemplates)
|
||||
if (permissions.participantCanEdit) {
|
||||
add(
|
||||
TemplateView.New(
|
||||
targetTypeId = TypeId(objType.id),
|
||||
targetTypeKey = TypeKey(objType.uniqueKey)
|
||||
)
|
||||
)
|
||||
uiTemplatesAddIconState.value = UiTemplatesAddIconState.Visible
|
||||
}
|
||||
val currentValue = uiTemplatesModalListState.value
|
||||
uiTemplatesModalListState.value = when (currentValue) {
|
||||
is UiTemplatesModalListState.Hidden -> currentValue.copy(updatedTemplates)
|
||||
is UiTemplatesModalListState.Visible -> currentValue.copy(
|
||||
updatedTemplates,
|
||||
showAddIcon = permissions.canCreateTemplatesForThisType
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -478,6 +466,22 @@ class ObjectTypeViewModel(
|
|||
}
|
||||
|
||||
is TypeEvent.OnTemplateMenuClick -> proceedWithTemplateMenuClick(event)
|
||||
|
||||
TypeEvent.OnTemplatesModalListDismiss -> {
|
||||
uiTemplatesModalListState.value = UiTemplatesModalListState.Hidden(
|
||||
items = uiTemplatesModalListState.value.items
|
||||
)
|
||||
}
|
||||
|
||||
TypeEvent.OnTemplatesButtonClick -> {
|
||||
viewModelScope.launch {
|
||||
val currentState = uiTemplatesModalListState.value
|
||||
uiTemplatesModalListState.value = UiTemplatesModalListState.Visible(
|
||||
items = currentState.items,
|
||||
showAddIcon = _objectTypePermissionsState.value?.canCreateTemplatesForThisType == true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -790,6 +790,7 @@
|
|||
<string name="layout">Layout</string>
|
||||
<string name="button_fields">Fields</string>
|
||||
<string name="button_layout">Layout</string>
|
||||
<string name="button_templates">Templates</string>
|
||||
<string name="restore_from_archive">Restore from archive</string>
|
||||
<string name="icon">Icon</string>
|
||||
<string name="icon_description">Emoji or image for object</string>
|
||||
|
@ -1869,7 +1870,7 @@ Please provide specific details of your needs here.</string>
|
|||
<string name="object_type_fields_section_file">File</string>
|
||||
<string name="object_type_fields_section_local_fields">Local fields</string>
|
||||
<string name="object_type_fields_title">Fields</string>
|
||||
<string name="object_type_fields_info_text">You editing type</string>
|
||||
<string name="object_type_fields_info_text">You\'re editing type</string>
|
||||
<string name="object_type_fields_edit_field">Edit field</string>
|
||||
<string name="object_type_fields_new_field">New field</string>
|
||||
<string name="object_type_fields_preview_field">Preview field</string>
|
||||
|
@ -1880,6 +1881,7 @@ Please provide specific details of your needs here.</string>
|
|||
<string name="object_type_fields_local_info_title">Local fields</string>
|
||||
<string name="object_type_fields_local_info_description">Some fields are not included in the object type. Please add them if you want to see them in all objects of this type, or remove them.</string>
|
||||
<string name="object_type_fields_local_info_button">Got it</string>
|
||||
<string name="object_type_templates_empty">This type doesn’t have\nany templates</string>
|
||||
|
||||
<string name="object_type_open_type_error">Error opening current object type</string>
|
||||
|
||||
|
@ -1907,7 +1909,7 @@ Please provide specific details of your needs here.</string>
|
|||
<string name="chat_message_reactions_no_reactions_message">Probably someone has just removed the reaction or technical issue happened</string>
|
||||
|
||||
<string name="object_types_human">Human</string>
|
||||
<string name="object_type_settings_item_remove">Delete completely</string>
|
||||
<string name="object_type_settings_item_remove">Delete type</string>
|
||||
|
||||
<string name="chats_alert_delete_this_message_description">It cannot be restored after confirmation</string>
|
||||
<string name="chats_alert_delete_this_message">Delete this message?</string>
|
||||
|
|
|
@ -559,7 +559,7 @@ fun MDVView.toCoreModels(): DVViewer = DVViewer(
|
|||
coverFit = coverFit,
|
||||
coverRelationKey = coverRelationKey.ifEmpty { null },
|
||||
defaultTemplate = defaultTemplateId.ifEmpty { null },
|
||||
defaultObjectType = defaultObjectTypeId.ifEmpty { ObjectTypeIds.PAGE }
|
||||
defaultObjectType = defaultObjectTypeId.ifEmpty { null }
|
||||
)
|
||||
|
||||
fun MDVRelation.toCoreModels(): DVViewerRelation = DVViewerRelation(
|
||||
|
|
|
@ -1028,6 +1028,10 @@ fun CoroutineScope.logEvent(
|
|||
is ObjectState.DataView.Set -> {
|
||||
Pair("ot-set", state.viewerByIdOrFirst(currentViewId)?.type?.formattedName)
|
||||
}
|
||||
|
||||
is ObjectState.DataView.TypeSet -> {
|
||||
Pair("ot-set", state.viewerByIdOrFirst(currentViewId)?.type?.formattedName)
|
||||
}
|
||||
}
|
||||
val scope = this
|
||||
when (event) {
|
||||
|
@ -1054,6 +1058,18 @@ fun CoroutineScope.logEvent(
|
|||
spaceParams = spaceParams
|
||||
)
|
||||
)
|
||||
|
||||
is ObjectState.DataView.TypeSet -> scope.sendEvent(
|
||||
analytics = analytics,
|
||||
eventName = setScreenShow,
|
||||
startTime = startTime,
|
||||
middleTime = middleTime,
|
||||
props = buildProps(
|
||||
embedType = embedTypeDefault,
|
||||
type = viewerType,
|
||||
spaceParams = spaceParams
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
ObjectStateAnalyticsEvent.TURN_INTO_COLLECTION -> {
|
||||
|
@ -1244,7 +1260,7 @@ fun CoroutineScope.logEvent(
|
|||
ObjectStateAnalyticsEvent.OBJECT_CREATE -> {
|
||||
val route = when (state) {
|
||||
is ObjectState.DataView.Collection -> EventsDictionary.Routes.objCreateCollection
|
||||
is ObjectState.DataView.Set -> EventsDictionary.Routes.objCreateSet
|
||||
is ObjectState.DataView.Set, is ObjectState.DataView.TypeSet -> EventsDictionary.Routes.objCreateSet
|
||||
}
|
||||
scope.sendEvent(
|
||||
analytics = analytics,
|
||||
|
@ -1262,7 +1278,7 @@ fun CoroutineScope.logEvent(
|
|||
ObjectStateAnalyticsEvent.SELECT_TEMPLATE -> {
|
||||
val route = when (state) {
|
||||
is ObjectState.DataView.Collection -> EventsDictionary.Routes.objCreateCollection
|
||||
is ObjectState.DataView.Set -> EventsDictionary.Routes.objCreateSet
|
||||
is ObjectState.DataView.Set, is ObjectState.DataView.TypeSet -> EventsDictionary.Routes.objCreateSet
|
||||
}
|
||||
scope.sendEvent(
|
||||
analytics = analytics,
|
||||
|
@ -1278,7 +1294,7 @@ fun CoroutineScope.logEvent(
|
|||
ObjectStateAnalyticsEvent.SHOW_TEMPLATES -> {
|
||||
val route = when (state) {
|
||||
is ObjectState.DataView.Collection -> EventsDictionary.Routes.objCreateCollection
|
||||
is ObjectState.DataView.Set -> EventsDictionary.Routes.objCreateSet
|
||||
is ObjectState.DataView.Set, is ObjectState.DataView.TypeSet -> EventsDictionary.Routes.objCreateSet
|
||||
}
|
||||
scope.sendEvent(
|
||||
analytics = analytics,
|
||||
|
@ -1294,7 +1310,7 @@ fun CoroutineScope.logEvent(
|
|||
ObjectStateAnalyticsEvent.CREATE_TEMPLATE -> {
|
||||
val route = when (state) {
|
||||
is ObjectState.DataView.Collection -> EventsDictionary.Routes.objCreateCollection
|
||||
is ObjectState.DataView.Set -> EventsDictionary.Routes.objCreateSet
|
||||
is ObjectState.DataView.Set, is ObjectState.DataView.TypeSet -> EventsDictionary.Routes.objCreateSet
|
||||
}
|
||||
scope.sendEvent(
|
||||
analytics = analytics,
|
||||
|
@ -1312,7 +1328,7 @@ fun CoroutineScope.logEvent(
|
|||
ObjectStateAnalyticsEvent.EDIT_TEMPLATE -> {
|
||||
val route = when (state) {
|
||||
is ObjectState.DataView.Collection -> EventsDictionary.Routes.objCreateCollection
|
||||
is ObjectState.DataView.Set -> EventsDictionary.Routes.objCreateSet
|
||||
is ObjectState.DataView.Set, is ObjectState.DataView.TypeSet -> EventsDictionary.Routes.objCreateSet
|
||||
}
|
||||
scope.sendEvent(
|
||||
analytics = analytics,
|
||||
|
@ -1330,7 +1346,7 @@ fun CoroutineScope.logEvent(
|
|||
ObjectStateAnalyticsEvent.DUPLICATE_TEMPLATE -> {
|
||||
val route = when (state) {
|
||||
is ObjectState.DataView.Collection -> EventsDictionary.Routes.objCreateCollection
|
||||
is ObjectState.DataView.Set -> EventsDictionary.Routes.objCreateSet
|
||||
is ObjectState.DataView.Set, is ObjectState.DataView.TypeSet -> EventsDictionary.Routes.objCreateSet
|
||||
}
|
||||
scope.sendEvent(
|
||||
analytics = analytics,
|
||||
|
@ -1348,7 +1364,7 @@ fun CoroutineScope.logEvent(
|
|||
ObjectStateAnalyticsEvent.DELETE_TEMPLATE -> {
|
||||
val route = when (state) {
|
||||
is ObjectState.DataView.Collection -> EventsDictionary.Routes.objCreateCollection
|
||||
is ObjectState.DataView.Set -> EventsDictionary.Routes.objCreateSet
|
||||
is ObjectState.DataView.Set, is ObjectState.DataView.TypeSet -> EventsDictionary.Routes.objCreateSet
|
||||
}
|
||||
scope.sendEvent(
|
||||
analytics = analytics,
|
||||
|
@ -1366,7 +1382,7 @@ fun CoroutineScope.logEvent(
|
|||
ObjectStateAnalyticsEvent.SET_AS_DEFAULT_TYPE -> {
|
||||
val route = when (state) {
|
||||
is ObjectState.DataView.Collection -> EventsDictionary.Routes.objCreateCollection
|
||||
is ObjectState.DataView.Set -> EventsDictionary.Routes.objCreateSet
|
||||
is ObjectState.DataView.Set, is ObjectState.DataView.TypeSet -> EventsDictionary.Routes.objCreateSet
|
||||
}
|
||||
if (state.isChangingDefaultTypeAvailable()) {
|
||||
scope.sendEvent(
|
||||
|
@ -1386,7 +1402,7 @@ fun CoroutineScope.logEvent(
|
|||
ObjectStateAnalyticsEvent.CHANGE_DEFAULT_TEMPLATE -> {
|
||||
val route = when (state) {
|
||||
is ObjectState.DataView.Collection -> EventsDictionary.Routes.objCreateCollection
|
||||
is ObjectState.DataView.Set -> EventsDictionary.Routes.objCreateSet
|
||||
is ObjectState.DataView.Set, is ObjectState.DataView.TypeSet -> EventsDictionary.Routes.objCreateSet
|
||||
}
|
||||
scope.sendEvent(
|
||||
analytics = analytics,
|
||||
|
|
|
@ -62,6 +62,14 @@ class DataViewObjectRelationProvider(
|
|||
}
|
||||
}
|
||||
}
|
||||
is ObjectState.DataView.TypeSet -> {
|
||||
val objectKeys = state.dataViewContent.relationLinks.map { it.key }
|
||||
flow {
|
||||
objectKeys.mapNotNull {
|
||||
storeOfRelations.getByKey(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> emptyFlow()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ class DataViewObjectValueProvider(
|
|||
) : Struct = when (state) {
|
||||
is ObjectState.DataView.Collection -> state.details.getStruct(target).orEmpty()
|
||||
is ObjectState.DataView.Set -> state.details.getStruct(target).orEmpty()
|
||||
is ObjectState.DataView.TypeSet -> state.details.getStruct(target).orEmpty()
|
||||
else -> emptyMap()
|
||||
}
|
||||
}
|
||||
|
@ -81,6 +82,7 @@ class SetOrCollectionObjectValueProvider(
|
|||
) : Struct = when (state) {
|
||||
is ObjectState.DataView.Collection -> state.details.getStruct(target).orEmpty()
|
||||
is ObjectState.DataView.Set -> state.details.getStruct(target).orEmpty()
|
||||
is ObjectState.DataView.TypeSet -> state.details.getStruct(target).orEmpty()
|
||||
else -> emptyMap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,10 @@ interface ObjectRelationListProvider {
|
|||
state.details
|
||||
}
|
||||
|
||||
is ObjectState.DataView.TypeSet -> {
|
||||
state.details
|
||||
}
|
||||
|
||||
else -> ObjectViewDetails.EMPTY
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,30 @@ sealed class DataViewViewState {
|
|||
) : Set()
|
||||
}
|
||||
|
||||
sealed class TypeSet : DataViewViewState() {
|
||||
|
||||
abstract val isCreateObjectAllowed: Boolean
|
||||
abstract val isEditingViewAllowed: Boolean
|
||||
|
||||
data class NoItems(
|
||||
val title: String,
|
||||
override val isCreateObjectAllowed: Boolean = true,
|
||||
override val isEditingViewAllowed: Boolean = false
|
||||
) : TypeSet()
|
||||
|
||||
data class Default(
|
||||
val viewer: Viewer?,
|
||||
override val isCreateObjectAllowed: Boolean = true,
|
||||
override val isEditingViewAllowed: Boolean = false
|
||||
) : TypeSet()
|
||||
|
||||
data class Error(
|
||||
val msg: String,
|
||||
override val isCreateObjectAllowed: Boolean = false,
|
||||
override val isEditingViewAllowed: Boolean = false
|
||||
) : TypeSet()
|
||||
}
|
||||
|
||||
object Init: DataViewViewState()
|
||||
data class Error(val msg: String) : DataViewViewState()
|
||||
}
|
||||
|
|
|
@ -92,6 +92,19 @@ class ObjectSetCreateBookmarkRecordViewModel(
|
|||
) { isCompleted.value = true }
|
||||
}
|
||||
}
|
||||
|
||||
is ObjectState.DataView.TypeSet -> {
|
||||
val viewer = state.viewerByIdOrFirst(session.currentViewerId.value) ?: return
|
||||
val prefilled = viewer.prefillNewObjectDetails(
|
||||
dateProvider = dateProvider,
|
||||
storeOfRelations = storeOfRelations,
|
||||
dataViewRelationLinks = state.dataViewContent.relationLinks
|
||||
)
|
||||
createBookmark(
|
||||
input = input,
|
||||
details = prefilled
|
||||
) { isCompleted.value = true }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sendToast("Url is invalid.")
|
||||
|
|
|
@ -397,6 +397,10 @@ fun ObjectState.DataView.Set.getSetOfValue(ctx: Id): List<Id> {
|
|||
return details.getObject(ctx)?.setOf.orEmpty()
|
||||
}
|
||||
|
||||
fun ObjectState.DataView.TypeSet.getSetOfValue(ctx: Id): List<Id> {
|
||||
return details.getObject(ctx)?.setOf.orEmpty()
|
||||
}
|
||||
|
||||
fun ObjectState.DataView.filterOutDeletedAndMissingObjects(query: List<Id>): List<Id> {
|
||||
return query.filter(::isValidObject)
|
||||
}
|
||||
|
@ -488,6 +492,16 @@ suspend fun ObjectState.DataView.toViewersView(ctx: Id, session: ObjectSetSessio
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
is ObjectState.DataView.TypeSet -> {
|
||||
val setOfValue = getSetOfValue(ctx)
|
||||
mapViewers(
|
||||
defaultObjectType = { setOfValue.firstOrNull() },
|
||||
viewers = viewers,
|
||||
session = session,
|
||||
storeOfRelations = storeOfRelations
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -551,6 +565,23 @@ suspend fun ObjectState.DataView.getActiveViewTypeAndTemplate(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
is ObjectState.DataView.TypeSet -> {
|
||||
val setOfValue = getSetOfValue(ctx)
|
||||
val setOf = setOfValue.firstOrNull()
|
||||
return if (setOf.isNullOrBlank()) {
|
||||
Timber.d("Set by type setOf param is null or empty, not possible to get Type and Template")
|
||||
Pair(null, null)
|
||||
} else {
|
||||
val defaultSetObjectType = details.getTypeObject(setOf)
|
||||
if (activeView.defaultTemplate.isNullOrEmpty()) {
|
||||
val defaultTemplateId = defaultSetObjectType?.defaultTemplateId
|
||||
Pair(defaultSetObjectType, defaultTemplateId)
|
||||
} else {
|
||||
Pair(defaultSetObjectType, activeView.defaultTemplate)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -580,6 +611,7 @@ fun ObjectState.DataView.isChangingDefaultTypeAvailable(): Boolean {
|
|||
val setOfValue = getSetOfValue(root)
|
||||
isSetByRelation(setOfValue = setOfValue)
|
||||
}
|
||||
is ObjectState.DataView.TypeSet -> false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ import com.anytypeio.anytype.presentation.relations.ObjectSetConfig.DEFAULT_LIMI
|
|||
import com.anytypeio.anytype.presentation.relations.RelationListViewModel
|
||||
import com.anytypeio.anytype.presentation.relations.render
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
|
||||
import com.anytypeio.anytype.presentation.sets.ObjectSetCommand.Modal.*
|
||||
import com.anytypeio.anytype.presentation.sets.model.CellView
|
||||
import com.anytypeio.anytype.presentation.sets.model.Viewer
|
||||
import com.anytypeio.anytype.presentation.sets.state.ObjectState
|
||||
|
@ -479,6 +480,22 @@ class ObjectSetViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
is ObjectState.DataView.TypeSet -> {
|
||||
Timber.d("subscribeToObjectState, NEW TYPE SET STATE")
|
||||
if (query.state.isInitialized) {
|
||||
dataViewSubscription.startObjectTypeSetSubscription(
|
||||
space = vmParams.space.id,
|
||||
context = vmParams.ctx,
|
||||
state = query.state,
|
||||
currentViewerId = query.currentViewerId,
|
||||
offset = query.offset,
|
||||
dataViewRelationLinks = query.state.dataViewContent.relationLinks
|
||||
)
|
||||
} else {
|
||||
emptyFlow()
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
Timber.d("subscribeToObjectState, NEW STATE, ${query.state}")
|
||||
emptyFlow()
|
||||
|
@ -584,6 +601,12 @@ class ObjectSetViewModel(
|
|||
)
|
||||
ObjectState.Init -> DataViewViewState.Init
|
||||
ObjectState.ErrorLayout -> DataViewViewState.Error(msg = "Wrong layout, couldn't open object")
|
||||
is ObjectState.DataView.TypeSet -> processTypeSetState(
|
||||
dataViewState = dataViewState,
|
||||
objectState = objectState,
|
||||
currentViewId = currentViewId,
|
||||
permission = permission
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -726,6 +749,75 @@ class ObjectSetViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun processTypeSetState(
|
||||
dataViewState: DataViewState,
|
||||
objectState: ObjectState.DataView.TypeSet,
|
||||
currentViewId: String?,
|
||||
permission: SpaceMemberPermissions?
|
||||
): DataViewViewState {
|
||||
if (!objectState.isInitialized) return DataViewViewState.Init
|
||||
|
||||
val setOfValue = objectState.getSetOfValue(ctx = vmParams.ctx)
|
||||
val query = objectState.filterOutDeletedAndMissingObjects(query = setOfValue)
|
||||
val viewer = objectState.viewerByIdOrFirst(currentViewId)
|
||||
|
||||
return when (dataViewState) {
|
||||
DataViewState.Init -> {
|
||||
_dvViews.value = emptyList()
|
||||
when {
|
||||
setOfValue.isEmpty() || query.isEmpty() || viewer == null ->
|
||||
DataViewViewState.TypeSet.Error(msg = "Error while rendering viewer")
|
||||
else -> DataViewViewState.Init
|
||||
}
|
||||
}
|
||||
is DataViewState.Loaded -> {
|
||||
_dvViews.value = objectState.dataViewState()?.toViewersView(
|
||||
ctx = vmParams.ctx,
|
||||
session = session,
|
||||
storeOfRelations = storeOfRelations
|
||||
) ?: emptyList()
|
||||
val relations = objectState.dataViewContent.relationLinks.mapNotNull {
|
||||
storeOfRelations.getByKey(it.key)
|
||||
}
|
||||
val render = viewer?.render(
|
||||
coverImageHashProvider = coverImageHashProvider,
|
||||
builder = urlBuilder,
|
||||
objects = dataViewState.objects,
|
||||
dataViewRelations = relations,
|
||||
store = objectStore,
|
||||
storeOfRelations = storeOfRelations,
|
||||
fieldParser = fieldParser
|
||||
)
|
||||
|
||||
when {
|
||||
render == null || query.isEmpty() || setOfValue.isEmpty() -> DataViewViewState.TypeSet.Error(
|
||||
msg = "Error while rendering viewer",
|
||||
)
|
||||
render.isEmpty() -> {
|
||||
val (defType, _) = objectState.getActiveViewTypeAndTemplate(
|
||||
vmParams.ctx, viewer, storeOfObjectTypes
|
||||
)
|
||||
DataViewViewState.TypeSet.NoItems(
|
||||
title = render.title,
|
||||
isCreateObjectAllowed = objectState.isCreateObjectAllowed(defType) && (permission?.isOwnerOrEditor() == true),
|
||||
isEditingViewAllowed = permission?.isOwnerOrEditor() == true
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
val (defType, _) = objectState.getActiveViewTypeAndTemplate(
|
||||
vmParams.ctx, viewer, storeOfObjectTypes
|
||||
)
|
||||
DataViewViewState.TypeSet.Default(
|
||||
viewer = render,
|
||||
isCreateObjectAllowed = objectState.isCreateObjectAllowed(defType) && (permission?.isOwnerOrEditor() == true),
|
||||
isEditingViewAllowed = permission?.isOwnerOrEditor() == true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun renderViewer(
|
||||
objectState: ObjectState.DataView.Collection,
|
||||
dataViewState: DataViewState.Loaded,
|
||||
|
@ -1015,7 +1107,7 @@ class ObjectSetViewModel(
|
|||
}
|
||||
|
||||
// TODO Multispaces refactor this method
|
||||
private suspend fun proceedWithCreatingSetObject(currentState: ObjectState.DataView.Set, templateChosenBy: Id?) {
|
||||
private suspend fun proceedWithCreatingSetObject(currentState: ObjectState.DataView, templateChosenBy: Id?) {
|
||||
if (isRestrictionPresent(DataViewRestriction.CREATE_OBJECT)) {
|
||||
toast(NOT_ALLOWED)
|
||||
} else {
|
||||
|
@ -1687,6 +1779,10 @@ class ObjectSetViewModel(
|
|||
dispatch(ObjectSetCommand.ShowOnlyAccessError)
|
||||
}
|
||||
}
|
||||
|
||||
is ObjectState.DataView.TypeSet -> {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
|
@ -2687,6 +2783,13 @@ class ObjectSetViewModel(
|
|||
templateChosenBy = templateId
|
||||
)
|
||||
}
|
||||
|
||||
is ObjectState.DataView.TypeSet -> {
|
||||
proceedWithCreatingSetObject(
|
||||
currentState = state,
|
||||
templateChosenBy = templateId
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,6 +133,12 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
details = ObjectViewDetails(event.details),
|
||||
dataViewRestrictions = event.dataViewRestrictions
|
||||
)
|
||||
ObjectType.Layout.OBJECT_TYPE.code -> ObjectState.DataView.TypeSet(
|
||||
root = event.root,
|
||||
blocks = event.blocks,
|
||||
details = ObjectViewDetails(event.details),
|
||||
dataViewRestrictions = event.dataViewRestrictions
|
||||
)
|
||||
else -> {
|
||||
Timber.e("Wrong layout type: $layout")
|
||||
ObjectState.ErrorLayout
|
||||
|
@ -157,6 +163,10 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
target = event.target,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
is ObjectState.DataView.TypeSet -> state.updateBlockContent(
|
||||
target = event.target,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
@ -184,6 +194,10 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
target = event.target,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
is ObjectState.DataView.TypeSet -> state.updateBlockContent(
|
||||
target = event.target,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
@ -211,6 +225,10 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
target = event.dv,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
is ObjectState.DataView.TypeSet -> state.updateBlockContent(
|
||||
target = event.dv,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
@ -236,6 +254,10 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
target = event.dv,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
is ObjectState.DataView.TypeSet -> state.updateBlockContent(
|
||||
target = event.dv,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
@ -261,6 +283,10 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
target = event.dv,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
is ObjectState.DataView.TypeSet -> state.updateBlockContent(
|
||||
target = event.dv,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
@ -284,6 +310,10 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
target = event.dv,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
is ObjectState.DataView.TypeSet -> state.updateBlockContent(
|
||||
target = event.dv,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
@ -360,6 +390,10 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
target = event.block,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
is ObjectState.DataView.TypeSet -> state.updateBlockContent(
|
||||
target = event.block,
|
||||
blockContentUpdate = updateBlockContent
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
@ -390,6 +424,15 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
)
|
||||
)
|
||||
}
|
||||
is ObjectState.DataView.TypeSet -> {
|
||||
state.copy(
|
||||
details = ObjectViewDetails(
|
||||
details = state.details.details.toMutableMap().apply {
|
||||
put(event.target, event.details)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
@ -418,6 +461,14 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
)
|
||||
)
|
||||
)
|
||||
is ObjectState.DataView.TypeSet -> state.copy(
|
||||
details = state.details.copy(
|
||||
details = state.details.details.amend(
|
||||
target = event.target,
|
||||
slice = event.details
|
||||
)
|
||||
)
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
@ -446,6 +497,14 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
)
|
||||
)
|
||||
)
|
||||
is ObjectState.DataView.TypeSet -> state.copy(
|
||||
details = state.details.copy(
|
||||
details = state.details.details.unset(
|
||||
target = event.target,
|
||||
keys = event.keys
|
||||
)
|
||||
)
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
@ -470,6 +529,12 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
target = { block -> block.id == event.id }
|
||||
)
|
||||
)
|
||||
is ObjectState.DataView.TypeSet -> state.copy(
|
||||
blocks = state.blocks.replace(
|
||||
replacement = { target -> target.copy(children = event.children) },
|
||||
target = { block -> block.id == event.id }
|
||||
)
|
||||
)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
@ -481,6 +546,7 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
return when (state) {
|
||||
is ObjectState.DataView.Collection -> state.copy(blocks = state.blocks + event.blocks)
|
||||
is ObjectState.DataView.Set -> state.copy(blocks = state.blocks + event.blocks)
|
||||
is ObjectState.DataView.TypeSet -> state.copy(blocks = state.blocks + event.blocks)
|
||||
ObjectState.Init -> state
|
||||
ObjectState.ErrorLayout -> state
|
||||
}
|
||||
|
@ -502,6 +568,7 @@ class DefaultObjectStateReducer : ObjectStateReducer {
|
|||
return when (this) {
|
||||
is ObjectState.DataView.Collection -> copy(blocks = updatedBlocks)
|
||||
is ObjectState.DataView.Set -> copy(blocks = updatedBlocks)
|
||||
is ObjectState.DataView.TypeSet -> copy(blocks = updatedBlocks)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,20 @@ sealed class ObjectState {
|
|||
override val dataViewContent get() = dataViewBlock.content as DV
|
||||
override val viewers get() = dataViewContent.viewers
|
||||
}
|
||||
|
||||
data class TypeSet(
|
||||
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(),
|
||||
) : DataView() {
|
||||
|
||||
override val isInitialized get() = blocks.any { it.content is DV }
|
||||
override val dataViewBlock get() = blocks.first { it.content is DV }
|
||||
override val dataViewContent get() = dataViewBlock.content as DV
|
||||
override val viewers get() = dataViewContent.viewers
|
||||
}
|
||||
}
|
||||
|
||||
object Init : ObjectState() {
|
||||
|
|
|
@ -40,6 +40,15 @@ interface DataViewSubscription {
|
|||
dataViewRelationLinks: List<RelationLink>
|
||||
): Flow<DataViewState>
|
||||
|
||||
suspend fun startObjectTypeSetSubscription(
|
||||
context: Id,
|
||||
space: Id,
|
||||
state: ObjectState.DataView.TypeSet,
|
||||
currentViewerId: Id?,
|
||||
offset: Long,
|
||||
dataViewRelationLinks: List<RelationLink>
|
||||
): Flow<DataViewState>
|
||||
|
||||
suspend fun unsubscribe(ids: List<Id>)
|
||||
}
|
||||
|
||||
|
@ -139,6 +148,59 @@ class DefaultDataViewSubscription(
|
|||
return dataViewSubscriptionContainer.observe(params)
|
||||
}
|
||||
|
||||
override suspend fun startObjectTypeSetSubscription(
|
||||
context: Id,
|
||||
space: Id,
|
||||
state: ObjectState.DataView.TypeSet,
|
||||
currentViewerId: Id?,
|
||||
offset: Long,
|
||||
dataViewRelationLinks: List<RelationLink>
|
||||
): Flow<DataViewState> {
|
||||
if (context.isEmpty()) {
|
||||
Timber.w("Data view TypeSet subscription: context is empty")
|
||||
return emptyFlow()
|
||||
}
|
||||
val activeViewer = state.viewerByIdOrFirst(currentViewerId)
|
||||
if (activeViewer == null) {
|
||||
Timber.w("Data view TypeSet subscription: active viewer is null")
|
||||
return emptyFlow()
|
||||
}
|
||||
|
||||
val setOfValue = state.getSetOfValue(ctx = context)
|
||||
if (setOfValue.isEmpty()) {
|
||||
Timber.w("Data view TypeSet subscription: setOf value is empty, proceed without subscription")
|
||||
return emptyFlow()
|
||||
}
|
||||
|
||||
val query = state.filterOutDeletedAndMissingObjects(setOfValue)
|
||||
if (query.isEmpty()) {
|
||||
Timber.w(
|
||||
"Data view TypeSet subscription: query has no valid types or relations, " +
|
||||
"proceed without subscription"
|
||||
)
|
||||
return emptyFlow()
|
||||
}
|
||||
|
||||
val filters = buildList {
|
||||
addAll(activeViewer.filters.updateFormatForSubscription(relationLinks = dataViewRelationLinks))
|
||||
addAll(defaultDataViewFilters())
|
||||
}
|
||||
val dataViewLinksKeys = state.dataViewContent.relationLinks.map { it.key }
|
||||
val keys = ObjectSearchConstants.defaultDataViewKeys + dataViewLinksKeys
|
||||
|
||||
val params = DataViewSubscriptionContainer.Params(
|
||||
space = SpaceId(space),
|
||||
subscription = getDataViewSubscriptionId(context),
|
||||
sorts = activeViewer.sorts.updateWithRelationFormat(relationLinks = dataViewRelationLinks),
|
||||
filters = filters,
|
||||
sources = query,
|
||||
keys = keys,
|
||||
limit = ObjectSetConfig.DEFAULT_LIMIT,
|
||||
offset = offset
|
||||
)
|
||||
return dataViewSubscriptionContainer.observe(params)
|
||||
}
|
||||
|
||||
override suspend fun unsubscribe(ids: List<Id>) {
|
||||
dataViewSubscriptionContainer.unsubscribe(ids)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue