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:
parent
6ad8e54721
commit
546ab62b6c
23 changed files with 821 additions and 154 deletions
|
@ -3,10 +3,13 @@ package com.anytypeio.anytype.feature_properties
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_ui.extensions.simpleIcon
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
|
@ -24,6 +27,8 @@ import com.anytypeio.anytype.feature_properties.edit.UiEditPropertyState
|
|||
import com.anytypeio.anytype.feature_properties.edit.UiEditPropertyState.Visible.*
|
||||
import com.anytypeio.anytype.feature_properties.edit.UiPropertyFormatsListState
|
||||
import com.anytypeio.anytype.feature_properties.edit.UiPropertyFormatsListState.*
|
||||
import com.anytypeio.anytype.feature_properties.edit.UiPropertyLimitTypeItem
|
||||
import com.anytypeio.anytype.presentation.mapper.objectIcon
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
@ -47,7 +52,8 @@ class EditTypePropertiesViewModel(
|
|||
private val stringResourceProvider: StringResourceProvider,
|
||||
private val createRelation: CreateRelation,
|
||||
private val setObjectDetails: SetObjectDetails,
|
||||
private val setObjectTypeRecommendedFields: SetObjectTypeRecommendedFields
|
||||
private val setObjectTypeRecommendedFields: SetObjectTypeRecommendedFields,
|
||||
private val urlBuilder: UrlBuilder
|
||||
) : ViewModel() {
|
||||
|
||||
private val _uiState = MutableStateFlow(UiEditTypePropertiesState.Companion.EMPTY)
|
||||
|
@ -193,12 +199,16 @@ class EditTypePropertiesViewModel(
|
|||
when (event) {
|
||||
is UiEditTypePropertiesEvent.OnCreate -> {
|
||||
val format = event.item.format
|
||||
uiPropertyEditState.value = New(
|
||||
name = event.item.title,
|
||||
formatName = stringResourceProvider.getPropertiesFormatPrettyString(format),
|
||||
formatIcon = format.simpleIcon(),
|
||||
format = format,
|
||||
)
|
||||
viewModelScope.launch {
|
||||
uiPropertyEditState.value = New(
|
||||
name = event.item.title,
|
||||
formatName = stringResourceProvider.getPropertiesFormatPrettyString(format),
|
||||
formatIcon = format.simpleIcon(),
|
||||
format = format,
|
||||
showLimitTypes = false,
|
||||
limitObjectTypes = getAllObjectTypesByFormat(format)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is UiEditTypePropertiesEvent.OnExistingClicked -> {
|
||||
|
@ -217,13 +227,17 @@ class EditTypePropertiesViewModel(
|
|||
}
|
||||
|
||||
is UiEditTypePropertiesEvent.OnTypeClicked -> {
|
||||
val format = event.item.format
|
||||
uiPropertyEditState.value = New(
|
||||
name = "",
|
||||
formatName = stringResourceProvider.getPropertiesFormatPrettyString(format),
|
||||
formatIcon = format.simpleIcon(),
|
||||
format = format,
|
||||
)
|
||||
viewModelScope.launch {
|
||||
val format = event.item.format
|
||||
uiPropertyEditState.value = New(
|
||||
name = "",
|
||||
formatName = stringResourceProvider.getPropertiesFormatPrettyString(format),
|
||||
formatIcon = format.simpleIcon(),
|
||||
format = format,
|
||||
showLimitTypes = false,
|
||||
limitObjectTypes = getAllObjectTypesByFormat(format)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
UiEditTypePropertiesEvent.OnEditPropertyScreenDismissed -> {
|
||||
|
@ -263,23 +277,56 @@ class EditTypePropertiesViewModel(
|
|||
}
|
||||
|
||||
is UiEditTypePropertiesEvent.OnPropertyFormatSelected -> {
|
||||
uiPropertyFormatsListState.value = Hidden
|
||||
val state = uiPropertyEditState.value as? UiEditPropertyState.Visible ?: return
|
||||
uiPropertyEditState.value = when (state) {
|
||||
is New -> {
|
||||
val newFormat = event.format.format
|
||||
state.copy(
|
||||
formatName = stringResourceProvider.getPropertiesFormatPrettyString(
|
||||
newFormat
|
||||
),
|
||||
formatIcon = newFormat.simpleIcon(),
|
||||
format = newFormat,
|
||||
)
|
||||
}
|
||||
viewModelScope.launch {
|
||||
uiPropertyFormatsListState.value = Hidden
|
||||
val state = uiPropertyEditState.value as? UiEditPropertyState.Visible ?: return@launch
|
||||
uiPropertyEditState.value = when (state) {
|
||||
is New -> {
|
||||
val newFormat = event.format.format
|
||||
state.copy(
|
||||
formatName = stringResourceProvider.getPropertiesFormatPrettyString(
|
||||
newFormat
|
||||
),
|
||||
formatIcon = newFormat.simpleIcon(),
|
||||
format = newFormat,
|
||||
limitObjectTypes = getAllObjectTypesByFormat(newFormat),
|
||||
selectedLimitTypeIds = emptyList(),
|
||||
showLimitTypes = false
|
||||
)
|
||||
}
|
||||
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UiEditTypePropertiesEvent.OnLimitTypesClick -> {
|
||||
uiPropertyEditState.value = when (val state = uiPropertyEditState.value) {
|
||||
is New -> state.copy(showLimitTypes = true)
|
||||
is View -> state.copy(showLimitTypes = true)
|
||||
is Edit -> state.copy(showLimitTypes = true)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
||||
UiEditTypePropertiesEvent.OnLimitTypesDismiss -> {
|
||||
uiPropertyEditState.value = when (val state = uiPropertyEditState.value) {
|
||||
is New -> state.copy(showLimitTypes = false)
|
||||
is View -> state.copy(showLimitTypes = false)
|
||||
is Edit -> state.copy(showLimitTypes = false)
|
||||
else -> state
|
||||
}
|
||||
}
|
||||
|
||||
is UiEditTypePropertiesEvent.OnLimitTypesDoneClick -> {
|
||||
val state = uiPropertyEditState.value as? New ?: return.also {
|
||||
Timber.e("Possible only for New state")
|
||||
}
|
||||
uiPropertyEditState.value = state.copy(
|
||||
selectedLimitTypeIds = event.items,
|
||||
showLimitTypes = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
@ -310,17 +357,12 @@ class EditTypePropertiesViewModel(
|
|||
|
||||
private fun proceedWithCreatingRelation() {
|
||||
viewModelScope.launch {
|
||||
val state = uiPropertyEditState.value as? UiEditPropertyState.Visible ?: return@launch
|
||||
val (name, format) = when (state) {
|
||||
is UiEditPropertyState.Visible.Edit -> state.name to state.format
|
||||
is UiEditPropertyState.Visible.View -> state.name to state.format
|
||||
is UiEditPropertyState.Visible.New -> state.name to state.format
|
||||
}
|
||||
val state = uiPropertyEditState.value as? New ?: return@launch
|
||||
val params = CreateRelation.Params(
|
||||
space = vmParams.spaceId.id,
|
||||
format = format,
|
||||
name = name,
|
||||
limitObjectTypes = emptyList(),
|
||||
format = state.format,
|
||||
name = state.name,
|
||||
limitObjectTypes = state.selectedLimitTypeIds,
|
||||
prefilled = emptyMap()
|
||||
)
|
||||
createRelation(params).process(
|
||||
|
@ -366,6 +408,39 @@ class EditTypePropertiesViewModel(
|
|||
}
|
||||
//endregion
|
||||
|
||||
//region Limit Object Types
|
||||
|
||||
private suspend fun getAllObjectTypesByFormat(format: RelationFormat): List<UiPropertyLimitTypeItem> {
|
||||
if (format != RelationFormat.OBJECT) return emptyList()
|
||||
return storeOfObjectTypes.getAll().mapNotNull { type ->
|
||||
when (type.recommendedLayout) {
|
||||
ObjectType.Layout.RELATION,
|
||||
ObjectType.Layout.DASHBOARD,
|
||||
ObjectType.Layout.SPACE,
|
||||
ObjectType.Layout.RELATION_OPTION_LIST,
|
||||
ObjectType.Layout.RELATION_OPTION,
|
||||
ObjectType.Layout.SPACE_VIEW,
|
||||
ObjectType.Layout.CHAT,
|
||||
ObjectType.Layout.DATE,
|
||||
ObjectType.Layout.OBJECT_TYPE,
|
||||
ObjectType.Layout.CHAT_DERIVED,
|
||||
ObjectType.Layout.TAG -> {
|
||||
null
|
||||
}
|
||||
else -> {
|
||||
UiPropertyLimitTypeItem(
|
||||
id = type.id,
|
||||
name = type.name.orEmpty(),
|
||||
icon = type.objectIcon(),
|
||||
uniqueKey = type.uniqueKey
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
//region Commands
|
||||
sealed class EditTypePropertiesCommand {
|
||||
data object Exit : EditTypePropertiesCommand()
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.anytypeio.anytype.feature_properties
|
|||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
|
@ -18,7 +19,8 @@ class EditTypePropertiesViewModelFactory @Inject constructor(
|
|||
private val createRelation: CreateRelation,
|
||||
private val setObjectDetails: SetObjectDetails,
|
||||
private val storeOfObjectTypes: StoreOfObjectTypes,
|
||||
private val setObjectTypeRecommendedFields: SetObjectTypeRecommendedFields
|
||||
private val setObjectTypeRecommendedFields: SetObjectTypeRecommendedFields,
|
||||
private val urlBuilder: UrlBuilder
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -30,6 +32,7 @@ class EditTypePropertiesViewModelFactory @Inject constructor(
|
|||
createRelation = createRelation,
|
||||
setObjectDetails = setObjectDetails,
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
setObjectTypeRecommendedFields = setObjectTypeRecommendedFields
|
||||
setObjectTypeRecommendedFields = setObjectTypeRecommendedFields,
|
||||
urlBuilder = urlBuilder
|
||||
) as T
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package com.anytypeio.anytype.feature_properties.add
|
||||
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
|
||||
sealed class UiEditTypePropertiesEvent {
|
||||
data class OnSearchQueryChanged(val query: String) : UiEditTypePropertiesEvent()
|
||||
data class OnCreate(val item: UiEditTypePropertiesItem.Create) : UiEditTypePropertiesEvent()
|
||||
|
@ -10,6 +12,10 @@ sealed class UiEditTypePropertiesEvent {
|
|||
data object OnEditPropertyScreenDismissed : UiEditTypePropertiesEvent()
|
||||
data class OnPropertyNameUpdate(val name: String) : UiEditTypePropertiesEvent()
|
||||
|
||||
data object OnLimitTypesClick : UiEditTypePropertiesEvent()
|
||||
data object OnLimitTypesDismiss : UiEditTypePropertiesEvent()
|
||||
data class OnLimitTypesDoneClick(val items: List<Id>) : UiEditTypePropertiesEvent()
|
||||
|
||||
data object OnPropertyFormatClick : UiEditTypePropertiesEvent()
|
||||
data object OnPropertyFormatsListDismiss : UiEditTypePropertiesEvent()
|
||||
data class OnPropertyFormatSelected(val format: UiEditTypePropertiesItem.Format) : UiEditTypePropertiesEvent()
|
||||
|
|
|
@ -183,6 +183,15 @@ fun AddFieldScreen(
|
|||
},
|
||||
onSaveButtonClicked = {
|
||||
event(UiEditTypePropertiesEvent.OnSaveButtonClicked)
|
||||
},
|
||||
onLimitTypesClick = {
|
||||
event(UiEditTypePropertiesEvent.OnLimitTypesClick)
|
||||
},
|
||||
onDismissLimitTypes = {
|
||||
event(UiEditTypePropertiesEvent.OnLimitTypesDismiss)
|
||||
},
|
||||
onLimitObjectTypesDoneClick = {
|
||||
event(UiEditTypePropertiesEvent.OnLimitTypesDoneClick(it))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ sealed class UiEditPropertyState {
|
|||
val formatIcon: Int?,
|
||||
val format: RelationFormat,
|
||||
val limitObjectTypes: List<UiPropertyLimitTypeItem> = emptyList(),
|
||||
val isPossibleToUnlinkFromType: Boolean
|
||||
val isPossibleToUnlinkFromType: Boolean,
|
||||
val showLimitTypes: Boolean
|
||||
) : Visible()
|
||||
|
||||
data class New(
|
||||
|
@ -26,7 +27,9 @@ sealed class UiEditPropertyState {
|
|||
val formatName: String,
|
||||
val formatIcon: Int?,
|
||||
val format: RelationFormat,
|
||||
val limitObjectTypes: List<UiPropertyLimitTypeItem> = emptyList()
|
||||
val limitObjectTypes: List<UiPropertyLimitTypeItem> = emptyList(),
|
||||
val selectedLimitTypeIds: List<Id> = emptyList(),
|
||||
val showLimitTypes: Boolean
|
||||
) : Visible()
|
||||
|
||||
data class View(
|
||||
|
@ -37,13 +40,26 @@ sealed class UiEditPropertyState {
|
|||
val formatIcon: Int?,
|
||||
val format: RelationFormat,
|
||||
val limitObjectTypes: List<UiPropertyLimitTypeItem> = emptyList(),
|
||||
val isPossibleToUnlinkFromType: Boolean
|
||||
val isPossibleToUnlinkFromType: Boolean,
|
||||
val showLimitTypes: Boolean
|
||||
) : Visible()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class UiPropertyLimitTypesScreen {
|
||||
data class Visible(
|
||||
val items: List<UiPropertyLimitTypeItem>
|
||||
) : UiPropertyLimitTypesScreen()
|
||||
|
||||
data object Hidden : UiPropertyLimitTypesScreen()
|
||||
}
|
||||
|
||||
data class UiPropertyLimitTypeItem(
|
||||
val id: Id, val key: Key, val title: String, val icon: ObjectIcon
|
||||
val id: Id,
|
||||
val name: String,
|
||||
val icon: ObjectIcon? = null,
|
||||
val uniqueKey: Key? = null,
|
||||
val number: Int? = null
|
||||
)
|
||||
|
||||
sealed class UiPropertyFormatsListState {
|
||||
|
|
|
@ -40,6 +40,7 @@ import com.anytypeio.anytype.core_ui.views.BodyRegular
|
|||
import com.anytypeio.anytype.core_ui.views.ButtonPrimary
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonSize
|
||||
import com.anytypeio.anytype.feature_properties.edit.UiEditPropertyState
|
||||
import com.anytypeio.anytype.feature_properties.edit.ui.limit_types.PropertyLimitTypesPreviewScreen
|
||||
|
||||
@Composable
|
||||
fun PropertyEditScreen(
|
||||
|
@ -49,7 +50,8 @@ fun PropertyEditScreen(
|
|||
onFormatClick: () -> Unit,
|
||||
onLimitTypesClick: () -> Unit,
|
||||
onPropertyNameUpdate: (String) -> Unit,
|
||||
onMenuUnlinkClick: (Id) -> Unit
|
||||
onMenuUnlinkClick: (Id) -> Unit,
|
||||
onDismissLimitTypes: () -> Unit
|
||||
) {
|
||||
|
||||
var innerValue by remember(uiState.name) { mutableStateOf(uiState.name) }
|
||||
|
@ -144,9 +146,9 @@ fun PropertyEditScreen(
|
|||
Divider()
|
||||
|
||||
if (uiState.format == RelationFormat.OBJECT) {
|
||||
PropertyLimitTypesEditSection(
|
||||
PropertyLimitTypesViewSection(
|
||||
limit = uiState.limitObjectTypes.size,
|
||||
onLimitTypesClick = { onLimitTypesClick() }
|
||||
onLimitTypesClick = onLimitTypesClick
|
||||
)
|
||||
Divider()
|
||||
}
|
||||
|
@ -167,6 +169,13 @@ fun PropertyEditScreen(
|
|||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
}
|
||||
|
||||
if (uiState.showLimitTypes) {
|
||||
PropertyLimitTypesPreviewScreen(
|
||||
items = uiState.limitObjectTypes,
|
||||
onDismissRequest = onDismissLimitTypes,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DefaultPreviews
|
||||
|
@ -182,12 +191,14 @@ fun EditPropertyPreview() {
|
|||
formatIcon = R.drawable.ic_relation_format_date_small,
|
||||
limitObjectTypes = emptyList(),
|
||||
format = RelationFormat.OBJECT,
|
||||
isPossibleToUnlinkFromType = true
|
||||
isPossibleToUnlinkFromType = true,
|
||||
showLimitTypes = false
|
||||
),
|
||||
onSaveButtonClicked = {},
|
||||
onFormatClick = {},
|
||||
onLimitTypesClick = {},
|
||||
onPropertyNameUpdate = {},
|
||||
onMenuUnlinkClick = {}
|
||||
onMenuUnlinkClick = {},
|
||||
onDismissLimitTypes = {}
|
||||
)
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package com.anytypeio.anytype.feature_properties.edit.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.SwitchDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.views.BodyRegular
|
||||
|
||||
@Composable
|
||||
fun PropertyIncludeTimeSection(
|
||||
modifier: Modifier,
|
||||
isIncluded: Boolean,
|
||||
isEditable: Boolean,
|
||||
onChangeIncludeTimeClick: () -> Unit
|
||||
) {
|
||||
Box(modifier = modifier) {
|
||||
Text(
|
||||
modifier = Modifier.align(Alignment.CenterStart),
|
||||
text = stringResource(id = R.string.property_include_time_section),
|
||||
style = BodyRegular,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
|
||||
var checked = remember { mutableStateOf(isIncluded) }
|
||||
|
||||
Switch(
|
||||
modifier = Modifier.align(Alignment.CenterEnd),
|
||||
checked = checked.value,
|
||||
onCheckedChange = {
|
||||
checked.value = it
|
||||
},
|
||||
enabled = isEditable,
|
||||
colors = SwitchDefaults.colors(
|
||||
checkedThumbColor = colorResource(id = R.color.white),
|
||||
disabledCheckedThumbColor = colorResource(id = R.color.white),
|
||||
uncheckedThumbColor = colorResource(id = R.color.white),
|
||||
disabledUncheckedThumbColor = colorResource(id = R.color.white),
|
||||
|
||||
checkedTrackColor = colorResource(id = R.color.palette_system_amber_50),
|
||||
disabledCheckedTrackColor = colorResource(id = R.color.palette_system_amber_50_opacity_12),
|
||||
uncheckedTrackColor = colorResource(id = R.color.shape_secondary),
|
||||
disabledUncheckedTrackColor = colorResource(id = R.color.shape_tertiary),
|
||||
|
||||
disabledUncheckedBorderColor = Color.Transparent,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.height
|
|||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
|
@ -19,6 +20,7 @@ import androidx.compose.ui.focus.FocusRequester
|
|||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
|
||||
|
@ -27,15 +29,19 @@ import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
|
|||
import com.anytypeio.anytype.core_ui.views.ButtonPrimary
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonSize
|
||||
import com.anytypeio.anytype.feature_properties.edit.UiEditPropertyState
|
||||
import com.anytypeio.anytype.feature_properties.edit.ui.limit_types.PropertyLimitTypesEditScreen
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun PropertyNewScreen(
|
||||
modifier: Modifier,
|
||||
uiState: UiEditPropertyState.Visible.New,
|
||||
onDismissLimitTypes: () -> Unit,
|
||||
onCreateNewButtonClicked: () -> Unit,
|
||||
onFormatClick: () -> Unit,
|
||||
onPropertyNameUpdate: (String) -> Unit,
|
||||
onLimitTypesClick: () -> Unit,
|
||||
onPropertyNameUpdate: (String) -> Unit
|
||||
onLimitObjectTypesDoneClick: (List<Id>) -> Unit
|
||||
) {
|
||||
|
||||
var innerValue by remember(uiState.name) { mutableStateOf(uiState.name) }
|
||||
|
@ -85,8 +91,12 @@ fun PropertyNewScreen(
|
|||
|
||||
if (uiState.format == RelationFormat.OBJECT) {
|
||||
PropertyLimitTypesEditSection(
|
||||
limit = uiState.limitObjectTypes.size,
|
||||
onLimitTypesClick = { onLimitTypesClick() }
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.height(52.dp)
|
||||
.padding(horizontal = 20.dp)
|
||||
.noRippleThrottledClickable { onLimitTypesClick() },
|
||||
limit = uiState.selectedLimitTypeIds.size,
|
||||
)
|
||||
Divider()
|
||||
}
|
||||
|
@ -107,6 +117,15 @@ fun PropertyNewScreen(
|
|||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
}
|
||||
|
||||
if (uiState.showLimitTypes) {
|
||||
PropertyLimitTypesEditScreen(
|
||||
items = uiState.limitObjectTypes,
|
||||
savedSelectedItemIds = uiState.selectedLimitTypeIds,
|
||||
onDismissRequest = onDismissLimitTypes,
|
||||
onDoneClick = onLimitObjectTypesDoneClick
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DefaultPreviews
|
||||
|
@ -119,10 +138,14 @@ fun MyPreviewNew() {
|
|||
formatName = "Text",
|
||||
format = RelationFormat.OBJECT,
|
||||
formatIcon = R.drawable.ic_relation_format_date_small,
|
||||
showLimitTypes = false,
|
||||
limitObjectTypes = listOf()
|
||||
),
|
||||
onCreateNewButtonClicked = {},
|
||||
onFormatClick = {},
|
||||
onPropertyNameUpdate = {},
|
||||
onLimitTypesClick = {},
|
||||
onPropertyNameUpdate = {}
|
||||
onDismissLimitTypes = {},
|
||||
onLimitObjectTypesDoneClick = {}
|
||||
)
|
||||
}
|
|
@ -6,10 +6,12 @@ import androidx.compose.foundation.layout.Box
|
|||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
|
@ -52,8 +54,10 @@ fun PropertyScreen(
|
|||
onLimitTypesClick: () -> Unit = {},
|
||||
onCreateNewButtonClicked: () -> Unit = {},
|
||||
onDismissRequest: () -> Unit,
|
||||
onDismissLimitTypes: () -> Unit = {},
|
||||
onPropertyNameUpdate: (String) -> Unit,
|
||||
onMenuUnlinkClick: (Id) -> Unit ={}
|
||||
onMenuUnlinkClick: (Id) -> Unit ={},
|
||||
onLimitObjectTypesDoneClick: (List<Id>) -> Unit = {}
|
||||
) {
|
||||
val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
ModalBottomSheet(
|
||||
|
@ -73,7 +77,8 @@ fun PropertyScreen(
|
|||
onFormatClick = onFormatClick,
|
||||
onLimitTypesClick = onLimitTypesClick,
|
||||
onPropertyNameUpdate = onPropertyNameUpdate,
|
||||
onMenuUnlinkClick = onMenuUnlinkClick
|
||||
onMenuUnlinkClick = onMenuUnlinkClick,
|
||||
onDismissLimitTypes = onDismissLimitTypes
|
||||
)
|
||||
|
||||
is UiEditPropertyState.Visible.View -> PropertyViewScreen(
|
||||
|
@ -81,7 +86,8 @@ fun PropertyScreen(
|
|||
uiState = uiState,
|
||||
onFormatClick = onFormatClick,
|
||||
onLimitTypesClick = onLimitTypesClick,
|
||||
onMenuUnlinkClick = onMenuUnlinkClick
|
||||
onMenuUnlinkClick = onMenuUnlinkClick,
|
||||
onDismissLimitTypes = onDismissLimitTypes
|
||||
)
|
||||
|
||||
is UiEditPropertyState.Visible.New -> PropertyNewScreen(
|
||||
|
@ -89,8 +95,10 @@ fun PropertyScreen(
|
|||
uiState = uiState,
|
||||
onCreateNewButtonClicked = onCreateNewButtonClicked,
|
||||
onFormatClick = onFormatClick,
|
||||
onPropertyNameUpdate = onPropertyNameUpdate,
|
||||
onLimitTypesClick = onLimitTypesClick,
|
||||
onPropertyNameUpdate = onPropertyNameUpdate
|
||||
onDismissLimitTypes = onDismissLimitTypes,
|
||||
onLimitObjectTypesDoneClick = onLimitObjectTypesDoneClick
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -213,16 +221,10 @@ fun PropertyFormatSection(
|
|||
|
||||
@Composable
|
||||
fun PropertyLimitTypesEditSection(
|
||||
modifier: Modifier,
|
||||
limit: Int,
|
||||
onLimitTypesClick: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(52.dp)
|
||||
.padding(horizontal = 20.dp)
|
||||
.noRippleThrottledClickable { onLimitTypesClick() }
|
||||
) {
|
||||
Box(modifier = modifier) {
|
||||
Row(
|
||||
modifier = Modifier.align(Alignment.CenterEnd),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
|
@ -267,29 +269,55 @@ fun PropertyLimitTypesViewSection(
|
|||
.fillMaxWidth()
|
||||
.height(52.dp)
|
||||
.padding(horizontal = 20.dp)
|
||||
.noRippleThrottledClickable { onLimitTypesClick() }
|
||||
.noRippleThrottledClickable {
|
||||
if (limit > 0) {
|
||||
onLimitTypesClick()
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.fillMaxWidth(),
|
||||
text = stringResource(id = R.string.edit_property_limit_objects),
|
||||
style = BodyRegular,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
if (limit > 0) {
|
||||
Text(
|
||||
modifier = Modifier.align(Alignment.CenterEnd),
|
||||
text = "$limit",
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.fillMaxWidth(),
|
||||
text = stringResource(id = R.string.edit_property_limit_objects),
|
||||
style = BodyRegular,
|
||||
color = colorResource(id = R.color.text_secondary)
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.align(Alignment.CenterEnd),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier,
|
||||
text = "$limit",
|
||||
style = BodyRegular,
|
||||
color = colorResource(id = R.color.text_secondary)
|
||||
)
|
||||
Image(
|
||||
modifier = Modifier.wrapContentSize().padding(start = 10.dp),
|
||||
painter = painterResource(id = R.drawable.ic_arrow_forward),
|
||||
contentDescription = "Change field format icon"
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.fillMaxWidth(),
|
||||
text = stringResource(id = R.string.edit_property_limit_objects_all),
|
||||
style = BodyRegular,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.align(Alignment.CenterEnd),
|
||||
text = stringResource(id = R.string.none),
|
||||
text = stringResource(id = R.string.edit_property_limit_all),
|
||||
style = BodyRegular,
|
||||
color = colorResource(id = R.color.text_secondary)
|
||||
)
|
||||
|
|
|
@ -37,6 +37,8 @@ import com.anytypeio.anytype.core_ui.foundation.Divider
|
|||
import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
|
||||
import com.anytypeio.anytype.core_ui.views.BodyRegular
|
||||
import com.anytypeio.anytype.feature_properties.edit.UiEditPropertyState
|
||||
import com.anytypeio.anytype.feature_properties.edit.UiPropertyLimitTypeItem
|
||||
import com.anytypeio.anytype.feature_properties.edit.ui.limit_types.PropertyLimitTypesPreviewScreen
|
||||
|
||||
@Composable
|
||||
fun PropertyViewScreen(
|
||||
|
@ -44,7 +46,8 @@ fun PropertyViewScreen(
|
|||
uiState: UiEditPropertyState.Visible.View,
|
||||
onFormatClick: () -> Unit,
|
||||
onLimitTypesClick: () -> Unit,
|
||||
onMenuUnlinkClick: (Id) -> Unit
|
||||
onMenuUnlinkClick: (Id) -> Unit,
|
||||
onDismissLimitTypes: () -> Unit,
|
||||
) {
|
||||
|
||||
var innerValue by remember(uiState.name) { mutableStateOf(uiState.name) }
|
||||
|
@ -139,13 +142,20 @@ fun PropertyViewScreen(
|
|||
if (uiState.format == RelationFormat.OBJECT) {
|
||||
PropertyLimitTypesViewSection(
|
||||
limit = uiState.limitObjectTypes.size,
|
||||
onLimitTypesClick = { onLimitTypesClick() }
|
||||
onLimitTypesClick = onLimitTypesClick
|
||||
)
|
||||
Divider()
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
}
|
||||
|
||||
if (uiState.showLimitTypes) {
|
||||
PropertyLimitTypesPreviewScreen(
|
||||
items = uiState.limitObjectTypes,
|
||||
onDismissRequest = onDismissLimitTypes,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DefaultPreviews
|
||||
|
@ -156,14 +166,25 @@ fun MyPreviewView() {
|
|||
uiState = UiEditPropertyState.Visible.View(
|
||||
id = "dummyId1",
|
||||
key = "dummyKey1",
|
||||
name = "View property",
|
||||
formatName = "Text",
|
||||
name = "View property very long name, so so long, very long",
|
||||
formatName = "Object Relation",
|
||||
formatIcon = R.drawable.ic_relation_format_date_small,
|
||||
format = RelationFormat.FILE,
|
||||
isPossibleToUnlinkFromType = true
|
||||
format = RelationFormat.OBJECT,
|
||||
isPossibleToUnlinkFromType = true,
|
||||
showLimitTypes = false,
|
||||
limitObjectTypes = listOf(
|
||||
UiPropertyLimitTypeItem(
|
||||
id = "dummyId1",
|
||||
name = "Limit type 1",
|
||||
icon = null,
|
||||
uniqueKey = null,
|
||||
number = 1
|
||||
)
|
||||
)
|
||||
),
|
||||
onFormatClick = {},
|
||||
onLimitTypesClick = {},
|
||||
onMenuUnlinkClick = {}
|
||||
onMenuUnlinkClick = {},
|
||||
onDismissLimitTypes = {}
|
||||
)
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
package com.anytypeio.anytype.feature_properties.edit.ui.limit_types
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_ui.foundation.Dragger
|
||||
import com.anytypeio.anytype.core_ui.relations.CircleIcon
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonPrimary
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonSize
|
||||
import com.anytypeio.anytype.core_ui.views.PreviewTitle1Regular
|
||||
import com.anytypeio.anytype.core_ui.views.Title1
|
||||
import com.anytypeio.anytype.core_ui.widgets.ListWidgetObjectIcon
|
||||
import com.anytypeio.anytype.feature_properties.R
|
||||
import com.anytypeio.anytype.feature_properties.add.ui.commonItemModifier
|
||||
import com.anytypeio.anytype.feature_properties.edit.UiPropertyLimitTypeItem
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun PropertyLimitTypesEditScreen(
|
||||
items: List<UiPropertyLimitTypeItem>,
|
||||
savedSelectedItemIds: List<Id>,
|
||||
onDismissRequest: () -> Unit,
|
||||
onDoneClick: (List<Id>) -> Unit
|
||||
) {
|
||||
|
||||
// Pre-populate currentItems with saved selection numbers, if available.
|
||||
val currentItems = remember {
|
||||
mutableStateListOf<UiPropertyLimitTypeItem>().apply {
|
||||
addAll(items.map { item ->
|
||||
if (savedSelectedItemIds.contains(item.id)) {
|
||||
// Assign number based on the order in savedSelectedItemIds (index + 1)
|
||||
val number = savedSelectedItemIds.indexOf(item.id) + 1
|
||||
item.copy(number = number)
|
||||
} else {
|
||||
item
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize selectedIds with the saved IDs to maintain the selection order.
|
||||
val selectedIds = remember {
|
||||
mutableStateListOf<Id>().apply {
|
||||
addAll(savedSelectedItemIds)
|
||||
}
|
||||
}
|
||||
|
||||
val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
|
||||
val lazyListState = rememberLazyListState()
|
||||
|
||||
ModalBottomSheet(
|
||||
modifier = Modifier
|
||||
.padding(top = 60.dp)
|
||||
.fillMaxWidth(),
|
||||
onDismissRequest = onDismissRequest,
|
||||
dragHandle = null,
|
||||
scrimColor = colorResource(id = R.color.modal_screen_outside_background),
|
||||
containerColor = colorResource(id = R.color.background_primary),
|
||||
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
||||
sheetState = bottomSheetState,
|
||||
content = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Dragger(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 6.dp)
|
||||
.align(Alignment.TopCenter)
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp)
|
||||
.height(48.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.property_limit_objects_title),
|
||||
style = Title1,
|
||||
color = colorResource(R.color.text_primary),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.padding(top = 64.dp)
|
||||
.fillMaxWidth()
|
||||
.nestedScroll(rememberNestedScrollInteropConnection()),
|
||||
state = lazyListState
|
||||
) {
|
||||
items(
|
||||
count = currentItems.size,
|
||||
key = { index -> currentItems[index].id },
|
||||
itemContent = { index ->
|
||||
val item = currentItems[index]
|
||||
TypeItem(
|
||||
modifier = commonItemModifier()
|
||||
.clickable {
|
||||
// Toggle selection: add if not selected; remove if already selected.
|
||||
if (!selectedIds.contains(item.id)) {
|
||||
// Select the item: add its id and set its number.
|
||||
selectedIds.add(item.id)
|
||||
currentItems[index] =
|
||||
item.copy(number = selectedIds.size)
|
||||
} else {
|
||||
// Deselect the item.
|
||||
val removedNumber = item.number ?: 0
|
||||
selectedIds.remove(item.id)
|
||||
currentItems[index] = item.copy(number = null)
|
||||
// Update the numbers for items that were selected after this item.
|
||||
currentItems.forEachIndexed { idx, current ->
|
||||
if (current.number != null && current.number > removedNumber) {
|
||||
currentItems[idx] =
|
||||
current.copy(number = current.number - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
item = item
|
||||
)
|
||||
}
|
||||
)
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(80.dp))
|
||||
}
|
||||
}
|
||||
|
||||
ButtonPrimary(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp)
|
||||
.align(Alignment.BottomCenter),
|
||||
text = stringResource(R.string.done),
|
||||
size = ButtonSize.Large,
|
||||
onClick = {
|
||||
// Filter and sort selected items by their 'number'
|
||||
val selectedItemsSorted = currentItems
|
||||
.filter { it.number != null }
|
||||
.sortedBy { it.number }
|
||||
onDoneClick(selectedItemsSorted.map { it.id })
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TypeItem(
|
||||
modifier: Modifier,
|
||||
item: UiPropertyLimitTypeItem
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(end = 56.dp)
|
||||
.fillMaxHeight(),
|
||||
verticalAlignment = CenterVertically,
|
||||
) {
|
||||
ListWidgetObjectIcon(
|
||||
modifier = Modifier,
|
||||
icon = item.icon!!,
|
||||
iconSize = 24.dp
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.size(10.dp))
|
||||
|
||||
Text(
|
||||
modifier = Modifier,
|
||||
text = item.name,
|
||||
style = PreviewTitle1Regular,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
|
||||
if (item.number != null) {
|
||||
CircleIcon(
|
||||
number = item.number.toString(),
|
||||
isSelected = true,
|
||||
modifier = Modifier
|
||||
.size(24.dp)
|
||||
.align(Alignment.CenterEnd)
|
||||
)
|
||||
} else {
|
||||
CircleIcon(
|
||||
isSelected = false,
|
||||
modifier = Modifier
|
||||
.size(24.dp)
|
||||
.align(Alignment.CenterEnd)
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package com.anytypeio.anytype.feature_properties.edit.ui.limit_types
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_ui.foundation.Dragger
|
||||
import com.anytypeio.anytype.core_ui.views.PreviewTitle1Regular
|
||||
import com.anytypeio.anytype.core_ui.views.Title1
|
||||
import com.anytypeio.anytype.core_ui.widgets.ListWidgetObjectIcon
|
||||
import com.anytypeio.anytype.feature_properties.R
|
||||
import com.anytypeio.anytype.feature_properties.add.ui.commonItemModifier
|
||||
import com.anytypeio.anytype.feature_properties.edit.UiPropertyLimitTypeItem
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun PropertyLimitTypesPreviewScreen(
|
||||
items: List<UiPropertyLimitTypeItem>,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
val currentItems = remember {
|
||||
mutableStateListOf<UiPropertyLimitTypeItem>().apply { addAll(items) }
|
||||
}
|
||||
|
||||
val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
|
||||
val lazyListState = rememberLazyListState()
|
||||
|
||||
ModalBottomSheet(
|
||||
modifier = Modifier
|
||||
.padding(top = 60.dp)
|
||||
.fillMaxWidth(),
|
||||
onDismissRequest = onDismissRequest,
|
||||
dragHandle = null,
|
||||
scrimColor = colorResource(id = R.color.modal_screen_outside_background),
|
||||
containerColor = colorResource(id = R.color.background_primary),
|
||||
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
|
||||
sheetState = bottomSheetState,
|
||||
content = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Dragger(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 6.dp)
|
||||
.align(Alignment.TopCenter)
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp)
|
||||
.height(48.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.property_limit_objects_title),
|
||||
style = Title1,
|
||||
color = colorResource(R.color.text_primary),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.padding(top = 64.dp)
|
||||
.fillMaxWidth()
|
||||
.nestedScroll(rememberNestedScrollInteropConnection()),
|
||||
state = lazyListState
|
||||
) {
|
||||
items(
|
||||
count = currentItems.size,
|
||||
key = { index -> currentItems[index].id },
|
||||
itemContent = { index ->
|
||||
val item = currentItems[index]
|
||||
TypeItem(
|
||||
modifier = commonItemModifier(),
|
||||
item = item
|
||||
)
|
||||
}
|
||||
)
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(80.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TypeItem(
|
||||
modifier: Modifier,
|
||||
item: UiPropertyLimitTypeItem
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(end = 20.dp)
|
||||
.fillMaxHeight(),
|
||||
verticalAlignment = CenterVertically,
|
||||
) {
|
||||
ListWidgetObjectIcon(
|
||||
modifier = Modifier,
|
||||
icon = item.icon!!,
|
||||
iconSize = 24.dp
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.size(10.dp))
|
||||
|
||||
Text(
|
||||
modifier = Modifier,
|
||||
text = item.name,
|
||||
style = PreviewTitle1Regular,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue