Skip to content

feat: 컬렉션 기능 추가 - #928

Open
devfeijoa wants to merge 66 commits into
developfrom
feat/924
Open

feat: 컬렉션 기능 추가#928
devfeijoa wants to merge 66 commits into
developfrom
feat/924

Conversation

@devfeijoa

@devfeijoa devfeijoa commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

📌𝘐𝘴𝘴𝘶𝘦𝘴

📎𝘞𝘰𝘳𝘬 𝘋𝘦𝘴𝘤𝘳𝘪𝘱𝘵𝘪𝘰𝘯

📷𝘚𝘤𝘳𝘦𝘦𝘯𝘴𝘩𝘰𝘵

💬𝘛𝘰 𝘙𝘦𝘷𝘪𝘦𝘸𝘦𝘳𝘴

Summary by CodeRabbit

  • 새 기능
    • 마이페이지에서 컬렉션 화면으로 이동할 수 있습니다.
    • 내 컬렉션과 좋아요한 컬렉션을 탭으로 확인할 수 있습니다.
    • 컬렉션 이름, 설명, 공개 여부를 설정해 새 컬렉션을 만들 수 있습니다.
    • 작품을 검색하거나 서재에서 선택해 컬렉션에 추가할 수 있습니다.
    • 작품 목록을 3열 그리드로 확인하고 선택 상태를 관리할 수 있습니다.
    • 선택한 작품 수와 작품 정보를 확인할 수 있습니다.
    • 컬렉션 생성 및 작품 선택 과정에서 뒤로가기와 완료 동작을 지원합니다.

devfeijoa added 12 commits July 28, 2026 11:58
- `feature/collection/build.gradle.kts`: collection 피처 모듈 빌드 스크립트 정의 및 네임스페이스 설정
- `feature/collection/src/main/AndroidManifest.xml`: 모듈용 매니페스트 파일 추가
- `settings.gradle.kts`: 프로젝트 모듈 목록에 `:feature:collection` 추가
- `libs.versions.toml`: Navigation Compose 라이브러리 버전(2.9.8) 및 카탈로그 정의 추가
- `feature/collection/build.gradle.kts`: `navigation-compose` 라이브러리 의존성 추가 적용
- `CollectionScreen.kt`: `CollectionScreen` 컴포저블 구현 및 프리뷰 추가
- `CollectionActivity.kt`: Hilt 의존성 주입을 위해 `CollectionActivity` 클래스에 `@AndroidEntryPoint` 어노테이션 추가
- `AndroidManifest.xml`: 컬렉션 화면 진입을 위한 `CollectionActivity` 추가 및 세로 방향(portrait) 고정 설정
- `fragment_my_page.xml`: 컬렉션 진입점을 위한 `ComposeView`(`cv_my_page_collection_entry`) 및 하단 구분선(`view_my_page_collection_divider`) 추가
- `fragment_my_page.xml`: 기존 장르 취향 섹션 및 취향 분석 섹션의 상단 제약 조건을 신규 구분선 기준으로 변경하여 레이아웃 구조 조정
- `MyPageFragment.kt`: `cvMyPageCollectionEntry`에 `CollectionEntry` 컴포저블을 적용하는 `setupCollectionEntry` 함수 추가
- `MyPageFragment.kt`: 컬렉션 화면으로 이동하는 `navigateToCollection` 함수 구현 및 연결
- `MyPageFragment.kt`: Compose View의 효율적인 생명주기 관리를 위한 `ViewCompositionStrategy` 설정 추가
- `CollectionAppBar.kt`: 뒤로가기 버튼과 "컬렉션" 타이틀을 포함한 상단 앱바 컴포저블 신규 구현
- `CollectionScreen.kt`: `CollectionAppBar` 적용 및 `statusBarsPadding` 추가, 내부 레이아웃 구조 조정
- `CollectionEntry.kt`: 파일 위치를 `component` 패키지로 이동
- `CollectionNavHost.kt` & `CollectionActivity.kt`: 뒤로가기 동작(finish)을 위한 `onNavigateBack` 콜백 추가 및 전달 로직 구현
- `MyPageFragment.kt`: `CollectionEntry` 패키지 위치 변경에 따른 임포트 경로 수정
@devfeijoa
devfeijoa requested review from Sadturtleman, m6z1 and s9hn July 28, 2026 11:39
@devfeijoa devfeijoa self-assigned this Jul 28, 2026
@devfeijoa devfeijoa added 🍯 [FEAT] 새로운 기능을 개발합니다. [👸 공주 은영] labels Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

