Skip to content

[UI] 피드 페이지 UI 수정 및 전체 QA 진행#63

Merged
JJUYAAA merged 24 commits intoTHIP-TextHip:developfrom
JJUYAAA:ui/#61-feed_qa
Aug 8, 2025
Merged

[UI] 피드 페이지 UI 수정 및 전체 QA 진행#63
JJUYAAA merged 24 commits intoTHIP-TextHip:developfrom
JJUYAAA:ui/#61-feed_qa

Conversation

@JJUYAAA
Copy link
Member

@JJUYAAA JJUYAAA commented Aug 2, 2025

➕ 이슈 링크


🔎 작업 내용

  • 피드 컴포넌트 수정 (이미지가 있는 경우 사이즈 100.dp & 3줄 max 로 통일)
  • 이미지 자세히 보기 모달 추가
  • QA 진행하며 변경된 디자인들을 반영했습니다

📸 스크린샷

###이미지 자세히 보기

bandicam.2025-08-01.19-54-52-892.mp4

###마이페이지 디자인 수정

bandicam.2025-08-02.11-32-44-400.mp4

###다른 유저의 띱 목록 스크린 추가

bandicam.2025-08-02.11-26-20-845.mp4

###홈/피드 페이지

bandicam.2025-08-02.10-44-09-921.mp4

###장르 선택 페이지

bandicam.2025-08-02.11-55-02-178.mp4

😢 해결하지 못한 과제

  • 피드 더보기 처리 관련 로직은 어제 회의에서 이야기한 방식으로 바꿔서 다음 pr에 추가하도록 하겠습니당

  • 데이터 없는 화면 -> 구현 안 한 것들이 많은데 다음 pr에..ㅎㅎ

  • pr 올리기 직전에 발견해버린 사용자 찾기 화면도 다음 pr에 같이 추가할게욥..ㅎ


📢 리뷰어들에게

  • 참고해야 할 사항들을 적어주세요

Summary by CodeRabbit

새 기능

  • 이미지 뷰어 모달 추가: 피드 내 여러 이미지를 전체 화면에서 스와이프하며 볼 수 있습니다.
  • 구독자 수 표시 기능 및 UI 개선: 구독 리스트에 구독자 수 노출 및 버튼/카운트 전환 지원.
  • 구독 목록 전용 화면 추가 및 다양한 UI 프리뷰 추가.
  • 댓글 화면에서 댓글 상태 외부 관리 및 롱프레스 메뉴(삭제/신고) 추가.

기능 개선

  • 피드 카드, 저장 피드 카드 등에서 단일 이미지에서 다중 이미지 지원으로 변경.
  • 피드 댓글 화면에 다중 이미지 갤러리 및 피드 타입별 아이콘(잠금/저장) 분기 적용, UI 레이아웃 및 패딩 개선.
  • 마이페이지 메뉴 구조 개편 및 "버전 정보", "로그아웃", "회원탈퇴" UI 개선.
  • UI 스타일 및 컬러(Black700, Black800) 추가, 일부 텍스트 및 버튼 스타일 개선.
  • 테마 기반 색상 적용 확대: 아이콘, 텍스트, 배경 등에서 하드코딩된 색상을 테마 색상으로 변경.
  • 피드 작성 화면 상태 관리 통합(FeedData) 및 피드 화면 레이아웃 개선.
  • 피드 화면 컴포저블 구조 재조정 및 클릭 콜백 추가.

버그 수정 및 스타일

  • Material3 컴포넌트 적용 및 색상 일관성 개선.
  • 일부 불필요한 코드 및 import 정리.

문서/리소스

  • 신규 아이콘(ic_doc, ic_version) 및 다수의 문자열 리소스 추가 및 수정.
  • Gradle 의존성 업데이트로 Compose foundation 라이브러리 버전 조정.

JJUYAAA added 17 commits July 28, 2025 14:30
@coderabbitai
Copy link

coderabbitai bot commented Aug 2, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

이 변경사항은 피드, 마이페이지, 구독 목록 등 앱의 주요 UI 컴포넌트와 화면에 대한 대규모 리팩토링 및 QA 피드백 반영을 포함합니다. 단일 이미지에서 다중 이미지 지원, 이미지 뷰어 모달 추가, 구독자 수 표시, 테마 색상 확장, 문자열 리소스 및 아이콘 추가, 상태 관리 단일화 등 다양한 UI 및 데이터 구조 개선이 이루어졌습니다.

Changes

Cohort / File(s) Change Summary
Feed 이미지 및 데이터 구조 리팩토링
app/src/main/java/com/texthip/thip/ui/mypage/mock/FeedItem.kt, app/src/main/java/com/texthip/thip/ui/mypage/viewmodel/SavedFeedViewModel.kt, app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt, app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt, app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt
단일 이미지(imageUrl)에서 다중 이미지(imageUrls)로 데이터 구조 변경 및 관련 UI 컴포넌트 반영, 클릭 가능한 텍스트 및 이미지 행 추가
이미지 뷰어 모달 및 관련 기능 추가
app/src/main/java/com/texthip/thip/ui/feed/component/ImageViewerModal.kt, app/build.gradle.kts, gradle/libs.versions.toml
이미지 뷰어 모달 컴포저블 신설, Accompanist Pager 의존성 제거 및 Compose Foundation 기반으로 전환
피드 코멘트 및 피드 타입 개선
app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt, app/src/main/java/com/texthip/thip/ui/feed/mock/FeedItemType.java
피드 타입(enum) 도입, 코멘트 리스트 외부 전달 방식으로 변경, 이미지 뷰어 연동, 저장/잠금 아이콘 조건부 처리
피드 작성 화면 상태 관리 통합
app/src/main/java/com/texthip/thip/ui/feed/screen/FeedWriteScreen.kt, app/src/main/java/com/texthip/thip/ui/feed/mock/FeedData.kt
여러 개별 상태를 하나의 FeedData 데이터 클래스로 통합하여 상태 관리 일원화
구독/마이구독 리스트 및 헤더 개선
app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt, app/src/main/java/com/texthip/thip/ui/feed/component/MySubscriptionList.kt, app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt, app/src/main/java/com/texthip/thip/ui/feed/screen/SubscriptionListScreen.kt
구독자 수 표시 기능 추가, 버튼/카운트 조건부 렌더링, 구독 리스트 화면 신설, 프리뷰 추가, 문자열 리소스 및 아이콘 추가
마이페이지 UI 및 메뉴 구조 변경
app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt, app/src/main/java/com/texthip/thip/ui/mypage/component/RoleCard.kt, app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageNotificationEditScreen.kt, app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt
스크롤 추가, 메뉴 구조 및 명칭 변경, 버전 및 로그아웃/탈퇴 UI 분리, 색상 및 배경 스타일 개선
기타 UI/리소스/문자열 개선
app/src/main/res/values/strings.xml, app/src/main/res/drawable/ic_doc.xml, app/src/main/res/drawable/ic_version.xml, app/src/main/java/com/texthip/thip/ui/theme/Color.kt, app/src/main/java/com/texthip/thip/ui/signin/screen/LoginScreen.kt, app/src/main/java/com/texthip/thip/ui/signin/screen/SignupGenreScreen.kt, app/src/main/java/com/texthip/thip/ui/feed/component/FeedSubscribelistBar.kt, app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt, app/src/main/java/com/texthip/thip/ui/common/modal/ScrollbarUtil.kt
신규 아이콘 및 문자열 리소스 추가/수정, 테마 색상 확장, 불필요한 import 정리 등
네비게이션 및 기타
app/src/main/java/com/texthip/thip/ui/navigator/navigations/FeedNavigation.kt
피드 네비게이션 파라미터 명시적 전달 및 TODO 주석 추가
테마 색상 및 UI 컬러 일관성 개선
app/src/main/java/com/texthip/thip/ui/common/buttons/ActionBarButton.kt, app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoom.kt, app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt, app/src/main/java/com/texthip/thip/ui/common/cards/CardRoomBook.kt, app/src/main/java/com/texthip/thip/ui/common/header/HeaderMenuBarTab.kt, app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupWheelPicker.kt, app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupEmptyCard.kt, app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupMainCard.kt, app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt
하드코딩된 색상(Color.White 등)을 테마 색상(colors.White 등)으로 변경하여 UI 일관성 유지

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant FeedScreen
    participant MyFeedCard
    participant ImageViewerModal

    User->>FeedScreen: 피드 목록 조회
    FeedScreen->>MyFeedCard: 피드 데이터 전달 (imageUrls 포함)
    User->>MyFeedCard: 이미지 클릭
    MyFeedCard->>FeedScreen: onContentClick or 이미지 클릭 콜백
    FeedScreen->>ImageViewerModal: 이미지 뷰어 모달 표시 (선택 이미지, 전체 리스트 전달)
    User->>ImageViewerModal: 스와이프/닫기 등 조작
    ImageViewerModal->>FeedScreen: onDismiss 콜백
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40분

