Skip to content

Commit

Permalink
목표 수정하기 캐릭터 Icon v2 로 수정 (#82)
Browse files Browse the repository at this point in the history
* feat: change rabbit image

* feat: Change icon based on character type

* chore: add call args
  • Loading branch information
murjune authored Feb 21, 2025
1 parent 3c2088f commit 4ca0402
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
Expand All @@ -19,9 +20,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.flowWithLifecycle
import com.chipichipi.dobedobe.core.designsystem.component.DobeDobeBackground
import com.chipichipi.dobedobe.core.designsystem.theme.DobeDobeTheme
import com.chipichipi.dobedobe.core.model.CharacterType
import com.chipichipi.dobedobe.feature.goal.component.GoalEditor
import com.chipichipi.dobedobe.feature.goal.component.GoalTopAppBar
import kotlinx.coroutines.flow.launchIn
Expand All @@ -38,6 +41,7 @@ fun AddGoalRoute(
val lifecycle = LocalLifecycleOwner.current.lifecycle
val focusManager = LocalFocusManager.current
val focusRequester = remember { FocusRequester() }
val characterType: CharacterType by viewModel.characterType.collectAsStateWithLifecycle()
val errorMessage =
viewModel.goalValidResult.addGoalErrorMessage()
?.let { stringResource(id = it) }
Expand Down Expand Up @@ -67,6 +71,7 @@ fun AddGoalRoute(
}
.imePadding(),
errorMessage = errorMessage,
characterType = characterType,
focusRequester = focusRequester,
onShowSnackbar = onShowSnackbar,
navigateToBack = navigateToBack,
Expand All @@ -79,6 +84,7 @@ fun AddGoalRoute(
private fun AddGoalScreen(
errorMessage: String?,
titleState: TextFieldState,
characterType: CharacterType,
focusRequester: FocusRequester,
onShowSnackbar: suspend (String, String?) -> Boolean,
navigateToBack: () -> Unit,
Expand All @@ -104,6 +110,7 @@ private fun AddGoalScreen(
supportMessage = stringResource(id = R.string.feature_detail_goal_editor_support_message),
buttonText = stringResource(id = R.string.feature_add_goal_action_button),
errorMessage = errorMessage,
characterType = characterType,
focusRequester = focusRequester,
onDone = onAddGoal,
)
Expand All @@ -120,6 +127,7 @@ private fun AddGoalScreenPreview() {
modifier = Modifier
.fillMaxSize(),
titleState = textFieldState,
characterType = CharacterType.Rabbit,
errorMessage = null,
focusRequester = FocusRequester(),
onShowSnackbar = { _, _ -> false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,33 @@ import androidx.compose.runtime.getValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.chipichipi.dobedobe.core.data.repository.GoalRepository
import com.chipichipi.dobedobe.core.data.repository.UserRepository
import com.chipichipi.dobedobe.core.model.CharacterType
import com.chipichipi.dobedobe.core.model.Goal
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch

class AddGoalViewModel(
private val goalRepository: GoalRepository,
userRepository: UserRepository,
) : ViewModel() {
val goalTitle = TextFieldState()
val goalValidResult by derivedStateOf { goalTitle.text.toString().let(Goal::validateTitle) }

val characterType: StateFlow<CharacterType> = userRepository.userData.map {
it.characterType
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = CharacterType.Rabbit,
)

private val _addGoalEvent = Channel<Unit>(capacity = Channel.BUFFERED)
val addGoalEvent: Flow<Unit> = _addGoalEvent.receiveAsFlow()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.flowWithLifecycle
import com.chipichipi.dobedobe.core.designsystem.component.ThemePreviews
import com.chipichipi.dobedobe.core.designsystem.theme.DobeDobeTheme
import com.chipichipi.dobedobe.core.model.CharacterType
import com.chipichipi.dobedobe.core.model.Goal
import com.chipichipi.dobedobe.feature.goal.component.GoalEditor
import com.chipichipi.dobedobe.feature.goal.component.GoalTopAppBar
Expand Down Expand Up @@ -124,6 +125,7 @@ private fun EditGoalScreen(
.padding(horizontal = 24.dp)
.padding(top = 8.dp, bottom = 12.dp),
titleState = goalTitleDraft,
characterType = uiState.characterType,
supportMessage = stringResource(id = R.string.feature_detail_goal_editor_support_message),
buttonText = stringResource(id = R.string.feature_add_goal_action_button),
errorMessage = errorMessage,
Expand All @@ -140,7 +142,10 @@ private fun EditGoalScreen(
private fun EditGoalScreenPreview() {
DobeDobeTheme {
EditGoalScreen(
uiState = EditGoalUiState.Success(Goal.todo("edit")),
uiState = EditGoalUiState.Success(
goal = Goal.todo("edit"),
characterType = CharacterType.Bird,
),
goalTitleDraft = rememberTextFieldState("edit"),
errorMessage = null,
saveGoalTitle = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.toRoute
import com.chipichipi.dobedobe.core.data.repository.GoalRepository
import com.chipichipi.dobedobe.core.data.repository.UserRepository
import com.chipichipi.dobedobe.core.model.CharacterType
import com.chipichipi.dobedobe.core.model.Goal
import com.chipichipi.dobedobe.feature.goal.navigation.GoalRoute
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
Expand All @@ -26,6 +28,7 @@ import kotlinx.coroutines.launch
internal class EditGoalViewModel(
savedStateHandle: SavedStateHandle,
private val goalRepository: GoalRepository,
userRepository: UserRepository,
) : ViewModel() {
val goalTitleDraft = TextFieldState("")
val goalValidResult by derivedStateOf {
Expand All @@ -40,7 +43,12 @@ internal class EditGoalViewModel(
}

val uiState: StateFlow<EditGoalUiState> = savedStateHandle.getGoalFlow()
.map(EditGoalUiState::Success)
.combine(userRepository.userData) { goal, user ->
EditGoalUiState.Success(
goal = goal,
characterType = user.characterType,
)
}
.onEach {
goalTitleDraft.edit {
delete(0, length)
Expand Down Expand Up @@ -93,6 +101,7 @@ sealed interface EditGoalUiState {

data class Success(
val goal: Goal,
val characterType: CharacterType,
) : EditGoalUiState

data object Error : EditGoalUiState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.chipichipi.dobedobe.feature.goal.component

import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
Expand All @@ -15,14 +14,12 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredSizeIn
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
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.Color
Expand All @@ -38,6 +35,7 @@ import com.chipichipi.dobedobe.core.designsystem.component.DobeDobeTextButton
import com.chipichipi.dobedobe.core.designsystem.component.DobeDobeTextField
import com.chipichipi.dobedobe.core.designsystem.component.TailPosition
import com.chipichipi.dobedobe.core.designsystem.theme.DobeDobeTheme
import com.chipichipi.dobedobe.core.model.CharacterType
import com.chipichipi.dobedobe.feature.goal.R

@Composable
Expand All @@ -47,6 +45,7 @@ fun GoalEditor(
modifier: Modifier = Modifier,
supportMessage: String = "",
errorMessage: String? = null,
characterType: CharacterType,
focusRequester: FocusRequester,
onDone: (() -> Unit)? = null,
) {
Expand All @@ -55,14 +54,9 @@ fun GoalEditor(
horizontalAlignment = Alignment.CenterHorizontally,
) {
Image(
painter = painterResource(id = R.drawable.rabit_avatar),
painter = painterResource(id = characterType.toImageRes()),
contentDescription = "Avatar",
modifier = Modifier
.size(84.dp)
.border(1.dp, Color(0xFFFFA8E7), CircleShape)
.padding(1.dp)
.clip(CircleShape)
.background(Color(0xFFFFF2FF)),
modifier = Modifier.size(80.dp),
contentScale = ContentScale.Crop,
)

Expand Down Expand Up @@ -115,6 +109,11 @@ fun GoalEditor(
}
}

private fun CharacterType.toImageRes(): Int = when (this) {
CharacterType.Bird -> R.drawable.bird_avatar
CharacterType.Rabbit -> R.drawable.rabbit_avatar
}

@Preview
@Composable
private fun GoalDetailEmptyPreview() {
Expand All @@ -128,6 +127,7 @@ private fun GoalDetailEmptyPreview() {
.imePadding(),
supportMessage = stringResource(R.string.feature_detail_goal_editor_support_message),
titleState = titleState,
characterType = CharacterType.Rabbit,
focusRequester = FocusRequester(),
buttonText = "Done",
)
Expand All @@ -148,6 +148,7 @@ private fun GoalDetailPreview() {
.imePadding(),
supportMessage = stringResource(R.string.feature_detail_goal_editor_support_message),
titleState = titleState,
characterType = CharacterType.Bird,
focusRequester = FocusRequester(),
buttonText = "Done",
)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed feature/goal/src/main/res/drawable/rabit_avatar.png
Binary file not shown.

0 comments on commit 4ca0402

Please sign in to comment.