mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3505 Primitives | Properties screens, ui updates (#2207)
This commit is contained in:
parent
5a505bf935
commit
cdc2ded35d
10 changed files with 442 additions and 189 deletions
|
@ -85,7 +85,8 @@ class ObjectFieldsFragment : BaseBottomSheetComposeFragment(),
|
|||
vm.onTypeIconClicked()
|
||||
},
|
||||
onRemoveFromObjectClicked = vm::onRemoveFromObjectClicked,
|
||||
onAddToTypeClicked = vm::onAddToTypeClicked
|
||||
onAddToTypeClicked = vm::onAddToTypeClicked,
|
||||
onHiddenToggle = vm::onHiddenToggle
|
||||
)
|
||||
val showLocalFieldExplanationScreen = vm.showLocalInfo.collectAsStateWithLifecycle().value
|
||||
if (showLocalFieldExplanationScreen) {
|
||||
|
@ -95,7 +96,9 @@ class ObjectFieldsFragment : BaseBottomSheetComposeFragment(),
|
|||
LocalInfoScreen(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
bottomSheetState = bottomSheetState,
|
||||
onDismiss = { vm.onDismissLocalInfo() }
|
||||
onDismiss = { vm.onDismissLocalInfo() },
|
||||
title = R.string.object_properties_local_info_title,
|
||||
description = R.string.object_properties_local_info_description
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import com.anytypeio.anytype.core_utils.ext.setupBottomSheetBehavior
|
|||
import com.anytypeio.anytype.core_utils.ext.subscribe
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.feature_object_type.fields.ui.FieldsMainScreen
|
||||
import com.anytypeio.anytype.feature_object_type.fields.ui.FieldsMainModalScreen
|
||||
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.viewmodel.ObjectTypeVMFactory
|
||||
|
@ -45,7 +45,7 @@ class ObjectTypeFieldsFragment : BaseBottomSheetComposeFragment() {
|
|||
savedInstanceState: Bundle?
|
||||
) = content {
|
||||
MaterialTheme {
|
||||
FieldsMainScreen(
|
||||
FieldsMainModalScreen(
|
||||
uiFieldsListState = vm.uiFieldsListState.collectAsStateWithLifecycle().value,
|
||||
uiTitleState = vm.uiTitleState.collectAsStateWithLifecycle().value,
|
||||
uiIconState = vm.uiIconState.collectAsStateWithLifecycle().value,
|
||||
|
|
|
@ -160,7 +160,6 @@ class ObjectTypeFragment : BaseComposeFragment() {
|
|||
uiIconState = vm.uiIconState.collectAsStateWithLifecycle().value,
|
||||
uiEditPropertyState = vm.uiEditPropertyScreen.collectAsStateWithLifecycle().value,
|
||||
uiFieldLocalInfoState = vm.uiFieldLocalInfoState.collectAsStateWithLifecycle().value,
|
||||
withDragger = false,
|
||||
fieldEvent = vm::onFieldEvent
|
||||
)
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/default_ripple"
|
||||
app:icon="@drawable/ic_obj_settings_fields_24"
|
||||
app:title="@string/fields" />
|
||||
app:title="@string/properties" />
|
||||
|
||||
<View
|
||||
android:id="@+id/relationsDivider"
|
||||
|
|
|
@ -5,12 +5,15 @@ import androidx.compose.foundation.Image
|
|||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
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.width
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
|
@ -45,7 +48,8 @@ fun FieldListScreen(
|
|||
onTypeIconClicked: () -> Unit,
|
||||
onLocalInfoIconClicked: () -> Unit,
|
||||
onAddToTypeClicked: (Model.Item) -> Unit,
|
||||
onRemoveFromObjectClicked: (Model.Item) -> Unit
|
||||
onRemoveFromObjectClicked: (Model.Item) -> Unit,
|
||||
onHiddenToggle: (Model.Section.Hidden) -> Unit = {}
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
|
@ -292,6 +296,11 @@ fun FieldListScreen(
|
|||
Model.Section.Local -> {
|
||||
SectionLocal(onLocalInfoIconClicked)
|
||||
}
|
||||
|
||||
is Model.Section.Hidden -> SectionHidden(
|
||||
item = item,
|
||||
onToggle = onHiddenToggle
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -305,37 +314,29 @@ fun FieldListScreen(
|
|||
private fun SectionLocal(
|
||||
onLocalInfoIconClicked: () -> Unit = {}
|
||||
) {
|
||||
Box(
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(52.dp)
|
||||
.padding(top = 23.dp)
|
||||
.height(22.dp).
|
||||
noRippleThrottledClickable{
|
||||
onLocalInfoIconClicked()
|
||||
},
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 7.dp, start = 20.dp)
|
||||
.align(Alignment.BottomStart),
|
||||
text = stringResource(id = R.string.object_type_fields_section_local_fields),
|
||||
modifier = Modifier.padding(start = 20.dp).weight(1.0f),
|
||||
text = stringResource(id = R.string.object_properties_section_local),
|
||||
style = BodyCalloutMedium,
|
||||
color = colorResource(R.color.text_primary),
|
||||
)
|
||||
Box(
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomEnd)
|
||||
.height(37.dp)
|
||||
.width(44.dp)
|
||||
.noRippleThrottledClickable {
|
||||
onLocalInfoIconClicked()
|
||||
}
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 9.dp, end = 20.dp)
|
||||
.wrapContentSize()
|
||||
.align(Alignment.BottomEnd),
|
||||
painter = painterResource(R.drawable.ic_section_local_fields),
|
||||
contentDescription = "Section local fields info"
|
||||
)
|
||||
}
|
||||
.wrapContentSize()
|
||||
.padding(end = 14.dp),
|
||||
painter = painterResource(R.drawable.ic_section_local_fields),
|
||||
contentDescription = "Section local fields info"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,17 +356,106 @@ private fun Section(item: Model.Section) {
|
|||
style = BodyCalloutMedium,
|
||||
color = colorResource(id = R.color.text_secondary),
|
||||
modifier = Modifier
|
||||
.padding(vertical = 17.dp)
|
||||
.padding(vertical = 11.dp)
|
||||
.padding(start = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SectionHidden(
|
||||
item: Model.Section.Hidden,
|
||||
onToggle: (Model.Section.Hidden) -> Unit = {}
|
||||
) {
|
||||
val text = stringResource(id = R.string.object_properties_section_hidden)
|
||||
val iconRes = when (item) {
|
||||
is Model.Section.Hidden.Shown -> R.drawable.ic_arrow_up_18
|
||||
is Model.Section.Hidden.Unshown -> R.drawable.ic_list_arrow_18
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
.noRippleThrottledClickable{
|
||||
onToggle(item)
|
||||
},
|
||||
contentAlignment = Alignment.CenterStart
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 7.dp)
|
||||
.padding(start = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(18.dp),
|
||||
painter = painterResource(iconRes),
|
||||
contentDescription = "Hidden section icon",
|
||||
)
|
||||
Spacer(modifier = Modifier.width(6.dp))
|
||||
Text(
|
||||
text = text,
|
||||
style = BodyCalloutMedium,
|
||||
color = colorResource(id = R.color.text_secondary),
|
||||
modifier = Modifier
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DefaultPreviews
|
||||
@Composable
|
||||
fun FieldListScreenPreview() {
|
||||
FieldListScreen(
|
||||
state = listOf(Model.Section.Local),
|
||||
state = listOf(
|
||||
Model.Item(
|
||||
view = ObjectRelationView.Default(
|
||||
id = "id3",
|
||||
system = false,
|
||||
key = "key3",
|
||||
name = "Name3",
|
||||
value = "Value3",
|
||||
format = RelationFormat.OBJECT
|
||||
),
|
||||
isLocal = false
|
||||
),
|
||||
Model.Section.Hidden.Shown(
|
||||
listOf(
|
||||
Model.Item(
|
||||
view = ObjectRelationView.Default(
|
||||
id = "id1",
|
||||
system = false,
|
||||
key = "key1",
|
||||
name = "Name1",
|
||||
value = "Value1",
|
||||
format = RelationFormat.LONG_TEXT
|
||||
),
|
||||
isLocal = false
|
||||
),
|
||||
Model.Item(
|
||||
view = ObjectRelationView.Default(
|
||||
id = "id2",
|
||||
system = false,
|
||||
key = "key2",
|
||||
name = "Name2",
|
||||
value = "Value2",
|
||||
format = RelationFormat.TAG
|
||||
),
|
||||
isLocal = false
|
||||
),
|
||||
)
|
||||
),
|
||||
Model.Section.Local,
|
||||
Model.Item(
|
||||
view = ObjectRelationView.Default(
|
||||
id = "id55",
|
||||
system = false,
|
||||
key = "key55",
|
||||
name = "Local 55",
|
||||
value = "Valu55",
|
||||
format = RelationFormat.OBJECT
|
||||
),
|
||||
isLocal = false
|
||||
),
|
||||
),
|
||||
onRelationClicked = {},
|
||||
onLocalInfoIconClicked = {},
|
||||
onTypeIconClicked = {},
|
||||
|
|
|
@ -115,24 +115,6 @@ sealed class UiFieldsListItem {
|
|||
const val ID = "section_file_recommended"
|
||||
}
|
||||
}
|
||||
|
||||
data class SpaceFields(
|
||||
override val id: Id = ID,
|
||||
override val canAdd: Boolean = false
|
||||
) : Section() {
|
||||
companion object {
|
||||
const val ID = "section_space_fields"
|
||||
}
|
||||
}
|
||||
|
||||
data class LibraryFields(
|
||||
override val id: Id = ID,
|
||||
override val canAdd: Boolean = false
|
||||
) : Section() {
|
||||
companion object {
|
||||
const val ID = "section_library_fields"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.anytypeio.anytype.feature_object_type.fields.ui
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
|
@ -54,6 +55,8 @@ fun SectionLocalFieldsInfo(
|
|||
fun LocalInfoScreen(
|
||||
modifier: Modifier,
|
||||
bottomSheetState: SheetState,
|
||||
@StringRes title : Int = R.string.object_type_fields_local_info_title,
|
||||
@StringRes description : Int = R.string.object_type_fields_local_info_description,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
ModalBottomSheet(
|
||||
|
@ -75,7 +78,7 @@ fun LocalInfoScreen(
|
|||
textAlign = TextAlign.Center,
|
||||
style = HeadlineHeading,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
text = stringResource(R.string.object_type_fields_local_info_title)
|
||||
text = stringResource(title)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(7.dp))
|
||||
Text(
|
||||
|
@ -85,7 +88,7 @@ fun LocalInfoScreen(
|
|||
textAlign = TextAlign.Center,
|
||||
style = BodyCalloutRegular,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
text = stringResource(R.string.object_type_fields_local_info_description)
|
||||
text = stringResource(description)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(30.dp))
|
||||
ButtonSecondary(
|
||||
|
|
|
@ -9,6 +9,7 @@ import androidx.compose.foundation.combinedClickable
|
|||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
|
@ -24,6 +25,7 @@ import androidx.compose.foundation.layout.windowInsetsPadding
|
|||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
|
@ -71,10 +73,8 @@ import com.anytypeio.anytype.feature_object_type.fields.UiFieldsListItem
|
|||
import com.anytypeio.anytype.feature_object_type.fields.UiFieldsListItem.Section
|
||||
import com.anytypeio.anytype.feature_object_type.fields.UiFieldsListState
|
||||
import com.anytypeio.anytype.feature_object_type.fields.UiLocalsFieldsInfoState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.TypeEvent
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiIconState
|
||||
import com.anytypeio.anytype.feature_object_type.ui.UiTitleState
|
||||
import com.anytypeio.anytype.feature_properties.add.UiEditTypePropertiesEvent
|
||||
import com.anytypeio.anytype.feature_properties.edit.UiEditPropertyState
|
||||
import com.anytypeio.anytype.feature_properties.edit.ui.PropertyScreen
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
|
@ -91,7 +91,6 @@ fun FieldsMainScreen(
|
|||
uiIconState: UiIconState,
|
||||
uiFieldLocalInfoState: UiLocalsFieldsInfoState,
|
||||
uiEditPropertyState: UiEditPropertyState,
|
||||
withDragger: Boolean = true,
|
||||
fieldEvent: (FieldEvent) -> Unit
|
||||
) {
|
||||
|
||||
|
@ -132,99 +131,20 @@ fun FieldsMainScreen(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
uiTitleState = uiTitleState,
|
||||
uiIconState = uiIconState,
|
||||
withDragger = withDragger,
|
||||
onBackClick = {
|
||||
fieldEvent(OnBackClick)
|
||||
}
|
||||
)
|
||||
},
|
||||
content = { paddingValues ->
|
||||
val contentModifier = if (Build.VERSION.SDK_INT >= EDGE_TO_EDGE_MIN_SDK) {
|
||||
Modifier
|
||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||
.fillMaxSize()
|
||||
.padding(top = paddingValues.calculateTopPadding())
|
||||
} else {
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
}
|
||||
LazyColumn(
|
||||
modifier = contentModifier,
|
||||
state = lazyListState,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
items(
|
||||
count = uiFieldsListState.items.size,
|
||||
key = { index -> uiFieldsListState.items[index].id },
|
||||
contentType = { index -> getContentType(uiFieldsListState.items[index]) },
|
||||
itemContent = { index ->
|
||||
val item = uiFieldsListState.items[index]
|
||||
when (item) {
|
||||
is UiFieldsListItem.Item.Draggable -> {
|
||||
FieldItemDraggable(
|
||||
modifier = commonItemModifier(),
|
||||
item = item,
|
||||
reorderingState = reorderableLazyColumnState,
|
||||
fieldEvent = fieldEvent,
|
||||
hapticFeedback = hapticFeedback
|
||||
)
|
||||
}
|
||||
|
||||
is UiFieldsListItem.Item.Local -> {
|
||||
FieldItemLocal(
|
||||
modifier = commonItemModifier(),
|
||||
item = item,
|
||||
fieldEvent = fieldEvent
|
||||
)
|
||||
}
|
||||
|
||||
is Section.SideBar -> {
|
||||
SectionItem(
|
||||
item = item,
|
||||
reorderingState = reorderableLazyColumnState,
|
||||
fieldEvent = fieldEvent,
|
||||
isReorderable = true,
|
||||
onAddIconClick = {
|
||||
fieldEvent(FieldEvent.Section.OnAddToSidebarIconClick)
|
||||
}
|
||||
)
|
||||
}
|
||||
is Section.Hidden -> {
|
||||
SectionItem(
|
||||
item = item,
|
||||
reorderingState = reorderableLazyColumnState,
|
||||
fieldEvent = fieldEvent,
|
||||
isReorderable = true
|
||||
)
|
||||
}
|
||||
is Section.Header -> {
|
||||
SectionItem(
|
||||
item = item,
|
||||
reorderingState = reorderableLazyColumnState,
|
||||
fieldEvent = fieldEvent,
|
||||
isReorderable = false
|
||||
)
|
||||
}
|
||||
is Section.Local,
|
||||
is Section.File -> {
|
||||
SectionItem(
|
||||
item = item,
|
||||
reorderingState = reorderableLazyColumnState,
|
||||
fieldEvent = fieldEvent,
|
||||
isReorderable = false
|
||||
)
|
||||
}
|
||||
|
||||
is Section.LibraryFields -> TODO()
|
||||
is Section.SpaceFields -> TODO()
|
||||
}
|
||||
}
|
||||
)
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(60.dp))
|
||||
}
|
||||
}
|
||||
Items(
|
||||
uiFieldsListState = uiFieldsListState,
|
||||
lazyListState = lazyListState,
|
||||
reorderableLazyColumnState = reorderableLazyColumnState,
|
||||
hapticFeedback = hapticFeedback,
|
||||
paddingValues = paddingValues,
|
||||
fieldEvent = fieldEvent
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -252,6 +172,203 @@ fun FieldsMainScreen(
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun FieldsMainModalScreen(
|
||||
uiFieldsListState: UiFieldsListState,
|
||||
uiTitleState: UiTitleState,
|
||||
uiIconState: UiIconState,
|
||||
uiFieldLocalInfoState: UiLocalsFieldsInfoState,
|
||||
uiEditPropertyState: UiEditPropertyState,
|
||||
fieldEvent: (FieldEvent) -> Unit
|
||||
) {
|
||||
|
||||
val hapticFeedback = rememberReorderHapticFeedback()
|
||||
|
||||
val lazyListState = rememberLazyListState()
|
||||
|
||||
val reorderableLazyColumnState = rememberReorderableLazyListState(lazyListState) { from, to ->
|
||||
fieldEvent(DragEvent.OnMove(from.key as String, to.key as String))
|
||||
hapticFeedback.performHapticFeedback(ReorderHapticFeedbackType.MOVE)
|
||||
}
|
||||
|
||||
var isDragging by remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(reorderableLazyColumnState.isAnyItemDragging) {
|
||||
if (reorderableLazyColumnState.isAnyItemDragging) {
|
||||
isDragging = true
|
||||
// Optional: Add a small delay to avoid triggering on very short drags
|
||||
delay(50)
|
||||
} else if (isDragging) {
|
||||
isDragging = false
|
||||
fieldEvent(DragEvent.OnDragEnd)
|
||||
hapticFeedback.performHapticFeedback(ReorderHapticFeedbackType.MOVE)
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
.nestedScroll(rememberNestedScrollInteropConnection())
|
||||
.background(
|
||||
color = colorResource(id = R.color.background_primary),
|
||||
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)
|
||||
)
|
||||
) {
|
||||
Dragger(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 6.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(48.dp)
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.wrapContentSize()
|
||||
.align(Alignment.Center),
|
||||
text = stringResource(R.string.object_type_fields_title),
|
||||
style = Title1,
|
||||
color = colorResource(R.color.text_primary)
|
||||
)
|
||||
}
|
||||
InfoBar(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(36.dp)
|
||||
.background(color = colorResource(R.color.shape_transparent_secondary)),
|
||||
uiTitleState = uiTitleState,
|
||||
uiIconState = uiIconState
|
||||
)
|
||||
Items(
|
||||
uiFieldsListState = uiFieldsListState,
|
||||
lazyListState = lazyListState,
|
||||
reorderableLazyColumnState = reorderableLazyColumnState,
|
||||
hapticFeedback = hapticFeedback,
|
||||
paddingValues = PaddingValues(0.dp),
|
||||
fieldEvent = fieldEvent
|
||||
)
|
||||
}
|
||||
|
||||
if (uiEditPropertyState is UiEditPropertyState.Visible) {
|
||||
PropertyScreen(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
uiState = uiEditPropertyState,
|
||||
onDismissRequest = { fieldEvent(OnEditPropertyScreenDismiss) },
|
||||
onFormatClick = {},
|
||||
onSaveButtonClicked = { fieldEvent(EditProperty.OnSaveButtonClicked) },
|
||||
onCreateNewButtonClicked = {},
|
||||
onPropertyNameUpdate = { fieldEvent(EditProperty.OnPropertyNameUpdate(it)) },
|
||||
onMenuUnlinkClick = { fieldEvent(OnDeleteFromTypeClick(it)) },
|
||||
onLimitTypesClick = { fieldEvent(OnLimitTypesClick) },
|
||||
onDismissLimitTypes = { fieldEvent(OnLimitTypesDismiss) },
|
||||
)
|
||||
}
|
||||
|
||||
if (uiFieldLocalInfoState is UiLocalsFieldsInfoState.Visible) {
|
||||
SectionLocalFieldsInfo(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
state = uiFieldLocalInfoState,
|
||||
fieldEvent = fieldEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Items(
|
||||
lazyListState: LazyListState,
|
||||
reorderableLazyColumnState: ReorderableLazyListState,
|
||||
uiFieldsListState: UiFieldsListState,
|
||||
paddingValues: PaddingValues,
|
||||
hapticFeedback: ReorderHapticFeedback,
|
||||
fieldEvent: (FieldEvent) -> Unit,
|
||||
) {
|
||||
val contentModifier = if (Build.VERSION.SDK_INT >= EDGE_TO_EDGE_MIN_SDK) {
|
||||
Modifier
|
||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||
.fillMaxSize()
|
||||
.padding(top = paddingValues.calculateTopPadding())
|
||||
} else {
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
}
|
||||
LazyColumn(
|
||||
modifier = contentModifier,
|
||||
state = lazyListState,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
items(
|
||||
count = uiFieldsListState.items.size,
|
||||
key = { index -> uiFieldsListState.items[index].id },
|
||||
contentType = { index -> getContentType(uiFieldsListState.items[index]) },
|
||||
itemContent = { index ->
|
||||
val item = uiFieldsListState.items[index]
|
||||
when (item) {
|
||||
is UiFieldsListItem.Item.Draggable -> {
|
||||
FieldItemDraggable(
|
||||
modifier = commonItemModifier(),
|
||||
item = item,
|
||||
reorderingState = reorderableLazyColumnState,
|
||||
fieldEvent = fieldEvent,
|
||||
hapticFeedback = hapticFeedback
|
||||
)
|
||||
}
|
||||
|
||||
is UiFieldsListItem.Item.Local -> {
|
||||
FieldItemLocal(
|
||||
modifier = commonItemModifier(),
|
||||
item = item,
|
||||
fieldEvent = fieldEvent
|
||||
)
|
||||
}
|
||||
|
||||
is Section.SideBar -> {
|
||||
SectionItem(
|
||||
item = item,
|
||||
reorderingState = reorderableLazyColumnState,
|
||||
fieldEvent = fieldEvent,
|
||||
isReorderable = true,
|
||||
onAddIconClick = {
|
||||
fieldEvent(FieldEvent.Section.OnAddToSidebarIconClick)
|
||||
}
|
||||
)
|
||||
}
|
||||
is Section.Hidden -> {
|
||||
SectionItem(
|
||||
item = item,
|
||||
reorderingState = reorderableLazyColumnState,
|
||||
fieldEvent = fieldEvent,
|
||||
isReorderable = true
|
||||
)
|
||||
}
|
||||
is Section.Header -> {
|
||||
SectionItem(
|
||||
item = item,
|
||||
reorderingState = reorderableLazyColumnState,
|
||||
fieldEvent = fieldEvent,
|
||||
isReorderable = false
|
||||
)
|
||||
}
|
||||
is Section.Local,
|
||||
is Section.File -> {
|
||||
SectionItem(
|
||||
item = item,
|
||||
reorderingState = reorderableLazyColumnState,
|
||||
fieldEvent = fieldEvent,
|
||||
isReorderable = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(60.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a content type string based on the item type. **/
|
||||
private fun getContentType(item: UiFieldsListItem): String {
|
||||
return when (item) {
|
||||
|
@ -262,8 +379,6 @@ private fun getContentType(item: UiFieldsListItem): String {
|
|||
is Section.Hidden -> FieldsItemsContentType.SECTION_HIDDEN
|
||||
is Section.Local -> FieldsItemsContentType.SECTION_LOCAL
|
||||
is Section.File -> FieldsItemsContentType.SECTION_FILE
|
||||
is Section.LibraryFields -> "content_type_section_library_fields"
|
||||
is Section.SpaceFields -> "content_type_section_space_fields"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,7 +398,6 @@ fun LazyItemScope.commonItemModifier() = Modifier
|
|||
@Composable
|
||||
private fun TopBar(
|
||||
modifier: Modifier,
|
||||
withDragger: Boolean = true,
|
||||
uiTitleState: UiTitleState,
|
||||
uiIconState: UiIconState,
|
||||
onBackClick: () -> Unit = {}
|
||||
|
@ -299,35 +413,26 @@ private fun TopBar(
|
|||
color = colorResource(id = R.color.background_primary),
|
||||
)
|
||||
) {
|
||||
if (withDragger) {
|
||||
Dragger(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 6.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(48.dp)
|
||||
) {
|
||||
if (!withDragger) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(56.dp)
|
||||
.height(48.dp)
|
||||
.align(Alignment.CenterStart)
|
||||
.noRippleThrottledClickable {
|
||||
onBackClick()
|
||||
},
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.wrapContentSize(),
|
||||
painter = painterResource(R.drawable.ic_default_top_back),
|
||||
contentDescription = stringResource(R.string.content_desc_back_button)
|
||||
)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(56.dp)
|
||||
.height(48.dp)
|
||||
.align(Alignment.CenterStart)
|
||||
.noRippleThrottledClickable {
|
||||
onBackClick()
|
||||
},
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.wrapContentSize(),
|
||||
painter = painterResource(R.drawable.ic_default_top_back),
|
||||
contentDescription = stringResource(R.string.content_desc_back_button)
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
|
@ -362,16 +467,16 @@ private fun InfoBar(modifier: Modifier, uiTitleState: UiTitleState, uiIconState:
|
|||
style = Caption1Medium,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
ListWidgetObjectIcon(
|
||||
modifier = Modifier
|
||||
|
||||
.padding(start = 4.dp)
|
||||
.size(18.dp),
|
||||
modifier = Modifier,
|
||||
icon = uiIconState.icon,
|
||||
backgroundColor = R.color.transparent_black
|
||||
backgroundColor = R.color.transparent_black,
|
||||
iconSize = 16.dp
|
||||
)
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 4.dp),
|
||||
modifier = Modifier,
|
||||
text = uiTitleState.title,
|
||||
style = Caption1Medium,
|
||||
maxLines = 1,
|
||||
|
@ -404,11 +509,9 @@ private fun LazyItemScope.SectionItem(
|
|||
)
|
||||
|
||||
is Section.Local -> stringResource(R.string.object_type_fields_section_local_fields) to colorResource(
|
||||
id = R.color.text_primary
|
||||
id = R.color.text_secondary
|
||||
)
|
||||
|
||||
is Section.LibraryFields -> TODO()
|
||||
is Section.SpaceFields -> TODO()
|
||||
is Section.File -> stringResource(R.string.object_type_fields_section_file) to colorResource(
|
||||
id = R.color.text_secondary
|
||||
)
|
||||
|
|
|
@ -1868,11 +1868,11 @@ Please provide specific details of your needs here.</string>
|
|||
<string name="object_type_templates_menu_edit">Edit</string>
|
||||
<string name="object_type_templates_menu_duplicate">Duplicate</string>
|
||||
<string name="object_type_templates_menu_delete">Delete</string>
|
||||
<string name="object_type_fields_section_header">Shown in object header</string>
|
||||
<string name="object_type_fields_section_fields_menu">Shown in properties menu</string>
|
||||
<string name="object_type_fields_section_header">Header</string>
|
||||
<string name="object_type_fields_section_fields_menu">Properties panel</string>
|
||||
<string name="object_type_fields_section_hidden">Hidden</string>
|
||||
<string name="object_type_fields_section_file">File</string>
|
||||
<string name="object_type_fields_section_local_fields">Local properties</string>
|
||||
<string name="object_type_fields_section_local_fields">Found in objects </string>
|
||||
<string name="object_type_fields_title">Properties</string>
|
||||
<string name="object_type_fields_info_text">You\'re editing type</string>
|
||||
<string name="object_type_fields_edit_field">Edit field</string>
|
||||
|
@ -1882,10 +1882,14 @@ Please provide specific details of your needs here.</string>
|
|||
<string name="object_type_fields_menu_delete">Unlink from type</string>
|
||||
<string name="object_type_fields_menu_add_to_type">Add to the current type</string>
|
||||
<string name="object_type_fields_menu_remove">Remove</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_title">Found in objects</string>
|
||||
<string name="object_type_fields_local_info_description">These properties exist in some objects but aren’t part of the Type. Add them to make them appear in all objects of this Type.</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_properties_section_local">Local properties</string>
|
||||
<string name="object_properties_section_hidden">Hidden</string>
|
||||
<string name="object_properties_local_info_title">Local properties</string>
|
||||
<string name="object_properties_local_info_description">These properties exist only in this object and aren’t part of its type. Add to the type to use in all objects, or remove.</string>
|
||||
|
||||
<string name="object_type_open_type_error">Error opening current object type</string>
|
||||
|
||||
|
|
|
@ -134,6 +134,19 @@ class RelationListViewModel(
|
|||
Model.Item(it, isLocal = false)
|
||||
}
|
||||
|
||||
val hiddenFields = parsedFields.hidden.mapNotNull {
|
||||
if (it.key == Relations.DESCRIPTION) return@mapNotNull null
|
||||
it.view(
|
||||
details = details,
|
||||
values = details.getObject(ctx)?.map.orEmpty(),
|
||||
urlBuilder = urlBuilder,
|
||||
fieldParser = fieldParser,
|
||||
storeOfObjectTypes = storeOfObjectTypes
|
||||
)
|
||||
}.map {
|
||||
Model.Item(it, isLocal = false)
|
||||
}
|
||||
|
||||
val sidebarFields = parsedFields.sidebar.mapNotNull {
|
||||
if (it.key == Relations.DESCRIPTION) return@mapNotNull null
|
||||
it.view(
|
||||
|
@ -175,24 +188,39 @@ class RelationListViewModel(
|
|||
}
|
||||
|
||||
return buildList {
|
||||
if (headerFields.isNotEmpty()) {
|
||||
add(Model.Section.Header)
|
||||
addAll(headerFields)
|
||||
}
|
||||
//DROID-3505 - temporarily disable header fields
|
||||
// if (headerFields.isNotEmpty()) {
|
||||
// add(Model.Section.Header)
|
||||
// addAll(headerFields)
|
||||
// }
|
||||
|
||||
//todo file fields are off for now
|
||||
if (false) {
|
||||
if (sidebarFields.isNotEmpty() || filesFields.isNotEmpty()) {
|
||||
add(Model.Section.SideBar)
|
||||
addAll(sidebarFields + filesFields)
|
||||
}
|
||||
} else {
|
||||
if (sidebarFields.isNotEmpty()) {
|
||||
add(Model.Section.SideBar)
|
||||
addAll(sidebarFields)
|
||||
}
|
||||
}
|
||||
|
||||
val currentHiddenState = views.value.firstOrNull { it is Model.Section.Hidden }
|
||||
if (currentHiddenState is Model.Section.Hidden.Shown) {
|
||||
add(
|
||||
Model.Section.Hidden.Shown(
|
||||
hiddenFields
|
||||
)
|
||||
)
|
||||
addAll(hiddenFields)
|
||||
} else {
|
||||
add(
|
||||
Model.Section.Hidden.Unshown(
|
||||
hiddenFields
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (localFields.isNotEmpty()) {
|
||||
add(Model.Section.Local)
|
||||
addAll(localFields)
|
||||
|
@ -300,6 +328,33 @@ class RelationListViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun onHiddenToggle(item: Model.Section.Hidden) {
|
||||
val currentList = views.value
|
||||
|
||||
val index = currentList.indexOfFirst {
|
||||
it is Model.Section.Hidden
|
||||
}
|
||||
if (index == -1) return
|
||||
|
||||
val newList = currentList.toMutableList()
|
||||
|
||||
when (item) {
|
||||
is Model.Section.Hidden.Shown -> {
|
||||
newList[index] = Model.Section.Hidden.Unshown(item.items)
|
||||
repeat(item.items.size) {
|
||||
if (newList.size > index + 1) {
|
||||
newList.removeAt(index + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
is Model.Section.Hidden.Unshown -> {
|
||||
newList[index] = Model.Section.Hidden.Shown(item.items)
|
||||
newList.addAll(index + 1, item.items)
|
||||
}
|
||||
}
|
||||
views.value = newList
|
||||
}
|
||||
|
||||
fun onRemoveFromObjectClicked(item: Model.Item) {
|
||||
onDeleteClicked(
|
||||
ctx = vmParams.objectId,
|
||||
|
@ -686,6 +741,20 @@ class RelationListViewModel(
|
|||
data object Local : Section() {
|
||||
override val identifier: String get() = "Section_Local"
|
||||
}
|
||||
|
||||
sealed class Hidden : Section() {
|
||||
data class Shown(
|
||||
val items: List<Model.Item>
|
||||
) : Hidden() {
|
||||
override val identifier: String get() = "Section_Hidden_Shown"
|
||||
}
|
||||
|
||||
data class Unshown(
|
||||
val items: List<Model.Item>
|
||||
) : Hidden() {
|
||||
override val identifier: String get() = "Section_Hidden_Unshown"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class Item(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue