Skip to content

[UI] 모임방 페이지 구현 완료#32

Merged
Nico1eKim merged 24 commits intoTHIP-TextHip:developfrom
Nico1eKim:ui/#23-group_room
Jul 2, 2025
Merged

[UI] 모임방 페이지 구현 완료#32
Nico1eKim merged 24 commits intoTHIP-TextHip:developfrom
Nico1eKim:ui/#23-group_room

Conversation

@Nico1eKim
Copy link
Member

@Nico1eKim Nico1eKim commented Jul 1, 2025

➕ 이슈 링크


🔎 작업 내용

  • 모임방 페이지 구현했습니다
  • 독서메이트 페이지 구현했습니다
  • 오늘의 한마디 페이지 구현했습니다
  • top app bar Box로 수정했습니다

📸 스크린샷

모임방

2025-07-01.3.46.04.mov

독서메이트

2025-07-01.3.44.44.mov

오늘의 한마디

2025-07-01.3.43.48.mov

😢 해결하지 못한 과제

  • [] 모임방에서 bottom sheet 뜨는건 2차 스프린트에서 구현하겠습니닷


📢 리뷰어들에게

  • top bar 수정한거 사용하는 방법은 제 코드 참고해주세영
  • gradation이 있는 top bar가 있고 배경이 그냥 까만 top bar가 있는데 잘 구분해서 사용해주세요 ! 사용법은 최대한 preview에 다 적어놓긴 했습니닷
  • 공통 컴포넌트도 만들었고, 기존에 있던 공통 컴포넌트도 좀 많이 건드려서 꼼꼼한 PR리뷰 부탁해용 ~

Summary by CodeRabbit

New Features

  • 그룹룸 화면, 채팅, 멤버 목록 등 그룹룸 관련 주요 UI 및 화면 추가
  • 그룹룸 헤더, 바디, 투표, 채팅 카드, 노트 카드, 채팅 입력창 등 다양한 컴포넌트 도입
  • 멤버 리스트, 투표 카드, 채팅 카드 등 프리뷰 및 샘플 데이터 제공
  • 투표 버튼 컴포넌트 상태 관리 외부화 및 스타일링 옵션 추가
  • 그라데이션 탑 앱바 컴포넌트 신규 도입

Bug Fixes

  • 구독자 수 문자열 리소스 포맷 수정

Refactor

  • 여러 TopAppBar 및 버튼, 바 컴포넌트 커스텀 레이아웃으로 구조 개선 및 파라미터 확장
  • 내부 상태 관리 방식 개선(Stateless 컴포저블로 전환 등)
  • CountingBar 등 일부 컴포넌트 파라미터 타입 및 구조 변경
  • 탑 앱바 컴포넌트 Material3 의존성 제거 및 커스텀 레이아웃 적용

Style

  • 색상(Yellow) 추가 및 테마 확장

Documentation

  • 문자열 리소스 다수 추가(그룹룸, 채팅, 참여자 등 관련)

Chores

  • 미사용 TopAppBar 파일 삭제

Nico1eKim added 22 commits June 28, 2025 20:02
@coderabbitai
Copy link

coderabbitai bot commented Jul 1, 2025

"""

Walkthrough

이 변경사항은 모임방(그룹룸) UI 전체를 Jetpack Compose로 구현하며, 화면 레이아웃, 카드 컴포넌트, 투표, 채팅, 멤버 리스트 등 다양한 UI 요소를 추가합니다. 기존 상단바 일부 구현을 삭제하고, 커스텀 상단바와 카드, 폼, 헤더, 바디, 채팅 등 그룹룸 관련 컴포넌트 및 목업 데이터 클래스를 대거 도입하였습니다.

Changes

파일/경로 요약 변경 요약
.../ui/common/buttons/GroupVoteButton.kt GroupVoteButton을 상태리스(stateless)로 리팩터링, 외부에서 선택 상태 관리, modifier 파라미터 추가
.../ui/common/cards/CardChat.kt
.../ui/common/cards/CardCommentGroup.kt
.../ui/common/cards/CardNote.kt
.../ui/common/cards/CardVote.kt
그룹룸용 카드 UI 컴포넌트(CardChat, CardCommentGroup, CardNote, CardVote) 신규 추가
.../ui/common/forms/CommentTextField.kt 댓글 입력 및 답글 기능 지원하는 CommentTextField 컴포저블 추가
.../ui/common/header/ProfileBar.kt ProfileBar에 onClick 및 bottomTextColor 파라미터 추가, 레이아웃 개선
.../ui/common/header/ProfileBarWithDate.kt ProfileBarWithDate 레이아웃 개선(정렬, 패딩 등)
.../ui/common/topappbar/BookTopAppBar.kt BookTopAppBar.kt 파일 전체 삭제
.../ui/common/topappbar/DefaultTopAppBar.kt
.../ui/common/topappbar/FeedListTopAppBar.kt
.../ui/common/topappbar/InputTopAppBar.kt
.../ui/common/topappbar/LeftNameTopAppBar.kt
.../ui/common/topappbar/LogoTopAppBar.kt
기존 Material3 TopAppBar 계열 컴포저블을 커스텀 레이아웃(Box/Row 등)으로 대체
.../ui/common/topappbar/GradationTopAppBar.kt 그라데이션 배경의 GradationTopAppBar 신규 추가
.../ui/common/view/CountingBar.kt CountingBar 파라미터 count(Int) → content(String)으로 변경
.../ui/group/room/component/GroupRoomBody.kt
.../ui/group/room/component/GroupRoomHeader.kt
.../ui/group/room/component/GroupRoomMatesList.kt
그룹룸 바디, 헤더, 멤버 리스트 컴포저블 신규 추가
.../ui/group/room/mock/GroupRoomBodyData.kt
.../ui/group/room/mock/GroupRoomChatData.kt
.../ui/group/room/mock/GroupRoomHeaderData.kt
.../ui/group/room/mock/GroupRoomMateData.kt
.../ui/group/room/mock/VoteData.kt
그룹룸 관련 목업 데이터 클래스 신규 추가
.../ui/group/room/screen/GroupRoomChatScreen.kt
.../ui/group/room/screen/GroupRoomMatesScreen.kt
.../ui/group/room/screen/GroupRoomScreen.kt
그룹룸, 채팅, 멤버 화면 컴포저블 신규 추가
.../ui/theme/Color.kt ThipColors에 Yellow 컬러 추가
.../res/values/strings.xml 그룹룸, 카드, 채팅 등 관련 string 리소스 다수 추가 및 일부 수정(subscriber_num 등)

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant GroupRoomScreen
    participant GroupRoomHeader
    participant GroupRoomBody
    participant CardNote
    participant CardVote
    participant CardChat
    participant GroupRoomMatesList
    participant GroupRoomChatScreen

    User->>GroupRoomScreen: 화면 진입
    GroupRoomScreen->>GroupRoomHeader: 헤더 데이터 렌더링
    GroupRoomScreen->>GroupRoomBody: 바디 데이터 렌더링
    GroupRoomBody->>CardNote: 독서노트 카드 표시
    GroupRoomBody->>CardVote: 투표 카드 표시
    GroupRoomBody->>CardChat: 채팅 카드 표시
    User->>GroupRoomMatesList: 멤버 리스트 보기
    User->>GroupRoomChatScreen: 채팅 화면 진입 및 메시지 입력
Loading

Assessment against linked issues

Objective Addressed Explanation
모임방 내부 페이지 UI 구현 (#23)
독서메이트(멤버 리스트) UI 구현 (#23)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
BookTopAppBar.kt 전체 삭제 (app/src/main/java/com/texthip/thip/ui/common/topappbar/BookTopAppBar.kt) BookTopAppBar는 모임방 화면 요구사항과 직접적으로 연결되지 않아 범위에서 벗어날 수 있음. 다만, 상단바 구조 일원화 목적이라면 허용될 수 있음.
CountingBar 파라미터 변경 (app/src/main/java/com/texthip/thip/ui/common/view/CountingBar.kt) 그룹룸 구현과 직접적 연관이 없으며, 기존 CountingBar 사용처 전체에 영향 줄 수 있음.
ThipColors에 Yellow 컬러 추가 (app/src/main/java/com/texthip/thip/ui/theme/Color.kt) Yellow 컬러 추가는 그룹룸 UI에서 사용되지 않을 경우 범위 밖일 수 있음.

Suggested reviewers

  • rbqks529

Poem

🐰
모임방에 토끼가 뛰어들어
채팅도 투표도 카드로 꾸며요.
멤버 리스트, 노트, 상단바까지
Compose로 새로 태어난 방!
토끼 귀 쫑긋, UI가 반짝—
오늘도 코드를 깡총깡총,
그룹룸 완성에 한 발짝!
🥕
"""


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2c41f8e and a985d4b.

