mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2121 Relations | Create or edit options screen (#821)
This commit is contained in:
parent
4af8a939f9
commit
ad58c376d3
6 changed files with 430 additions and 105 deletions
|
@ -12,9 +12,11 @@ import androidx.compose.ui.res.colorResource
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_ui.relations.CreateOrEditOptionScreen
|
||||
import com.anytypeio.anytype.core_utils.ext.argString
|
||||
import com.anytypeio.anytype.core_utils.ext.argStringOrNull
|
||||
import com.anytypeio.anytype.core_utils.ext.subscribe
|
||||
|
@ -54,12 +56,18 @@ class CreateOrEditOptionFragment : BaseBottomSheetComposeFragment() {
|
|||
colors = MaterialTheme.colors.copy(
|
||||
surface = colorResource(id = R.color.context_menu_background)
|
||||
)
|
||||
) {}
|
||||
) {
|
||||
CreateOrEditOptionScreen(
|
||||
state = vm.viewState.collectAsStateWithLifecycle().value,
|
||||
onButtonClicked = { vm.onButtonClick() },
|
||||
onTextChanged = { vm.updateName(it) },
|
||||
onColorChanged = { vm.updateColor(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
skipCollapsed()
|
||||
|
|
|
@ -12,11 +12,14 @@ import androidx.compose.ui.res.colorResource
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_ui.relations.RelationsLazyList
|
||||
import com.anytypeio.anytype.core_ui.relations.TagOrStatusValueScreen
|
||||
import com.anytypeio.anytype.core_utils.ext.argBoolean
|
||||
import com.anytypeio.anytype.core_utils.ext.argString
|
||||
import com.anytypeio.anytype.core_utils.ext.subscribe
|
||||
|
@ -55,11 +58,11 @@ class TagOrStatusValueFragment : BaseBottomSheetComposeFragment() {
|
|||
surface = colorResource(id = R.color.context_menu_background)
|
||||
)
|
||||
) {
|
||||
// RelationsValueScreen(
|
||||
// state = vm.viewState.collectAsStateWithLifecycle().value,
|
||||
// action = vm::onAction,
|
||||
// onQueryChanged = vm::onQueryChanged
|
||||
// )
|
||||
TagOrStatusValueScreen(
|
||||
state = vm.viewState.collectAsStateWithLifecycle().value,
|
||||
action = vm::onAction,
|
||||
onQueryChanged = vm::onQueryChanged
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
package com.anytypeio.anytype.core_ui.relations
|
||||
|
||||
|
||||
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.Column
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.Text
|
||||
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
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
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.platform.SoftwareKeyboardController
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.extensions.dark
|
||||
import com.anytypeio.anytype.core_ui.foundation.Divider
|
||||
import com.anytypeio.anytype.core_ui.foundation.Dragger
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonPrimary
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonSize
|
||||
import com.anytypeio.anytype.core_ui.views.Caption1Regular
|
||||
import com.anytypeio.anytype.core_ui.views.Title1
|
||||
import com.anytypeio.anytype.presentation.relations.option.CreateOrEditOptionScreenViewState
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
fun CreateOrEditOptionScreen(
|
||||
state: CreateOrEditOptionScreenViewState,
|
||||
onButtonClicked: () -> Unit,
|
||||
onTextChanged: (String) -> Unit,
|
||||
onColorChanged: (ThemeColor) -> Unit
|
||||
) {
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
|
||||
val currentState by rememberUpdatedState(state)
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
|
||||
var selectedColor by remember { mutableStateOf(currentState.color) }
|
||||
var editableText by remember { mutableStateOf(currentState.text) }
|
||||
|
||||
val (title, buttonText) = getTexts(currentState)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(bottom = 20.dp, start = 20.dp, end = 20.dp)
|
||||
) {
|
||||
Header(text = title)
|
||||
TextInput(
|
||||
initialValue = currentState.text,
|
||||
color = currentState.color,
|
||||
onTextChanged = {
|
||||
editableText = it
|
||||
onTextChanged(it)
|
||||
},
|
||||
focusRequester = focusRequester,
|
||||
keyboardController = keyboardController
|
||||
)
|
||||
Divider(paddingEnd = 0.dp, paddingStart = 0.dp)
|
||||
Spacer(modifier = Modifier.height(26.dp))
|
||||
Text(
|
||||
text = stringResource(id = R.string.color),
|
||||
style = Caption1Regular,
|
||||
color = colorResource(id = R.color.text_secondary)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
CirclesContainer(selectedColor = selectedColor) { newColor ->
|
||||
selectedColor = newColor
|
||||
onColorChanged(newColor)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(115.dp))
|
||||
ButtonPrimary(
|
||||
text = buttonText,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.imePadding(),
|
||||
onClick = { onButtonClicked() },
|
||||
size = ButtonSize.Large
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun CirclesContainer(selectedColor: ThemeColor, action: (ThemeColor) -> Unit) {
|
||||
FlowRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight(),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
maxItemsInEachRow = 5
|
||||
) {
|
||||
val itemModifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxWidth()
|
||||
.clip(CircleShape)
|
||||
.aspectRatio(1f)
|
||||
.align(Alignment.CenterVertically)
|
||||
ThemeColor.values().drop(1).forEach { color ->
|
||||
Box(
|
||||
itemModifier
|
||||
.noRippleClickable { action(color) }
|
||||
.background(
|
||||
color = dark(color = color)
|
||||
)
|
||||
) {
|
||||
if (selectedColor == color) {
|
||||
Image(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
painter = painterResource(id = R.drawable.ic_tick_24),
|
||||
contentDescription = "option selected"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
private fun TextInput(
|
||||
initialValue: String,
|
||||
color: ThemeColor,
|
||||
focusRequester: FocusRequester,
|
||||
keyboardController: SoftwareKeyboardController?,
|
||||
onTextChanged: (String) -> Unit
|
||||
) {
|
||||
var innerValue by remember { mutableStateOf(initialValue) }
|
||||
val focusManager = LocalFocusManager.current
|
||||
|
||||
if (initialValue.isEmpty()) {
|
||||
LaunchedEffect(Unit) {
|
||||
focusRequester.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
BasicTextField(
|
||||
value = innerValue,
|
||||
onValueChange = {
|
||||
innerValue = it
|
||||
onTextChanged(it)
|
||||
},
|
||||
textStyle = Title1.copy(color = dark(color = color)),
|
||||
singleLine = true,
|
||||
enabled = true,
|
||||
cursorBrush = SolidColor(dark(color = color)),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(start = 0.dp, top = 2.dp)
|
||||
.focusRequester(focusRequester),
|
||||
keyboardOptions = KeyboardOptions(
|
||||
imeAction = ImeAction.Done
|
||||
),
|
||||
keyboardActions = KeyboardActions {
|
||||
keyboardController?.hide()
|
||||
focusManager.clearFocus()
|
||||
},
|
||||
decorationBox = { innerTextField ->
|
||||
if (innerValue.isEmpty()) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.hint_enter_name),
|
||||
style = Title1,
|
||||
color = colorResource(id = R.color.text_tertiary),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
)
|
||||
}
|
||||
innerTextField()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Header(text: String) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 6.dp)
|
||||
) {
|
||||
Dragger(modifier = Modifier.align(Alignment.Center))
|
||||
}
|
||||
|
||||
// Main content box
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(48.dp)
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(Alignment.Center)
|
||||
.padding(horizontal = 74.dp),
|
||||
text = text,
|
||||
style = Title1.copy(),
|
||||
color = colorResource(R.color.text_primary),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getTexts(state: CreateOrEditOptionScreenViewState): Pair<String, String> {
|
||||
return when (state) {
|
||||
is CreateOrEditOptionScreenViewState.Create -> {
|
||||
stringResource(id = R.string.option_widget_create) to stringResource(id = R.string.create)
|
||||
}
|
||||
|
||||
is CreateOrEditOptionScreenViewState.Edit -> {
|
||||
stringResource(id = R.string.option_widget_edit) to stringResource(id = R.string.apply)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, backgroundColor = 0xFFFFFFFF, device = Devices.PIXEL_4_XL)
|
||||
@Composable
|
||||
fun PreviewOptionWidget() {
|
||||
CreateOrEditOptionScreen(
|
||||
state = CreateOrEditOptionScreenViewState.Create(
|
||||
text = "Urgent",
|
||||
color = ThemeColor.BLUE,
|
||||
),
|
||||
onButtonClicked = {},
|
||||
onTextChanged = {},
|
||||
onColorChanged = {}
|
||||
)
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package com.anytypeio.anytype.core_ui.relations
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.platform.SoftwareKeyboardController
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.presentation.relations.option.OptionScreenViewState
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
fun OptionWidget(
|
||||
state: OptionScreenViewState,
|
||||
onButtonClicked: () -> Unit,
|
||||
onTextChanged: (String) -> Unit,
|
||||
onColorChanged: (ThemeColor) -> Unit
|
||||
) {
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
val focusManager = LocalFocusManager.current
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight(),
|
||||
contentAlignment = Alignment.TopCenter,
|
||||
) {
|
||||
|
||||
val currentState by rememberUpdatedState(state)
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
|
||||
OptionWidgetContent(
|
||||
state = currentState,
|
||||
onButtonClicked = onButtonClicked,
|
||||
focusRequester = focusRequester,
|
||||
keyboardController = keyboardController,
|
||||
onTextChanged = onTextChanged,
|
||||
onColorChanged = onColorChanged
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
fun OptionWidgetContent(
|
||||
state: OptionScreenViewState,
|
||||
onButtonClicked: () -> Unit,
|
||||
focusRequester: FocusRequester,
|
||||
keyboardController: SoftwareKeyboardController?,
|
||||
onTextChanged: (String) -> Unit,
|
||||
onColorChanged: (ThemeColor) -> Unit
|
||||
) {
|
||||
|
||||
}
|
|
@ -26,9 +26,7 @@ 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.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.foundation.Divider
|
||||
import com.anytypeio.anytype.core_ui.foundation.Dragger
|
||||
|
@ -42,7 +40,7 @@ import com.anytypeio.anytype.presentation.relations.value.tagstatus.TagStatusAct
|
|||
import com.anytypeio.anytype.presentation.relations.value.tagstatus.TagStatusViewState
|
||||
|
||||
@Composable
|
||||
fun RelationsValueScreen(
|
||||
fun TagOrStatusValueScreen(
|
||||
state: TagStatusViewState,
|
||||
action: (TagStatusAction) -> Unit,
|
||||
onQueryChanged: (String) -> Unit
|
||||
|
@ -193,12 +191,14 @@ fun RelationsViewLoading() {
|
|||
|
||||
private fun isClearButtonVisible(state: TagStatusViewState): Boolean {
|
||||
if (state !is TagStatusViewState.Content) return false
|
||||
return state.items.any { it is RelationsListItem.Item.Tag && it.isSelected
|
||||
|| it is RelationsListItem.Item.Status && it.isSelected } && state.isRelationEditable
|
||||
return state.items.any {
|
||||
it is RelationsListItem.Item.Tag && it.isSelected
|
||||
|| it is RelationsListItem.Item.Status && it.isSelected
|
||||
} && state.isRelationEditable
|
||||
}
|
||||
|
||||
private fun isPlusButtonVisible(state: TagStatusViewState): Boolean {
|
||||
return when (state) {
|
||||
return when (state) {
|
||||
is TagStatusViewState.Content -> state.isRelationEditable
|
||||
is TagStatusViewState.Empty -> state.isRelationEditable
|
||||
is TagStatusViewState.Loading -> false
|
||||
|
@ -211,29 +211,4 @@ private fun getTitle(state: TagStatusViewState): String {
|
|||
is TagStatusViewState.Empty -> state.title
|
||||
is TagStatusViewState.Loading -> ""
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(backgroundColor = 0xFFFFFFFF, showBackground = true)
|
||||
@Composable
|
||||
fun MyWidgetHeader() {
|
||||
Header(state = TagStatusViewState.Content(
|
||||
isRelationEditable = true,
|
||||
title = "Tags",
|
||||
items = listOf(
|
||||
RelationsListItem.Item.Tag(
|
||||
name = "Urgent",
|
||||
color = ThemeColor.RED,
|
||||
number = 1,
|
||||
isSelected = true,
|
||||
optionId = "1"
|
||||
),
|
||||
RelationsListItem.Item.Tag(
|
||||
name = "Personal",
|
||||
color = ThemeColor.ORANGE,
|
||||
number = 2,
|
||||
isSelected = false,
|
||||
optionId = "1"
|
||||
)
|
||||
)
|
||||
), action = {})
|
||||
}
|
|
@ -1,18 +1,26 @@
|
|||
package com.anytypeio.anytype.presentation.relations.option
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_utils.ext.typeOf
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
|
||||
import com.anytypeio.anytype.domain.relations.CreateRelationOption
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.common.BaseViewModel
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsRelationValueEvent
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
class CreateOrEditOptionViewModel(
|
||||
private val viewModelParams: ViewModelParams,
|
||||
|
@ -25,7 +33,133 @@ class CreateOrEditOptionViewModel(
|
|||
) : BaseViewModel() {
|
||||
|
||||
val command = MutableSharedFlow<Command>(replay = 0)
|
||||
val viewState: MutableStateFlow<OptionScreenViewState?>? = null
|
||||
val viewState: MutableStateFlow<CreateOrEditOptionScreenViewState> =
|
||||
MutableStateFlow(initialViewState())
|
||||
|
||||
private fun initialViewState(): CreateOrEditOptionScreenViewState {
|
||||
val optionId = viewModelParams.optionId
|
||||
val color = getOptionColor()
|
||||
return if (optionId != null) {
|
||||
Timber.d("Editing option with id: $optionId")
|
||||
CreateOrEditOptionScreenViewState.Edit(
|
||||
optionId = optionId,
|
||||
text = viewModelParams.name.orEmpty(),
|
||||
color = color
|
||||
)
|
||||
|
||||
} else {
|
||||
Timber.d("Creating new option")
|
||||
CreateOrEditOptionScreenViewState.Create(
|
||||
text = viewModelParams.name.orEmpty(),
|
||||
color = color
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateName(name: String) {
|
||||
viewState.value = when (val state = viewState.value) {
|
||||
is CreateOrEditOptionScreenViewState.Create -> state.copy(text = name)
|
||||
is CreateOrEditOptionScreenViewState.Edit -> state.copy(text = name)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateColor(color: ThemeColor) {
|
||||
viewState.value = when (val state = viewState.value) {
|
||||
is CreateOrEditOptionScreenViewState.Create -> state.copy(color = color)
|
||||
is CreateOrEditOptionScreenViewState.Edit -> state.copy(color = color)
|
||||
}
|
||||
}
|
||||
|
||||
fun onButtonClick() {
|
||||
when (viewState.value) {
|
||||
is CreateOrEditOptionScreenViewState.Create -> proceedWithCreatingOption()
|
||||
is CreateOrEditOptionScreenViewState.Edit -> proceedWithUpdatingOption()
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithCreatingOption() {
|
||||
viewModelScope.launch {
|
||||
val params = CreateRelationOption.Params(
|
||||
space = spaceManager.get(),
|
||||
relation = viewModelParams.relationKey,
|
||||
name = viewState.value.text,
|
||||
color = viewState.value.color.code
|
||||
)
|
||||
if (params.name.isNotEmpty()) {
|
||||
createOption.invoke(params).proceed(
|
||||
success = { option ->
|
||||
proceedWithAddingTagToObject(
|
||||
ctx = viewModelParams.ctx,
|
||||
objectId = viewModelParams.objectId,
|
||||
relationKey = viewModelParams.relationKey,
|
||||
option = option
|
||||
)
|
||||
},
|
||||
failure = { Timber.e(it, "Error while creating option") }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithUpdatingOption() {
|
||||
val optionId = viewModelParams.optionId ?: return
|
||||
viewModelScope.launch {
|
||||
val params = SetObjectDetails.Params(
|
||||
ctx = optionId,
|
||||
details = mapOf(
|
||||
Relations.NAME to viewState.value.text,
|
||||
Relations.RELATION_OPTION_COLOR to viewState.value.color.code
|
||||
)
|
||||
)
|
||||
setObjectDetails.execute(params).fold(
|
||||
onFailure = { Timber.e(it, "Error while updating option") },
|
||||
onSuccess = {
|
||||
dispatcher.send(it)
|
||||
viewModelScope.sendAnalyticsRelationValueEvent(analytics)
|
||||
command.emit(Command.Dismiss)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun proceedWithAddingTagToObject(
|
||||
ctx: Id,
|
||||
objectId: Id,
|
||||
relationKey: Key,
|
||||
option: ObjectWrapper.Option
|
||||
) {
|
||||
Timber.d("Adding option to object with id: $objectId")
|
||||
val obj = values.get(target = objectId, ctx = ctx)
|
||||
val result = mutableListOf<Id>()
|
||||
val value = obj[relationKey]
|
||||
if (value is List<*>) {
|
||||
result.addAll(value.typeOf())
|
||||
} else if (value is Id) {
|
||||
result.add(value)
|
||||
}
|
||||
result.add(option.id)
|
||||
val params = SetObjectDetails.Params(
|
||||
ctx = objectId,
|
||||
details = mapOf(relationKey to result)
|
||||
)
|
||||
setObjectDetails.execute(params).fold(
|
||||
onFailure = { Timber.e(it, "Error while adding tag to object") },
|
||||
onSuccess = {
|
||||
dispatcher.send(it)
|
||||
viewModelScope.sendAnalyticsRelationValueEvent(analytics)
|
||||
command.emit(Command.Dismiss)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun getOptionColor(): ThemeColor {
|
||||
val color = viewModelParams.color
|
||||
return if (color != null) {
|
||||
ThemeColor.fromCode(color)
|
||||
} else {
|
||||
ThemeColor.values().filter { it != ThemeColor.DEFAULT }.random()
|
||||
}
|
||||
}
|
||||
|
||||
data class ViewModelParams(
|
||||
val ctx: Id,
|
||||
|
@ -41,7 +175,7 @@ class CreateOrEditOptionViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
sealed class OptionScreenViewState {
|
||||
sealed class CreateOrEditOptionScreenViewState {
|
||||
abstract val text: String
|
||||
abstract val color: ThemeColor
|
||||
|
||||
|
@ -49,10 +183,10 @@ sealed class OptionScreenViewState {
|
|||
val optionId: Id,
|
||||
override val text: String,
|
||||
override val color: ThemeColor
|
||||
) : OptionScreenViewState()
|
||||
) : CreateOrEditOptionScreenViewState()
|
||||
|
||||
data class Create(
|
||||
override val text: String,
|
||||
override val color: ThemeColor
|
||||
) : OptionScreenViewState()
|
||||
) : CreateOrEditOptionScreenViewState()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue