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
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue