1
0
Fork 0
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:
Konstantin Ivanov 2025-03-28 17:03:20 +01:00 committed by GitHub
parent 5a505bf935
commit cdc2ded35d
Signed by: github
GPG key ID: B5690EEEBB952194
10 changed files with 442 additions and 189 deletions

View file

@ -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
)
}
}

View file

@ -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,

View file

@ -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
)
}

View file

@ -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"

View file

@ -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 = {},

View file

@ -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

View file

@ -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(

View file

@ -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
)

View file

@ -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 arent 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 doesnt 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 arent 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>

View file

@ -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(