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

DROID-3527 Primitives | Edit Type title screen (#2240)

This commit is contained in:
Konstantin Ivanov 2025-04-04 16:02:59 +02:00 committed by GitHub
parent 33796425b4
commit 4727bebae9
Signed by: github
GPG key ID: B5690EEEBB952194
9 changed files with 227 additions and 201 deletions

View file

@ -13,7 +13,6 @@ import androidx.core.os.bundleOf
import androidx.fragment.app.viewModels
import androidx.fragment.compose.content
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavOptions
import androidx.navigation.fragment.findNavController
import androidx.navigation.navOptions
import com.anytypeio.anytype.R
@ -28,7 +27,6 @@ import com.anytypeio.anytype.feature_object_type.viewmodel.CreateObjectTypeVMFac
import com.anytypeio.anytype.feature_object_type.viewmodel.CreateObjectTypeViewModel
import com.anytypeio.anytype.feature_object_type.viewmodel.CreateTypeCommand
import com.anytypeio.anytype.feature_object_type.viewmodel.CreateTypeVmParams
import com.anytypeio.anytype.ui.base.navigation
import javax.inject.Inject
import kotlin.getValue
import timber.log.Timber
@ -50,8 +48,6 @@ class CreateTypeFragment: BaseBottomSheetComposeFragment() {
SetTypeTitlesAndIconScreen(
uiState = vm.uiState.collectAsStateWithLifecycle().value,
onDismiss = vm::onDismiss,
onTitleChanged = vm::onTypeTitleChanged,
onPluralChanged = vm::onTypePluralChanged,
onIconClicked = vm::onIconClicked,
onButtonClicked = vm::onButtonClicked
)

View file

@ -33,6 +33,7 @@ import com.anytypeio.anytype.feature_object_type.ui.ObjectTypeVmParams
import com.anytypeio.anytype.feature_object_type.ui.TypeEvent
import com.anytypeio.anytype.feature_object_type.ui.UiErrorState
import com.anytypeio.anytype.feature_object_type.ui.UiIconsPickerState
import com.anytypeio.anytype.feature_object_type.ui.create.SetTypeTitlesAndIconScreen
import com.anytypeio.anytype.feature_object_type.ui.icons.ChangeIconScreen
import com.anytypeio.anytype.feature_object_type.viewmodel.ObjectTypeVMFactory
import com.anytypeio.anytype.feature_object_type.viewmodel.ObjectTypeViewModel
@ -60,6 +61,7 @@ class ObjectTypeFragment : BaseComposeFragment() {
) = content {
MaterialTheme {
ObjectTypeScreen()
IconAndTitleUpdateScreen()
IconsPickerScreen()
ErrorScreen()
}
@ -216,6 +218,16 @@ class ObjectTypeFragment : BaseComposeFragment() {
}
}
@Composable
private fun IconAndTitleUpdateScreen() {
SetTypeTitlesAndIconScreen(
uiState = vm.uiTitleAndIconUpdateState.collectAsStateWithLifecycle().value,
onDismiss = vm::onDismissTitleAndIconScreen,
onIconClicked = vm::onIconClickedTitleAndIconScreen,
onButtonClicked = vm::onButtonClickedTitleAndIconScreen
)
}
override fun injectDependencies() {
val params = ObjectTypeVmParams(
spaceId = SpaceId(space),

View file

@ -20,6 +20,7 @@ sealed class TypeEvent {
//region Object Type Header
data object OnObjectTypeIconClick : TypeEvent()
data class OnObjectTypeTitleUpdate(val title: String) : TypeEvent()
data object OnObjectTypeTitleClick : TypeEvent()
//endregion
//region Templates

View file

@ -43,9 +43,9 @@ data class UiTitleState(val title: String, val isEditable: Boolean) {
}
}
data class UiIconState(val icon: ObjectIcon, val isEditable: Boolean) {
data class UiIconState(val icon: ObjectIcon.TypeIcon, val isEditable: Boolean) {
companion object {
val EMPTY = UiIconState(icon = ObjectIcon.None, isEditable = false)
val EMPTY = UiIconState(icon = ObjectIcon.TypeIcon.Default.DEFAULT, isEditable = false)
}
}
//endregion

View file

@ -21,6 +21,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@ -59,13 +60,13 @@ import com.anytypeio.anytype.presentation.objects.custom_icon.CustomIconColor
fun SetTypeTitlesAndIconScreen(
uiState: UiTypeSetupTitleAndIconState,
modifier: Modifier = Modifier,
onTitleChanged: (String) -> Unit,
onPluralChanged: (String) -> Unit,
onIconClicked: () -> Unit,
onDismiss: () -> Unit,
onButtonClicked: () -> Unit
onButtonClicked: (String, String) -> Unit
) {
if (uiState !is UiTypeSetupTitleAndIconState.Visible) return
val bottomSheetState = rememberModalBottomSheetState(
skipPartiallyExpanded = true
)
@ -89,8 +90,6 @@ fun SetTypeTitlesAndIconScreen(
) {
CreateNewTypeScreenContent(
uiState = uiState,
onTitleChanged = onTitleChanged,
onPluralChanged = onPluralChanged,
onIconClicked = onIconClicked,
onButtonClicked = onButtonClicked
)
@ -99,15 +98,22 @@ fun SetTypeTitlesAndIconScreen(
@Composable
private fun ColumnScope.CreateNewTypeScreenContent(
uiState: UiTypeSetupTitleAndIconState,
onTitleChanged: (String) -> Unit,
onPluralChanged: (String) -> Unit,
uiState: UiTypeSetupTitleAndIconState.Visible,
onIconClicked: () -> Unit,
onButtonClicked: () -> Unit
onButtonClicked: (String, String) -> Unit
) {
var isButtonEnabled by remember {
mutableStateOf(false)
// Maintain individual state for each field's "not empty" condition.
var isTitleNotEmpty by remember { mutableStateOf(false) }
var isPluralNotEmpty by remember { mutableStateOf(false) }
var titleText by remember { mutableStateOf(uiState.getInitialTitleValue()) }
var pluralText by remember { mutableStateOf(uiState.getInitialPluralValue()) }
// Compute the button enabled state.
val isButtonEnabled = isTitleNotEmpty && isPluralNotEmpty
val icon = when(uiState) {
is UiTypeSetupTitleAndIconState.Visible.CreateNewType -> uiState.icon
is UiTypeSetupTitleAndIconState.Visible.EditType -> uiState.icon
}
Spacer(modifier = Modifier.height(12.dp))
@ -139,7 +145,7 @@ private fun ColumnScope.CreateNewTypeScreenContent(
onIconClicked()
},
iconSize = 48.dp,
icon = uiState.icon,
icon = icon,
backgroundColor = R.color.amp_transparent
)
Spacer(modifier = Modifier.width(0.dp))
@ -149,9 +155,12 @@ private fun ColumnScope.CreateNewTypeScreenContent(
.padding(top = 11.5.dp)
.wrapContentHeight(),
hint = uiState.getTitleHint(),
initialValue = uiState.getInitialTitleValue(),
onTextChanged = {
onTitleChanged(it)
isButtonEnabled = it.isNotEmpty()
titleText = it
},
onButtonEnabled = { enable ->
isTitleNotEmpty = enable
}
)
}
@ -183,8 +192,14 @@ private fun ColumnScope.CreateNewTypeScreenContent(
.fillMaxWidth()
.wrapContentHeight(),
hint = uiState.getPluralHint(),
initialValue = uiState.getInitialPluralValue(),
textStyle = BodyRegular,
onTextChanged = onPluralChanged
onTextChanged = {
pluralText = it
},
onButtonEnabled = { enable ->
isPluralNotEmpty = enable
}
)
}
Spacer(modifier = Modifier.height(22.dp))
@ -194,7 +209,7 @@ private fun ColumnScope.CreateNewTypeScreenContent(
.fillMaxWidth()
.padding(horizontal = 20.dp),
onClick = {
onButtonClicked()
onButtonClicked(titleText, pluralText)
},
enabled = isButtonEnabled,
text = uiState.getButtonTitle(),
@ -206,17 +221,23 @@ private fun ColumnScope.CreateNewTypeScreenContent(
@Composable
private fun CreateTypeField(
modifier: Modifier,
initialValue: String = "",
textStyle: androidx.compose.ui.text.TextStyle = HeadlineHeading,
hint: String,
onButtonEnabled: (Boolean) -> Unit = {},
onTextChanged: (String) -> Unit
) {
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(
TextFieldValue("")
TextFieldValue(initialValue)
)
}
LaunchedEffect(textFieldValue) {
onButtonEnabled(textFieldValue.text.isNotEmpty())
}
val focusManager = LocalFocusManager.current
val focusRequester = remember { FocusRequester() }
@ -261,35 +282,49 @@ private fun CreateTypeField(
)
}
@Composable
fun UiTypeSetupTitleAndIconState.getTitleHint(): String {
fun UiTypeSetupTitleAndIconState.Visible.getInitialTitleValue(): String {
return when (this) {
is UiTypeSetupTitleAndIconState.CreateNewType -> stringResource(id = R.string.object_type_create_title_hint)
is UiTypeSetupTitleAndIconState.EditType -> stringResource(id = R.string.untitled)
is UiTypeSetupTitleAndIconState.Visible.CreateNewType -> ""
is UiTypeSetupTitleAndIconState.Visible.EditType -> this.initialTitle ?: ""
}
}
fun UiTypeSetupTitleAndIconState.Visible.getInitialPluralValue(): String {
return when (this) {
is UiTypeSetupTitleAndIconState.Visible.CreateNewType -> ""
is UiTypeSetupTitleAndIconState.Visible.EditType -> this.initialPlural ?: ""
}
}
@Composable
fun UiTypeSetupTitleAndIconState.getPluralHint(): String {
fun UiTypeSetupTitleAndIconState.Visible.getTitleHint(): String {
return when (this) {
is UiTypeSetupTitleAndIconState.CreateNewType -> stringResource(id = R.string.object_type_create_plural_title_hint)
is UiTypeSetupTitleAndIconState.EditType -> stringResource(id = R.string.untitled)
is UiTypeSetupTitleAndIconState.Visible.CreateNewType -> stringResource(id = R.string.object_type_create_title_hint)
is UiTypeSetupTitleAndIconState.Visible.EditType -> stringResource(id = R.string.untitled)
}
}
@Composable
fun UiTypeSetupTitleAndIconState.getTitle(): String {
fun UiTypeSetupTitleAndIconState.Visible.getPluralHint(): String {
return when (this) {
is UiTypeSetupTitleAndIconState.CreateNewType -> stringResource(id = R.string.object_type_create_new_title)
is UiTypeSetupTitleAndIconState.EditType -> stringResource(id = R.string.object_type_rename_title)
is UiTypeSetupTitleAndIconState.Visible.CreateNewType -> stringResource(id = R.string.object_type_create_plural_title_hint)
is UiTypeSetupTitleAndIconState.Visible.EditType -> stringResource(id = R.string.untitled)
}
}
@Composable
fun UiTypeSetupTitleAndIconState.getButtonTitle(): String {
fun UiTypeSetupTitleAndIconState.Visible.getTitle(): String {
return when (this) {
is UiTypeSetupTitleAndIconState.CreateNewType -> stringResource(id = R.string.create)
is UiTypeSetupTitleAndIconState.EditType -> stringResource(id = R.string.done)
is UiTypeSetupTitleAndIconState.Visible.CreateNewType -> stringResource(id = R.string.object_type_create_new_title)
is UiTypeSetupTitleAndIconState.Visible.EditType -> stringResource(id = R.string.object_type_rename_title)
}
}
@Composable
fun UiTypeSetupTitleAndIconState.Visible.getButtonTitle(): String {
return when (this) {
is UiTypeSetupTitleAndIconState.Visible.CreateNewType -> stringResource(id = R.string.create)
is UiTypeSetupTitleAndIconState.Visible.EditType -> stringResource(id = R.string.done)
}
}
@ -298,16 +333,14 @@ fun UiTypeSetupTitleAndIconState.getButtonTitle(): String {
fun CreateNewTypeScreenPreview() {
Column {
CreateNewTypeScreenContent(
uiState = UiTypeSetupTitleAndIconState.CreateNewType(
uiState = UiTypeSetupTitleAndIconState.Visible.CreateNewType(
icon = ObjectIcon.TypeIcon.Default(
rawValue = "american-football",
color = CustomIconColor.Red
)
),
onTitleChanged = {},
onPluralChanged = {},
onIconClicked = { /* no-op */ },
onButtonClicked = { /* no-op */ }
onButtonClicked = { _, _ -> }
)
}
}
@ -317,16 +350,16 @@ fun CreateNewTypeScreenPreview() {
fun EditTypeScreenPreview() {
Column {
CreateNewTypeScreenContent(
uiState = UiTypeSetupTitleAndIconState.EditType(
uiState = UiTypeSetupTitleAndIconState.Visible.EditType(
icon = ObjectIcon.TypeIcon.Default(
rawValue = "american-football",
color = CustomIconColor.Red
)
),
initialTitle = "Page",
initialPlural = "Pages"
),
onTitleChanged = {},
onPluralChanged = {},
onIconClicked = { /* no-op */ },
onButtonClicked = { /* no-op */ }
onButtonClicked = { _, _ -> }
)
}
}

View file

@ -4,17 +4,20 @@ import com.anytypeio.anytype.presentation.objects.ObjectIcon
sealed class UiTypeSetupTitleAndIconState {
abstract val icon: ObjectIcon.TypeIcon.Default
data object Hidden : UiTypeSetupTitleAndIconState()
data class CreateNewType(
override val icon: ObjectIcon.TypeIcon.Default,
val initialTitle: String = "",
val initialPlural: String = ""
) : UiTypeSetupTitleAndIconState()
sealed class Visible : UiTypeSetupTitleAndIconState() {
data class EditType(
override val icon: ObjectIcon.TypeIcon.Default,
val initialTitle: String = "",
val initialPlural: String = ""
) : UiTypeSetupTitleAndIconState()
data class CreateNewType(
val icon: ObjectIcon.TypeIcon.Default,
val initialTitle: String = "",
val initialPlural: String = ""
) : Visible()
data class EditType(
val icon: ObjectIcon.TypeIcon,
val initialTitle: String?,
val initialPlural: String?
) : Visible()
}
}

View file

@ -1,5 +1,6 @@
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
@ -65,7 +66,6 @@ fun IconAndTitleWidget(
.fillMaxWidth()
.wrapContentHeight(),
initialName = uiTitleState.title,
enabled = uiTitleState.isEditable,
onTypeEvent = onTypeEvent,
)
}
@ -75,68 +75,21 @@ fun IconAndTitleWidget(
fun NameField(
modifier: Modifier,
initialName: String,
enabled: Boolean,
onTypeEvent: (TypeEvent) -> Unit
) {
var textFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(
TextFieldValue(initialName)
)
val (text, color) = if (initialName.isEmpty()) {
stringResource(R.string.untitled) to colorResource(id = R.color.text_tertiary)
} else {
initialName to colorResource(id = R.color.text_primary)
}
val focusManager = LocalFocusManager.current
val focusRequester = remember { FocusRequester() }
val keyboardController = LocalSoftwareKeyboardController.current
BasicTextField(
value = textFieldValue,
onValueChange = { newValue ->
textFieldValue = newValue
onTypeEvent.invoke(
TypeEvent.OnObjectTypeTitleUpdate(
title = textFieldValue.text
)
)
},
textStyle = HeadlineTitle.copy(color = colorResource(id = R.color.text_primary)),
singleLine = false,
enabled = enabled,
cursorBrush = SolidColor(colorResource(id = R.color.text_primary)),
Text(
text = text,
style = HeadlineTitle.copy(color = color),
modifier = modifier
.padding(start = 12.dp, end = 20.dp)
.focusRequester(focusRequester),
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions {
keyboardController?.hide()
focusManager.clearFocus()
onTypeEvent.invoke(
TypeEvent.OnObjectTypeTitleUpdate(
title = textFieldValue.text
)
)
},
decorationBox = { innerTextField ->
Box(
modifier = Modifier
.fillMaxWidth()
.height(32.dp),
contentAlignment = Alignment.CenterStart
) {
if (textFieldValue.text.isEmpty()) {
Text(
modifier = Modifier.wrapContentSize(),
text = stringResource(id = R.string.untitled),
style = HeadlineTitle,
color = colorResource(id = R.color.text_tertiary),
)
}
.noRippleThrottledClickable {
onTypeEvent(TypeEvent.OnObjectTypeTitleClick)
}
innerTextField()
}
)
}
@ -148,7 +101,7 @@ fun IconAndTitleWidgetPreview() {
.fillMaxWidth()
.wrapContentHeight(),
onTypeEvent = {},
uiIconState = UiIconState(icon = ObjectIcon.Task(isChecked = false), isEditable = true),
uiIconState = UiIconState(icon = ObjectIcon.TypeIcon.Default.DEFAULT, isEditable = true),
uiTitleState = UiTitleState(
title = "I understand that contributing to this repository will require me to agree with the",
isEditable = true
@ -164,7 +117,7 @@ fun IconAndTitleEmptyWidgetPreview() {
.fillMaxWidth()
.wrapContentHeight(),
onTypeEvent = {},
uiIconState = UiIconState(icon = ObjectIcon.Task(isChecked = false), isEditable = true),
uiIconState = UiIconState(icon = ObjectIcon.TypeIcon.Default.DEFAULT, isEditable = true),
uiTitleState = UiTitleState(
title = "",
isEditable = true

View file

@ -31,18 +31,11 @@ class CreateObjectTypeViewModel(
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
private val INIT =
when (vmParams.mode) {
MODE.CREATE -> UiTypeSetupTitleAndIconState.CreateNewType(
icon = ObjectIcon.TypeIcon.Default.DEFAULT
)
MODE.EDIT -> UiTypeSetupTitleAndIconState.EditType(
icon = ObjectIcon.TypeIcon.Default.DEFAULT
)
}
private val _uiState = MutableStateFlow<UiTypeSetupTitleAndIconState>(INIT)
private val _uiState = MutableStateFlow<UiTypeSetupTitleAndIconState>(
UiTypeSetupTitleAndIconState.Visible.CreateNewType(
icon = ObjectIcon.TypeIcon.Default.DEFAULT
)
)
val uiState = _uiState.asStateFlow()
//icons picker screen
@ -50,21 +43,10 @@ class CreateObjectTypeViewModel(
val commands = MutableSharedFlow<CreateTypeCommand>(replay = 0)
private val typeTitle = MutableStateFlow("")
private val typePlural = MutableStateFlow("")
init {
Timber.d("CreateObjectTypeViewModel initialized")
}
fun onTypeTitleChanged(title: String) {
typeTitle.value = title
}
fun onTypePluralChanged(plural: String) {
typePlural.value = plural
}
fun onDismiss() {
viewModelScope.launch {
commands.emit(CreateTypeCommand.Dismiss)
@ -72,23 +54,20 @@ class CreateObjectTypeViewModel(
}
fun onRemoveIcon() {
val defaultIcon = ObjectIcon.TypeIcon.Default.DEFAULT
_uiState.value = when (val currentState = _uiState.value) {
is UiTypeSetupTitleAndIconState.CreateNewType -> currentState.copy(icon = defaultIcon)
is UiTypeSetupTitleAndIconState.EditType -> currentState.copy(icon = defaultIcon)
}
val currentState =
_uiState.value as? UiTypeSetupTitleAndIconState.Visible.CreateNewType ?: return
_uiState.value = currentState.copy(icon = ObjectIcon.TypeIcon.Default.DEFAULT)
uiIconsPickerScreen.value = UiIconsPickerState.Hidden
}
fun onNewIconPicked(iconName: String, color: CustomIconColor?) {
val currentState =
_uiState.value as? UiTypeSetupTitleAndIconState.Visible.CreateNewType ?: return
val newIcon = ObjectIcon.TypeIcon.Default(
rawValue = iconName,
color = color ?: CustomIconColor.DEFAULT
)
_uiState.value = when (val currentState = _uiState.value) {
is UiTypeSetupTitleAndIconState.CreateNewType -> currentState.copy(icon = newIcon)
is UiTypeSetupTitleAndIconState.EditType -> currentState.copy(icon = newIcon)
}
_uiState.value = currentState.copy(icon = newIcon)
uiIconsPickerScreen.value = UiIconsPickerState.Hidden
}
@ -100,24 +79,20 @@ class CreateObjectTypeViewModel(
uiIconsPickerScreen.value = UiIconsPickerState.Hidden
}
fun onButtonClicked() {
when (vmParams.mode) {
MODE.CREATE -> createNewType()
MODE.EDIT -> updateType()
}
fun onButtonClicked(title: String, plurals: String) {
createNewType(title = title, plurals = plurals)
}
private fun createNewType() {
val icon = _uiState.value.icon
val name = typeTitle.value
val plural = typePlural.value
Timber.d("Creating new type with name: $name, plural: $plural, icon: $icon")
private fun createNewType(title: String, plurals: String) {
val state = _uiState.value as? UiTypeSetupTitleAndIconState.Visible.CreateNewType ?: return
val icon = state.icon
Timber.d("Creating new type with title: $title, plurals: $plurals, icon: $icon")
viewModelScope.launch {
createObjectType.execute(
CreateObjectType.Params(
space = vmParams.spaceId,
name = name,
pluralName = plural,
name = title,
pluralName = plurals,
iconName = icon.rawValue,
iconColor = icon.color.iconOption.toDouble()
)
@ -149,26 +124,12 @@ class CreateObjectTypeViewModel(
}
}
private fun updateType() {
val icon = _uiState.value.icon
val name = typeTitle.value
val plural = typePlural.value
viewModelScope.launch {
}
}
}
data class CreateTypeVmParams(
val spaceId: Id,
val mode: MODE = MODE.CREATE
val spaceId: Id
)
enum class MODE {
CREATE,
EDIT
}
sealed class CreateTypeCommand {
data object Dismiss : CreateTypeCommand()
data class NavigateToObjectType(val id: Id, val space: Id) : CreateTypeCommand()

View file

@ -51,6 +51,7 @@ import com.anytypeio.anytype.feature_object_type.ui.UiTemplatesButtonState
import com.anytypeio.anytype.feature_object_type.ui.UiTemplatesModalListState
import com.anytypeio.anytype.feature_object_type.ui.UiTitleState
import com.anytypeio.anytype.feature_object_type.ui.buildUiPropertiesList
import com.anytypeio.anytype.feature_object_type.ui.create.UiTypeSetupTitleAndIconState
import com.anytypeio.anytype.feature_object_type.ui.toTemplateView
import com.anytypeio.anytype.feature_properties.edit.UiEditPropertyState
import com.anytypeio.anytype.feature_properties.edit.UiEditPropertyState.Visible.View
@ -59,6 +60,7 @@ import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
import com.anytypeio.anytype.presentation.extension.sendAnalyticsScreenObjectType
import com.anytypeio.anytype.presentation.mapper.objectIcon
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.objects.custom_icon.CustomIconColor
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants.defaultKeys
import com.anytypeio.anytype.presentation.sync.SyncStatusWidgetState
@ -143,6 +145,10 @@ class ObjectTypeViewModel(
//icons picker screen
val uiIconsPickerScreen = MutableStateFlow<UiIconsPickerState>(UiIconsPickerState.Hidden)
//title and icon update screen
val uiTitleAndIconUpdateState =
MutableStateFlow<UiTypeSetupTitleAndIconState>(UiTypeSetupTitleAndIconState.Hidden)
//error
val errorState = MutableStateFlow<UiErrorState>(UiErrorState.Hidden)
//endregion
@ -315,13 +321,17 @@ class ObjectTypeViewModel(
_objectTypePermissionsState.value = objectPermissions
uiTitleState.value = UiTitleState(
title = fieldParser.getObjectPluralName(objectWrapper = objType),
title = objType.pluralName.orEmpty(),
isEditable = objectPermissions.canEditDetails
)
val newIcon = objType.objectIcon()
uiIconState.value = UiIconState(
icon = objType.objectIcon(),
icon = newIcon,
isEditable = objectPermissions.canEditDetails
)
(uiTitleAndIconUpdateState.value as? UiTypeSetupTitleAndIconState.Visible.EditType)?.let {
uiTitleAndIconUpdateState.value = it.copy(icon = newIcon)
}
if (objectPermissions.canDelete) {
uiEditButtonState.value = UiEditButton.Visible
}
@ -395,31 +405,32 @@ class ObjectTypeViewModel(
val formatName = stringResourceProvider.getPropertiesFormatPrettyString(item.format)
val formatIcon = item.format.simpleIcon()
uiEditPropertyScreen.value = if (permissions?.participantCanEdit == true && item.isEditableField) {
UiEditPropertyState.Visible.Edit(
id = item.id,
key = item.fieldKey,
name = item.fieldTitle,
formatName = formatName,
formatIcon = formatIcon,
format = item.format,
limitObjectTypes = computedLimitTypes,
isPossibleToUnlinkFromType = item.isPossibleToUnlinkFromType,
showLimitTypes = false
)
} else {
UiEditPropertyState.Visible.View(
id = item.id,
key = item.fieldKey,
name = item.fieldTitle,
formatName = formatName,
formatIcon = formatIcon,
format = item.format,
limitObjectTypes = computedLimitTypes,
isPossibleToUnlinkFromType = item.isPossibleToUnlinkFromType,
showLimitTypes = false
)
}
uiEditPropertyScreen.value =
if (permissions?.participantCanEdit == true && item.isEditableField) {
UiEditPropertyState.Visible.Edit(
id = item.id,
key = item.fieldKey,
name = item.fieldTitle,
formatName = formatName,
formatIcon = formatIcon,
format = item.format,
limitObjectTypes = computedLimitTypes,
isPossibleToUnlinkFromType = item.isPossibleToUnlinkFromType,
showLimitTypes = false
)
} else {
UiEditPropertyState.Visible.View(
id = item.id,
key = item.fieldKey,
name = item.fieldTitle,
formatName = formatName,
formatIcon = formatIcon,
format = item.format,
limitObjectTypes = computedLimitTypes,
isPossibleToUnlinkFromType = item.isPossibleToUnlinkFromType,
showLimitTypes = false
)
}
}
}
//endregion
@ -472,6 +483,10 @@ class ObjectTypeViewModel(
updateTitle(event.title)
}
is TypeEvent.OnObjectTypeTitleClick -> {
showTitleAndIconUpdateScreen()
}
TypeEvent.OnMenuItemDeleteClick -> {
uiAlertState.value = UiDeleteAlertState.Show
}
@ -865,6 +880,7 @@ class ObjectTypeViewModel(
else -> state
}
}
FieldEvent.EditProperty.OnLimitTypesDismiss -> {
uiEditPropertyScreen.value = when (val state = uiEditPropertyScreen.value) {
is UiEditPropertyState.Visible.Edit -> state.copy(showLimitTypes = false)
@ -1034,6 +1050,57 @@ class ObjectTypeViewModel(
}
//endregion
//region Title and Icon Update Screen
private fun showTitleAndIconUpdateScreen() {
val objType = _objTypeState.value ?: return
val initialIcon = uiIconState.value.icon
val initialTitle = objType.name
val initialPlural = objType.pluralName
Timber.d(
"showTitleAndIconUpdateScreen, initialIcon: $initialIcon, " +
"initialTitle: $initialTitle, initialPlural: $initialPlural"
)
uiTitleAndIconUpdateState.value = UiTypeSetupTitleAndIconState.Visible.EditType(
icon = initialIcon,
initialTitle = initialTitle,
initialPlural = initialPlural
)
}
fun onDismissTitleAndIconScreen() {
uiTitleAndIconUpdateState.value = UiTypeSetupTitleAndIconState.Hidden
}
fun onIconClickedTitleAndIconScreen() {
uiIconsPickerScreen.value = UiIconsPickerState.Visible
}
fun onButtonClickedTitleAndIconScreen(title: String, plurals: String) {
val objType = _objTypeState.value ?: return
Timber.d("onButtonClickedTitleAndIconScreen, title: $title, plural: $plurals")
val params = SetObjectDetails.Params(
ctx = objType.id,
details = mapOf(
Relations.NAME to title,
Relations.PLURAL_NAME to plurals
)
)
viewModelScope.launch {
setObjectDetails.async(params).fold(
onSuccess = {
Timber.d("Object type title updated")
uiTitleAndIconUpdateState.value = UiTypeSetupTitleAndIconState.Hidden
},
onFailure = {
Timber.e(it, "Error while updating object type title")
}
)
}
}
//endregion
companion object {
const val TEMPLATE_MAX_COUNT = 100