-
Notifications
You must be signed in to change notification settings - Fork 0
[Fix] 푸시 알림 설정 변경 사항 반영 안되는 거 수정(공통), 안드로이드 스타일 복구(폰트, 그림자) #12 #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| package com.konkuk.medicarecall.ui.theme | ||
|
|
||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.draw.drawWithCache | ||
| import androidx.compose.ui.graphics.Paint | ||
| import androidx.compose.ui.graphics.drawscope.drawIntoCanvas | ||
| import androidx.compose.ui.graphics.nativeCanvas | ||
| import androidx.compose.ui.graphics.toArgb | ||
| import androidx.compose.ui.unit.Dp | ||
|
|
||
| actual fun Modifier.figmaShadow( | ||
| group: ShadowGroup, | ||
| cornerRadius: Dp, | ||
| ): Modifier = this.drawWithCache { | ||
| val radiusPx = cornerRadius.toPx() | ||
| val paint = Paint().asFrameworkPaint().apply { | ||
| isAntiAlias = true | ||
| color = 0 | ||
| } | ||
|
|
||
| onDrawWithContent { | ||
| group.layers.forEach { layer -> | ||
| paint.setShadowLayer( | ||
| layer.blurRadius.toPx(), | ||
| layer.offsetX.toPx(), | ||
| layer.offsetY.toPx(), | ||
| layer.color.toArgb(), | ||
| ) | ||
| drawIntoCanvas { canvas -> | ||
| val nc = canvas.nativeCanvas | ||
| nc.drawRoundRect( | ||
| 0f, | ||
| 0f, | ||
| size.width, | ||
| size.height, | ||
| radiusPx, | ||
| radiusPx, | ||
| paint, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| paint.clearShadowLayer() | ||
|
|
||
| drawIntoCanvas { canvas -> | ||
| val nc = canvas.nativeCanvas | ||
| nc.drawRoundRect( | ||
| 0f, | ||
| 0f, | ||
| size.width, | ||
| size.height, | ||
| radiusPx, | ||
| radiusPx, | ||
| paint, | ||
| ) | ||
| } | ||
|
|
||
| drawContent() | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ package com.konkuk.medicarecall.ui.feature.settings.mydata.viewmodel | |
| import androidx.lifecycle.ViewModel | ||
| import androidx.lifecycle.viewModelScope | ||
| import com.konkuk.medicarecall.data.repository.UserRepository | ||
| import com.konkuk.medicarecall.domain.model.PushNotification | ||
| import com.konkuk.medicarecall.domain.model.UserInfo | ||
| import com.konkuk.medicarecall.domain.model.type.GenderType | ||
| import kotlinx.coroutines.flow.MutableStateFlow | ||
|
|
@@ -56,7 +57,12 @@ class SettingsEditMyDataViewModel( | |
| try { | ||
| userRepository.updateMyInfo(userInfo) | ||
| .onSuccess { | ||
| _uiState.update { it.copy(isUpdateSuccess = true) } | ||
| _uiState.update { | ||
| it.copy( | ||
| isUpdateSuccess = true, | ||
| myDataInfo = userInfo, // 저장 성공 시 최신 데이터로 동기화 | ||
| ) | ||
| } | ||
| onComplete?.invoke() | ||
| } | ||
| .onFailure { e -> | ||
|
|
@@ -72,11 +78,6 @@ class SettingsEditMyDataViewModel( | |
| } | ||
| } | ||
|
|
||
| // 화면 진입 시나 필요 시 상태 초기화 | ||
| fun resetStatus() { | ||
| _uiState.update { it.copy(isUpdateSuccess = false, errorMessage = null) } | ||
| } | ||
|
|
||
| fun initializeNotificationSettings(myDataInfo: UserInfo) { | ||
| val masterOn = myDataInfo.pushNotification.isAllEnabled | ||
| _uiState.update { | ||
|
|
@@ -89,42 +90,70 @@ class SettingsEditMyDataViewModel( | |
| } | ||
| } | ||
|
|
||
| fun setMasterChecked(value: Boolean) { | ||
| _uiState.update { | ||
| it.copy( | ||
| masterChecked = value, | ||
| completeChecked = value, | ||
| abnormalChecked = value, | ||
| missedChecked = value, | ||
| ) | ||
| } | ||
| } | ||
| // 토글 타입별로 새 상태를 계산하고 서버에 반영하는 함수 | ||
| fun updateNotificationSettingByType( | ||
| type: String, | ||
| checked: Boolean, | ||
| ) { | ||
| val currentInfo = uiState.value.myDataInfo ?: return | ||
| val currentState = uiState.value | ||
|
|
||
| fun setCompleteChecked(value: Boolean) { | ||
| _uiState.update { | ||
| it.copy( | ||
| completeChecked = value, | ||
| masterChecked = if (!value) false else it.masterChecked, | ||
| ) | ||
| } | ||
| } | ||
| val newMasterChecked: Boolean | ||
| val newCompleteChecked: Boolean | ||
| val newAbnormalChecked: Boolean | ||
| val newMissedChecked: Boolean | ||
|
|
||
| fun setAbnormalChecked(value: Boolean) { | ||
| _uiState.update { | ||
| it.copy( | ||
| abnormalChecked = value, | ||
| masterChecked = if (!value) false else it.masterChecked, | ||
| ) | ||
| when (type) { | ||
| "master" -> { | ||
| newMasterChecked = checked | ||
| newCompleteChecked = checked | ||
| newAbnormalChecked = checked | ||
| newMissedChecked = checked | ||
| } | ||
|
|
||
| "complete" -> { | ||
| newCompleteChecked = checked | ||
| newAbnormalChecked = currentState.abnormalChecked | ||
| newMissedChecked = currentState.missedChecked | ||
| newMasterChecked = checked && newAbnormalChecked && newMissedChecked | ||
| } | ||
|
|
||
| "abnormal" -> { | ||
| newCompleteChecked = currentState.completeChecked | ||
| newAbnormalChecked = checked | ||
| newMissedChecked = currentState.missedChecked | ||
| newMasterChecked = newCompleteChecked && checked && newMissedChecked | ||
| } | ||
|
|
||
| "missed" -> { | ||
| newCompleteChecked = currentState.completeChecked | ||
| newAbnormalChecked = currentState.abnormalChecked | ||
| newMissedChecked = checked | ||
| newMasterChecked = newCompleteChecked && newAbnormalChecked && checked | ||
| } | ||
|
|
||
| else -> return | ||
| } | ||
| } | ||
|
|
||
| fun setMissedChecked(value: Boolean) { | ||
| _uiState.update { | ||
| it.copy( | ||
| missedChecked = value, | ||
| masterChecked = if (!value) false else it.masterChecked, | ||
| masterChecked = newMasterChecked, | ||
| completeChecked = newCompleteChecked, | ||
| abnormalChecked = newAbnormalChecked, | ||
| missedChecked = newMissedChecked, | ||
| ) | ||
| } | ||
|
|
||
| val updatedUserInfo = currentInfo.copy( | ||
| pushNotification = PushNotification( | ||
| all = if (newMasterChecked) "ON" else "OFF", | ||
| carecallCompleted = if (newCompleteChecked) "ON" else "OFF", | ||
| healthAlert = if (newAbnormalChecked) "ON" else "OFF", | ||
| carecallMissed = if (newMissedChecked) "ON" else "OFF", | ||
| ), | ||
| ) | ||
|
|
||
| updateUserData(updatedUserInfo) | ||
|
Comment on lines
138
to
+156
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 낙관적 업데이트(Optimistic Update) 시 에러 발생 시 롤백 로직 부재 UI 상태를 먼저 업데이트(Line 138-145)한 후 서버 호출(Line 156)을 하는 낙관적 업데이트 패턴을 사용하고 있는데, 사용자 경험을 위해 에러 발생 시 이전 상태로 롤백하거나, 실패 토스트 메시지와 함께 상태를 복원하는 로직을 추가하면 좋을 것 같습니다. 🛡️ 롤백 로직 추가 예시+ // 롤백을 위해 이전 상태 저장
+ val previousState = _uiState.value.copy()
+
_uiState.update {
it.copy(
masterChecked = newMasterChecked,
completeChecked = newCompleteChecked,
abnormalChecked = newAbnormalChecked,
missedChecked = newMissedChecked,
)
}
val updatedUserInfo = currentInfo.copy(
pushNotification = PushNotification(
all = if (newMasterChecked) "ON" else "OFF",
carecallCompleted = if (newCompleteChecked) "ON" else "OFF",
healthAlert = if (newAbnormalChecked) "ON" else "OFF",
carecallMissed = if (newMissedChecked) "ON" else "OFF",
),
)
- updateUserData(updatedUserInfo)
+ updateUserData(updatedUserInfo) {
+ // onComplete - 성공 시 아무것도 안 함
+ }
+ // 또는 실패 시 롤백하는 별도 콜백 파라미터 추가 고려
🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| fun initializeFormData(myDataInfo: UserInfo) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: Medicare-Call/Medicare-Call-KMP
Length of output: 4049
offset 속성 처리 필요해요 🎨
코드 구조는 깔끔하고 fold 패턴으로 여러 shadow layer를 쌓아가는 방식도 좋습니다. 근데 예상대로
ShadowLayer에는offsetX와offsetY속성이 있는데, 현재 구현에서는 이게 무시되고 있어요.Modifier.shadow()는 x/y offset을 직접 지원하지 않기 때문에, offset 값들을 반영하려면Modifier.offset()을 조합하거나 다른 접근이 필요합니다. Figma 디자인에서 offset이 중요하다면 다음처럼 처리할 수 있어요:offset 없이도 디자인이 괜찮다면 현재대로 두셔도 괜찮지만, Figma와의 정확한 일치가 필요하다면 위처럼 처리해주세요.
🤖 Prompt for AI Agents