컬렉션 전용 모듈과 Compose 화면을 추가했습니다. 컬렉션 생성, 작품 검색, 도서관 작품 선택 흐름을 구성했습니다. 도서관에 필터 없는 페이징 API를 추가했습니다. 마이페이지에서 CollectionActivity로 이동하도록 연결했습니다.

Changes

컬렉션 기능

Layer / File(s) Summary
컬렉션 모듈 구성
gradle/libs.versions.toml, settings.gradle.kts, feature/collection/..., app/build.gradle.kts, core/resource/...
컬렉션 모듈과 Navigation Compose 의존성을 등록하고 관련 매니페스트 및 아이콘 리소스를 추가했습니다.
컬렉션 목록 화면과 내비게이션
feature/collection/.../CollectionScreen.kt, CollectionNavHost.kt, component/*, model/CollectionTab.kt
컬렉션 탭, 앱바, 생성 버튼과 기본 내비게이션 라우트를 구현했습니다.
컬렉션 생성 입력과 소설 검색 화면
feature/collection/.../CollectionCreateScreen.kt, CollectionNovelSearchScreen.kt, component/*
비공개 설정, 이름·설명 입력 제한, 작품 추가 영역, 검색어 입력 및 선택 작품 수 표시를 구현했습니다.
도서관 소설 선택 흐름
data/library/..., feature/collection/.../CollectionLibraryNovel*, mapper/*, model/*
필터 없는 도서관 페이징 흐름과 UI 변환을 추가하고, 소설 선택 상태 및 3열 그리드 화면을 구현했습니다.
마이페이지 진입 및 액티비티 연결
app/src/main/.../CollectionActivity.kt, MyPageFragment.kt, fragment_my_page.xml, app/src/main/AndroidManifest.xml
마이페이지에 컬렉션 엔트리를 추가하고 클릭 시 CollectionActivity를 실행하도록 연결했습니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MyPageFragment
  participant CollectionActivity
  participant CollectionNavHost
  participant CollectionNovelSearchScreen
  participant CollectionLibraryNovelSelectionViewModel
  participant LibraryRepository

  MyPageFragment->>CollectionActivity: 컬렉션 Intent 실행
  CollectionActivity->>CollectionNavHost: Compose 콘텐츠 구성
  CollectionNavHost->>CollectionNovelSearchScreen: 검색 화면 표시
  CollectionNovelSearchScreen->>CollectionNavHost: 도서관 선택 화면 이동
  CollectionNavHost->>CollectionLibraryNovelSelectionViewModel: 선택 화면 구성
  CollectionLibraryNovelSelectionViewModel->>LibraryRepository: 필터 없는 소설 페이징 요청
  LibraryRepository-->>CollectionLibraryNovelSelectionViewModel: PagingData 반환
  CollectionLibraryNovelSelectionViewModel-->>CollectionNavHost: 선택된 소설 ID 전달
  CollectionNavHost-->>CollectionNovelSearchScreen: SavedStateHandle로 선택 결과 복원
Loading

Possibly related PRs

  • Team-WSS/WSS-Android#914: 컬렉션 소설 선택 화면이 getUnfilteredLibraryFlow()와 도서관 페이징 흐름을 사용합니다.

Suggested reviewers: m6z1, sadturtleman

Poem

당근을 먹던 토끼가 컬렉션을 열었네
탭과 버튼이 가지런히 놓였네
작품을 골라 담고
이름과 설명을 적고
마이페이지에서 폴짝 이동하네
깡총, 새 기능 완성! 🐇

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning 이슈 번호는 기재했지만 작업 설명, 스크린샷, 리뷰어 안내 내용이 비어 있습니다. 작업 설명에 주요 변경 사항과 검증 내용을 작성하고, 필요한 경우 스크린샷과 리뷰어 안내를 추가하세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 컬렉션 기능 추가라는 PR의 주요 변경 내용을 명확하게 요약합니다.
Linked Issues check ✅ Passed PR은 컬렉션 화면, 생성 흐름, 소설 선택 기능을 추가하여 연결된 이슈 #924의 컬렉션 기능 요구를 충족합니다.
Out of Scope Changes check ✅ Passed 변경 사항은 컬렉션 기능과 해당 기능에 필요한 라이브러리 조회 확장 및 모듈 설정 범위에 포함됩니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/924

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

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionScreen.kt`:
- Around line 51-55: Update CollectionScreen so users no longer see the
temporary “임시화면” content: either replace it with the implemented collection UI
or, until that exists, hide the MyPage entry point that launches
CollectionActivity. Ensure the user cannot navigate into an unfinished
collection screen.

In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt`:
- Around line 42-45: Update the back-navigation Image inside the
CollectionAppBar IconButton to use the existing Korean string resource for “뒤로
가기” as its contentDescription instead of null, preserving the current icon and
button behavior.

In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionEntry.kt`:
- Line 29: Update the CollectionEntry usage in MyPageFragment so it receives the
actual collection count, or make collectionCount nullable and omit the count
display when unavailable. Remove the misleading default value that causes valid
collection data to render as “0개,” while preserving the existing count rendering
when a real value is provided.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4a57c726-409d-47d7-b8bc-1322bd22bc2d

📥 Commits

Reviewing files that changed from the base of the PR and between 88a1b48 and 8e94a05.

📒 Files selected for processing (13)
  • app/build.gradle.kts
  • app/src/main/AndroidManifest.xml
  • app/src/main/java/com/into/websoso/ui/collection/CollectionActivity.kt
  • app/src/main/java/com/into/websoso/ui/main/myPage/MyPageFragment.kt
  • app/src/main/res/layout/fragment_my_page.xml
  • feature/collection/build.gradle.kts
  • feature/collection/src/main/AndroidManifest.xml
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNavHost.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionScreen.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionEntry.kt
  • gradle/libs.versions.toml
  • settings.gradle.kts

Comment on lines +42 to +45
Image(
painter = painterResource(id = ic_navigate_left),
contentDescription = null,
modifier = Modifier.size(24.dp),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
fd -a 'CollectionAppBar\.kt$' .

echo "== file excerpt =="
file=$(fd 'CollectionAppBar\.kt$' . | head -n1)
if [ -n "${file:-}" ]; then
  wc -l "$file"
  sed -n '1,120p' "$file" | cat -n
fi

echo "== accessibility contentDescription occurrences in Jetpack Compose Image usage =="
rg -n "Image\\(|contentDescription\\s*=" feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt

Repository: Team-WSS/WSS-Android

Length of output: 2963


뒤로가기 버튼에 접근성 라벨을 지정해 주세요.

IconButton 내부 이미지의 contentDescriptionnull이라 TalkBack에서 버튼의 목적을 알 수 없습니다. "뒤로 가기" 문자열 리소스를 사용해 접근성 라벨을 지정해 주세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt`
around lines 42 - 45, Update the back-navigation Image inside the
CollectionAppBar IconButton to use the existing Korean string resource for “뒤로
가기” as its contentDescription instead of null, preserving the current icon and
button behavior.

fun CollectionEntry(
onClick: () -> Unit,
modifier: Modifier = Modifier,
collectionCount: Int = 0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

실제 컬렉션 수를 전달하거나 기본값을 제거해 주세요.

MyPageFragment.kt의 현재 호출부는 CollectionEntry(onClick = ...)만 전달하므로 collectionCount가 항상 기본값 0입니다. 실제 컬렉션이 있어도 마이페이지에 항상 컬렉션 0개가 표시됩니다. 실제 수를 전달하거나, 수가 준비되지 않았다면 카운트를 렌더링하지 않도록 계약을 정리해 주세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionEntry.kt`
at line 29, Update the CollectionEntry usage in MyPageFragment so it receives
the actual collection count, or make collectionCount nullable and omit the count
display when unavailable. Remove the misleading default value that causes valid
collection data to render as “0개,” while preserving the existing count rendering
when a real value is provided.

- `CollectionTabRow.kt`: "내 컬렉션"과 "좋아요한 컬렉션"을 전환할 수 있는 탭 바 컴포저블 `CollectionTabRow` 및 내부 `CollectionTab` 구현
- `CollectionScreen.kt`: 상단 앱바 하단에 `CollectionTabRow` 배치
- `CollectionTab.kt`: 컬렉션 탭 구분을 위한 `CollectionTab` Enum 클래스 정의
- `CollectionScreen.kt`: `rememberSaveable`을 이용해 선택된 탭 상태(`selectedTab`)를 관리하고 `CollectionTabRow`와 연동
- `CollectionTabRow.kt`:
    - `CollectionTab` Enum을 순회하며 탭 항목을 생성하도록 로직 수정
    - 탭 클릭 처리를 위해 `onTabSelected` 콜백 추가 및 `selectable` Modifier 적용
    - 기존 `CollectionTab` 컴포저블을 `CollectionTabItem`으로 명칭 변경
    - Enum 값에 따른 탭 타이틀 문자열을 반환하는 확장 프로퍼티 `title` 추가
- `CollectionCreateButton.kt`: "컬렉션 만들기" 버튼 구현
- `CollectionScreen.kt`: 컬렉션 화면 내 상단 탭 하단에 `CollectionCreateButton` 추가 및 레이아웃 적용
- `CollectionScreen.kt`: 화면 중앙에 위치하던 "컬렉션", "임시화면" 안내 문구와 이를 포함하던 `Box` 레이아웃 및 미사용 임포트 삭제

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionCreateButton.kt`:
- Around line 26-60: Update CollectionCreateButton in
feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionCreateButton.kt:26-60
to accept an onClick callback and make its Row invoke it with clickable
semantics such as Role.Button. Update CollectionScreen in
feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionScreen.kt:23-46
to accept onCreateCollection and pass it to CollectionCreateButton so callers
can launch the actual creation flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ffde6f8d-ba28-4bac-a82c-e0a3854724ef

📥 Commits

Reviewing files that changed from the base of the PR and between 8e94a05 and 55f7aab.

📒 Files selected for processing (5)
  • core/resource/src/main/res/drawable/ic_collection_create.xml
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionScreen.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionCreateButton.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionTabRow.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/model/CollectionTab.kt

- `CollectionCreateButton.kt`: 컴포저블 함수 파라미터와 Modifier 체이닝의 불필요한 줄바꿈을 제거하고 임포트 구문을 정렬하여 가독성 개선
- `CollectionTabRow.kt`: `TabItem` 내 `modifier` 체이닝의 불필요한 줄바꿈 제거 및 코드 정렬 수정
- `CollectionCreateButton.kt`: `onClick` 콜백 매개변수를 추가하고 `Modifier.clickable` 및 `clip`을 적용하여 클릭 상호작용 구현
- `CollectionScreen.kt`: `CollectionCreateButton` 호출부에 `onClick` 핸들러 추가
- `CollectionScreen.kt`: 생성 버튼 클릭 시 호출될 `onNavigateToCreate` 콜백 파라미터 추가 및 `CollectionCreateButton`에 연결
- `CollectionNavHost.kt`: `CollectionScreen`에서 `COLLECTION_CREATE_ROUTE`로 이동하는 네비게이션 로직 구현 및 전달

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt (1)

43-55: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

뒤로가기 버튼에 접근성 라벨이 여전히 없습니다.

IconButton 내부 ImagecontentDescriptionnull입니다. TalkBack 사용자는 이 버튼의 목적을 알 수 없습니다. "뒤로 가기" 문자열 리소스를 contentDescription에 지정하세요. 이 문제는 이전 리뷰에서 이미 지적되었습니다.

🔧 제안 수정
             Image(
                 painter = painterResource(id = ic_navigate_left),
-                contentDescription = null,
+                contentDescription = "뒤로 가기",
                 modifier = Modifier.size(24.dp),
             )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt`
around lines 43 - 55, Update the back-navigation IconButton in CollectionAppBar
to provide the localized “뒤로 가기” string resource as the Image contentDescription
instead of null, preserving the existing layout and click behavior.
feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt (1)

34-39: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

폼 콘텐츠가 여전히 스크롤·IME 대응이 없습니다.

키보드가 열리거나 화면이 작으면 작품 추가 영역이 화면 밖으로 밀릴 수 있습니다. verticalScrollimePadding을 적용하세요. 이 문제는 이전 리뷰에서 이미 지적되었습니다.

🔧 제안 수정
+import androidx.compose.foundation.layout.imePadding
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll

     Column(
         modifier = modifier
             .fillMaxSize()
             .background(White)
             .statusBarsPadding()
+            .imePadding()
+            .verticalScroll(rememberScrollState()),
     ) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt`
around lines 34 - 39, Update the root Column in CollectionCreateScreen to apply
verticalScroll and imePadding alongside the existing modifier chain, ensuring
the form content remains scrollable and visible when the IME opens or available
screen height is limited.
🧹 Nitpick comments (1)
feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionLibraryNovelSelectionScreen.kt (1)

100-108: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

LazyVerticalGrid 아이템에 안정적인 key가 없습니다.

items(novels.itemCount)key 파라미터를 지정하지 않았습니다. 페이지가 갱신될 때 Compose가 항목을 인덱스로만 구분해 불필요한 리컴포지션이나 상태 유실이 발생할 수 있습니다. paging-compose가 제공하는 itemKey 확장 함수를 사용하세요.

Android 공식 가이드는 key = lazyPagingItems.itemKey { it.id }를 items()에 전달하는 패턴을 권장합니다.

🔧 제안 수정
+import androidx.paging.compose.itemKey

                 LazyVerticalGrid(
                     columns = GridCells.Fixed(3),
                     modifier = Modifier.fillMaxSize(),
                     contentPadding = PaddingValues(
                         start = 20.dp,
                         top = 11.dp,
                         end = 20.dp,
                     ),
                     horizontalArrangement = Arrangement.spacedBy(6.dp),
                     verticalArrangement = Arrangement.spacedBy(18.dp),
                 ) {
-                    items(novels.itemCount) { index ->
+                    items(
+                        count = novels.itemCount,
+                        key = novels.itemKey { it.novelId },
+                    ) { index ->
                         novels[index]?.let { novel ->
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionLibraryNovelSelectionScreen.kt`
around lines 100 - 108, Update the LazyVerticalGrid items call in the novels
rendering block to pass the paging-compose itemKey extension using each novel’s
novelId as the stable key. Keep the existing novels[index] lookup and
CollectionLibraryNovelItem rendering unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionLibraryNovelSelectionScreen.kt`:
- Around line 86-119: Update the collection grid around the refresh and append
load-state checks to handle LoadState.Error. For an initial refresh failure,
show an error message with a retry action calling novels.retry() instead of
rendering only the empty grid; for an append failure, add a bottom retry UI that
also invokes novels.retry(), while preserving the existing loading indicators
and successful-content behavior.

In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt`:
- Around line 51-56: Connect the novel-selection completion flow across all
affected sites: in CollectionNovelSearchScreen.kt lines 51-56, pass
onActionClick to CollectionAppBar; in CollectionNavHost.kt lines 46-58, save
selectedNovelIds in the COLLECTION_CREATE_ROUTE savedStateHandle and then call
popBackStack(); in CollectionCreateScreen.kt lines 40-43, read the selected IDs
from savedStateHandle for CollectionNovelSection and connect onActionClick to
the collection creation logic.

---

Duplicate comments:
In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt`:
- Around line 34-39: Update the root Column in CollectionCreateScreen to apply
verticalScroll and imePadding alongside the existing modifier chain, ensuring
the form content remains scrollable and visible when the IME opens or available
screen height is limited.

In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt`:
- Around line 43-55: Update the back-navigation IconButton in CollectionAppBar
to provide the localized “뒤로 가기” string resource as the Image contentDescription
instead of null, preserving the existing layout and click behavior.

---

Nitpick comments:
In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionLibraryNovelSelectionScreen.kt`:
- Around line 100-108: Update the LazyVerticalGrid items call in the novels
rendering block to pass the paging-compose itemKey extension using each novel’s
novelId as the stable key. Keep the existing novels[index] lookup and
CollectionLibraryNovelItem rendering unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ec3f3a78-3a96-4856-a6c3-94817c88ea72

📥 Commits

Reviewing files that changed from the base of the PR and between 5c4c650 and 47ecaa8.

📒 Files selected for processing (16)
  • data/library/src/main/java/com/into/websoso/data/library/LibraryRepository.kt
  • data/library/src/main/java/com/into/websoso/data/library/repository/MyLibraryRepository.kt
  • data/library/src/main/java/com/into/websoso/data/library/repository/UserLibraryRepository.kt
  • feature/collection/build.gradle.kts
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionLibraryNovelSelectionScreen.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionLibraryNovelSelectionViewModel.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNavHost.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionScreen.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionLibraryNovelItem.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSearchField.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSelectionInfo.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/mapper/CollectionLibraryNovelMapper.kt
  • feature/collection/src/main/java/com/into/websoso/feature/collection/model/CollectionLibraryNovelUiModel.kt
🚧 Files skipped from review as they are similar to previous changes (2)
  • feature/collection/build.gradle.kts
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionScreen.kt

Comment on lines +51 to +56
CollectionAppBar(
title = "작품 리스트",
actionLabel = "완료",
onNavigateBack = onNavigateBack,
isActionEnabled = addedNovelCount > 0,
)

@coderabbitai coderabbitai Bot Aug 1, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
fd -a 'Collection(NovelSearchSearchScreen|NavHost|CreateScreen|AppBar|CollectionNovelSection)\.kt$' . || true

echo
echo "== outline relevant files =="
for f in \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNavHost.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionAppBar.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSection.kt; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    wc -l "$f"
    ast-grep outline "$f" || true
  fi
done

echo
echo "== targeted snippets =="
for f in \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNavHost.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionAppBar.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSection.kt; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    nl -ba "$f" | sed -n '1,140p'
  fi
done

Repository: Team-WSS/WSS-Android

Length of output: 1733


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== exact files =="
git ls-files 'feature/collection/src/main/java/com/into/websoso/feature/collection/*' | sed -n '1,120p'

echo
echo "== snippets =="
for f in \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNavHost.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionAppBar.kt; do
  if [ -f "$f" ]; then
    echo "--- $f ($(wc -l < "$f") lines) ---"
    cat -n "$f" | sed -n '1,140p'
  fi
done

echo
echo "== symbols =="
rg -n "onActionClick|CollectionNovelSearchScreen|COLLECTION_NOVEL_SEARCH_ROUTE|COLLECTION_LIBRARY_NOVEL_SELECTION_ROUTE|COLLECTION_CREATE_ROUTE|savedStateHandle|selectedNovelIds|selectedNovelIdsKey|SELECTED_NOVEL_IDS_KEY|CollectionNovelSection|CollectionAppBar" feature/collection/src/main -S || true

Repository: Team-WSS/WSS-Android

Length of output: 25917


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== CollectionNovelSection =="
cat -n feature/collection/src/main/java/com/into/websoso/feature/collection/component/CollectionNovelSection.kt | sed -n '1,140p'

echo
echo "== CollectionScreen route construction == "
cat -n feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionScreen.kt | sed -n '1,120p'

echo
echo "== focused call graph text =="
rg -n "CollectionNovelSearchScreen\\(|CollectionCreateScreen\\(|CollectionAppBar\\(|ACTION|isActionEnabled|onActionClick|previousBackStackEntry|SELECTED_NOVEL_IDS_KEY|collection/create" feature/collection/src/main/java/com/into/websoso/feature/collection -S

Repository: Team-WSS/WSS-Android

Length of output: 11156


작품 선택 후 컬렉션 생성 완료로 흐름을 연결하세요.

  • CollectionNovelSearchScreen.kt#L51-L56: CollectionAppBar 호출에 onActionClick을 전달하세요. 기본값이 없어 컴파일 오류가 발생합니다.
  • CollectionNavHost.kt#L46-L58: 검색 화면 완료 동작에서 COLLECTION_CREATE_ROUTEsavedStateHandleselectedNovelIds를 저장한 뒤 popBackStack()하도록 연결하세요.
  • CollectionCreateScreen.kt#L40-L43: 생성 화면은 선택 작품 ID를 savedStateHandle에서 읽어 CollectionNovelSection에 표시하고, onActionClick을 컬렉션 생성 로직으로 연결하세요.
📍 Affects 3 files
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt#L51-L56 (this comment)
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNavHost.kt#L46-L58
  • feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionCreateScreen.kt#L40-L43
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt`
around lines 51 - 56, Connect the novel-selection completion flow across all
affected sites: in CollectionNovelSearchScreen.kt lines 51-56, pass
onActionClick to CollectionAppBar; in CollectionNavHost.kt lines 46-58, save
selectedNovelIds in the COLLECTION_CREATE_ROUTE savedStateHandle and then call
popBackStack(); in CollectionCreateScreen.kt lines 40-43, read the selected IDs
from savedStateHandle for CollectionNovelSection and connect onActionClick to
the collection creation logic.

@Sadturtleman Sadturtleman Aug 16, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

fragments는 현대 android architecture guideline에서 잘 사용되지 않는 것으로 알고있는데 굳이 fragments를 사용할 이유가 있을까요?(이러면 코드래빗한테 리뷰가나요)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in \
  app/src/main/java/com/into/websoso/ui/main/myPage/MyPageFragment.kt \
  app/src/main/java/com/into/websoso/ui/collection/CollectionActivity.kt \
  feature/collection/src/main/java/com/into/websoso/feature/collection/CollectionNovelSearchScreen.kt; do
  echo "--- $f ---"
  ast-grep outline "$f" --items all || true
  cat -n "$f" | sed -n '1,180p'
done

Length of output: 26566


@Sadturtleman, 확인 결과 현재 구조에서 Fragment 사용은 기존 화면과의 호환성을 위한 선택입니다.

MyPageFragment는 기존 XML 레이아웃, BaseFragment, LiveData, RecyclerView 기반의 마이페이지를 유지합니다. 이 PR은 MyPageFragmentComposeViewCollectionEntry만 추가하고, 클릭 시 CollectionActivity를 시작합니다.

CollectionActivityComponentActivity와 Compose CollectionNavHost를 사용합니다. 따라서 새 컬렉션 화면은 Fragment에 추가하지 않았습니다.

신규 앱 또는 전체 Compose 전환 작업이라면 단일 Activity와 Compose Navigation을 기본 구조로 선택하는 편이 적절합니다. 하지만 이 PR에서 MyPageFragment를 제거하면 기존 마이페이지의 내비게이션과 상태 관리까지 함께 변경해야 합니다. 그 변경은 컬렉션 기능 추가 범위를 넘습니다.

또한 현재 CollectionNovelSearchScreenonActionClick = onNavigateBack을 전달합니다. 컴파일 오류 지적은 더 이상 적용되지 않습니다. 다만 완료 동작이 선택 작품을 생성 화면으로 전달하는지 여부는 별도로 검토해야 합니다.

You are interacting with an AI system.

- `CollectionLibraryNovelSelectionScreen.kt`: `novels.loadState.refresh`가 `LoadState.Error`인 경우 노출될 에러 화면(이미지, 안내 문구, 재시도 버튼) 구현
- `CollectionLibraryNovelSelectionScreen.kt`: 에러 화면 내 재시도 버튼 클릭 시 `PagingData`의 `retry()`를 호출하는 로직 추가
- `CollectionLibraryNovelSelectionScreen.kt`: 데이터 추가 로딩(`append`) 중 에러가 발생한 경우에도 에러 UI가 노출되도록 조건식을 수정하고, `when` 문의 가독성 개선을 위해 구조 변경
- `data/novel/build.gradle.kts`: Retrofit, Paging, Serialization 등 의존성 설정 및 Android 라이브러리 모듈 환경 구성
- `settings.gradle.kts`: 전체 프로젝트 구성 내 `:data:novel` 모듈 추가
- `data/novel/src/main/AndroidManifest.xml`: 라이브러리 구성을 위한 기본 매니페스트 파일 추가
- `NovelSearchEntity.kt`: 작품 ID, 제목, 작가, 이미지 URL 정보를 포함하는 `NovelSearchEntity` 데이터 클래스 정의
- `CollectionNovelSearchRoute`: ViewModel의 검색 상태(`selectedNovels`, `submittedQuery`) 및 페이징 데이터를 UI에 전달하는 Route 구현
- `CollectionNovelSearchScreen`: `LazyColumn`을 활용하여 선택된 작품 목록과 페이징 기반 검색 결과 리스트를 통합하여 표시
- `CollectionNovelSearchEmpty`: 검색 결과가 없을 때 노출되는 안내 뷰 구현 및 작품 문의를 위한 외부 링크(`LocalUriHandler`) 연동
- 검색 필드 내 검색 실행(`onSearchClick`) 및 초기화(`onClearClick`) 시의 검색 상태 동기화 로직 추가
- 검색 결과 리스트에서 이미 선택된 작품은 제외하고 표시하도록 필터링 로직 적용
- 데이터 로딩 상태(Loading) 및 네트워크 에러(Error)에 따른 대응 UI 추가
- `CollectionNovelSearchItem.kt`: 검색된 소설과 선택된 소설을 표시하기 위한 공통 `CollectionNovelSearchItem` 컴포저블 및 이를 활용한 `CollectionNovelSearchItem`, `CollectionSelectedNovelItem` 구현
- `ic_collection_novel_add.xml`: 소설 추가 버튼을 위한 플러스(+) 아이콘 리소스 추가
- `ic_collection_novel_delete.xml`: 소설 삭제 버튼을 위한 엑스(x) 아이콘 리소스 추가
- `CollectionSelectedNovel.kt`: 소설 ID, 제목, 작가, 이미지 URL 정보를 포함하는 `CollectionSelectedNovel` 데이터 클래스 정의
- `NovelSearchRepository.kt`: `NovelSearchPagingSource`를 사용하여 작품 검색 결과를 PagingData로 반환하는 `searchNovels` 함수 구현
- 페이징 처리를 위한 `PAGE_SIZE` 상수를 20으로 정의 및 `PagingConfig` 설정 적용
- `CollectionNovelSearchViewModel.kt`: 작품 검색 및 선택 상태 관리를 위한 `CollectionNovelSearchViewModel` 구현
- `searchResults`: 입력된 검색어에 따라 `NovelSearchRepository`로부터 검색 결과를 페이징 데이터로 가져오는 Flow 정의
- `addNovel`/`removeNovel`: 선택된 작품 리스트에 작품을 추가하거나 제거하는 기능 구현
- `toSelectedNovel`: `NovelSearchEntity`를 컬렉션 선택 모델로 변환하는 확장 함수 추가
- `CollectionNetworkError.kt`: 네트워크 로딩 실패 시 노출되는 이미지, 안내 문구 및 재시도 버튼을 포함한 `CollectionNetworkError` 컴포저블 구현
- `CollectionNovelSearchField.kt`: 검색 수행을 위한 `onSearchClick` 콜백 파라미터 추가 및 `BasicTextField`의 `keyboardActions`에 연결
- `CollectionNovelSearchField.kt`: 검색 아이콘 영역에 `clickable` 속성을 추가하여 클릭 시 `onSearchClick`이 호출되도록 수정
- `CollectionNovelSearchField.kt`: 검색 아이콘에 `Role.Button`을 지정하고 `contentDescription`을 추가하여 접근성 개선
- `CollectionLibraryNovelSelectionViewModel.kt`:
    - `selectedNovelIds`를 `selectedNovels`(`List<CollectionSelectedNovel>`)로 변경하여 선택된 작품의 ID뿐만 아니라 제목, 이미지 등의 정보를 함께 관리하도록 수정
    - `toggleNovelSelection`의 파라미터를 `Long`에서 `CollectionLibraryNovelUiModel`로 변경하고, 선택 여부에 따라 리스트 내 객체를 추가/삭제하도록 로직 수정
    - 기존 `setSelectedNovelIds`를 `setSelectedNovels`로 변경하여 초기 선택 상태 설정 방식 수정
    - `CollectionLibraryNovelUiModel`을 `CollectionSelectedNovel` 데이터 모델로 변환하는 확장 함수 `toSelectedNovel` 추가
- `CollectionNovelSearchItem.kt`: 작품 제목의 최대 줄 수를 1줄에서 2줄(`maxLines = 2`)로 변경
- `CollectionNovelSearchItem.kt`: 작품 정보 영역과 액션 버튼 사이에 16dp 간격(`Spacer`) 추가
- `CollectionNovelSearchItem.kt`: import 구문 순서 정렬 및 최적화
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[👸 공주 은영] 🍯 [FEAT] 새로운 기능을 개발합니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 컬렉션 기능 추가

2 participants