1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-3426 Space settings | Type and properties library (#2247)

This commit is contained in:
Konstantin Ivanov 2025-04-07 13:22:28 +02:00 committed by GitHub
parent c45901934a
commit cd8eb2b1e9
Signed by: github
GPG key ID: B5690EEEBB952194
21 changed files with 1176 additions and 260 deletions

View file

@ -4,7 +4,6 @@ import com.anytypeio.anytype.core_models.CoverType
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_models.permissions.ObjectPermissions
import com.anytypeio.anytype.core_models.primitives.TypeId
@ -12,6 +11,7 @@ import com.anytypeio.anytype.core_models.primitives.TypeKey
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.objects.mapLimitObjectTypes
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.resources.StringResourceProvider
import com.anytypeio.anytype.feature_object_type.fields.UiFieldsListItem
@ -162,28 +162,6 @@ suspend fun buildUiPropertiesList(
}
}
/**
* Shared helper to build the limit object types for a property.
*/
private suspend fun mapLimitObjectTypes(
property: ObjectWrapper.Relation,
storeOfObjectTypes: StoreOfObjectTypes
): List<Id> {
return if (property.format == RelationFormat.OBJECT && property.relationFormatObjectTypes.isNotEmpty()) {
property.relationFormatObjectTypes.mapNotNull { id ->
storeOfObjectTypes.get(id)?.let { objType ->
if (objType.isValid) {
objType.id
} else {
null
}
}
}
} else {
emptyList()
}
}
/**
* Maps a property to a draggable UI list item.
* Returns null if the property key equals DESCRIPTION.
@ -202,9 +180,8 @@ private suspend fun mapToUiPropertiesDraggableListItem(
fieldKey = property.key,
fieldTitle = property.getName(stringResourceProvider),
format = property.format,
limitObjectTypes = mapLimitObjectTypes(
property = property,
storeOfObjectTypes = storeOfObjectTypes
limitObjectTypes = storeOfObjectTypes.mapLimitObjectTypes(
property = property
),
isEditableField = fieldParser.isPropertyEditable(property),
isPossibleToUnlinkFromType =
@ -231,9 +208,8 @@ private suspend fun mapToUiPropertiesLocalListItem(
fieldKey = property.key,
fieldTitle = property.getName(stringResourceProvider),
format = property.format,
limitObjectTypes = mapLimitObjectTypes(
property = property,
storeOfObjectTypes = storeOfObjectTypes
limitObjectTypes = storeOfObjectTypes.mapLimitObjectTypes(
property = property
),
isEditableField = fieldParser.isPropertyEditable(property)
)

View file

@ -1,35 +1,15 @@
package com.anytypeio.anytype.feature_object_type.ui.header
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
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.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.common.DefaultPreviews

View file

@ -0,0 +1,233 @@
package com.anytypeio.anytype.feature_object_type.ui.space
import android.os.Build
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
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.safeDrawing
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
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.res.colorResource
import androidx.compose.ui.res.painterResource
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.R
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
import com.anytypeio.anytype.core_ui.extensions.swapList
import com.anytypeio.anytype.core_ui.foundation.Divider
import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
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.core_utils.insets.EDGE_TO_EDGE_MIN_SDK
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.objects.custom_icon.CustomIconColor
import com.anytypeio.anytype.presentation.types.UiSpaceTypeItem
import com.anytypeio.anytype.presentation.types.UiSpaceTypesScreenState
@Composable
fun SpaceTypesListScreen(
uiState: UiSpaceTypesScreenState,
onTypeClicked: (UiSpaceTypeItem) -> Unit,
onBackPressed: () -> Unit,
onAddIconClicked: () -> Unit
) {
Column(
modifier = Modifier
.fillMaxSize()
.background(color = colorResource(id = R.color.background_primary))
.systemBarsPadding()
) {
Topbar(
onBackPressed = onBackPressed,
onAddIconClicked = onAddIconClicked
)
val contentModifier =
if (Build.VERSION.SDK_INT >= EDGE_TO_EDGE_MIN_SDK)
Modifier
.windowInsetsPadding(WindowInsets.safeDrawing)
.fillMaxWidth()
else
Modifier
.fillMaxWidth()
val lazyListState = rememberLazyListState()
val items = remember {
mutableStateListOf<UiSpaceTypeItem>()
}
items.swapList(uiState.items)
LazyColumn(
modifier = contentModifier,
state = lazyListState,
) {
items(
count = items.size,
key = { index -> items[index].id },
itemContent = {
val item = items[it]
Type(
modifier = Modifier
.fillMaxWidth()
.height(52.dp)
.padding(start = 12.dp, end = 20.dp)
.clickable {
onTypeClicked(item)
},
item = item
)
Divider()
}
)
item {
Spacer(
modifier = Modifier
.fillMaxWidth()
.height(32.dp)
)
}
}
}
}
@Composable
private fun Type(
modifier: Modifier,
item: UiSpaceTypeItem
) {
Row(
modifier = modifier.fillMaxWidth(),
verticalAlignment = CenterVertically
) {
ListWidgetObjectIcon(
icon = item.icon,
modifier = Modifier,
iconSize = 40.dp
)
val name = item.name.trim().ifBlank { stringResource(R.string.untitled) }
Text(
modifier = Modifier
.fillMaxWidth()
.padding(start = 2.dp),
text = name,
style = PreviewTitle1Regular,
color = colorResource(id = R.color.text_primary),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun Topbar(
onBackPressed: () -> Unit,
onAddIconClicked: () -> Unit
) {
Box(
modifier = Modifier
.fillMaxWidth()
.windowInsetsPadding(WindowInsets.statusBars)
.height(48.dp),
) {
Box(
modifier = Modifier
.width(56.dp)
.height(48.dp)
.align(Alignment.CenterStart)
.noRippleThrottledClickable {
onBackPressed()
},
contentAlignment = Alignment.CenterStart
) {
Image(
modifier = Modifier
.padding(start = 12.dp)
.wrapContentSize(),
painter = painterResource(R.drawable.ic_default_top_back),
contentDescription = stringResource(R.string.content_desc_back_button)
)
}
Text(
modifier = Modifier.align(Alignment.Center),
text = stringResource(R.string.space_types_screen_title),
style = Title1,
color = colorResource(R.color.text_primary),
textAlign = TextAlign.Center
)
Box(
modifier = Modifier
.width(56.dp)
.height(48.dp)
.align(Alignment.CenterEnd)
.noRippleThrottledClickable {
onAddIconClicked()
},
contentAlignment = Alignment.CenterStart
) {
Image(
modifier = Modifier
.padding(start = 12.dp)
.wrapContentSize(),
painter = painterResource(R.drawable.ic_default_plus),
contentDescription = "Add new type"
)
}
}
}
@DefaultPreviews
@Composable
fun SpaceTypesListScreenPreview() {
SpaceTypesListScreen(
uiState = UiSpaceTypesScreenState(
items = listOf(
UiSpaceTypeItem(
id = "1",
name = "Type 1",
icon = ObjectIcon.TypeIcon.Default(
rawValue = "american-football",
color = CustomIconColor.Teal
)
),
UiSpaceTypeItem(
id = "2",
name = "Type 2",
icon = ObjectIcon.TypeIcon.Default(
rawValue = "bluetooth",
color = CustomIconColor.Red
)
)
)
),
onBackPressed = {},
onTypeClicked = {},
onAddIconClicked = {}
)
}