[Feature/#57] 기록장 댓글 바텀시트 컴포넌트 #78
Conversation
TODO: 스타일 관련 디테일 수정 필요
📝 WalkthroughWalkthrough이 PR은 기록장에 완전한 댓글 바텀시트 기능을 추가합니다. RecordBookLayout의 헤더 렌더링을 RecordBookScreen으로 이동하고, CustomBottomSheet·ChatInputBar·CommentRoot 등 공유 UI 컴포넌트를 확장하여 입력 포커스 추적, 동적 스타일링, 문맥별 렌더링을 지원합니다. RecordComment 컴포넌트는 댓글 목록, 입력 필드, 답글 기능, 키보드 높이 자동 조정을 구현하며, 더미 데이터로 댓글/대댓글을 제공합니다. Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~25 minutes 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: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
screens/record-book/components/record-comment/index.tsx (1)
19-30:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winP3: 바텀시트 재오픈 시 이전 입력/답글 상태가 남을 수 있어요
isVisible이false가 될 때comment,replyCommentId,replyNickname,isInputFocus를 초기화하지 않아 이전 작성 컨텍스트가 다음 오픈에 이어질 수 있습니다. 닫힘 시점 reset 한 번만 넣으면 UX가 훨씬 안정적입니다.예시 개선안
+ import { useEffect, useState } from "react"; ... + useEffect(() => { + if (!isVisible) { + setComment(""); + setReplyCommentId(null); + setReplyNickname(""); + setIsInputFocus(false); + } + }, [isVisible]);Also applies to: 58-66
🤖 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 `@screens/record-book/components/record-comment/index.tsx` around lines 19 - 30, When the RecordComment component's isVisible prop flips to false, the previous draft and reply context remain; add a useEffect inside RecordComment that watches isVisible and when it becomes false calls setComment(""), setReplyCommentId(null), setReplyNickname(""), setIsInputFocus(false) (and any other relevant reset like setInputBarHeight(0) if needed) to fully clear the input state before the sheet is reopened; reference the RecordComment component and the state setters (setComment, setReplyCommentId, setReplyNickname, setIsInputFocus) to locate where to implement this reset.
🧹 Nitpick comments (1)
screens/record-book/components/record-comment/index.tsx (1)
31-117: ⚡ Quick winP3: 상호작용 테스트 3가지만 추가하면 회귀 방어가 확 올라갑니다 🚀
기능 복잡도가 올라간 구간이라 아래 테스트를 추천합니다:
- 답글 선택 후 전송 시
targetName/reply 상태 초기화 확인isVisiblefalse → true 전환 시 입력값/답글 상태 초기화 확인- 포커스 변화(
handleIsFocus)에 따라container높이 분기(0.7/0.93) 확인As per coding guidelines
미작성한 테스트 코드 케이스가 있다면, 어떤 테스트가 필요한지 제안해주세요. (예: 컨트롤러는 E2E테스트, 나머지는 단위 테스트)🤖 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 `@screens/record-book/components/record-comment/index.tsx` around lines 31 - 117, Add three tests: (1) unit test for RecordComment/handleSendText: simulate selecting a reply via handlePressReply (set replyCommentId/replyNickname), type a comment, call handleSendText and assert setComment becomes empty and ChatInputBar receives targetName="" (reply cleared) and reply states reset; (2) integration/unit test for visibility toggle: render the RecordComment component with isVisible false → true and assert comment, replyCommentId, and replyNickname are reset when isVisible becomes true (check ChatInputBar props and internal states); (3) unit/test for layout behavior: simulate handleIsFocus toggles (isInputFocus true/false) and assert CustomBottomSheet containerStyle height equals height * 0.93 vs height * 0.7 respectively. Prefer unit tests for ChatInputBar and CommentRoot/RecordComment logic; use an integration test for the isVisible toggle to cover props/state interaction.
🤖 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 `@screens/record-book/components/record-comment/index.tsx`:
- Around line 47-50: handlePressReply currently only sets reply state
(setReplyCommentId, setReplyNickname) but doesn't ensure the target comment
stays visible when the keyboard opens; update handlePressReply to also call the
FlatList ref's scrollToIndex/scrollToOffset to bring the target comment into
view (use the same list ref used to render comments, compute the item's index
from the comments array or use getItemLayout for stable heights, and call
listRef.current?.scrollToIndex({ index, viewPosition: 0.3 }) with a try/catch
fallback to scrollToOffset if scrollToIndex fails); apply the same
visibility-scroll logic to the other reply entry path referenced in the
component so that both reply entry points guarantee the original comment is
visible.
---
Outside diff comments:
In `@screens/record-book/components/record-comment/index.tsx`:
- Around line 19-30: When the RecordComment component's isVisible prop flips to
false, the previous draft and reply context remain; add a useEffect inside
RecordComment that watches isVisible and when it becomes false calls
setComment(""), setReplyCommentId(null), setReplyNickname(""),
setIsInputFocus(false) (and any other relevant reset like setInputBarHeight(0)
if needed) to fully clear the input state before the sheet is reopened;
reference the RecordComment component and the state setters (setComment,
setReplyCommentId, setReplyNickname, setIsInputFocus) to locate where to
implement this reset.
---
Nitpick comments:
In `@screens/record-book/components/record-comment/index.tsx`:
- Around line 31-117: Add three tests: (1) unit test for
RecordComment/handleSendText: simulate selecting a reply via handlePressReply
(set replyCommentId/replyNickname), type a comment, call handleSendText and
assert setComment becomes empty and ChatInputBar receives targetName="" (reply
cleared) and reply states reset; (2) integration/unit test for visibility
toggle: render the RecordComment component with isVisible false → true and
assert comment, replyCommentId, and replyNickname are reset when isVisible
becomes true (check ChatInputBar props and internal states); (3) unit/test for
layout behavior: simulate handleIsFocus toggles (isInputFocus true/false) and
assert CustomBottomSheet containerStyle height equals height * 0.93 vs height *
0.7 respectively. Prefer unit tests for ChatInputBar and
CommentRoot/RecordComment logic; use an integration test for the isVisible
toggle to cover props/state interaction.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6d9781ee-3ea4-48dd-b5d5-f44373f67ff5
📒 Files selected for processing (10)
app/record-book/_layout.tsxscreens/feed-detail/feed-detail-screen.tsxscreens/record-book/components/record-book-post-item/index.tsxscreens/record-book/components/record-book-top-tab-bar/index.tsxscreens/record-book/components/record-comment/index.tsxscreens/record-book/constants/index.tsscreens/record-book/record-book-screen.tsxsrc/shared/ui/chat-input-bar/index.tsxsrc/shared/ui/comment-list/comment-root.tsxsrc/shared/ui/custom-bottom-sheet/index.tsx
| const handlePressReply = (commentId: number, replyNickname: string) => { | ||
| setReplyCommentId(commentId); | ||
| setReplyNickname(replyNickname); | ||
| }; |
There was a problem hiding this comment.
P2: 답글 진입 시 대상 댓글 가시성 고정 로직이 빠져 있어요 (구현 방향은 아주 좋습니다 👏)
현재는 답글 대상 상태만 저장하고 있어, 키보드가 올라오면 원댓글이 화면 밖으로 밀릴 수 있습니다. 이 PR 목표(답글 시 관련 댓글 즉시 노출) 기준으로 FlatList ref + scrollToIndex/scrollToOffset 동작을 handlePressReply에 연결하는 쪽이 안전합니다. React Native FlatList의 scrollToIndex 문서 패턴을 그대로 가져오면 구현이 깔끔합니다.
예시 개선안
+ import { useRef } from "react";
+ import type { FlatList as RNFlatList } from "react-native";
...
+ const listRef = useRef<RNFlatList<CommentListType>>(null);
const handlePressReply = (commentId: number, replyNickname: string) => {
setReplyCommentId(commentId);
setReplyNickname(replyNickname);
+ const index = DUMMY_RECORD_COMMENT_LIST.findIndex(
+ (item) => item.commentId === commentId,
+ );
+ if (index >= 0) {
+ listRef.current?.scrollToIndex({ index, animated: true, viewPosition: 0.2 });
+ }
};
...
<FlatList
+ ref={listRef}
...
/>Also applies to: 76-92
🤖 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 `@screens/record-book/components/record-comment/index.tsx` around lines 47 -
50, handlePressReply currently only sets reply state (setReplyCommentId,
setReplyNickname) but doesn't ensure the target comment stays visible when the
keyboard opens; update handlePressReply to also call the FlatList ref's
scrollToIndex/scrollToOffset to bring the target comment into view (use the same
list ref used to render comments, compute the item's index from the comments
array or use getItemLayout for stable heights, and call
listRef.current?.scrollToIndex({ index, viewPosition: 0.3 }) with a try/catch
fallback to scrollToOffset if scrollToIndex fails); apply the same
visibility-scroll logic to the other reply entry path referenced in the
component so that both reply entry points guarantee the original comment is
visible.
📌 Related Issues
📄 Tasks
📷 Screenshot
Summary by CodeRabbit
릴리스 노트
새로운 기능
스타일