diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextArea.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextArea.kt
index 06af1699..60ec6ecb 100644
--- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextArea.kt
+++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextArea.kt
@@ -14,13 +14,17 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Surface
import androidx.compose.material3.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.setValue
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.team.prezel.core.designsystem.component.textfield.component.PrezelTextFieldLabel
@@ -46,18 +50,28 @@ fun PrezelTextArea(
keyboardActions: KeyboardActions = KeyboardActions.Default,
) {
var focused by remember { mutableStateOf(false) }
+ var textFieldValue by remember { mutableStateOf(TextFieldValue(text = value, selection = TextRange(value.length))) }
+
+ LaunchedEffect(value) {
+ if (value != textFieldValue.text) {
+ textFieldValue = TextFieldValue(text = value, selection = TextRange(value.length))
+ }
+ }
val style = rememberPrezelTextFieldState(
- value = value,
+ value = textFieldValue.text,
enabled = enabled,
focused = focused,
).let { state -> PrezelTextFieldStyle(state = state, status = status) }
PrezelTextArea(
- value = value,
+ value = textFieldValue,
onValueChange = { newValue ->
- val applied = applyPrezelTextInputPolicy(newValue, maxLength)
- if (applied != value) onValueChange(applied)
+ val applied = applyPrezelTextInputPolicy(currentValue = textFieldValue, newValue = newValue, maxLength = maxLength)
+ if (applied != textFieldValue) {
+ textFieldValue = applied
+ if (applied.text != value) onValueChange(applied.text)
+ }
},
placeholder = placeholder,
style = style,
@@ -75,8 +89,8 @@ fun PrezelTextArea(
@Composable
private fun PrezelTextArea(
- value: String,
- onValueChange: (String) -> Unit,
+ value: TextFieldValue,
+ onValueChange: (TextFieldValue) -> Unit,
placeholder: String,
maxLength: Int,
style: PrezelTextFieldStyle,
@@ -110,13 +124,13 @@ private fun PrezelTextArea(
decorationBox = { innerTextField ->
PrezelTextAreaDecorationBox(
innerTextField = innerTextField,
- showPlaceholder = !focused && value.isEmpty(),
+ showPlaceholder = !focused && value.text.isEmpty(),
placeholder = placeholder,
state = style,
+ showCounter = showCount,
counter = {
if (showCount) {
- Spacer(modifier = Modifier.height(PrezelTheme.spacing.V16))
- Counter(currentLength = value.length, maxLength = maxLength, state = style)
+ Counter(currentLength = value.text.length, maxLength = maxLength, state = style)
}
},
modifier = Modifier.heightIn(min = 72.dp),
@@ -154,6 +168,7 @@ private fun PrezelTextAreaDecorationBox(
counter: @Composable () -> Unit,
placeholder: String,
state: PrezelTextFieldStyle,
+ showCounter: Boolean,
modifier: Modifier = Modifier,
) {
Surface(
@@ -163,20 +178,25 @@ private fun PrezelTextAreaDecorationBox(
border = state.borderStroke(),
contentColor = state.textColor(),
) {
- Column(
+ Box(
modifier = Modifier
.fillMaxWidth()
.padding(PrezelTheme.spacing.V12),
- verticalArrangement = Arrangement.SpaceBetween,
) {
- Box {
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(bottom = if (showCounter) PrezelTheme.spacing.V24 else 0.dp),
+ ) {
innerTextField()
if (showPlaceholder) {
PrezelTextFieldPlaceholder(placeholder = placeholder)
}
}
- counter()
+ Box(modifier = Modifier.align(Alignment.BottomEnd)) {
+ counter()
+ }
}
}
}
@@ -304,7 +324,7 @@ private fun PrezelTextAreaPreviewItem(
focused: Boolean = false,
) {
PrezelTextArea(
- value = value,
+ value = TextFieldValue(text = value, selection = TextRange(value.length)),
onValueChange = {},
placeholder = "Placeholder",
label = label,
diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextField.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextField.kt
index 942f23d9..d627b18d 100644
--- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextField.kt
+++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextField.kt
@@ -18,6 +18,7 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -27,6 +28,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import com.team.prezel.core.designsystem.component.textfield.component.PrezelTextFieldLabel
import com.team.prezel.core.designsystem.component.textfield.component.PrezelTextFieldPlaceholder
@@ -52,18 +55,28 @@ fun PrezelTextField(
keyboardActions: KeyboardActions = KeyboardActions.Default,
) {
var focused by remember { mutableStateOf(false) }
+ var textFieldValue by remember { mutableStateOf(TextFieldValue(text = value, selection = TextRange(value.length))) }
+
+ LaunchedEffect(value) {
+ if (value != textFieldValue.text) {
+ textFieldValue = TextFieldValue(text = value, selection = TextRange(value.length))
+ }
+ }
val state = rememberPrezelTextFieldState(
- value = value,
+ value = textFieldValue.text,
enabled = enabled,
focused = focused,
).let { state -> PrezelTextFieldStyle(state = state, status = status) }
PrezelTextField(
- value = value,
+ value = textFieldValue,
onValueChange = { newValue ->
- val applied = applyPrezelTextInputPolicy(newValue, maxLength)
- if (applied != value) onValueChange(applied)
+ val applied = applyPrezelTextInputPolicy(currentValue = textFieldValue, newValue = newValue, maxLength = maxLength)
+ if (applied != textFieldValue) {
+ textFieldValue = applied
+ if (applied.text != value) onValueChange(applied.text)
+ }
},
placeholder = placeholder,
style = state,
@@ -80,8 +93,8 @@ fun PrezelTextField(
@Composable
private fun PrezelTextField(
- value: String,
- onValueChange: (String) -> Unit,
+ value: TextFieldValue,
+ onValueChange: (TextFieldValue) -> Unit,
placeholder: String,
style: PrezelTextFieldStyle,
focused: Boolean,
@@ -115,7 +128,7 @@ private fun PrezelTextField(
decorationBox = { innerTextField ->
PrezelTextFieldDecorationBox(
innerTextField = innerTextField,
- showPlaceholder = !focused && value.isEmpty(),
+ showPlaceholder = !focused && value.text.isEmpty(),
placeholder = placeholder,
trailingIcon = trailingIcon,
state = style,
@@ -296,7 +309,7 @@ private fun PreviewTextFieldItem(
focused: Boolean = false,
) {
PrezelTextField(
- value = value,
+ value = TextFieldValue(text = value, selection = TextRange(value.length)),
onValueChange = {},
placeholder = "Placeholder",
label = label,
diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextFieldState.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextFieldState.kt
index 190a1e84..b36b3219 100644
--- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextFieldState.kt
+++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/textfield/PrezelTextFieldState.kt
@@ -5,6 +5,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import com.team.prezel.core.designsystem.foundation.color.PrezelColors
import com.team.prezel.core.designsystem.theme.PrezelTheme
@@ -223,11 +224,11 @@ internal fun rememberPrezelTextFieldState(
)
internal fun applyPrezelTextInputPolicy(
- value: String,
+ currentValue: TextFieldValue,
+ newValue: TextFieldValue,
maxLength: Int,
-): String {
- require(maxLength >= 0) { "maxLength must be >= 0" }
- return value
- .replace("\n", "")
- .take(maxLength)
+): TextFieldValue {
+ require(maxLength >= 0) { "maxLength는 0 이상이어야 합니다." }
+
+ return if (newValue.text.length > maxLength) currentValue else newValue
}
diff --git a/Prezel/feature/feedback/impl/src/main/java/com/team/prezel/feature/feedback/impl/FeedbackScreen.kt b/Prezel/feature/feedback/impl/src/main/java/com/team/prezel/feature/feedback/impl/FeedbackScreen.kt
index 04bf67ee..d684b315 100644
--- a/Prezel/feature/feedback/impl/src/main/java/com/team/prezel/feature/feedback/impl/FeedbackScreen.kt
+++ b/Prezel/feature/feedback/impl/src/main/java/com/team/prezel/feature/feedback/impl/FeedbackScreen.kt
@@ -17,11 +17,13 @@ import androidx.compose.material3.Text
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.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalResources
import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -174,6 +176,8 @@ private fun FeedbackContent(
modifier: Modifier = Modifier,
) {
val focusManager = LocalFocusManager.current
+ val placeholders = stringArrayResource(R.array.feature_feedback_impl_placeholders)
+ val placeholder = remember(placeholders.contentHashCode()) { placeholders.random() }
Column(
modifier = modifier
@@ -193,7 +197,7 @@ private fun FeedbackContent(
PrezelTextArea(
value = content,
onValueChange = onContentChanged,
- placeholder = stringResource(R.string.feature_feedback_impl_placeholder),
+ placeholder = placeholder,
maxLength = 200,
showCount = true,
)
diff --git a/Prezel/feature/feedback/impl/src/main/res/values/strings.xml b/Prezel/feature/feedback/impl/src/main/res/values/strings.xml
index c5db6ad0..c5d5555c 100644
--- a/Prezel/feature/feedback/impl/src/main/res/values/strings.xml
+++ b/Prezel/feature/feedback/impl/src/main/res/values/strings.xml
@@ -2,7 +2,11 @@
셀프 피드백
닫기
\'%1$s\'는 어떠셨나요?
- 다음 발표에는 어떤 부분을 신경쓰고 싶나요?
+
+ - 발표를 마친 지금, 어떤 기분이 드나요?
+ - 다음 발표에서는 무엇을 조금 더 신경 써보고 싶나요?
+ - 이번 발표에서 만족스러웠던 부분은 무엇이었나요?
+
저장하기
셀프 피드백을 불러오지 못했어요.
해당 데이터에 접근할 권한이 없습니다.
diff --git a/Prezel/feature/home/impl/src/main/java/com/team/prezel/feature/home/impl/main/component/body/PresentationSheet.kt b/Prezel/feature/home/impl/src/main/java/com/team/prezel/feature/home/impl/main/component/body/PresentationSheet.kt
index e8a84bf3..43358c53 100644
--- a/Prezel/feature/home/impl/src/main/java/com/team/prezel/feature/home/impl/main/component/body/PresentationSheet.kt
+++ b/Prezel/feature/home/impl/src/main/java/com/team/prezel/feature/home/impl/main/component/body/PresentationSheet.kt
@@ -30,7 +30,13 @@ internal fun PresentationSheet(
modifier = modifier,
contentPadding = PaddingValues(vertical = PrezelTheme.spacing.V32, horizontal = PrezelTheme.spacing.V20),
) {
- HomeBottomSheetTitle(title = stringResource(R.string.feature_home_impl_bottom_sheet_content_title, presentation.practiceCount))
+ HomeBottomSheetTitle(
+ title = if (presentation.practiceCount == 0) {
+ stringResource(R.string.feature_home_impl_empty_sheet_practice_card_title)
+ } else {
+ stringResource(R.string.feature_home_impl_bottom_sheet_content_title, presentation.practiceCount)
+ },
+ )
PracticeCard(
dDay = presentation.practiceRecords.endDate,
items = presentation.practiceRecords.practices,
diff --git a/Prezel/feature/home/impl/src/main/java/com/team/prezel/feature/home/impl/main/component/title/PracticeActionCard.kt b/Prezel/feature/home/impl/src/main/java/com/team/prezel/feature/home/impl/main/component/title/PracticeActionCard.kt
index 6547f2cd..c2d3957c 100644
--- a/Prezel/feature/home/impl/src/main/java/com/team/prezel/feature/home/impl/main/component/title/PracticeActionCard.kt
+++ b/Prezel/feature/home/impl/src/main/java/com/team/prezel/feature/home/impl/main/component/title/PracticeActionCard.kt
@@ -32,29 +32,29 @@ internal fun PracticeActionCard(
modifier: Modifier = Modifier,
onClick: () -> Unit,
) {
- PrezelTouchArea(
- onClick = onClick,
- shape = PrezelTheme.shapes.V8,
+ Column(
+ modifier = modifier
+ .fillMaxWidth()
+ .clip(shape = PrezelTheme.shapes.V8)
+ .border(
+ width = PrezelTheme.stroke.V1,
+ shape = PrezelTheme.shapes.V8,
+ color = PrezelTheme.colors.borderSmall,
+ ).background(color = PrezelTheme.colors.bgRegular)
+ .padding(horizontal = PrezelTheme.spacing.V16, vertical = PrezelTheme.spacing.V12),
) {
- Column(
- modifier = modifier
- .fillMaxWidth()
- .clip(shape = PrezelTheme.shapes.V8)
- .border(
- width = PrezelTheme.stroke.V1,
- shape = PrezelTheme.shapes.V8,
- color = PrezelTheme.colors.borderSmall,
- ).background(color = PrezelTheme.colors.bgRegular)
- .padding(horizontal = PrezelTheme.spacing.V16, vertical = PrezelTheme.spacing.V12),
- ) {
- Text(
- text = title,
- color = titleColor,
- style = PrezelTheme.typography.body2Bold,
- )
+ Text(
+ text = title,
+ color = titleColor,
+ style = PrezelTheme.typography.body2Bold,
+ )
- Spacer(modifier = Modifier.height(PrezelTheme.spacing.V6))
+ Spacer(modifier = Modifier.height(PrezelTheme.spacing.V6))
+ PrezelTouchArea(
+ onClick = onClick,
+ shape = PrezelTheme.shapes.V4,
+ ) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = actionText,