Skip to content

Blocked Users screen UI based on Design QA#1095

Merged
DongJun-H merged 3 commits intodevelopfrom
qa/setting-block
Mar 18, 2026
Merged

Blocked Users screen UI based on Design QA#1095
DongJun-H merged 3 commits intodevelopfrom
qa/setting-block

Conversation

@DongJun-H
Copy link
Member

@DongJun-H DongJun-H commented Mar 17, 2026

작업 내용

  • 차단관리 화면 내 Top Navigation Bar Alignment Center 추가
  • 로딩 실패시 재시도 레이아웃 수정
  • 재시도 문구 "재시도" -> "다시 시도"로 변경
  • 에러 아이콘 피그마 디자인에 맞게 변경

참고

차단된 사용자 화면 UI 개선 (Design QA 적용)

1. 기능 및 사용자 영향

BlockedUsersScreen.kt - 레이아웃 및 상태 관리 개선

  • 에러 상태 처리: blockedUsers.status == Status.ERROR 시 새로운 BlockedUsersErrorLayout 컴포저블로 전환하여 에러 UI를 독립적으로 관리
  • 네비게이션 바 타이틀 정렬: TopNavigationAlign.CENTER를 적용하여 차단된 사용자 제목을 화면 중앙에 정렬
  • 콘텐츠 패딩 조정: LazyColumn에 좌우 20.dp 패딩 추가로 일관된 여백 확보
  • 에러 레이아웃 구성: Spacer의 weight를 활용(176f, 336f)하여 이미지/텍스트/재시도 버튼을 수직 중앙 배치

