Conversation
- `PopularNovelsEntity`에 작가, 장르, 완료 여부, 키워드, 작품 설명 등 신규 필드 추가 - 유저 피드 존재 여부를 확인하는 `hasUserFeed` 속성 추가 - `PopularNovelsResponseDto` 및 `NovelMapper`에 추가된 데이터 필드 반영 및 null 허용 처리 - `PopularNovelsViewHolder`에서 유저 피드 유무에 따라 아바타 및 텍스트 레이아웃의 가시성(Visibility)을 조절하도록 수정 - 피드 내용이 없을 경우 작품 설명(`novelDescription`)을 우선적으로 표시하도록 바인딩 로직 고도화
- `PopularNovelsAdapter`에서 코드 내에 직접 정의되어 있던 아이템 너비 계산 및 설정 로직 제거 - `onBindViewHolder`를 단일 식 함수 형태로 간소화
- `bg_popular_novel_gradient_radius_14dp.xml`의 배경색을 그라데이션에서 흰색 단색(@color/white)으로 변경
- `toPopularNovelTitle`: 제목의 최대 노출 길이를 제한하고 단어 단위로 줄바꿈을 처리하는 로직 추가 - `toAuthorStatus`: 작가명(최대 6자)과 작품 연재 상태(완결/연재)를 결합한 문자열 생성 로직 추가 - `wrapByWord`: `TextPaint`를 사용해 TextView 너비를 초과하는 텍스트에 단어 단위 줄바꿈 적용 - `textAreaWidth`: 패딩을 제외한 TextView의 실제 텍스트 영역 너비를 계산하는 프로퍼티 추가
- `PopularNovelsViewHolder`에서 작품 제목(`tvPopularNovelTitle`) 및 작가 상태(`tvPopularNovelAuthorStatus`) 데이터 바인딩 로직 추가
- 작품 제목 생략 처리를 위한 말줄임표(`...`) 추가 - 작가 및 연재 상태 표시를 위한 포맷(`%1$s · %2$s`) 추가 - 연재 및 완결 상태를 나타내는 문자열(`연재작`, `완결작`) 추가
- 아이템 전체 크기를 고정 수치(292dp x 362dp)로 변경 - 작품 이미지를 활용한 블러 배경(`iv_popular_novel_blur_background`) 및 투명도 적용 - 작품 제목, 작가 정보, 커버 이미지의 레이아웃 배치 및 크기 수정 - 작품 제목 텍스트에 말줄임표(`ellipsize`) 및 최대 줄 수(`maxLines`) 제한 추가 - 상단 'BEST' 아이콘 제거 및 하단 정보 영역(`cl_popular_novel_in_short`) 위치 조정
- `PopularNovelsViewHolder`에서 작품 장르(genreName)에 따른 SVG 아이콘 로드 로직 추가 (Coil 사용) - 장르별 이미지 경로 매핑을 위한 `toPopularNovelGenreImagePath` 확장 함수 추가 - `item_popular_novel.xml` 레이아웃에 장르 아이콘 및 프레임 표시를 위한 `ImageView` 추가 - `iv_popular_novel_blur_background` 속성 순서 변경 및 코드 정리
- `item_popular_novel.xml` 내 키워드 표시를 위한 `LinearLayout` 및 `TextView` 레이아웃 추가 - `PopularNovelsViewHolder`에 키워드 바인딩을 위한 `bindPopularNovelKeywords` 확장 함수 및 로직 구현 - 최대 2개의 키워드를 표시하도록 제한하는 상수 추가 및 예외 처리 로직 적용
- `PopularNovelsViewHolder`에서 하드코딩된 더미 키워드 바인딩 로직 삭제
- `bg_popular_novel_gradient_radius_14dp`의 배경색을 흰색에서 투명도가 적용된 흰색(#B2FFFFFF)으로 변경
Walkthrough이 PR은 홈 화면 인기소설 카드 UI를 개선하는 작업입니다. 데이터 모델에 작가, 장르, 완결 여부, 키워드, 설명 필드를 추가하고, 텍스트 포맷팅 유틸로 제목과 작가 정보를 처리한 뒤, 뷰홀더에서 이를 조건부로 바인딩하며, 마지막으로 레이아웃과 스타일을 업데이트합니다. Changes인기소설 카드 UI 개선
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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
`@app/src/main/java/com/into/websoso/ui/main/home/adpater/PopularNovelsViewHolder.kt`:
- Around line 22-58: The issue: bindPopularNovelKeywords(popularNovel) is
defined but never invoked, so keyword UI stays empty; fix by calling
bindPopularNovelKeywords(popularNovel) from inside the bind(popularNovel:
PopularNovelEntity) method (after binding.popularNovel is set or before
executePendingBindings()) so the keyword view logic runs and the "max 2
keywords" display is applied; reference the bind() method and the
bindPopularNovelKeywords() helper to locate where to insert the call.
In `@app/src/main/res/drawable/bg_popular_novel_gradient_radius_14dp.xml`:
- Around line 1-5: The drawable filename
bg_popular_novel_gradient_radius_14dp.xml is misleading because the XML uses a
solid color (<solid android:color="`#B2FFFFFF`" />) not a gradient; rename the
resource to match its content (e.g.
bg_popular_novel_solid_white_transparent_radius_14dp) and update the single
reference in item_popular_novel.xml (the android:background attribute at its use
site) to the new resource name; ensure the XML root/contents (shape, solid,
corners) remain unchanged and keep the 14dp radius in the renamed file.
🪄 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
Run ID: 8bb1b765-addb-4923-abab-44704412845b
📒 Files selected for processing (9)
app/src/main/java/com/into/websoso/data/mapper/NovelMapper.ktapp/src/main/java/com/into/websoso/data/model/PopularNovelsEntity.ktapp/src/main/java/com/into/websoso/data/remote/response/PopularNovelsResponseDto.ktapp/src/main/java/com/into/websoso/ui/main/home/adpater/PopularNovelTextExtensions.ktapp/src/main/java/com/into/websoso/ui/main/home/adpater/PopularNovelsAdapter.ktapp/src/main/java/com/into/websoso/ui/main/home/adpater/PopularNovelsViewHolder.ktapp/src/main/res/drawable/bg_popular_novel_gradient_radius_14dp.xmlapp/src/main/res/layout/item_popular_novel.xmlcore/resource/src/main/res/values/strings.xml
- `toPopularNovelGenreImagePath` 확장 함수를 별도 파일(`PopularNovelGenreExtensions.kt`)로 분리하여 모듈화 - `PopularNovelsViewHolder`에서 키워드 바인딩(`bindPopularNovelKeywords`) 로직 호출 추가 및 관련 확장 함수 정리
- `bind` 메서드의 로직을 `bindTopInformation`, `bindGenreFlag`, `bindPopularNovelKeywords`, `bindFeedHeader` 등 역할별로 분리하여 모듈화 - `PopularNovelEntity`에 대한 확장 함수(`toAvatarImageUrl`, `toFeedDescription`)를 추가하여 데이터 변환 로직 정돈 - 키워드 표시 로직 및 뷰 바인딩 순서 최적화 - `POPULAR_NOVEL_KEYWORD_MAX_COUNT` 상수를 `companion object` 내부로 이동하여 캡슐화 강화
- `item_popular_novel.xml` 내 피드 내용(`feedContent`) 데이터 바인딩 제거 - `PopularNovelTextExtensions.kt`에 `takeWithEllipsis` 확장 함수를 추가하여 말줄임표 처리 로직 고도화 및 코드 가독성 개선
- `item_popular_novel.xml`에서 사용되는 배경 드로어블 파일명 수정 (`bg_popular_novel_fcf8f6_bottom_radius_14dp` -> `bg_popular_novel_bottom_radius_14dp`) - 리소스명에서 특정 색상 코드(`fcf8f6`)를 제거하여 명칭 최적화 및 레이아웃 반영
- `bg_popular_novel_gradient_radius_14dp` 리소스 이름을 `bg_popular_novel_translucent_radius_14dp`로 변경 - `item_popular_novel.xml` 레이아웃에 변경된 배경 리소스 적용
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/src/main/java/com/into/websoso/ui/main/home/adpater/PopularNovelTextExtensions.kt (1)
40-44:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
textAreaWidth가 음수/0이 될 수 있어 제목 줄바꿈이 오동작할 수 있습니다.Line 42에서
layoutParams.width를 그대로 쓰면-1/-2/0이 들어와wrapByWord의maxWidth가 비정상값이 될 수 있습니다. 그 경우 실제 폭과 무관하게 줄바꿈이 발생할 수 있습니다.수정 예시
private val TextView.textAreaWidth: Float get() { - val measuredWidth = width.takeIf { it > 0 } ?: layoutParams.width - return (measuredWidth - paddingStart - paddingEnd).toFloat() + val measuredWidth = width.takeIf { it > 0 } ?: measuredWidth + val contentWidth = measuredWidth - paddingStart - paddingEnd + return contentWidth.coerceAtLeast(0).toFloat() }🤖 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 `@app/src/main/java/com/into/websoso/ui/main/home/adpater/PopularNovelTextExtensions.kt` around lines 40 - 44, The current TextView.textAreaWidth getter can return negative or zero when layoutParams.width is MATCH_PARENT/MATCH_PARENT constants (-1,-2) or unspecified; change the logic in the textAreaWidth property to prefer actual measured width values and fall back safely, then clamp to a non-negative value. Specifically, in the TextView.textAreaWidth getter (the property), use width.takeIf { it > 0 } ?: measuredWidth.takeIf { it > 0 } ?: (layoutParams?.width?.takeIf { it > 0 } ?: (rootView?.width ?: 0)) and finally compute ((resolvedWidth - paddingStart - paddingEnd).coerceAtLeast(0)).toFloat() so wrapByWord receives a valid non-negative maxWidth.
🤖 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.
Outside diff comments:
In
`@app/src/main/java/com/into/websoso/ui/main/home/adpater/PopularNovelTextExtensions.kt`:
- Around line 40-44: The current TextView.textAreaWidth getter can return
negative or zero when layoutParams.width is MATCH_PARENT/MATCH_PARENT constants
(-1,-2) or unspecified; change the logic in the textAreaWidth property to prefer
actual measured width values and fall back safely, then clamp to a non-negative
value. Specifically, in the TextView.textAreaWidth getter (the property), use
width.takeIf { it > 0 } ?: measuredWidth.takeIf { it > 0 } ?:
(layoutParams?.width?.takeIf { it > 0 } ?: (rootView?.width ?: 0)) and finally
compute ((resolvedWidth - paddingStart - paddingEnd).coerceAtLeast(0)).toFloat()
so wrapByWord receives a valid non-negative maxWidth.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3c6b49d1-2c0b-42e6-9b61-fce12dd3787b
📒 Files selected for processing (5)
app/src/main/java/com/into/websoso/ui/main/home/adpater/PopularNovelTextExtensions.ktapp/src/main/java/com/into/websoso/ui/main/home/adpater/PopularNovelsViewHolder.ktapp/src/main/res/drawable/bg_popular_novel_bottom_radius_14dp.xmlapp/src/main/res/drawable/bg_popular_novel_translucent_radius_14dp.xmlapp/src/main/res/layout/item_popular_novel.xml
💤 Files with no reviewable changes (1)
- app/src/main/res/drawable/bg_popular_novel_translucent_radius_14dp.xml
🚧 Files skipped from review as they are similar to previous changes (2)
- app/src/main/res/layout/item_popular_novel.xml
- app/src/main/java/com/into/websoso/ui/main/home/adpater/PopularNovelsViewHolder.kt
| val avatarImage: String?, | ||
| val avatarImage: String? = null, | ||
| @SerialName("feedContent") | ||
| val feedContent: String, | ||
| val feedContent: String? = null, | ||
| @SerialName("genreName") | ||
| val genreName: String = "", | ||
| @SerialName("isNovelCompleted") | ||
| val isNovelCompleted: Boolean = false, | ||
| @SerialName("keywords") | ||
| val keywords: List<String> = emptyList(), |
There was a problem hiding this comment.
@m6z1 API 필드값 개편 중에 일부 필드가 누락되면 홈 화면 전체가 역직렬화 실패로 홈 화면 전체가 나오지 않는 상황이 종종 있어 기본값을 넣었습니다.
genreName은 없으면 장르 깃발을 숨기고, keywords는 빈 리스트면 키워드 칩을 숨길 수 있어서 fallback이 가능하다고 봤습니다. isNovelCompleted도 홈 전체가 깨지는 것을 막기 위한 방어값으로 넣었습니다.
별개로, 사용자 피드가 없는 인기 작품에서는 avatarImage, nickname, feedContent가 null로 내려올 수 있어 nullable로 받도록 했고, UI에서는 이 값들이 모두 유효할 때만 한마디로 판단합니다. 그렇지 않으면 null님의 한마디가 아니라 작품 소개로 표시되도록 정리했습니다.
다만 isNovelCompleted값이 누락될 일이 없어보이고 누락 된다면 연재작으로 보이는 게 정책적으로 맞는지는 조금 애매한듯 하여 이 값은 기본값 없이 받아도 될 듯 합니다!
| internal fun String.toPopularNovelGenreImagePath(): String = | ||
| when (this) { | ||
| "romance" -> "/icGenre/romance" | ||
| "romanceFantasy" -> "/icGenre/romance-fantasy" | ||
| "BL" -> "/icGenre/bl" | ||
| "fantasy" -> "/icGenre/fantasy" | ||
| "modernFantasy" -> "/icGenre/modern-fantasy" | ||
| "wuxia" -> "/icGenre/wuxia" | ||
| "lightNovel" -> "/icGenre/light-novel" | ||
| "drama" -> "/icGenre/drama" | ||
| "mystery" -> "/icGenre/mystery" | ||
| else -> "" | ||
| } |
There was a problem hiding this comment.
c: 이건 고민이 좀 필요할 것 같은데 추후에 resource 모듈로 옮기면 좋을 것 같아요
There was a problem hiding this comment.
@m6z1 좋습니다 👍🏻 현재는 "오늘의 발견"에서만 사용해서 home adapter 하위에 두었는데 공통으로 쓸 수 있는 로직에 가까워 추후 resource 모듈로 옮기면 좋을 것 같네요 !
📌𝘐𝘴𝘴𝘶𝘦𝘴
📎𝘞𝘰𝘳𝘬 𝘋𝘦𝘴𝘤𝘳𝘪𝘱𝘵𝘪𝘰𝘯
홈
오늘의 발견카드 UI 개편/novels/popularapi 응답 변경 반영author,genreName,keywords,novelDescription,isNovelCompleted매핑feedContent기준 한마디/작품소개 표시 정책을 이전에는 avatar & nickname null 여부로 feedContent 에서 한마디 / 작품 소개로 내려오던것을 avatart & nickname & feedContent 가 null 이면 novelDescription에서 작품소개가 내려오게끔 정책 정리관련 ViewHolder/Text helper/drawable 네이밍 정리
카드 ui width 크기를 강제로 이전 크기로 계산하는 로직이 있어 카드 ui가 변경됨에 따라 제거하였습니다.
📷𝘚𝘤𝘳𝘦𝘦𝘯𝘴𝘩𝘰𝘵
💬𝘛𝘰 𝘙𝘦𝘷𝘪𝘦𝘸𝘦𝘳𝘴
Summary by CodeRabbit
릴리스 노트
새로운 기능
개선 사항