Assessment against linked issues

Objective Addressed Explanation
피드 컴포넌트 수정, 이미지 자세히 보기 모달 추가 (#61)
피드/내피드 QA, 피드 작성 QA (#61)
마이페이지 QA, 로그인 QA (#61)

Assessment against linked issues: Out-of-scope changes

해당 변경사항에서 요구사항과 무관한 기능적 코드 변경은 발견되지 않았습니다.

Possibly related PRs

Suggested labels

✅ OK merge

Suggested reviewers

  • rbqks529

Poem

🐰
피드에 사진이 쏟아지고
모달이 열려, 이미지를 크게 보고
구독자 수와 버튼이 반짝이는 밤
마이페이지도 새 옷을 입고
QA 토끼가 깡총깡총 춤을 추네!

(띱과 함께, 버그도 안녕!)

Note

🔌 MCP (Model Context Protocol) integration is now available in Early Access!

Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context.


📜 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 c4edd46 and a3dfdf1.

📒 Files selected for processing (3)
  • app/build.gradle.kts (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt (10 hunks)
  • gradle/libs.versions.toml (2 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.
  • 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.

Support

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

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 generate unit tests to generate unit tests for 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: 5

🔭 Outside diff range comments (1)
app/src/main/java/com/texthip/thip/ui/feed/component/FeedSubscribelistBar.kt (1)

67-67: 하드코딩된 문자열을 strings.xml로 추출해야 합니다.

"이 띱 하는중" 텍스트가 하드코딩되어 있습니다. 유지보수성과 현지화를 위해 string resource로 추출하는 것이 좋습니다.

다음과 같이 수정하세요:

-                    append("이 띱 하는중")
+                    append(stringResource(R.string.thip_in_progress))

strings.xml에 다음을 추가하세요:

<string name="thip_in_progress">이 띱 하는중</string>
🧹 Nitpick comments (10)
app/src/main/java/com/texthip/thip/ui/mypage/mock/FeedItem.kt (1)

18-18: 기본값 일관성 개선 제안

imageUrls 속성이 nullable List이지만 기본값으로 빈 리스트를 사용하고 있습니다. null을 허용하는 타입이라면 기본값도 null로 하거나, 빈 리스트를 사용한다면 non-null 타입 List<Int>로 변경하는 것이 더 일관성 있습니다.

옵션 1: Non-null 타입으로 변경 (권장)

-    val imageUrls: List<Int>? = emptyList()
+    val imageUrls: List<Int> = emptyList()

옵션 2: null 기본값 사용

-    val imageUrls: List<Int>? = emptyList()
+    val imageUrls: List<Int>? = null
app/src/main/java/com/texthip/thip/ui/feed/mock/FeedData.kt (1)

16-21: 유효성 검증 로직 개선 제안

isReadyToSubmit 검증 로직이 합리적이지만, 일부 추가 검증을 고려해볼 수 있습니다:

 val isReadyToSubmit: Boolean
     get() = selectedBook != null &&
             feedContent.isNotBlank() &&
+            feedContent.length <= MAX_CONTENT_LENGTH &&
             selectedGenreIndex != -1 &&
             selectedSubGenres.isNotEmpty()
+            // && imageUris.isNotEmpty() // 이미지가 필수인 경우

콘텐츠 길이 제한이나 이미지 필수 여부 등의 비즈니스 규칙도 고려해보세요.

app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt (1)

33-46: 하드코딩된 문자열 리소스 추출 권장

모킹 데이터에 하드코딩된 한국어 문자열들이 있습니다. 유지보수성과 다국어 지원을 위해 strings.xml로 추출하는 것을 권장합니다.

예시:

-ReactionItem("@user 1님의 피드 글","어쩌구 저쩌구 콘텐츠 내용입니다...","좋아요", "2"),
+ReactionItem(stringResource(R.string.mock_user_feed), stringResource(R.string.mock_content), stringResource(R.string.likes), "2"),
app/src/main/java/com/texthip/thip/ui/feed/mock/FeedItemType.java (2)

3-5: Java 대신 Kotlin 사용을 고려하세요.

프로젝트가 Kotlin 기반으로 보이는데 새로운 enum을 Java로 작성한 이유가 있는지 확인해보세요. 일관성을 위해 Kotlin으로 작성하는 것이 좋겠습니다.

Kotlin으로 변환하려면:

-public enum FeedItemType {
-    LOCKED, SAVABLE
-}
+enum class FeedItemType {
+    LOCKED, SAVABLE
+}

4-4: enum 상수에 대한 문서 추가를 고려하세요.

LOCKEDSAVABLE의 정확한 의미와 사용 용도에 대한 문서를 추가하면 코드 가독성이 향상됩니다.

app/src/main/java/com/texthip/thip/ui/navigator/navigations/FeedNavigation.kt (1)

15-20: 하드코딩된 값들의 임시성을 명시하세요.

현재 하드코딩된 값들("ThipUser01", "문학가" 등)이 임시값임을 주석으로 더 명확하게 표시하면 좋겠습니다.

예시:

 FeedScreen(
     navController = navController,
-    nickname = "ThipUser01",
-    userRole = "문학가",
+    nickname = "ThipUser01", // 임시값 - ViewModel에서 가져올 예정
+    userRole = "문학가", // 임시값 - ViewModel에서 가져올 예정
app/src/main/java/com/texthip/thip/ui/feed/screen/FeedWriteScreen.kt (1)

294-296: 코드 스타일 일관성을 유지하세요.

띄어쓰기가 일관되지 않습니다.

-                                    feedData = feedData.copy(
-                                        selectedSubGenres =feedData.selectedSubGenres - subGenre
-                                    )
+                                    feedData = feedData.copy(
+                                        selectedSubGenres = feedData.selectedSubGenres - subGenre
+                                    )
app/src/main/java/com/texthip/thip/ui/feed/screen/SubscriptionListScreen.kt (2)

36-124: 목 데이터가 다양한 테스트 케이스를 잘 커버합니다.

다양한 구독자 수와 역할을 포함하여 실제 시나리오를 잘 시뮬레이션합니다. 향후 데이터가 더 커지면 별도 파일로 분리하는 것을 고려해보세요.


36-122: 샘플 데이터가 하드코딩되어 있습니다.

현재 initialmembers 리스트가 함수 내부에 하드코딩되어 있습니다. 유지보수성을 위해 별도 상수나 함수로 분리하는 것을 고려해보세요.

다음과 같이 리팩토링할 수 있습니다:

+private fun getInitialMembers() = listOf(
+    MySubscriptionData(
+        profileImageUrl = null,
+        nickname = "Thiper",
+        role = "칭호칭호",
+        roleColor = ThipTheme.colors.Yellow,
+        subscriberCount = 100
+    ),
+    // ... 나머지 데이터
+)

 @Composable
 fun SubscriptionScreen(
     navController: NavController? = null,
     titleText: String = stringResource(R.string.thip_list)
 ) {
-    val initialmembers = listOf(
-        MySubscriptionData(
-            // ... 하드코딩된 데이터
-        )
-    )
+    val initialmembers = getInitialMembers()
app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt (1)

177-179: TODO 주석이 있습니다.

계정 삭제 로직이 아직 구현되지 않았습니다. 향후 구현이 필요한 부분입니다.

계정 삭제 기능 구현을 도와드릴까요? 확인 다이얼로그와 API 호출 로직을 포함한 구현을 제안할 수 있습니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6290b07 and 50e47d9.

📒 Files selected for processing (31)
  • app/build.gradle.kts (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt (4 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/modal/ScrollbarUtil.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/component/FeedSubscribelistBar.kt (2 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/component/ImageViewerModal.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt (4 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt (2 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/component/MySubscriptionList.kt (5 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/mock/FeedData.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/mock/FeedItemType.java (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt (10 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt (3 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/screen/FeedWriteScreen.kt (11 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt (3 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/screen/SubscriptionListScreen.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/mypage/component/MypageSaveFeed.kt (0 hunks)
  • app/src/main/java/com/texthip/thip/ui/mypage/component/RoleCard.kt (2 hunks)
  • app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt (5 hunks)
  • app/src/main/java/com/texthip/thip/ui/mypage/mock/FeedItem.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageNotificationEditScreen.kt (2 hunks)
  • app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt (3 hunks)
  • app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt (10 hunks)
  • app/src/main/java/com/texthip/thip/ui/mypage/viewmodel/SavedFeedViewModel.kt (3 hunks)
  • app/src/main/java/com/texthip/thip/ui/navigator/navigations/FeedNavigation.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/signin/screen/LoginScreen.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/signin/screen/SignupGenreScreen.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/theme/Color.kt (3 hunks)
  • app/src/main/res/drawable/ic_doc.xml (1 hunks)
  • app/src/main/res/drawable/ic_version.xml (1 hunks)
  • app/src/main/res/values/strings.xml (3 hunks)
  • gradle/libs.versions.toml (2 hunks)
💤 Files with no reviewable changes (1)
  • app/src/main/java/com/texthip/thip/ui/mypage/component/MypageSaveFeed.kt
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: the user rbqks529 prefers to extract hardcoded ui strings to stringresource files (strings.xml) rath...
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.

Applied to files:

  • app/src/main/java/com/texthip/thip/ui/signin/screen/LoginScreen.kt
  • app/src/main/java/com/texthip/thip/ui/common/modal/ScrollbarUtil.kt
  • app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageNotificationEditScreen.kt
  • app/src/main/java/com/texthip/thip/ui/feed/component/FeedSubscribelistBar.kt
  • app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt
  • app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt
  • app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt
  • app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt
  • app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt
  • app/src/main/java/com/texthip/thip/ui/feed/screen/FeedWriteScreen.kt
  • app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt
  • app/src/main/java/com/texthip/thip/ui/signin/screen/SignupGenreScreen.kt
  • app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt
  • app/src/main/java/com/texthip/thip/ui/mypage/viewmodel/SavedFeedViewModel.kt
  • app/src/main/res/values/strings.xml
📚 Learning: grouppagescreen의 mypageviewmodel은 임시 viewmodel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다....
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/myPage/groupPage/GroupPageScreen.kt:34-37
Timestamp: 2025-07-01T07:19:01.239Z
Learning: GroupPageScreen의 MyPageViewModel은 임시 ViewModel로, 현재는 프로토타입 단계이므로 오류 처리 등의 추가 기능은 나중에 구현 예정입니다.

Applied to files:

  • app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt
🧬 Code Graph Analysis (6)
app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageNotificationEditScreen.kt (1)
app/src/main/java/com/texthip/thip/ui/common/topappbar/DefaultTopAppBar.kt (1)
  • DefaultTopAppBar (22-65)
app/src/main/java/com/texthip/thip/ui/navigator/navigations/FeedNavigation.kt (1)
app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt (1)
  • FeedScreen (42-251)
app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt (1)
app/src/main/java/com/texthip/thip/ui/common/buttons/ActionBookButton.kt (1)
  • ActionBookButton (27-71)
app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt (1)
app/src/main/java/com/texthip/thip/ui/theme/Theme.kt (1)
  • ThipTheme (41-69)
app/src/main/java/com/texthip/thip/ui/feed/component/ImageViewerModal.kt (1)
app/src/main/java/com/texthip/thip/ui/theme/Theme.kt (1)
  • ThipTheme (41-69)
app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt (1)
app/src/main/java/com/texthip/thip/ui/theme/Theme.kt (1)
  • ThipTheme (41-69)
🔇 Additional comments (68)
app/src/main/java/com/texthip/thip/ui/feed/mock/FeedData.kt (1)

14-14: 데이터 클래스 내 SnapshotStateList 생성은 컴포저블 내부에서 관리됩니다

FeedWriteScreen 컴포저블의 remember { mutableStateOf(FeedData()) } 블록에서 FeedData()가 초기화되므로, mutableStateListOf() 호출도 컴포저블 레이어에서 한 번만 실행됩니다. 해당 구현은 Compose 상태 관리 관점에서 문제가 없으므로 별도 변경이 필요하지 않습니다.

Likely an incorrect or invalid review comment.

app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageReactionScreen.kt (2)

74-74: 필터 버튼 상태 로직 확인 필요

OptionChipButton이 이제 항상 isFilled = true로 설정되어 있어 선택 상태를 시각적으로 구분할 수 없습니다. 사용자가 어떤 필터가 활성화되었는지 알기 어려울 수 있습니다.

의도된 디자인 변경인지 확인해주세요. 만약 선택 상태를 표시해야 한다면:

 OptionChipButton(
     text = stringResource(R.string.likes),
-    isFilled = true,
+    isFilled = isLikesSelected,
     onClick = {isLikesSelected = !isLikesSelected}
 )

Also applies to: 80-80


91-105: LazyColumn 아이템 처리 개선 완료

itemsIndexed 사용과 마지막 아이템에 대한 조건부 패딩 적용이 잘 구현되었습니다. 이는 더 나은 사용자 경험을 제공합니다.

app/src/main/java/com/texthip/thip/ui/common/modal/ScrollbarUtil.kt (2)

4-4: 사용되지 않는 import 확인이 필요합니다.

@Composable import가 추가되었지만 현재 파일에서 사용되지 않고 있습니다. 향후 컴포저블 함수 추가를 위한 준비라면 TODO 주석을 추가하는 것이 좋겠습니다.


11-11: 사용되지 않는 import 확인이 필요합니다.

@Preview import도 현재 사용되지 않고 있습니다. 미래 사용을 위해서라면 주석으로 명시해주세요.

app/src/main/java/com/texthip/thip/ui/mypage/viewmodel/SavedFeedViewModel.kt (3)

39-39: LGTM!

단일 이미지에서 다중 이미지 지원으로의 전환이 올바르게 적용되었습니다.


54-54: LGTM!

imageUrls 리스트를 사용한 다중 이미지 지원이 적절하게 구현되었습니다.


69-69: LGTم!

일관된 다중 이미지 데이터 구조 적용이 확인됩니다.

app/src/main/java/com/texthip/thip/ui/navigator/navigations/FeedNavigation.kt (1)

12-21: LGTM!

FeedScreen의 새로운 파라미터 구조에 맞게 잘 업데이트되었습니다. TODO 주석도 적절하게 추가되어 향후 ViewModel 적용 계획이 명확합니다.

app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt (3)

195-195: LGTM!

onContentClick 콜백 추가로 피드 상세 화면으로의 네비게이션 준비가 잘 되어있습니다.


233-234: LGTM!

SavedFeedCard에도 onContentClick 콜백이 일관되게 추가되었습니다.


257-274: LGTM!

새로운 imageUrls 구조를 사용한 목 데이터 생성이 적절하게 구현되었습니다.

app/src/main/java/com/texthip/thip/ui/feed/component/MyFeedCard.kt (1)

35-79: 다중 이미지 지원 구현이 잘 되었습니다!

이미지가 있을 때와 없을 때의 조건부 렌더링이 깔끔하게 구현되었고, 최대 3개 이미지 제한도 적절합니다.

app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt (1)

206-228: 피드 타입별 아이콘 처리가 깔끔하게 구현되었습니다!

FeedItemType enum을 사용한 조건부 렌더링이 명확하고 확장 가능한 구조입니다.

app/src/main/java/com/texthip/thip/ui/theme/Color.kt (3)

46-47: 새로운 어두운 색상 상수 추가 승인

Black700Black800 색상이 적절히 정의되었습니다. 기존 색상 네이밍 규칙과 일관되며, UI 컴포넌트에서 더 세밀한 색상 구분이 가능해집니다.


87-88: ThipColors 데이터 클래스 업데이트 승인

새로운 색상 속성들이 데이터 클래스에 올바르게 추가되었습니다.


125-127: 색상 초기화 업데이트 승인

새로운 색상들이 defaultThipColors에서 올바르게 초기화되었습니다.

app/src/main/res/drawable/ic_version.xml (1)

1-15: 버전 아이콘 벡터 드로어블 추가 승인

새로운 ic_version 아이콘이 적절히 정의되었습니다. 24dp 크기로 일관된 아이콘 표준을 따르며, 흰색 색상으로 앱의 다크 테마와 잘 어울립니다.

app/src/main/java/com/texthip/thip/ui/mypage/component/RoleCard.kt (2)

54-65: 배경 스타일링 로직 단순화 승인

복잡한 그라데이션 브러시를 새로운 Black700/Black800 단색으로 교체한 것은 좋은 개선입니다. 코드가 더 간결해지고 유지보수하기 쉬워졌습니다.


59-59: 조건부 장르 색상 로직 개선 승인

actualGenreColor 변수를 도입하여 선택 상태에 따라 장르 텍스트 색상을 동적으로 설정하는 것은 사용자 경험을 향상시키는 좋은 개선입니다.

Also applies to: 91-91

app/src/main/java/com/texthip/thip/ui/signin/screen/SignupGenreScreen.kt (1)

1-31: 사용하지 않는 import 정리 승인

사용하지 않는 import들이 적절히 제거되고 import 순서가 재정렬되었습니다. 코드베이스 전반의 개선 사항과 일치하는 좋은 정리 작업입니다.

app/src/main/java/com/texthip/thip/ui/signin/screen/LoginScreen.kt (1)

51-51: 문자열 리소스 업데이트 승인

로그인 화면의 제목에 사용되는 문자열 리소스가 splash_thip으로 변경되어 앱 전체의 문자열 표준화에 기여하고 있습니다.

app/src/main/java/com/texthip/thip/ui/feed/component/FeedSubscribelistBar.kt (2)

14-15: Material3 마이그레이션이 적절히 수행되었습니다.

Icon과 Text 컴포넌트를 androidx.compose.material에서 androidx.compose.material3로 변경한 것이 올바릅니다.


50-50: 테마 색상 적용이 일관성 있게 처리되었습니다.

Icon의 tint를 Color.Unspecified에서 colors.White로 변경하여 테마 색상을 일관성 있게 적용했습니다.

app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt (2)

15-16: Material3 마이그레이션이 일관성 있게 적용되었습니다.

Icon과 Text 컴포넌트의 import를 material3로 변경한 것이 다른 컴포넌트들과 일관성을 유지합니다.


65-65: 테마 색상 통일성이 잘 유지되었습니다.

Icon tint를 colors.White로 변경하여 FeedSubscribelistBar와 동일한 스타일을 적용했습니다.

app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageNotificationEditScreen.kt (2)

28-28: DefaultTopAppBar로 표준화가 적절히 수행되었습니다.

InputTopAppBar에서 DefaultTopAppBar로 변경하여 다른 화면들과 일관성을 유지합니다.


69-72: 빈 onLeftClick 콜백을 확인해주세요.

onLeftClick이 빈 함수로 구현되어 있어 뒤로가기 동작이 작동하지 않을 수 있습니다. 적절한 네비게이션 로직이 필요한지 확인해보세요.

다음과 같이 수정하는 것을 고려해보세요:

            DefaultTopAppBar(
                title = stringResource(R.string.notification_settings),
-                onLeftClick = {},
+                onLeftClick = { /* TODO: Add navigation logic */ },
            )
app/src/main/res/drawable/ic_doc.xml (1)

1-42: 벡터 드로어블이 올바르게 구현되었습니다.

문서 아이콘이 표준 벡터 드로어블 형식으로 잘 정의되어 있으며, 일관된 스트로크 색상(#FEFEFE)과 두께(1.5)를 사용합니다.

app/src/main/java/com/texthip/thip/ui/feed/screen/MySubscriptionListScreen.kt (3)

12-12: Material3 마이그레이션이 일관성 있게 적용되었습니다.

Text 컴포넌트 import를 material3로 변경하여 다른 파일들과 통일성을 유지합니다.


40-43: 유연한 타이틀 매개변수 추가가 잘 구현되었습니다.

titleText 매개변수를 추가하여 화면 제목을 커스터마이징할 수 있게 하면서도, 기본값을 통해 하위 호환성을 유지했습니다.


164-164: 동적 타이틀 적용이 적절합니다.

DefaultTopAppBar에서 titleText 매개변수를 사용하여 유연한 타이틀 설정을 구현했습니다.

app/src/main/java/com/texthip/thip/ui/common/header/AuthorHeader.kt (6)

14-14: 새로운 파라미터와 임포트가 적절히 추가되었습니다.

showThipNumthipNum 파라미터가 적절한 기본값과 함께 추가되었고, 필요한 임포트 문들이 정확히 포함되었습니다.

Also applies to: 20-21, 26-26, 41-42


100-112: 구독자 수 표시 기능이 잘 구현되었습니다.

조건부 렌더링 로직과 문자열 리소스 사용이 적절하며, 기존 디자인 시스템과 일관성을 유지하고 있습니다.


132-135: 프리뷰가 두 가지 모드를 효과적으로 보여줍니다.

버튼 표시 모드와 구독자 수 표시 모드를 모두 보여주는 프리뷰가 잘 구성되었습니다.


41-42: 새로운 파라미터 추가가 적절합니다.

showThipNumthipNum 파라미터를 통해 구독자 수 표시 기능을 선택적으로 활성화할 수 있도록 구현했습니다. 기본값 설정도 적절합니다.


100-112: 구독자 수 표시 로직이 올바르게 구현되었습니다.

조건부 렌더링과 null 체크가 적절히 구현되어 있으며, 문자열 리소스 사용도 좋은 관례를 따르고 있습니다. 스페이싱과 아이콘 배치도 일관성 있게 구성되어 있습니다.


132-135: 프리뷰에서 새로운 기능을 잘 보여주고 있습니다.

버튼 숨김과 구독자 수 표시 기능을 프리뷰에서 시연하여 디자인 타임에 UI를 확인할 수 있도록 했습니다.

app/src/main/java/com/texthip/thip/ui/feed/component/MySubscriptionList.kt (8)

5-5: 새로운 파라미터와 임포트가 적절히 추가되었습니다.

isMine 파라미터의 기본값이 true로 설정되어 기존 호출 코드와의 호환성을 유지하고 있습니다.

Also applies to: 7-7, 23-23


40-42: 조건부 UI 표시 로직이 직관적으로 구현되었습니다.

사용자 본인의 목록일 때는 버튼을, 다른 사용자의 목록일 때는 구독자 수를 표시하는 로직이 UX 관점에서 적절합니다.


53-55: 레이아웃 개선이 적절합니다.

마지막 아이템 뒤에 구분선 대신 여백을 추가하여 더 나은 시각적 계층구조를 제공합니다.


98-135: 새로운 프리뷰가 추가된 기능을 잘 보여줍니다.

isMine=false 모드를 보여주는 프리뷰가 컴포넌트의 다양한 사용 사례를 효과적으로 검증할 수 있게 합니다.


23-23: isMine 파라미터 추가가 적절합니다.

UI 표시 모드를 제어하는 Boolean 파라미터로 컴포넌트의 재사용성을 높였습니다. 기본값을 true로 설정한 것도 기존 동작을 유지하는 좋은 선택입니다.


40-42: 조건부 UI 로직이 올바르게 구현되었습니다.

isMine 값에 따라 버튼 표시와 구독자 수 표시를 적절히 전환하도록 AuthorHeader의 새로운 파라미터들을 활용했습니다.


53-55: 마지막 아이템 처리 개선이 좋습니다.

마지막 아이템에서 구분선 대신 고정 높이 스페이서를 사용하여 하단 패딩을 제공하는 것이 더 적절한 UI 구성입니다.


98-134: 새로운 프리뷰가 유용합니다.

isMine = false 시나리오를 보여주는 프리뷰를 추가하여 두 가지 UI 모드를 모두 확인할 수 있도록 했습니다.

app/src/main/java/com/texthip/thip/ui/feed/screen/SubscriptionListScreen.kt (5)

1-34: 스크린 구조와 함수 시그니처가 잘 설계되었습니다.

패키지 구조가 적절하고, 문자열 리소스 사용과 선택적 NavController 파라미터가 유연성을 제공합니다.


126-168: UI 레이아웃 구조가 적절합니다.

LazyColumn 사용으로 성능을 고려했고, 헤더-카운트-구분선-콘텐츠 순서의 계층구조가 논리적입니다.


171-177: 프리뷰가 적절히 구성되었습니다.

ThipTheme으로 감싸서 정확한 디자인 타임 렌더링을 보장합니다.


161-161: MySubscriptionList 통합이 적절합니다.

isMine = false로 설정하여 구독자 수를 표시하는 모드로 올바르게 사용하고 있습니다.


131-167: 화면 구조가 일관성 있게 구성되었습니다.

TopAppBar, 전체 개수 텍스트, 구분선, LazyColumn으로 이어지는 레이아웃 구조가 표준적이고 적절합니다.

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

69-69: 마이페이지 관련 문자열 리소스가 적절히 추가되었습니다.

"기타"로 변경된 용어가 더 적절하고, 새로운 메뉴 항목들의 한국어 번역이 자연스럽습니다.

Also applies to: 76-77


288-289: 피드 관련 문자열 리소스가 일관된 브랜딩으로 잘 정리되었습니다.

"띱" 브랜딩이 일관되게 사용되고, 구독자 수 표시를 위한 포맷 문자열이 적절히 구성되었습니다.

Also applies to: 295-295, 309-309


69-69: 새로운 문자열 리소스가 적절히 추가되었습니다.

"기타" 문자열이 MyPage 화면의 메뉴 섹션명 변경에 맞게 추가되었습니다.


76-77: 버전 및 약관 관련 문자열이 추가되었습니다.

"버전 1.0"과 "이용약관" 문자열이 MyPage 메뉴 아이템에 맞게 적절히 추가되었습니다.


288-295: 피드 관련 문자열들이 업데이트되었습니다.

"내 띱 목록", "띱 목록", "띱 하는 중" 등의 문자열이 새로운 UI 용어에 맞게 추가/수정되었습니다. 특히 thip_num의 포맷 문자열("%d명이 띱 하는 중")이 구독자 수 표시 기능과 잘 연계됩니다.


309-309: 기존 문자열 용어가 일관성 있게 변경되었습니다.

"내 구독"에서 "내 띱"으로 용어를 통일하여 앱 전체의 일관성을 높였습니다.

app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt (11)

4-5: 스크롤 기능 추가를 위한 임포트와 상태 관리가 적절합니다.

필요한 임포트들이 정확히 추가되었고, rememberScrollState()를 사용한 스크롤 상태 관리가 Compose 패턴을 잘 따르고 있습니다.

Also applies to: 13-14, 21-21, 34-34, 45-45


51-51: 스크롤 기능과 간격 조정이 적절합니다.

전체 Column에 스크롤을 적용하고, 상단 여백을 줄여서 화면 공간을 효율적으로 활용했습니다.

Also applies to: 62-62


101-101: 메뉴 섹션 재구성이 논리적으로 잘 정리되었습니다.

고객 서비스 관련 항목들을 그룹화하고, 버전 정보를 비상호작용적으로 만든 것이 적절합니다. 아이콘 변경도 새로운 의미에 맞게 잘 적용되었습니다.

Also applies to: 119-156


158-181: 하단 섹션 구현이 UX 모범 사례를 잘 따르고 있습니다.

민감한 작업(로그아웃, 계정 삭제)을 하단에 배치하고, 일관된 스타일링과 적절한 간격으로 구현했습니다. 계정 삭제 기능의 TODO는 점진적 개발 방식으로 적절합니다.


205-211: 프리뷰가 ThipTheme으로 적절히 감싸져 있습니다.

정확한 디자인 타임 렌더링을 위해 테마가 적용되었고, 적절한 샘플 데이터가 사용되었습니다.


45-51: 전체 화면 스크롤 기능이 적절히 추가되었습니다.

rememberScrollState()verticalScroll()을 사용하여 콘텐츠가 많을 때 스크롤할 수 있도록 개선했습니다. 사용자 경험 향상에 도움이 됩니다.


62-62: 상단 스페이싱 조정이 적절합니다.

40.dp에서 20.dp로 줄여 더 효율적인 공간 활용을 했습니다.


101-101: 메뉴 섹션명 변경이 적절합니다.

"메뉴"에서 "기타"로 변경하여 더 명확한 의미를 전달합니다.


119-156: 메뉴 아이템들이 논리적으로 재구성되었습니다.

고객센터, 이용약관, 가이드, 버전 정보 순서로 재배치하고 각각에 적절한 아이콘을 배정했습니다. 버전 정보가 클릭할 수 없는 정보성 아이템으로 배치된 것도 적절합니다.


160-181: 하단 액션 영역이 잘 구성되었습니다.

로그아웃과 계정 삭제를 하단에 별도 영역으로 배치하여 일반적인 UI 패턴을 따랐습니다. 클릭 가능한 텍스트로 구성하고 회색 색상을 사용한 것도 적절합니다.


205-211: 프리뷰가 테마로 적절히 래핑되었습니다.

ThipTheme으로 프리뷰를 감싸서 일관된 테마 적용을 보장합니다.

implementation(libs.accompanist.pager)
implementation(libs.accompanist.pager.indicators)
implementation(libs.coil.compose)
implementation(libs.foundation)
Copy link

@coderabbitai coderabbitai bot Aug 2, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

의존성 관리 개선 필요

Foundation 라이브러리가 중복으로 추가되어 있고 서로 다른 버전을 사용하고 있습니다:

  • libs.foundation (라인 61): 1.9.0-rc01 버전
  • 직접 구현 (라인 69): 1.5.0 버전

이는 클래스패스 충돌과 예측할 수 없는 동작을 야기할 수 있습니다.

다음과 같이 하나의 버전으로 통합하세요:

     implementation(libs.foundation)
-    implementation("androidx.compose.foundation:foundation:1.5.0")

또는 더 최신 버전이 필요하다면 libs.versions.toml에서 버전을 업데이트하고 버전 카탈로그만 사용하세요.

Also applies to: 69-69

🤖 Prompt for AI Agents
In app/build.gradle.kts at lines 61 and 69, the Foundation library is included
twice with different versions (1.9.0-rc01 and 1.5.0), causing potential
conflicts. Remove the direct implementation at line 69 and keep only the version
managed via libs.foundation at line 61. If a newer version is needed, update the
version in libs.versions.toml and use only the version catalog reference to
ensure consistent dependency management.

Copy link
Collaborator

Choose a reason for hiding this comment

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

그러게요 이거는 아래 implementation은 빼면 될듯요?

Copy link

Choose a reason for hiding this comment

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

@rbqks529 맞습니다! 아래쪽의 직접 구현된 dependency를 제거하는 것이 정확한 해결책입니다.

// 이 라인을 제거하세요
implementation("androidx.compose.foundation:foundation:1.5.0")

libs.foundation (1.9.0-rc01)만 남겨두면 더 최신 버전을 사용하면서 버전 카탈로그를 통한 일관된 의존성 관리가 가능합니다. 중복 제거로 빌드 시간도 단축되고 잠재적인 충돌도 방지할 수 있어요.


🧠 Learnings used
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.

Comment on lines +50 to +52
Icon(
painter = painterResource(R.drawable.ic_x),
contentDescription = "닫기",
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

하드코딩된 문자열을 리소스 파일로 추출하세요.

접근성을 위한 contentDescription에 하드코딩된 한국어 문자열이 있습니다. 다국어 지원과 유지보수를 위해 string resource로 추출해야 합니다.

         Icon(
             painter = painterResource(R.drawable.ic_x),
-            contentDescription = "닫기",
+            contentDescription = stringResource(R.string.close),
             tint = Color.White,
📝 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_x),
contentDescription = "닫기",
Icon(
painter = painterResource(R.drawable.ic_x),
contentDescription = stringResource(R.string.close),
tint = Color.White,
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/feed/component/ImageViewerModal.kt
around lines 50 to 52, the contentDescription for the Icon uses a hardcoded
Korean string. To support localization and maintainability, move this string
into the strings resource file and reference it via stringResource or equivalent
method in the code.

Comment on lines +283 to +292
ThipTheme {
FeedScreen(
nickname = "ThipUser01",
userRole = "문학 칭호",
selectedTabIndex = 0,
feeds = mockFeeds,
totalFeedCount = mockFeeds.size,
followerProfileImageUrls = mockFollowerImages
)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

중첩된 ThipTheme 제거가 필요합니다.

미리보기에서 ThipTheme이 중복으로 적용되고 있습니다. 이는 테마가 두 번 적용되어 의도치 않은 결과를 가져올 수 있습니다.

다음과 같이 수정하세요:

 @Preview(showBackground = true)
 @Composable
 private fun FeedScreenPreview() {
     ThipTheme {
         val mockFeeds = List(5) {
             // ... mock data ...
         }
         val mockFollowerImages = listOf(
             // ... mock follower images ...
         )
-
-        ThipTheme {
-            FeedScreen(
-                nickname = "ThipUser01",
-                userRole = "문학 칭호", 
-                selectedTabIndex = 0,
-                feeds = mockFeeds,
-                totalFeedCount = mockFeeds.size,
-                followerProfileImageUrls = mockFollowerImages
-            )
-        }
+        FeedScreen(
+            nickname = "ThipUser01",  
+            userRole = "문학 칭호",
+            selectedTabIndex = 0,
+            feeds = mockFeeds,
+            totalFeedCount = mockFeeds.size,
+            followerProfileImageUrls = mockFollowerImages
+        )
     }
 }
📝 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
ThipTheme {
FeedScreen(
nickname = "ThipUser01",
userRole = "문학 칭호",
selectedTabIndex = 0,
feeds = mockFeeds,
totalFeedCount = mockFeeds.size,
followerProfileImageUrls = mockFollowerImages
)
}
@Preview(showBackground = true)
@Composable
private fun FeedScreenPreview() {
ThipTheme {
val mockFeeds = List(5) {
// ... mock data ...
}
val mockFollowerImages = listOf(
// ... mock follower images ...
)
FeedScreen(
nickname = "ThipUser01",
userRole = "문학 칭호",
selectedTabIndex = 0,
feeds = mockFeeds,
totalFeedCount = mockFeeds.size,
followerProfileImageUrls = mockFollowerImages
)
}
}
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt around lines
283 to 292, the ThipTheme composable is nested redundantly, causing the theme to
be applied twice. Remove the outer or inner ThipTheme wrapper so that the theme
is applied only once to avoid unintended styling issues.

Comment on lines +42 to +44
val images = feedItem.imageUrls.orEmpty().map { painterResource(id = it) }
val imagePainters = feedItem.imageUrls.orEmpty().map { painterResource(it) }
val hasImages = imagePainters.isNotEmpty()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

중복된 변수 선언을 제거하세요.

imagesimagePainters가 동일한 값을 가지고 있습니다. 하나의 변수만 사용하도록 수정이 필요합니다.

-    val images = feedItem.imageUrls.orEmpty().map { painterResource(id = it) }
-    val imagePainters = feedItem.imageUrls.orEmpty().map { painterResource(it) }
-    val hasImages = imagePainters.isNotEmpty()
+    val images = feedItem.imageUrls.orEmpty().map { painterResource(id = it) }
+    val hasImages = images.isNotEmpty()
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/mypage/component/SavedFeedCard.kt
around lines 42 to 44, the variables images and imagePainters are both assigned
the same mapped list of painterResource from feedItem.imageUrls. Remove one of
these duplicate variables and update the code to use only the remaining variable
for image handling to eliminate redundancy.

accompanistPagerIndicators = "0.36.0"
coilCompose = "2.7.0"
kotlinxSerializationJson = "1.9.0"
foundationVersion = "1.9.0-rc01"
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

중복된 Foundation 라이브러리 의존성 정리 필요

현재 두 개의 서로 다른 Foundation 라이브러리 버전이 정의되어 있습니다:

  • androidx-foundation: 1.9.0-beta01 (라인 37)
  • foundation: 1.9.0-rc01 (라인 44)

이는 의존성 충돌이나 혼란을 야기할 수 있습니다.

하나의 버전으로 통합하는 것을 권장합니다:

 [versions]
-foundationVersion = "1.9.0-rc01"
+foundation = "1.9.0-rc01"

 [libraries]
-androidx-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "foundation" }
-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "foundationVersion" }
+androidx-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "foundation" }

Also applies to: 44-44

🤖 Prompt for AI Agents
In gradle/libs.versions.toml at lines 19 and 44, there are two different
versions defined for the Foundation library: 1.9.0-rc01 and 1.9.0-beta01, which
can cause dependency conflicts. To fix this, choose a single consistent version
for the Foundation library and update both entries to use that same version,
removing any duplicate or conflicting definitions.

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.

코드 확인헀고 궁금한점 답변 달아주시면 감사하겠습니다!

implementation(libs.accompanist.pager)
implementation(libs.accompanist.pager.indicators)
implementation(libs.coil.compose)
implementation(libs.foundation)
Copy link
Collaborator

Choose a reason for hiding this comment

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

그러게요 이거는 아래 implementation은 빼면 될듯요?


@Composable
fun ImageViewerModal(
images: List<Painter>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

이거 혹시 Painter를 받아오게 되어있는데 이미지 자세히 보기 화면인가요? 또 Painter로 하신 이유가 있을까요?

Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Black)
Copy link
Collaborator

Choose a reason for hiding this comment

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

해당 화면에서 Color를 사용하는데 저희 ThipColor가 아니라 Compose Color를 사용하는거 같은데 상관없으면 괜찮은데 의도하지 않았다면 수정이 필요할거 같네요

authName = "한강",
timeAgo = "3시간 전",
content = "한줄만 입력 가능",
content = "세 줄만 보여줄거임!!세 줄만 보여줄거임!!세 줄만 보여줄거임!!세 줄만 보여줄거임!!세 줄만 보여줄거임!!세 줄만 보여줄거임!!세 줄만 보여줄거임!!세 줄만 보여줄거임!!세 줄만 보여줄거임!!세 줄만 보여줄거임!!세 줄만 보여줄거임!!",
Copy link
Collaborator

Choose a reason for hiding this comment

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

강력한 의지...

onSendClick: () -> Unit = {}
) {
onSendClick: () -> Unit = {},
commentList: SnapshotStateList<FeedCommentItem> = remember { mutableStateListOf() },
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
Member Author

Choose a reason for hiding this comment

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

엇 지금 리뷰해주신 FeedCommentItem이 댓글 데이터 클래스 입니다!
파라미터 상태 선언은 가능은 한데, 권장되지는 않는다고 하네요 수정할게요!

Copy link
Collaborator

Choose a reason for hiding this comment

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

요것도 나중에 api 연결할거 생각해서 데이터 클래스로 만들면 좋을 듯 싶네용

Copy link
Member

@Nico1eKim Nico1eKim left a comment

Choose a reason for hiding this comment

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

수고하셨습니다! 화면에서 수정사항이 보이네용

  1. 피드 댓글에서 케밥버튼 눌렀을 때 배경 흐려지는거 적용이 안됩니다!
  2. 피드 댓글 꾹 눌렀을 때 본인 댓글이면 삭제, 남의 댓글이면 신고 구현해야합니두
  3. 마이페이지에서 스크롤할 때 헤더는 고정 -> 피그마에 써있는 설명 참고해주세여
  4. 홈/피드페이지 top app bar 디자인이 좀 다른거같은데 확인부탁해여! 스크롤 했을 때 하단부에 여백이 없어보이네요
  5. 홈/피드 페이지 스크롤 범위도 수정하면 좋을거같아요 ~

// 이미지 카운터 (예: 1/3)
if (images.size > 1) {
Text(
text = "${pagerState.currentPage + 1}/${images.size}",
Copy link
Member

Choose a reason for hiding this comment

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

string에 tag_count라고 있는데 그걸로 수정하면 좋을거같아요 ~

Text(
text = "${pagerState.currentPage + 1}/${images.size}",
style = typography.copy_r400_s14,
color = Color.White,
Copy link
Member

Choose a reason for hiding this comment

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

저희 colors로 수정해주세여


Column(
Modifier
.background(colors.Black)
Copy link
Member

Choose a reason for hiding this comment

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

이거 빼도 될거가타여

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

🔭 Outside diff range comments (2)
app/src/main/java/com/texthip/thip/ui/common/buttons/ActionBarButton.kt (1)

80-87: 접근성: contentDescription 추가 필요

클릭 가능한 핀 아이콘이 contentDescription = null 입니다. 스크린리더 사용자를 위해 의미 있는 설명을 제공하세요.

예시 수정안:

-    Icon(
+    Icon(
       modifier = Modifier.clickable { onPinClick() },
       painter = painterResource(R.drawable.ic_pin),
-      contentDescription = null,
+      contentDescription = stringResource(R.string.cd_pin),
       tint = colors.White
     )

strings.xml에 해당 키 추가 필요:

<string name="cd_pin">핀 고정</string>
app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt (1)

381-399: 대댓글 추가 시 nickName 기준 매칭은 충돌 위험이 있습니다

동일 닉네임 사용자가 둘 이상일 경우 잘못된 댓글에 달릴 수 있습니다.
고유 식별자(commentId 또는 userId)로 부모 댓글을 찾도록 로직을 수정하세요.

🧹 Nitpick comments (5)
app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt (1)

118-120: i18n/접근성: contentDescription 하드코딩 문자열 제거

contentDescription = "그룹 아이콘"은 하드코딩입니다. 다국어 및 접근성 대응을 위해 string 리소스로 분리하세요.

예시 수정안:

- contentDescription = "그룹 아이콘",
+ contentDescription = stringResource(R.string.cd_group_icon),

strings.xml:

<string name="cd_group_icon">그룹 아이콘</string>
app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoom.kt (1)

109-113: i18n/접근성: contentDescription 리소스화

contentDescription = "그룹 아이콘"은 하드코딩입니다. string 리소스로 전환해 주세요.

예시 수정안:

- contentDescription = "그룹 아이콘",
+ contentDescription = stringResource(R.string.cd_group_icon),

(strings.xml에 cd_group_icon 추가 필요)

app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt (3)

87-90: images 리스트를 remember 없이 매 재구성마다 새로 생성합니다

feedItem.imageUrls.orEmpty().map { … } 는 리컴포지션마다 실행되어 비용이 불필요하게 증가합니다.

val images by remember(feedItem.imageUrls) {
    mutableStateOf(feedItem.imageUrls.orEmpty().map { painterResource(id = it) })
}

처럼 remember 로 캐싱하세요.


160-174: take(3) 매직넘버 중복 사용

이미지·모달 모두 take(3) 으로 잘라내는데, 3이라는 값이 하드코딩돼 유지보수성이 떨어집니다. 상수로 추출하거나 MAX_PREVIEW_IMAGE_COUNT 같은 의미 있는 이름을 사용해주세요.

Also applies to: 457-458


245-276: selectedCommentcopy() 이후 참조 불일치로 해제되지 않습니다

댓글 삭제/신고 메뉴 표시 후 parentComment.copy(...) 로 리스트를 갱신하면 기존 객체와 레퍼런스가 달라져 selectedComment 와 불일치가 발생할 수 있습니다.
commentId 비교 등 식별자 기반 상태로 변경하는 편이 안전합니다.

Also applies to: 398-400

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 50e47d9 and c4edd46.

📒 Files selected for processing (15)
  • app/src/main/java/com/texthip/thip/ui/common/buttons/ActionBarButton.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoom.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/cards/CardRoomBook.kt (2 hunks)
  • app/src/main/java/com/texthip/thip/ui/common/header/HeaderMenuBarTab.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/component/ImageViewerModal.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt (4 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt (9 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt (3 hunks)
  • app/src/main/java/com/texthip/thip/ui/feed/screen/SubscriptionListScreen.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupWheelPicker.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupEmptyCard.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupMainCard.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt (1 hunks)
  • app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt (4 hunks)
✅ Files skipped from review due to trivial changes (8)
  • app/src/main/java/com/texthip/thip/ui/common/cards/CardRoomBook.kt
  • app/src/main/java/com/texthip/thip/ui/group/note/component/ReplyItem.kt
  • app/src/main/java/com/texthip/thip/ui/group/makeroom/component/GroupWheelPicker.kt
  • app/src/main/java/com/texthip/thip/ui/feed/component/MySubscribelistBar.kt
  • app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupEmptyCard.kt
  • app/src/main/java/com/texthip/thip/ui/common/header/HeaderMenuBarTab.kt
  • app/src/main/java/com/texthip/thip/ui/feed/screen/SubscriptionListScreen.kt
  • app/src/main/java/com/texthip/thip/ui/group/myroom/component/GroupMainCard.kt
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/src/main/java/com/texthip/thip/ui/mypage/screen/MypageScreen.kt
  • app/src/main/java/com/texthip/thip/ui/feed/component/ImageViewerModal.kt
  • app/src/main/java/com/texthip/thip/ui/feed/screen/FeedScreen.kt
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-01T07:19:10.981Z
Learnt from: rbqks529
PR: THIP-TextHip/THIP-Android#30
File: app/src/main/java/com/texthip/thip/ui/common/cards/CardItemRoomSmall.kt:108-112
Timestamp: 2025-07-01T07:19:10.981Z
Learning: The user rbqks529 prefers to extract hardcoded UI strings to StringResource files (strings.xml) rather than keeping them inline in Compose components, which is a good practice for maintainability and localization in Android development.

Applied to files:

  • app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt
🔇 Additional comments (5)
app/src/main/java/com/texthip/thip/ui/common/buttons/ActionBarButton.kt (2)

80-87: 테마 컬러 통일 👍

핀 아이콘 tint를 colors.White로 변경한 점 좋습니다. 테마 일관성과 다크/라이트 모드 대응 관점에서 적절합니다.


51-56: 다크 테마 아이콘 대비 적정함 확인됨

검증 결과:

  • ic_heart.xml/ic_save.xml
    • android:strokeColor="#FEFEFE" (거의 순백) → 다크 배경에서 충분한 대비 확보
  • ic_heart_filled.xml/ic_save_filled.xml
    • android:fillColor="#6868FF" (브랜드/테마 컬러) → 선택 상태 시 고유색 유지

따라서 tint = Color.Unspecified 사용을 그대로 유지해도 무방합니다.

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

114-121: 테마 컬러 적용 잘됐습니다

그룹 아이콘 tint를 colors.White로 통일한 점 좋습니다. 테마 일관성 유지에 도움이 됩니다.

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

108-114: 테마 컬러 적용 적합

그룹 아이콘 tint를 colors.White로 변경해 테마 일관성이 향상되었습니다.

app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt (1)

155-167: 이미지 크기가 기획(100.dp)과 불일치합니다

PR 설명에 따르면 피드 썸네일은 고정 100.dp 이어야 합니다. 현재 200.dp 로 설정되어 있어 UI 일관성이 깨집니다. 확인 후 수정 바랍니다.

Comment on lines 66 to 71
modifier: Modifier = Modifier,
feedItem: FeedItem,
bookImage: Painter? = null,
feedType: FeedItemType,
profileImage: Painter? = null,
currentUserId: Int,
currentUserName: String,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

feedType 파라미터가 전혀 사용되지 않습니다

feedType을 활용하여 잠금/저장 여부에 따른 UI 분기를 하거나, 그렇지 않다면 파라미터를 제거해 Dead Code를 없애주세요.

🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ui/feed/screen/FeedCommentScreen.kt around
lines 66 to 71, the parameter feedType is declared but never used. Either
implement logic using feedType to conditionally render UI elements based on
lock/save status, or remove the feedType parameter entirely to eliminate dead
code.

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] 홈/ 피드 UI 완성 및 담당 페이지 전체 QA [(THIP2025-162)]

3 participants