ic_blocked_users_empty.xml - 에러 아이콘 교체

  • 기존의 복잡한 clip-path 기반 벡터에서 단순화된 디자인으로 변경
  • 새로운 아이콘: 원형 링(strokeColor #F6F6F7, strokeWidth 3) + 2개의 회색 filled 경로(#E8EAEE)로 구성
  • 시각적으로 더 깔끔하고 Figma 디자인과 일치

strings.xml - 재시도 텍스트 업데이트

  • "재시도" → "다시 시도"로 변경하여 자연스러운 한글 표현 적용

TopNavigation.kt - 타이포그래피 통일 (부수 변경)

  • LEFT/CENTER 타이틀 모두 b3 스타일로 통일하여 일관성 강화

2. 리스크 포인트

에러 처리 및 상태 일관성

  • ERROR 상태 진입 조건: blockedUsers.status == Status.ERROR로의 상태 전환 로직이 ViewModel에서 올바르게 트리거되어야 함
  • 재시도 콜백: onRetry 함수에서 profileSettingViewModel.requestBlockList() 호출 시 중복 요청 방지 필요 (로딩 중 상태 체크)
  • 네트워크 에러 vs 데이터 비어있음: ERROR 상태와 빈 리스트(empty data) 상태가 명확히 구분되어야 UI가 올바르게 렌더링됨

레이아웃 스페이싱

  • Spacer weight 값(176f, 336f)의 상대성: 화면 높이가 변경되거나 다양한 디바이스에서 의도한 대로 배치되는지 검증 필요
  • 이미지 크기 불일치 방지: LazyColumn의 empty 상태에서는 wrapContentHeight() 사용, ErrorLayout에서는 명시적 height(100.dp) 사용 → 두 상태 간 이미지 크기 일관성 확인

Composable 재구성

  • blockedUsers 상태 변화 시 전체 화면이 ERROR 또는 LIST 상태로 전환되는데, 빈 리스트에서 에러로의 상태 전이가 부자연스러울 수 있음

3. 필수 검증 및 후속 테스트

UI/UX 검증

  • 모든 디바이스(스마트폰 정도, 태블릿)에서 Spacer weight 비율에 따른 이미지/텍스트/버튼 배치 확인
  • 에러 상태 아이콘이 Figma 디자인과 정확히 일치하는지 비교
  • 네비게이션 바 타이틀이 중앙 정렬되었는지, 양쪽 여백이 동일한지 확인
  • 재시도 버튼 텍스트 "다시 시도"가 자연스럽게 표시되는지 확인

상태 관리 및 네트워크 테스트

  • 네트워크 오류 발생 시 ERROR 상태로 정상 전환되는지 테스트
  • 재시도 버튼 클릭 후 로딩 중 상태 표시 및 중복 요청 방지 검증
  • 데이터가 비어있는 경우(정상 상태)와 에러 상태를 명확히 구분 가능한지 확인
  • 차단 해제 성공 후 리스트가 정상 새로고침되고 에러 상태에서 빠져나오는지 테스트

다국어 및 호환성

  • 재시도 텍스트 "다시 시도"가 다른 언어로도 제대로 표시되는지 확인
  • 구형 안드로이드 버전(API 레벨 낮음)에서 레이아웃 깨짐 여부 확인

@DongJun-H DongJun-H requested a review from yuni-ju March 17, 2026 12:39
@DongJun-H DongJun-H self-assigned this Mar 17, 2026
@DongJun-H DongJun-H added the QA label Mar 17, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Walkthrough

차단된 사용자 화면의 에러 상태 UI를 개선합니다. 새로운 BlockedUsersErrorLayout 컴포저블을 도입하여 에러 및 빈 상태를 처리하고, 헤더 타이포그래피를 조정하며, 에러 상태 아이콘을 단순화하고 재시도 문구를 갱신합니다.

Changes

Cohort / File(s) Summary
에러 상태 레이아웃
presentation/src/main/java/daily/dayo/presentation/screen/settings/BlockedUsersScreen.kt
Box 래퍼 도입, 새로운 BlockedUsersErrorLayout 컴포저블 추가, 에러 및 빈 상태 UI를 전담 컴포저블로 분리, LazyColumn에 수평 패딩 적용, TopNavigationAlign CENTER 정렬 추가
헤더 타이포그래피
presentation/src/main/java/daily/dayo/presentation/view/TopNavigation.kt
제목 타이포그래피 스타일 h3에서 b3으로 변경 (LEFT, CENTER 모두 적용)
에러 상태 UI 자산
presentation/src/main/res/drawable/ic_blocked_users_empty.xml, presentation/src/main/res/values/strings.xml
벡터 드로어블 단순화 (클립패스 제거, 경로 축약), 재시도 버튼 문구 "재시도"에서 "다시 시도"로 변경
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 Blocked Users 화면의 UI를 Design QA에 맞춰 개선한다는 주요 변경사항을 명확하게 요약합니다.
Linked Issues check ✅ Passed PR은 #1060 #1061의 모든 요구사항을 충족합니다: TopNavigation 제목 정렬 조정, 에러 레이아웃 개선, 재시도 텍스트 업데이트, 에러 아이콘 교체.
Out of Scope Changes check ✅ Passed 모든 변경사항이 #1060 #1061의 Design QA 요구사항과 직접적으로 관련되어 있으며 범위 내에 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch qa/setting-block
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can disable the changed files summary in the walkthrough.

Disable the reviews.changed_files_summary setting to disable the changed files summary in the walkthrough.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
presentation/src/main/java/daily/dayo/presentation/view/TopNavigation.kt (1)

43-43: 공용 TopNavigation 타이포 변경은 화면 전반 회귀 위험이 있습니다.

Line 43, Line 58 변경은 TopNavigation 사용 화면 전체에 영향을 줍니다. 해당 화면만 요구된 변경이라면 titleTextStyle 파라미터로 화면별 오버라이드가 더 안전합니다.

변경 범위 국소화를 위한 예시 diff
+import androidx.compose.ui.text.TextStyle
...
 fun TopNavigation(
     title: String = "",
     leftIcon: `@Composable` () -> Unit = {},
     rightIcon: `@Composable` () -> Unit = {},
     titleAlignment: TopNavigationAlign = TopNavigationAlign.LEFT,
-    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets
+    windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
+    titleTextStyle: TextStyle = DayoTheme.typography.h3,
 ) {
...
-                    Text(text = title, maxLines = 1, style = DayoTheme.typography.b3)
+                    Text(text = title, maxLines = 1, style = titleTextStyle)
...
-                    Text(text = title, maxLines = 1, style = DayoTheme.typography.b3)
+                    Text(text = title, maxLines = 1, style = titleTextStyle)

Also applies to: 58-58

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@presentation/src/main/java/daily/dayo/presentation/view/TopNavigation.kt` at
line 43, The shared TopNavigation composable was changed to alter the global
typography (the Text at both occurrences using DayoTheme.typography.b3), which
risks regressions across all screens; instead add a new optional parameter
titleTextStyle (type TextStyle) to TopNavigation with a default of
DayoTheme.typography.b3 and replace the hard-coded DayoTheme.typography.b3
references in the Text(...) calls inside TopNavigation with this parameter so
individual screens can override the title style without affecting other usages
(update the TopNavigation function signature and both Text usages accordingly).
presentation/src/main/java/daily/dayo/presentation/screen/settings/BlockedUsersScreen.kt (1)

187-208: 가중치 매직넘버(176f/336f)는 레이아웃 유지보수 리스크가 큽니다.

Line 187, Line 208은 디바이스별 높이 편차에 취약합니다. 중앙 콘텐츠/하단 버튼 배치는 Box 정렬로 표현하면 의도가 명확하고 안정적입니다.

레이아웃 단순화 예시 diff
-    Column(
-        modifier = Modifier
-            .fillMaxSize()
-            .padding(horizontal = 20.dp),
-        horizontalAlignment = Alignment.CenterHorizontally,
-    ) {
-        Spacer(modifier = Modifier.weight(176f))
-
-        Column(
-            modifier = Modifier.wrapContentHeight(),
-            horizontalAlignment = Alignment.CenterHorizontally,
-        ) {
+    Box(
+        modifier = Modifier
+            .fillMaxSize()
+            .padding(horizontal = 20.dp),
+    ) {
+        Column(
+            modifier = Modifier
+                .align(Alignment.Center)
+                .wrapContentHeight(),
+            horizontalAlignment = Alignment.CenterHorizontally,
+        ) {
             Image(
                 painter = painterResource(id = R.drawable.ic_blocked_users_empty),
                 contentDescription = null,
                 modifier = Modifier
                     .width(136.dp)
                     .height(100.dp)
             )
             Spacer(modifier = Modifier.height(20.dp))
             Text(
                 text = stringResource(R.string.blocked_users_error_description),
                 style = DayoTheme.typography.h3.copy(color = Gray3_9FA5AE),
                 modifier = Modifier.wrapContentSize()
             )
         }
-
-        Spacer(modifier = Modifier.weight(336f))
-
         FilledRoundedCornerButton(
             modifier = Modifier
+                .align(Alignment.BottomCenter)
                 .fillMaxWidth()
                 .height(52.dp)
                 .padding(bottom = 20.dp),
             onClick = onRetry,
             label = stringResource(R.string.re_try),
         )
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@presentation/src/main/java/daily/dayo/presentation/screen/settings/BlockedUsersScreen.kt`
around lines 187 - 208, The hardcoded Spacer weight magic numbers (176f/336f)
around the Column with Image/Text should be replaced with a Box-based layout to
avoid device-dependent spacing; wrap the Image/Text block inside a Box using
contentAlignment = Alignment.Center and place the bottom button (or other bottom
content) with Modifier.align(Alignment.BottomCenter) instead of Spacer, removing
the two Spacer(...) calls and the Column-centered alignment approach; update
references to the existing Column/Image/Text/Spacer usages in this composable to
use Box, Modifier.fillMaxSize(), contentAlignment, and Modifier.align so the
center content and bottom content are positioned declaratively and reliably
across screen sizes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@presentation/src/main/java/daily/dayo/presentation/screen/settings/BlockedUsersScreen.kt`:
- Around line 108-113: The current UI branches only check Status.ERROR and
treats all other states the same, causing Status.LOADING to render the
empty-state LazyColumn; update the branching in BlockedUsersScreen (use a when
on blockedUsers.status) to explicitly handle Status.LOADING (render a loading
indicator), Status.ERROR (render BlockedUsersErrorLayout with onRetry calling
profileSettingViewModel.requestBlockList()), and Status.SUCCESS (render the
LazyColumn with the actual content), ensuring all NetworkResponse branches are
covered in one when expression.

---

Nitpick comments:
In
`@presentation/src/main/java/daily/dayo/presentation/screen/settings/BlockedUsersScreen.kt`:
- Around line 187-208: The hardcoded Spacer weight magic numbers (176f/336f)
around the Column with Image/Text should be replaced with a Box-based layout to
avoid device-dependent spacing; wrap the Image/Text block inside a Box using
contentAlignment = Alignment.Center and place the bottom button (or other bottom
content) with Modifier.align(Alignment.BottomCenter) instead of Spacer, removing
the two Spacer(...) calls and the Column-centered alignment approach; update
references to the existing Column/Image/Text/Spacer usages in this composable to
use Box, Modifier.fillMaxSize(), contentAlignment, and Modifier.align so the
center content and bottom content are positioned declaratively and reliably
across screen sizes.

In `@presentation/src/main/java/daily/dayo/presentation/view/TopNavigation.kt`:
- Line 43: The shared TopNavigation composable was changed to alter the global
typography (the Text at both occurrences using DayoTheme.typography.b3), which
risks regressions across all screens; instead add a new optional parameter
titleTextStyle (type TextStyle) to TopNavigation with a default of
DayoTheme.typography.b3 and replace the hard-coded DayoTheme.typography.b3
references in the Text(...) calls inside TopNavigation with this parameter so
individual screens can override the title style without affecting other usages
(update the TopNavigation function signature and both Text usages accordingly).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 659e26e2-74cd-4713-afb9-a52429875777

📥 Commits

Reviewing files that changed from the base of the PR and between 2b8da49 and 172ddbd.

📒 Files selected for processing (4)
  • presentation/src/main/java/daily/dayo/presentation/screen/settings/BlockedUsersScreen.kt
  • presentation/src/main/java/daily/dayo/presentation/view/TopNavigation.kt
  • presentation/src/main/res/drawable/ic_blocked_users_empty.xml
  • presentation/src/main/res/values/strings.xml

Comment on lines +108 to +113
if (blockedUsers.status == Status.ERROR) {
BlockedUsersErrorLayout(
onRetry = { profileSettingViewModel.requestBlockList() },
)
} else {
LazyColumn(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

로딩 상태가 빈 상태로 오인 노출됩니다.

Line 108-113 로직에서는 Status.ERROR만 분기하고 나머지를 동일 처리해서, Status.LOADING일 때도 빈 상태 UI가 보일 수 있습니다. when으로 LOADING/ERROR/SUCCESS를 명시 분기해 주세요.

안전한 상태 분기 예시 diff
-                if (blockedUsers.status == Status.ERROR) {
-                    BlockedUsersErrorLayout(
-                        onRetry = { profileSettingViewModel.requestBlockList() },
-                    )
-                } else {
+                when (blockedUsers.status) {
+                    Status.ERROR -> {
+                        BlockedUsersErrorLayout(
+                            onRetry = { profileSettingViewModel.requestBlockList() },
+                        )
+                    }
+                    Status.LOADING -> {
+                        // TODO: 로딩 상태 UI (progress/skeleton)
+                    }
+                    Status.SUCCESS -> {
                     LazyColumn(
                         modifier = Modifier
                             .fillMaxSize()
                             .padding(start = 20.dp, end = 20.dp),
                         verticalArrangement = Arrangement.spacedBy(16.dp),
                         contentPadding = PaddingValues(vertical = 16.dp)
                     ) {
                         blockedUsers.data.orEmpty().let { blockedUsers ->
                             if (blockedUsers.isEmpty()) {
                                 item {
                                     Column(
...
                                     )
                                 }
                             } else {
                                 itemsIndexed(
                                     blockedUsers,
                                     key = { _, user -> user.memberId }
                                 ) { _, user ->
...
                                 }
                             }
                         }
                     }
-                }
+                    }
+                }

As per coding guidelines "one when expression handles all NetworkResponse branches".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@presentation/src/main/java/daily/dayo/presentation/screen/settings/BlockedUsersScreen.kt`
around lines 108 - 113, The current UI branches only check Status.ERROR and
treats all other states the same, causing Status.LOADING to render the
empty-state LazyColumn; update the branching in BlockedUsersScreen (use a when
on blockedUsers.status) to explicitly handle Status.LOADING (render a loading
indicator), Status.ERROR (render BlockedUsersErrorLayout with onRetry calling
profileSettingViewModel.requestBlockList()), and Status.SUCCESS (render the
LazyColumn with the actual content), ensuring all NetworkResponse branches are
covered in one when expression.

@github-project-automation github-project-automation bot moved this from Todo to In Progress in DAYO 2.0 Mar 18, 2026
@DongJun-H DongJun-H merged commit 71a27c4 into develop Mar 18, 2026
2 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in DAYO 2.0 Mar 18, 2026
@DongJun-H DongJun-H deleted the qa/setting-block branch March 18, 2026 12:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[QA] Fix Empty State in Setting-block-loading [QA] Fix nav_icn in Setting-block-loading

2 participants