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

DROID-3484 Primitives | Create type screen, part 1 (#2229)

This commit is contained in:
Konstantin Ivanov 2025-04-04 09:30:16 +02:00 committed by GitHub
parent 6138ee309b
commit 5264490f3b
Signed by: github
GPG key ID: B5690EEEBB952194
21 changed files with 500 additions and 241 deletions

View file

@ -0,0 +1,20 @@
package com.anytypeio.anytype.feature_object_type.ui.create
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SetTypeTitlesAndIconScreen(
uiState: UiTypeSetupTitleAndIconState,
modifier: Modifier = Modifier,
onTitleChanged: (String) -> Unit,
onPluralChanged: (String) -> Unit,
onIconClicked: () -> Unit,
onDismiss: () -> Unit,
onButtonClicked: () -> Unit
) {
//next PR
}

View file

@ -0,0 +1,20 @@
package com.anytypeio.anytype.feature_object_type.ui.create
import com.anytypeio.anytype.presentation.objects.ObjectIcon
sealed class UiTypeSetupTitleAndIconState {
abstract val icon: ObjectIcon.TypeIcon.Default
data class CreateNewType(
override val icon: ObjectIcon.TypeIcon.Default,
val initialTitle: String = "",
val initialPlural: String = ""
) : UiTypeSetupTitleAndIconState()
data class EditType(
override val icon: ObjectIcon.TypeIcon.Default,
val initialTitle: String = "",
val initialPlural: String = ""
) : UiTypeSetupTitleAndIconState()
}

View file

@ -0,0 +1,190 @@
package com.anytypeio.anytype.feature_object_type.viewmodel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.analytics.base.EventsDictionary.libraryCreateType
import com.anytypeio.anytype.analytics.base.EventsPropertiesKey
import com.anytypeio.anytype.analytics.base.sendEvent
import com.anytypeio.anytype.analytics.props.Props
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.types.CreateObjectType
import com.anytypeio.anytype.feature_object_type.ui.UiIconsPickerState
import com.anytypeio.anytype.feature_object_type.ui.create.UiTypeSetupTitleAndIconState
import com.anytypeio.anytype.feature_object_type.viewmodel.CreateTypeCommand.NavigateToObjectType
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.objects.custom_icon.CustomIconColor
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import timber.log.Timber
class CreateObjectTypeViewModel(
private val vmParams: CreateTypeVmParams,
private val createObjectType: CreateObjectType,
private val analytics: Analytics,
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)
val uiState = _uiState.asStateFlow()
//icons picker screen
val uiIconsPickerScreen = MutableStateFlow<UiIconsPickerState>(UiIconsPickerState.Hidden)
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)
}
}
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)
}
uiIconsPickerScreen.value = UiIconsPickerState.Hidden
}
fun onNewIconPicked(iconName: String, color: CustomIconColor?) {
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)
}
uiIconsPickerScreen.value = UiIconsPickerState.Hidden
}
fun onIconClicked() {
uiIconsPickerScreen.value = UiIconsPickerState.Visible
}
fun onDismissIconPicker() {
uiIconsPickerScreen.value = UiIconsPickerState.Hidden
}
fun onButtonClicked() {
when (vmParams.mode) {
MODE.CREATE -> createNewType()
MODE.EDIT -> updateType()
}
}
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")
viewModelScope.launch {
createObjectType.execute(
CreateObjectType.Params(
space = vmParams.spaceId,
name = name,
pluralName = plural,
iconName = icon.rawValue,
iconColor = icon.color.iconOption.toDouble()
)
).fold(
onSuccess = { objTypeId ->
val spaceParams = provideParams(vmParams.spaceId)
viewModelScope.sendEvent(
analytics = analytics,
eventName = libraryCreateType,
props = Props(
mapOf(
EventsPropertiesKey.permissions to spaceParams.permission,
EventsPropertiesKey.spaceType to spaceParams.spaceType
)
)
)
commands.emit(
NavigateToObjectType(
id = objTypeId,
space = vmParams.spaceId
)
)
},
onFailure = {
Timber.e(it, "Error while creating type")
}
)
}
}
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
)
enum class MODE {
CREATE,
EDIT
}
sealed class CreateTypeCommand {
data object Dismiss : CreateTypeCommand()
data class NavigateToObjectType(val id: Id, val space: Id) : CreateTypeCommand()
}
class CreateObjectTypeVMFactory @Inject constructor(
private val vmParams: CreateTypeVmParams,
private val createObjectType: CreateObjectType,
private val analytics: Analytics,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T = CreateObjectTypeViewModel(
vmParams = vmParams,
createObjectType = createObjectType,
analytics = analytics,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
) as T
}