📒 Files selected for processing (2)
  • app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt (5 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/topappbar/GradationTopAppBar.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/src/main/java/com/texthip/thip/ui/common/topappbar/GradationTopAppBar.kt
  • app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 13

🧹 Nitpick comments (17)
app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomBodyData.kt (1)

6-7: 페이지 번호와 퍼센티지 필드의 유효성 검사 고려

currentPagepercentage 필드가 음수 값을 가질 수 있는 상황을 방지하기 위해 유효성 검사를 고려해보세요.

data class GroupRoomBodyData(
    val bookTitle: String,
    val bookAuthor: String,
-   val currentPage: Int,
-   val percentage: Int,
+   val currentPage: Int, // 1 이상의 값이어야 함
+   val percentage: Int, // 0-100 범위의 값이어야 함
    val voteList: List<VoteData>
)

특히 percentage는 일반적으로 0-100 범위의 값이므로, 필요시 require() 검사나 커스텀 setter를 통해 범위를 제한하는 것을 권장합니다.

app/src/main/java/com/texthip/thip/ui/common/cards/CardChat.kt (1)

49-52: 접근성 개선을 위한 contentDescription 현지화 고려

chevron 아이콘의 contentDescription이 하드코딩되어 있습니다. 다국어 지원을 위해 string resource 사용을 고려해보세요.

Icon(
    painter = painterResource(R.drawable.ic_chevron),
-   contentDescription = "Chevron Icon",
+   contentDescription = stringResource(R.string.chevron_icon_description),
    tint = colors.Grey02,
)
app/src/main/java/com/texthip/thip/ui/common/cards/CardCommentGroup.kt (1)

27-31: ProfileBarWithDate의 onMenuClick 콜백 누락을 확인해주세요.

ProfileBarWithDate 컴포넌트에서 onMenuClick 매개변수를 전달하지 않고 있습니다. 메뉴 기능이 필요하다면 CardCommentGroup에도 콜백을 추가하는 것을 고려해보세요.

 @Composable
 fun CardCommentGroup(
-    data: GroupRoomChatData
+    data: GroupRoomChatData,
+    onMenuClick: () -> Unit = {}
 ) {
     // ...
     ProfileBarWithDate(
         profileImage = data.profileImage,
         nickname = data.nickname,
-        dateText = data.date
+        dateText = data.date,
+        onMenuClick = onMenuClick
     )
app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomMatesList.kt (2)

26-42: 성능 최적화를 위해 LazyColumn 사용을 고려해보세요.

현재 forEachIndexed를 사용하여 리스트를 렌더링하고 있는데, 멤버 수가 많아질 경우 성능 문제가 발생할 수 있습니다. LazyColumn을 사용하면 더 나은 성능을 얻을 수 있습니다.

+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.itemsIndexed

 @Composable
 fun GroupRoomMatesList(
     members: List<GroupRoomMateData>
 ) {
-    Column(
-        verticalArrangement = Arrangement.spacedBy(16.dp),
+    LazyColumn(
+        verticalArrangement = Arrangement.spacedBy(16.dp),
         modifier = Modifier
             .fillMaxWidth()
             .padding(20.dp)
     ) {
-        members.forEachIndexed { index, member ->
+        itemsIndexed(members) { index, member ->
             ProfileBar(
                 profileImage = member.profileImageUrl,
                 topText = member.nickname,
                 bottomText = member.role,
                 bottomTextColor = member.roleColor,
                 showSubscriberInfo = true,
                 subscriberCount = member.subscriberCount
             ) {}

             if (index != members.lastIndex) {
                 HorizontalDivider(
                     color = colors.DarkGrey02,
                     thickness = 1.dp
                 )
             }
-        }
+        }
     }
 }

34-34: ProfileBar의 빈 onClick 콜백을 의미있게 처리해보세요.

ProfileBar에 빈 람다 {}를 전달하고 있습니다. 멤버 클릭 시 동작이 필요하다면 매개변수로 콜백을 받는 것을 고려해보세요.

 @Composable
 fun GroupRoomMatesList(
-    members: List<GroupRoomMateData>
+    members: List<GroupRoomMateData>,
+    onMemberClick: (GroupRoomMateData) -> Unit = {}
 ) {
     // ...
     ProfileBar(
         // ...
-    ) {}
+    ) { onMemberClick(member) }
app/src/main/java/com/texthip/thip/ui/common/topappbar/FeedListTopAppBar.kt (1)

58-68: 텍스트 너비 설정 개선 필요

닉네임과 구독자 텍스트 모두에 동일한 고정 너비(100.dp)가 설정되어 있습니다. 이는 긴 닉네임이나 다양한 언어에서 레이아웃 문제를 야기할 수 있습니다.

다음과 같이 개선을 제안합니다:

-            Text(
-                text = nickname,
-                color = colors.White,
-                style = typography.bigtitle_b700_s22_h24,
-                modifier = Modifier.width(100.dp),
-                maxLines = 1,
-                overflow = TextOverflow.Ellipsis
-            )
-            Text(
-                text = stringResource(R.string.subscriber),
-                color = colors.White,
-                style = typography.bigtitle_b700_s22_h24,
-                modifier = Modifier.width(100.dp),
-                maxLines = 1
-            )
+            Text(
+                text = nickname,
+                color = colors.White,
+                style = typography.bigtitle_b700_s22_h24,
+                modifier = Modifier.weight(1f, false),
+                maxLines = 1,
+                overflow = TextOverflow.Ellipsis
+            )
+            Text(
+                text = stringResource(R.string.subscriber),
+                color = colors.White,
+                style = typography.bigtitle_b700_s22_h24,
+                maxLines = 1
+            )
app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt (1)

36-37: 상태 관리 개선 제안

현재 상태 관리는 올바르지만, 컴포넌트가 재구성될 때 상태가 유지되도록 하기 위해 key를 고려해볼 수 있습니다.

    // 각 투표에 따라 투표한거 기록
-    val selectedIndexes = remember { mutableStateMapOf<Int, Int?>() }
+    val selectedIndexes = remember(voteData) { mutableStateMapOf<Int, Int?>() }
app/src/main/java/com/texthip/thip/ui/common/cards/CardNote.kt (1)

86-91: 퍼센트 값 검증 개선 제안

현재 percentage / 100f로 진행률을 계산하고 있지만, 값의 범위 검증이 없어 예상치 못한 UI 동작이 발생할 수 있습니다.

            Box(
                modifier = Modifier
-                    .fillMaxWidth(fraction = percentage / 100f)
+                    .fillMaxWidth(fraction = (percentage.coerceIn(0, 100) / 100f))
                    .fillMaxHeight()
                    .background(color = colors.Purple, shape = RoundedCornerShape(12.dp))
            )
app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt (2)

43-46: 반응형 이미지 높이 개선 제안

고정된 360.dp 높이 대신 화면 크기에 따른 비율을 사용하는 것이 더 나은 사용자 경험을 제공할 수 있습니다.

+import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxWidth

                modifier = Modifier
                    .fillMaxWidth()
-                    .height(360.dp)
+                    .aspectRatio(16f/9f) // 또는 적절한 비율

97-101: 빈 클릭 핸들러 구현 필요

상단 앱바의 클릭 핸들러가 비어있습니다. 매개변수로 전달받거나 적절한 액션을 구현해야 합니다.

        GradationTopAppBar(
-            onLeftClick = {},
-            onRightClick = {},
+            onLeftClick = onBackClick,
+            onRightClick = onMoreClick,
        )
app/src/main/java/com/texthip/thip/ui/common/buttons/GroupVoteButton.kt (2)

33-39: 매개변수 문서화 및 명명 개선

상태가 외부화된 중요한 변경사항에 대한 문서화를 추가하고, 매개변수명을 더 명확하게 개선할 수 있습니다.

+/**
+ * 투표 버튼 컴포넌트 - 선택 상태는 외부에서 관리됩니다.
+ * @param selectedOptionIndex 현재 선택된 옵션의 인덱스 (null이면 선택 없음)
+ * @param onSelectionChange 선택 변경 시 호출되는 콜백
+ */
@Composable
fun GroupVoteButton(
    modifier: Modifier = Modifier,
    options: List<String>,
    voteResults: List<Int>,
-    selectedIndex: Int?, // 외부에서 전달받은 선택 상태
-    onOptionSelected: (Int?) -> Unit // 클릭 시 선택 변경 콜백
+    selectedOptionIndex: Int?, // 외부에서 전달받은 선택 상태
+    onSelectionChange: (Int?) -> Unit // 클릭 시 선택 변경 콜백
)

77-82: 토글 로직 명확성 개선

토글 로직이 올바르지만 더 명확하게 표현할 수 있습니다.

                    .clickable {
-                        if (isSelected) {
-                            onOptionSelected(null) // -1 → 취소 의미
-                        } else {
-                            onOptionSelected(index)
-                        }
+                        val newSelection = if (isSelected) null else index
+                        onOptionSelected(newSelection)
                    }
app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomHeader.kt (3)

125-125: 참가자 목록 네비게이션 구현 필요

참가자 목록으로의 네비게이션이 구현되지 않았습니다. 콜백을 매개변수로 받는 것을 고려해보세요.

@Composable
fun GroupRoomHeader(
-    data: GroupRoomHeaderData
+    data: GroupRoomHeaderData,
+    onParticipantListClick: () -> Unit = {}
) {
    // ...
                    IconButton(
-                        onClick = { /* TODO: Navigate to participant list */ },
+                        onClick = onParticipantListClick,
                        modifier = Modifier.size(24.dp)
                    ) {

161-161: 장르별 색상 매핑 시스템 구현 필요

장르에 따른 동적 색상 변경이 필요합니다. 장르-색상 매핑 로직을 구현하는 것이 좋겠습니다.

+fun getGenreColor(genre: String): androidx.compose.ui.graphics.Color {
+    return when (genre) {
+        "문학" -> colors.Orange
+        "에세이" -> colors.Purple
+        "자기계발" -> colors.Green
+        else -> colors.Grey02
+    }
+}

                Text(
                    text = data.genre,
                    style = typography.info_m500_s12,
-                    color = colors.Orange // TODO: 장르에 맞는 색으로 변경
+                    color = getGenreColor(data.genre)
                )

장르별 색상 매핑 시스템을 구현하시겠습니까?


35-35: 하드코딩된 패딩 값 테마로 이동 고려

반복적으로 사용되는 20.dp 패딩을 테마의 spacing 시스템으로 관리하는 것을 고려해보세요.

app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt (1)

52-68: Mock 데이터 중복 제거 고려

Preview의 mock 데이터가 다른 파일들과 유사합니다. 공통 mock 데이터 객체를 만들어 재사용하는 것을 고려해보세요.

Mock 데이터를 별도의 객체로 분리하여 테스트와 프리뷰에서 재사용할 수 있도록 개선할 수 있습니다.

app/src/main/java/com/texthip/thip/ui/common/forms/CommentTextField.kt (1)

121-144: 전송 버튼의 상태 관리 및 접근성 개선 제안

현재 구현은 잘 되어 있지만, 접근성을 위해 다음과 같은 개선을 고려해보세요:

 Box(
     modifier = Modifier
         .padding(end = 4.dp)
         .size(width = 42.dp, height = 28.dp)
         .background(
             color = if (isEnabled) colors.Purple else colors.Grey02,
             shape = RoundedCornerShape(20.dp)
         )
-        .clickable(enabled = isEnabled) {
+        .clickable(
+            enabled = isEnabled,
+            role = Role.Button
+        ) {
             onSendClick()
             focusManager.clearFocus()
         },
     contentAlignment = Alignment.Center
 ) {
     Icon(
         painter = painterResource(id = R.drawable.ic_send),
-        contentDescription = "Send",
+        contentDescription = if (isEnabled) "댓글 전송" else "댓글 전송 비활성화",
         tint = colors.White,
         modifier = Modifier.size(24.dp)
     )
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between afdfdae and 2c41f8e.

⛔ Files ignored due to path filters (1)
  • app/src/main/res/drawable/img_group_room.png is excluded by !**/*.png
📒 Files selected for processing (29)
  • app/src/main/java/com/texthip/thip/ui/common/buttons/GroupVoteButton.kt (4 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/cards/CardChat.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/cards/CardCommentGroup.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/cards/CardNote.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/forms/CommentTextField.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt (5 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/header/ProfileBarWithDate.kt (3 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/topappbar/BookTopAppBar.kt (0 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/topappbar/DefaultTopAppBar.kt (2 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/topappbar/FeedListTopAppBar.kt (2 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/topappbar/GradationTopAppBar.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/topappbar/InputTopAppBar.kt (2 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/topappbar/LeftNameTopAppBar.kt (2 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/topappbar/LogoTopAppBar.kt (3 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/view/CountingBar.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomHeader.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomMatesList.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomBodyData.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomChatData.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomHeaderData.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomMateData.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomChatScreen.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomMatesScreen.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomScreen.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/theme/Color.kt (3 hunks)
  • app/src/main/res/values/strings.xml (3 hunks)
💤 Files with no reviewable changes (1)
  • app/src/main/java/com/texthip/thip/ui/common/topappbar/BookTopAppBar.kt
🧰 Additional context used
🧬 Code Graph Analysis (7)
app/src/main/java/com/texthip/thip/ui/common/cards/CardCommentGroup.kt (1)
app/src/main/java/com/texthip/thip/ui/common/header/ProfileBarWithDate.kt (1)
  • ProfileBarWithDate (32-87)
app/src/main/java/com/texthip/thip/ui/common/topappbar/InputTopAppBar.kt (1)
app/src/main/java/com/texthip/thip/ui/common/buttons/HeaderButton.kt (1)
  • HeaderButton (22-47)
app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt (1)
app/src/main/java/com/texthip/thip/ui/common/buttons/GroupVoteButton.kt (1)
  • GroupVoteButton (32-119)
app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomMatesScreen.kt (3)
app/src/main/java/com/texthip/thip/ui/common/topappbar/DefaultTopAppBar.kt (1)
  • DefaultTopAppBar (23-66)
app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomMatesList.kt (1)
  • GroupRoomMatesList (16-44)
app/src/main/java/com/texthip/thip/ui/theme/Theme.kt (1)
  • ThipTheme (41-69)
app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomMatesList.kt (1)
app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt (1)
  • ProfileBar (33-114)
app/src/main/java/com/texthip/thip/ui/common/topappbar/GradationTopAppBar.kt (1)
app/src/main/java/com/texthip/thip/ui/common/view/CountingBar.kt (1)
  • CountingBar (19-38)
app/src/main/java/com/texthip/thip/ui/common/forms/CommentTextField.kt (1)
app/src/main/java/com/texthip/thip/ui/theme/Theme.kt (1)
  • ThipTheme (41-69)
🔇 Additional comments (26)
app/src/main/java/com/texthip/thip/ui/theme/Color.kt (1)

24-24: 새로운 Yellow 색상이 올바르게 추가되었습니다.

기존 색상 시스템과 일관된 패턴으로 Yellow 색상이 추가되어 있습니다. 색상 상수 정의, 데이터 클래스 속성 추가, 기본 인스턴스 초기화가 모두 적절하게 구현되었습니다.

Also applies to: 60-60, 93-93

app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomHeaderData.kt (1)

3-10: 그룹룸 헤더 데이터 구조가 잘 설계되었습니다.

속성들이 명확하고 적절한 타입으로 정의되어 있으며, 그룹룸 헤더 UI에 필요한 모든 정보를 포함하고 있습니다.

app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomChatData.kt (1)

5-10: 채팅 데이터 구조가 Compose UI에 적합하게 설계되었습니다.

Painter? 타입의 nullable 프로필 이미지 속성과 기타 채팅 메시지 정보들이 적절하게 구성되어 있습니다. Compose에서 사용하기에 적합한 구조입니다.

app/src/main/java/com/texthip/thip/ui/common/header/ProfileBar.kt (2)

39-39: 클릭 기능과 색상 커스터마이징이 잘 추가되었습니다.

onClick 매개변수와 bottomTextColor 커스터마이징, 그리고 clickable 수정자 추가로 컴포넌트의 유연성과 상호작용성이 향상되었습니다.

Also applies to: 43-43, 48-48


68-71: Column의 spacing 처리가 개선되었습니다.

Arrangement.spacedBy(4.dp)를 사용하여 더 명확하고 일관된 간격 처리가 되었습니다.

app/src/main/java/com/texthip/thip/ui/group/room/mock/GroupRoomMateData.kt (1)

6-12: 데이터 클래스 구조가 잘 설계되었습니다

프로필 이미지의 nullable 처리와 Color 타입 사용이 적절합니다. 구독자 수(subscriberCount)가 음수가 되지 않도록 하는 것만 고려해보시면 좋겠습니다.

app/src/main/java/com/texthip/thip/ui/common/view/CountingBar.kt (2)

22-22: 파라미터 변경으로 컴포넌트 유연성 향상

count에서 content로 파라미터를 변경한 것은 좋은 리팩토링입니다. 문자열 포맷팅 책임을 컴포넌트 외부로 이동시켜 재사용성과 유연성이 크게 향상되었습니다.


24-37: 레이아웃 구조 단순화로 성능 개선

중첩된 BoxRow 구조를 단일 Row로 단순화한 것이 좋습니다. 불필요한 레이아웃 중첩을 제거하여 성능이 향상되고 코드 가독성도 좋아졌습니다.

app/src/main/java/com/texthip/thip/ui/common/cards/CardChat.kt (1)

23-61: 잘 구성된 채팅 카드 컴포넌트

클릭 가능한 카드 구조, 적절한 스타일링, 그리고 레이아웃 간격이 잘 설정되어 있습니다. Compose 모범 사례를 잘 따르고 있습니다.

app/src/main/java/com/texthip/thip/ui/common/header/ProfileBarWithDate.kt (2)

45-76: 프로필 정보 그룹핑을 위한 레이아웃 구조 개선

프로필 이미지와 텍스트 정보를 내부 Row로 그룹핑한 것이 좋은 개선입니다. 관련 요소들이 더 명확하게 묶여서 레이아웃의 의미가 더 명확해졌습니다.


62-75: 간격 조정으로 시각적 계층 구조 개선

Spacer를 적절히 사용하여 프로필 이미지, 닉네임, 날짜 간의 시각적 계층 구조가 잘 구성되었습니다. 4dp, 2dp의 간격 설정이 적절합니다.

app/src/main/java/com/texthip/thip/ui/common/cards/CardCommentGroup.kt (1)

18-40: 잘 구현된 댓글 카드 컴포넌트입니다.

컴포넌트 구조가 깔끔하고 재사용 가능하게 잘 작성되었습니다. ProfileBarWithDate와 Text를 적절히 조합하여 댓글 표시 기능을 구현했습니다.

app/src/main/java/com/texthip/thip/ui/common/topappbar/InputTopAppBar.kt (1)

34-68: Material3에서 커스텀 레이아웃으로의 리팩토링이 잘 되었습니다.

TopAppBar에서 Box 기반 커스텀 레이아웃으로 성공적으로 변경되었습니다. 동일한 기능을 유지하면서 더 세밀한 스타일 제어가 가능해졌습니다.

app/src/main/java/com/texthip/thip/ui/common/topappbar/LogoTopAppBar.kt (2)

37-71: Material3에서 커스텀 레이아웃으로의 리팩토링이 잘 수행되었습니다.

TopAppBar에서 Box와 Row를 사용한 커스텀 레이아웃으로 깔끔하게 변경되었습니다. 로고와 아이콘들의 배치가 적절하고 간격도 잘 설정되어 있습니다.


52-70: 아이콘 배치와 간격이 잘 구성되었습니다.

Row를 사용하여 오른쪽 아이콘들을 배치하고 spacedBy(20.dp)로 적절한 간격을 설정했습니다. 각 아이콘의 클릭 핸들링도 올바르게 구현되어 있습니다.

app/src/main/java/com/texthip/thip/ui/common/cards/CardVote.kt (1)

29-96: 잘 구현된 투표 카드 컴포넌트

HorizontalPager와 상태 관리를 활용한 투표 카드 구현이 매우 잘 되어 있습니다. 페이지별 선택 상태 관리와 UI 구성이 적절합니다.

app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomChatScreen.kt (2)

29-110: 잘 구현된 채팅 화면

채팅 화면의 구현이 매우 잘 되어 있습니다. 역순 LazyColumn 사용, 날짜별 메시지 그룹핑, 상태 관리가 모두 적절합니다.


72-76: 날짜 변경 감지 로직 및 정렬 일치 확인 완료

메시지 리스트가 아래 위치에서 .sortedByDescending { it.date }로 내림차순 정렬되고 있어
index 0부터 이전 항목과의 date 비교를 통해 날짜 변경을 감지하는 로직(isNewDate)이 올바르게 동작합니다.
추가 조치가 필요하지 않습니다.

  • 파일: app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomChatScreen.kt
    • 52행: ).sortedByDescending { it.date } 적용 확인
app/src/main/java/com/texthip/thip/ui/common/cards/CardNote.kt (1)

27-94: 잘 구현된 독서 진행률 카드

독서 진행률을 시각적으로 잘 표현한 카드 컴포넌트입니다. 진행률 바 구현과 UI 레이아웃이 적절합니다.

app/src/main/java/com/texthip/thip/ui/common/forms/CommentTextField.kt (3)

40-49: 함수 매개변수 구성이 잘 설계되었습니다

컴포넌트의 매개변수가 명확하고 기본값이 적절히 설정되어 있어 사용성이 좋습니다. 답글 기능이 선택적으로 동작하도록 설계된 점도 우수합니다.


100-119: BasicTextField의 decorationBox 사용이 적절합니다

플레이스홀더 구현을 위해 decorationBox를 올바르게 사용하고 있으며, 커서 색상도 브랜드 컬러인 NeonGreen으로 설정되어 일관된 UI를 제공합니다.


148-167: Preview 구현이 우수합니다

상태 관리와 다양한 시나리오를 포함한 프리뷰가 잘 구현되어 있어 개발 및 디자인 검토에 도움이 됩니다.

app/src/main/java/com/texthip/thip/ui/common/topappbar/LeftNameTopAppBar.kt (2)

36-48: Box 레이아웃을 사용한 커스텀 구현이 적절합니다

Material3 TopAppBar에서 커스텀 Box 레이아웃으로의 리팩토링이 잘 구현되었습니다. 타이틀의 정렬과 배경색 설정이 적절합니다.


31-32: 기본 아이콘 설정이 적절합니다

검색과 추가 아이콘을 기본값으로 설정한 것이 합리적입니다.

app/src/main/res/values/strings.xml (2)

43-44: 새로운 카드 컴포넌트 문자열이 잘 정의되었습니다

record_bookvote_title 문자열이 적절히 정의되어 있으며, 이모지를 포함한 vote_title이 사용자 경험을 향상시킬 것으로 보입니다.


53-66: 그룹룸 기능 문자열이 체계적으로 추가되었습니다

그룹룸 관련 새로운 문자열 리소스들이 논리적으로 그룹화되어 있고, 한국어 현지화가 자연스럽게 되어 있습니다. 특히 participate_num과 같은 동적 콘텐츠를 위한 포맷 지정자도 올바르게 설정되어 있습니다.

Comment on lines +3 to +7
data class VoteData(
val description: String,
val options: List<String>,
val votes: List<Int>
) No newline at end of file
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

투표 데이터 구조의 일관성을 보장하는 검증 로직을 고려해보세요.

optionsvotes 리스트의 크기가 일치해야 하는데, 현재 구조에서는 이를 보장할 수 없습니다. 또한 votes 속성명이 모호할 수 있습니다.

다음과 같은 개선을 제안합니다:

 data class VoteData(
     val description: String,
     val options: List<String>,
-    val votes: List<Int>
+    val voteCounts: List<Int>
 )

또는 데이터 검증을 위한 init 블록 추가를 고려해보세요:

data class VoteData(
    val description: String,
    val options: List<String>, 
    val voteCounts: List<Int>
) {
    init {
        require(options.size == voteCounts.size) {
            "Options and vote counts must have the same size"
        }
    }
}
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/group/room/mock/VoteData.kt around
lines 3 to 7, the data class lacks validation to ensure the options and votes
lists have the same size, and the votes property name is ambiguous. Rename the
votes property to voteCounts for clarity and add an init block that checks if
options.size equals voteCounts.size, throwing an exception if they differ to
enforce data consistency.

) {
DefaultTopAppBar(
title = stringResource(R.string.group_room_mates),
onLeftClick = {},
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

DefaultTopAppBar의 빈 onLeftClick 콜백을 구현하세요.

뒤로 가기 버튼의 onClick 콜백이 비어있습니다. 실제 네비게이션 동작을 구현하거나 매개변수로 받아 처리하는 것을 고려해보세요.

 @Composable
-fun GroupRoomMatesScreen() {
+fun GroupRoomMatesScreen(
+    onBackClick: () -> Unit = {}
+) {
     // ...
     DefaultTopAppBar(
         title = stringResource(R.string.group_room_mates),
-        onLeftClick = {},
+        onLeftClick = onBackClick,
     )
🤖 Prompt for AI Agents
In
app/src/main/java/com/texthip/thip/ui/group/room/screen/GroupRoomMatesScreen.kt
at line 31, the onLeftClick callback for DefaultTopAppBar is currently empty.
Implement this callback to handle the back navigation action, either by invoking
a navigation function directly or by passing a navigation handler as a parameter
to the composable and calling it here.

modifier = Modifier
.fillMaxWidth()
.background(color = colors.Black)
.height(56.dp)
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

고정 높이 사용을 확인해주세요.

height(56.dp)로 고정 높이를 사용하고 있습니다. 다른 top app bar 컴포넌트들과 일관성을 유지하고 있는지 확인해보세요.

다른 top app bar 컴포넌트들의 높이 설정을 확인해보세요:


🏁 Script executed:

#!/bin/bash
# Description: Check height usage in other top app bar components
# Expected: Consistent height usage across top app bars

rg -A 2 -B 2 "\.height\(" app/src/main/java/com/texthip/thip/ui/common/topappbar/

Length of output: 1709


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' app/src/main/java/com/texthip/thip/ui/common/topappbar/LogoTopAppBar.kt

Length of output: 2725


LogoTopAppBar에도 명시적 고정 높이(56.dp) 적용 필요

InputTopAppBar와 GradationTopAppBar는 height(56.dp)를 사용하고 있지만, LogoTopAppBar는 vertical = 16.dp 패딩만으로 높이를 맞추고 있어 코드 일관성이 떨어집니다. 아래와 같이 Box에 고정 높이를 추가하고 세로 패딩은 제거하거나 조정해주세요.

• 수정 위치

  • app/src/main/java/com/texthip/thip/ui/common/topappbar/LogoTopAppBar.kt

• 제안하는 변경 예시

 Box(
     modifier = Modifier
-        .fillMaxWidth()
-        .background(color = colors.Black)
-        .padding(horizontal = 20.dp, vertical = 16.dp),
+        .fillMaxWidth()
+        .height(56.dp)
+        .background(color = colors.Black)
+        .padding(horizontal = 20.dp),
     contentAlignment = Alignment.CenterStart
 ) {
     Image(
         painter = painterResource(R.drawable.ic_logo),
         contentDescription = "Logo",
         modifier = Modifier
-            .height(24.dp)
-            .align(Alignment.CenterStart)
+            .height(24.dp)
+            .align(Alignment.CenterStart)
     )
     …
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/common/topappbar/LogoTopAppBar.kt
around line 38, add an explicit fixed height of 56.dp to the Box component and
remove or adjust the vertical padding to maintain consistent height styling with
InputTopAppBar and GradationTopAppBar. This will improve code consistency by
standardizing the height definition across these components.

Comment on lines +56 to +64
Icon(
painter = painterResource(R.drawable.ic_more),
contentDescription = "More Options",
tint = Color.Unspecified,
modifier = Modifier
.align(Alignment.CenterEnd)
.clickable { onRightClick() }
)
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

오른쪽 아이콘도 동일한 접근성 개선 필요

일관성을 위해 오른쪽 아이콘도 IconButton을 사용해야 합니다.

        if (isRightIconVisible) {
-            Icon(
-                painter = painterResource(R.drawable.ic_more),
-                contentDescription = "More Options",
-                tint = Color.Unspecified,
-                modifier = Modifier
-                    .align(Alignment.CenterEnd)
-                    .clickable { onRightClick() }
-            )
+            IconButton(
+                onClick = onRightClick,
+                modifier = Modifier.align(Alignment.CenterEnd)
+            ) {
+                Icon(
+                    painter = painterResource(R.drawable.ic_more),
+                    contentDescription = "More Options",
+                    tint = Color.Unspecified
+                )
+            }
        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Icon(
painter = painterResource(R.drawable.ic_more),
contentDescription = "More Options",
tint = Color.Unspecified,
modifier = Modifier
.align(Alignment.CenterEnd)
.clickable { onRightClick() }
)
}
if (isRightIconVisible) {
IconButton(
onClick = onRightClick,
modifier = Modifier.align(Alignment.CenterEnd)
) {
Icon(
painter = painterResource(R.drawable.ic_more),
contentDescription = "More Options",
tint = Color.Unspecified
)
}
}
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/common/topappbar/DefaultTopAppBar.kt
between lines 56 and 64, the right icon is implemented using Icon with a
clickable modifier, which lacks proper accessibility support. Replace the Icon
wrapped with Modifier.clickable by using an IconButton composable for the right
icon to ensure consistent accessibility and interaction behavior.

Comment on lines +37 to +44
Icon(
painter = painterResource(R.drawable.ic_arrow_back),
contentDescription = "Back Button",
tint = Color.Unspecified,
modifier = Modifier
.align(Alignment.CenterStart)
.clickable { onLeftClick() }
)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

접근성 및 터치 피드백 개선 제안

clickable 모디파이어 대신 IconButton을 사용하는 것이 접근성과 사용자 경험 측면에서 더 좋습니다.

+import androidx.compose.material3.IconButton

-        Icon(
-            painter = painterResource(R.drawable.ic_arrow_back),
-            contentDescription = "Back Button",
-            tint = Color.Unspecified,
-            modifier = Modifier
-                .align(Alignment.CenterStart)
-                .clickable { onLeftClick() }
-        )
+        IconButton(
+            onClick = onLeftClick,
+            modifier = Modifier.align(Alignment.CenterStart)
+        ) {
+            Icon(
+                painter = painterResource(R.drawable.ic_arrow_back),
+                contentDescription = "Back Button",
+                tint = Color.Unspecified
+            )
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Icon(
painter = painterResource(R.drawable.ic_arrow_back),
contentDescription = "Back Button",
tint = Color.Unspecified,
modifier = Modifier
.align(Alignment.CenterStart)
.clickable { onLeftClick() }
)
// Add at top of file with the other imports
import androidx.compose.material3.IconButton
//
IconButton(
onClick = onLeftClick,
modifier = Modifier.align(Alignment.CenterStart)
) {
Icon(
painter = painterResource(R.drawable.ic_arrow_back),
contentDescription = "Back Button",
tint = Color.Unspecified
)
}
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/common/topappbar/DefaultTopAppBar.kt
around lines 37 to 44, replace the Icon composable wrapped with a clickable
modifier by using an IconButton composable instead. This change improves
accessibility and touch feedback by providing built-in support for these
features. Wrap the Icon inside IconButton and move the onLeftClick callback to
the IconButton's onClick parameter.

Comment on lines +28 to +46
ActionBookButton(
bookTitle = data.bookTitle,
bookAuthor = data.bookAuthor
) {}

CardNote(
currentPage = data.currentPage,
percentage = data.percentage,
) {}

CardChat(
title = stringResource(R.string.group_room_chat),
subtitle = stringResource(R.string.group_room_chat_description)
) {}

CardVote(
voteData = data.voteList
)
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

빈 클릭 핸들러 콜백으로 개선

모든 버튼과 카드의 클릭 핸들러가 비어있습니다. 매개변수로 콜백을 받아 처리하는 것이 좋겠습니다.

@Composable
fun GroupRoomBody(
    modifier: Modifier = Modifier,
-    data: GroupRoomBodyData
+    data: GroupRoomBodyData,
+    onBookClick: () -> Unit = {},
+    onNoteClick: () -> Unit = {},
+    onChatClick: () -> Unit = {}
) {
    // ...
        ActionBookButton(
            bookTitle = data.bookTitle,
            bookAuthor = data.bookAuthor
-        ) {}
+        ) { onBookClick() }

        CardNote(
            currentPage = data.currentPage,
            percentage = data.percentage,
-        ) {}
+        ) { onNoteClick() }

        CardChat(
            title = stringResource(R.string.group_room_chat),
            subtitle = stringResource(R.string.group_room_chat_description)
-        ) {}
+        ) { onChatClick() }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ActionBookButton(
bookTitle = data.bookTitle,
bookAuthor = data.bookAuthor
) {}
CardNote(
currentPage = data.currentPage,
percentage = data.percentage,
) {}
CardChat(
title = stringResource(R.string.group_room_chat),
subtitle = stringResource(R.string.group_room_chat_description)
) {}
CardVote(
voteData = data.voteList
)
}
@Composable
fun GroupRoomBody(
modifier: Modifier = Modifier,
data: GroupRoomBodyData,
onBookClick: () -> Unit = {},
onNoteClick: () -> Unit = {},
onChatClick: () -> Unit = {}
) {
// ...
ActionBookButton(
bookTitle = data.bookTitle,
bookAuthor = data.bookAuthor
) { onBookClick() }
CardNote(
currentPage = data.currentPage,
percentage = data.percentage,
) { onNoteClick() }
CardChat(
title = stringResource(R.string.group_room_chat),
subtitle = stringResource(R.string.group_room_chat_description)
) { onChatClick() }
CardVote(
voteData = data.voteList
)
}
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/group/room/component/GroupRoomBody.kt
between lines 28 and 46, all button and card components have empty click handler
callbacks. Modify these components to accept click handler callbacks as
parameters and pass them accordingly, enabling proper handling of click events
instead of empty lambdas.

Comment on lines +50 to +72
Row(
modifier = Modifier
.align(Alignment.CenterEnd),
horizontalArrangement = spacedBy(20.dp),
) {
if (isLeftIconVisible) {
IconButton(onClick = onLeftClick) {
Icon(
painter = leftIcon,
contentDescription = "Left Icon",
tint = Color.Unspecified
)
}
Icon(
painter = leftIcon,
contentDescription = "Left Icon",
tint = Color.Unspecified,
modifier = Modifier.clickable { onLeftClick() }
)
}
if (isRightIconVisible) {
IconButton(onClick = onRightClick) {
Icon(
painter = rightIcon,
contentDescription = "Right Icon",
tint = Color.Unspecified
)
}
Icon(
painter = rightIcon,
contentDescription = "Right Icon",
tint = Color.Unspecified,
modifier = Modifier.clickable { onRightClick() }
)
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = Color.Transparent,
)
)
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

아이콘 버튼의 접근성 개선이 필요합니다

IconButton에서 Icon + clickable로 변경된 것은 괜찮지만, 접근성을 위해 다음과 같은 개선이 필요합니다:

 if (isLeftIconVisible) {
     Icon(
         painter = leftIcon,
         contentDescription = "Left Icon",
         tint = Color.Unspecified,
-        modifier = Modifier.clickable { onLeftClick() }
+        modifier = Modifier
+            .clickable(
+                role = Role.Button,
+                onClickLabel = "왼쪽 버튼"
+            ) { onLeftClick() }
+            .padding(4.dp) // 터치 영역 확보
     )
 }
 if (isRightIconVisible) {
     Icon(
         painter = rightIcon,
         contentDescription = "Right Icon",
         tint = Color.Unspecified,
-        modifier = Modifier.clickable { onRightClick() }
+        modifier = Modifier
+            .clickable(
+                role = Role.Button,
+                onClickLabel = "오른쪽 버튼"
+            ) { onRightClick() }
+            .padding(4.dp) // 터치 영역 확보
     )
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Row(
modifier = Modifier
.align(Alignment.CenterEnd),
horizontalArrangement = spacedBy(20.dp),
) {
if (isLeftIconVisible) {
IconButton(onClick = onLeftClick) {
Icon(
painter = leftIcon,
contentDescription = "Left Icon",
tint = Color.Unspecified
)
}
Icon(
painter = leftIcon,
contentDescription = "Left Icon",
tint = Color.Unspecified,
modifier = Modifier.clickable { onLeftClick() }
)
}
if (isRightIconVisible) {
IconButton(onClick = onRightClick) {
Icon(
painter = rightIcon,
contentDescription = "Right Icon",
tint = Color.Unspecified
)
}
Icon(
painter = rightIcon,
contentDescription = "Right Icon",
tint = Color.Unspecified,
modifier = Modifier.clickable { onRightClick() }
)
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = Color.Transparent,
)
)
}
}
Row(
modifier = Modifier
.align(Alignment.CenterEnd),
horizontalArrangement = spacedBy(20.dp),
) {
if (isLeftIconVisible) {
Icon(
painter = leftIcon,
contentDescription = "Left Icon",
tint = Color.Unspecified,
modifier = Modifier
.clickable(
role = Role.Button,
onClickLabel = "왼쪽 버튼"
) { onLeftClick() }
.padding(4.dp) // 터치 영역 확보
)
}
if (isRightIconVisible) {
Icon(
painter = rightIcon,
contentDescription = "Right Icon",
tint = Color.Unspecified,
modifier = Modifier
.clickable(
role = Role.Button,
onClickLabel = "오른쪽 버튼"
) { onRightClick() }
.padding(4.dp) // 터치 영역 확보
)
}
}
}
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/common/topappbar/LeftNameTopAppBar.kt
between lines 50 and 72, the Icon components use Modifier.clickable for
interaction but lack proper accessibility support. Replace the Icon with
IconButton components or add appropriate semantics and roles to the clickable
Icons to improve accessibility. Ensure contentDescription is meaningful and that
the clickable area is properly recognized by screen readers.

Copy link
Collaborator

@rbqks529 rbqks529 left a comment

Choose a reason for hiding this comment

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

다 본다고 했는데 놓친게 있는거 같아서 시간날 때 한번더 보겠습니다!

Copy link
Collaborator

Choose a reason for hiding this comment

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

오늘의 한마디에 쓰이는 component 맞나요?

Copy link
Collaborator

Choose a reason for hiding this comment

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

댓글에 쓰는거네요 확인했씁니다

Copy link
Collaborator

Choose a reason for hiding this comment

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

TopAppBar Box로 수정하신거 같은데 그러면 content 안에 Column으로 같이 넣으면 될까요? 또 그때 못 물어본게 있는데 Row 말고 Box로 하는 이유가 있나요?

Copy link
Member Author

Choose a reason for hiding this comment

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

넹 그냥 content 말고 column안에 같이 넣고 스크롤 적용 범위를 Top Bar 빼고 설정하면 됩니다!

Row 말고 Box로 한 이유는 요소들 위치를 좀 더 자유롭게 설정하고 싶어서입니닷 !
Row로 하면 요소들 배치하는데 verticalAlignment나 horizontalArrangement를 써야하는데 Box를 쓰면 내부 요소들에 .align(Alignment.CenterStart) 와 같이 위치를 직접 지정할 수 있어서 Box로 했습니당 ~

Copy link
Collaborator

Choose a reason for hiding this comment

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

이거 scaffold로 안감싸도 되나용?

Copy link
Member Author

Choose a reason for hiding this comment

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

일부러 안감쌌습니다! Scaffold를 적용하면 innerpadding을 적용해야되는데 그럼 필요 없는 padding이 생기고, 추후 bottom bar를 지정할 때 padding이 2번 적용돼서 안감싸는게 좋다고 판단했습니닷

Copy link
Collaborator

Choose a reason for hiding this comment

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

확인했습니다!

tint = Color.Unspecified
)
}
Icon(
Copy link
Collaborator

Choose a reason for hiding this comment

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

보다가 궁금한게 있는데 아이콘 버튼이 좋나요 아니면 아이콘 + clickable이 좋나요?

Copy link
Member Author

Choose a reason for hiding this comment

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

IconButton이 좋은데 제 애뮬이 이상한건지 .. IconButton을 적용하면 이상한 padding이 하나 더 생기더라구요 ..? 그래서 그냥 Icon + clickable로 수정했습니닷

Copy link
Member

@JJUYAAA JJUYAAA left a comment

Choose a reason for hiding this comment

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

수고하셨숩니당 ~~~

style = typography.timedate_r400_s11,
color = colors.Grey01
)
Row {
Copy link
Member

Choose a reason for hiding this comment

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

이거 혹시 이중 Row로 바꾼 이유가 뭐죵?

Copy link
Member Author

Choose a reason for hiding this comment

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

첫번째 Row는 전체를 감싸는 Row이고 두번째는 프로필 이미지 + (닉네임 + 날짜)를 감싸는 Row인데

첫번째 Row는 verticalAlignment에서 세로 중간 정렬를 적용해야됐고, 두번째 Row는 세로 상단 정렬이라서(프로필 이미지가 상단에 붙어야함) 수정했습니당

Comment on lines +31 to +32
leftIcon: Painter = painterResource(R.drawable.ic_search),
rightIcon: Painter = painterResource(R.drawable.ic_plus),
Copy link
Member

Choose a reason for hiding this comment

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

👍

modifier = Modifier
.fillMaxSize()
) {
DefaultTopAppBar(
Copy link
Member

Choose a reason for hiding this comment

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

오옹 탑앱바 이렇게 수정하니까 깔끔하긴 하네용

)

LazyColumn(
reverseLayout = true,
Copy link
Member

Choose a reason for hiding this comment

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

오오 최신것부터 불러오는거군여! 좋아여 ~

Spacer(modifier = Modifier.width(4.dp))
Spacer(modifier = Modifier.width(2.dp))
Text(
text = stringResource(R.string.subscriber_num, subscriberCount),
Copy link
Member

Choose a reason for hiding this comment

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

이거 strings.xml 에서는 %02d 를 빼셨던데여 ?? 오류 안나나여??

Copy link
Member Author

Choose a reason for hiding this comment

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

아 오류나서 그렇게 한건가여 ?? 이게 팔로워?수인데 팔로워 수가 100명이 넘어갈 수도 있다고 생각해서 일부러 없앴습니다 ! 오류는 안나여 ~

Copy link
Member

Choose a reason for hiding this comment

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

아하 왜 포맷팅을 제거했지 했는데 위에서 구독자수를 String으로 변환시킨걸 못봤네요!
근데 그러면 여기선 stringResource(R.string.subscriber_num) 으로 해야하지 않나여 ~?

Copy link
Member Author

Choose a reason for hiding this comment

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

마자용 ㅋㅎㅋㅎㅋ 수정하겟숨미닷

Text(
text = data.genre,
style = typography.info_m500_s12,
color = colors.Orange // TODO: 장르에 맞는 색으로 변경
Copy link
Member

Choose a reason for hiding this comment

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

안드측에서 장르랑 색상 맵핑하는 Map 객체를 만들어두면 좋을 것 같네영

@Nico1eKim Nico1eKim merged commit 6793af4 into THIP-TextHip:develop Jul 2, 2025
1 check passed
@coderabbitai coderabbitai bot mentioned this pull request Jul 8, 2025
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[UI] 모임방 페이지 [(THIP2025-48)]

3 participants