docs(creator): 답글 상세 계획을 추가한다
This commit is contained in:
306
docs/20260707_글_상세_답글_쓰기/plan-task.md
Normal file
306
docs/20260707_글_상세_답글_쓰기/plan-task.md
Normal file
@@ -0,0 +1,306 @@
|
||||
# 글 상세 - 답글 쓰기 구현 계획
|
||||
|
||||
> **For agentic workers:** PRD를 기준으로 task 단위로 진행한다. 구현 중 요구사항 변경이 생기면 먼저 `docs/20260707_글_상세_답글_쓰기/prd.md`를 보강하고 이 문서의 체크리스트를 갱신한다.
|
||||
|
||||
**Goal:** 커뮤니티 댓글 또는 본인 채널 팬Talk 댓글을 터치해 답글 상세 화면에 진입하고, 기존 API로 답글 작성/수정/삭제를 수행한다.
|
||||
|
||||
**Architecture:** V2 전용 답글 상세 화면과 ViewModel을 새로 만들고, 네트워크 mutation은 기존 `CreatorCommunityRepository`와 `ExplorerRepository`를 재사용한다. 커뮤니티와 팬Talk의 화면 표시/입력/수정 모드는 공통 ViewModel 상태로 처리하되, API 호출과 갱신 전략은 source enum으로 분기한다.
|
||||
|
||||
**Tech Stack:** SwiftUI, Combine, Moya, Kingfisher, 기존 `AppCoordinator`, 기존 V2 design token(`Color`, `SodaSpacing`, `appFont`)
|
||||
|
||||
---
|
||||
|
||||
## 기준 문서
|
||||
|
||||
- PRD: `docs/20260707_글_상세_답글_쓰기/prd.md`
|
||||
- 문서 정책: `docs/agent-guides/documentation-policy.md`
|
||||
- 코드 스타일: `docs/agent-guides/code-style.md`
|
||||
- 빌드/검증: `docs/agent-guides/build-test-verification.md`
|
||||
- Figma 답글 없음: `669:40462`, `https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=669-40462&m=dev`
|
||||
- Figma 답글 있음: `669:40468`, `https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=669-40468&m=dev`
|
||||
|
||||
## 구현 원칙
|
||||
|
||||
- 신규 화면과 상태 관리는 `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/**` 아래에 둔다.
|
||||
- 기존 답글 작성 API를 새로 만들지 않는다.
|
||||
- 커뮤니티 답글 API는 `CreatorCommunityRepository.createCommunityPostComment`, `getCommentReplyList`, `modifyComment`를 사용한다.
|
||||
- 팬Talk 답글 API는 `ExplorerRepository.writeCheers`, `modifyCheers`를 사용한다.
|
||||
- 팬Talk 답글 작성/수정/삭제 성공 후에는 팬Talk 목록 첫 페이지를 재조회하는 callback을 호출한다.
|
||||
- 커뮤니티 원댓글이 비밀댓글이면 답글 작성 시 `isSecret`에 원댓글의 `isSecret` 값을 그대로 전달한다.
|
||||
- send 버튼 활성 기준은 `trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false`로 통일한다.
|
||||
- 답글 수정은 별도 화면을 열지 않고 하단 입력창에 수정 대상 내용을 채운 뒤 send 버튼으로 수정 API를 호출한다.
|
||||
- 수정/삭제는 Figma 더보기 메뉴 노출 범위 안에서 구현하되, 기존 권한 규칙을 유지한다.
|
||||
- `ic_arrow_up_gray`, `ic_arrow_up_white` asset은 이미 추가된 것으로 간주하고, 구현 시 asset catalog 등록 상태를 검증한다.
|
||||
|
||||
## 주요 대상 파일
|
||||
|
||||
### 생성
|
||||
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Models/CreatorChannelReplyDetailContext.swift`
|
||||
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Models/CreatorChannelReplyDetailDisplayItem.swift`
|
||||
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailView.swift`
|
||||
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift`
|
||||
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailTitleBar.swift`
|
||||
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailFeedView.swift`
|
||||
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailInputBar.swift`
|
||||
- `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailActionPopup.swift`
|
||||
|
||||
### 수정
|
||||
- `SodaLive/Sources/App/AppStep.swift`
|
||||
- `SodaLive/Sources/ContentView.swift`
|
||||
- `SodaLive/Sources/V2/CreatorChannel/FanTalk/CreatorChannelFanTalkTabView.swift`
|
||||
- `SodaLive/Sources/V2/CreatorChannel/FanTalk/Components/CreatorChannelFanTalkListItem.swift`
|
||||
- `SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityTabView.swift`
|
||||
- `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentListView.swift`
|
||||
- `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentItemView.swift`
|
||||
- `SodaLive/Sources/I18n/I18n.swift`
|
||||
- `SodaLive.xcodeproj/project.pbxproj`
|
||||
|
||||
## TASK 체크리스트
|
||||
|
||||
### Phase 1: 모델과 라우팅 기반
|
||||
|
||||
- [x] **Task 1.1: 답글 상세 context/display 모델 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Models/CreatorChannelReplyDetailContext.swift`
|
||||
- 생성: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Models/CreatorChannelReplyDetailDisplayItem.swift`
|
||||
- 작업 내용:
|
||||
- `CreatorChannelReplyDetailContext`에 `.community`와 `.fanTalk` source를 둔다.
|
||||
- 커뮤니티 context는 `creatorId`, `postId`, `parentComment: GetCommunityPostCommentListItem`을 보유한다.
|
||||
- 팬Talk context는 `creatorId`, `parentFanTalk: CreatorChannelFanTalkItemResponse`를 보유한다.
|
||||
- display item은 id, writerId, nickname, profileImageUrl, content, relativeTimeText, isSecret, isMine, isCreatorReply 여부를 담는다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "enum CreatorChannelReplyDetailContext|case community|case fanTalk|struct CreatorChannelReplyDetailDisplayItem|isSecret|isCreatorReply" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Models`
|
||||
- 기대 결과: 커뮤니티와 팬Talk를 모두 표현하는 context/display 모델이 확인된다.
|
||||
|
||||
- [x] **Task 1.2: AppStep에 답글 상세 route 추가**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/App/AppStep.swift`
|
||||
- 수정: `SodaLive/Sources/ContentView.swift`
|
||||
- 작업 내용:
|
||||
- `AppStep`에 `creatorChannelReplyDetail(context:onFanTalkRefresh:)` case를 추가한다.
|
||||
- `ContentView` switch에서 `CreatorChannelReplyDetailView(context:onFanTalkRefresh:)`를 반환한다.
|
||||
- `onFanTalkRefresh`는 팬Talk 상세에서 작성/수정/삭제 성공 후 팬Talk 목록 첫 페이지를 재조회하기 위한 optional callback으로 둔다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "creatorChannelReplyDetail|CreatorChannelReplyDetailView|onFanTalkRefresh" SodaLive/Sources/App/AppStep.swift SodaLive/Sources/ContentView.swift`
|
||||
- 기대 결과: 새 navigation step과 화면 연결이 확인된다.
|
||||
|
||||
### Phase 2: ViewModel과 기존 API 재사용
|
||||
|
||||
- [x] **Task 2.1: 답글 상세 ViewModel 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift`
|
||||
- 작업 내용:
|
||||
- `@Published` 상태로 `replyText`, `replies`, `isLoading`, `errorMessage`, `isShowPopup`, `selectedActionItem`, `editingItem`을 둔다.
|
||||
- `isSendEnabled`는 `replyText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false`로 계산한다.
|
||||
- `configure(context:)`에서 원댓글 display item과 초기 답글 display items를 구성한다.
|
||||
- 커뮤니티 context는 `fetchCommunityReplies()`로 기존 답글 목록을 조회한다.
|
||||
- 팬Talk context는 `parentFanTalk.creatorReplies`를 초기 답글 목록으로 표시한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "final class CreatorChannelReplyDetailViewModel|replyText|replies|isSendEnabled|editingItem|configure\\(|fetchCommunityReplies|creatorReplies" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift`
|
||||
- 기대 결과: 입력 상태, 수정 상태, 커뮤니티 조회, 팬Talk 초기 답글 표시 상태가 확인된다.
|
||||
|
||||
- [x] **Task 2.2: 커뮤니티 답글 작성/수정/삭제 처리**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift`
|
||||
- 작업 내용:
|
||||
- 작성 모드 send 시 `CreatorCommunityRepository.createCommunityPostComment(comment:postId:parentId:isSecret:)`를 호출한다.
|
||||
- `parentId`는 원댓글 id, `postId`는 context post id, `isSecret`은 원댓글 `isSecret` 값을 전달한다.
|
||||
- 수정 모드 send 시 `ModifyCommunityPostCommentRequest(commentId:)`에 수정 content를 담아 `modifyComment(request:)`를 호출한다.
|
||||
- 삭제 confirm 시 `ModifyCommunityPostCommentRequest(commentId:)`에 `isActive = false`를 담아 `modifyComment(request:)`를 호출한다.
|
||||
- 성공 후 `replyText`와 `editingItem`을 초기화하고 `fetchCommunityReplies()`로 목록을 갱신한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "createCommunityPostComment|parentId|isSecret|ModifyCommunityPostCommentRequest|modifyComment|isActive = false|fetchCommunityReplies" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift`
|
||||
- 기대 결과: 커뮤니티 작성/수정/삭제가 기존 repository로 연결된다.
|
||||
|
||||
- [x] **Task 2.3: 팬Talk 답글 작성/수정/삭제 처리**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift`
|
||||
- 작업 내용:
|
||||
- 작성 모드 send 시 `ExplorerRepository.writeCheers(parentCheersId:creatorId:content:)`를 호출한다.
|
||||
- `parentCheersId`는 원 팬Talk의 `fanTalkId`, `creatorId`는 context creator id를 전달한다.
|
||||
- 수정 모드 send 시 `ExplorerRepository.modifyCheers(cheersId:content:isActive:)`를 호출하고 `isActive`는 `nil`로 전달한다.
|
||||
- 삭제 confirm 시 `ExplorerRepository.modifyCheers(cheersId:content:isActive:)`를 호출하고 `content`는 `nil`, `isActive`는 `false`로 전달한다.
|
||||
- 성공 후 `replyText`와 `editingItem`을 초기화하고 `onFanTalkRefresh` callback을 호출한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "writeCheers|parentCheersId|modifyCheers|isActive: nil|isActive: false|onFanTalkRefresh|editingItem = nil" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift`
|
||||
- 기대 결과: 팬Talk 작성/수정/삭제가 기존 ExplorerRepository로 연결되고 성공 후 첫 페이지 재조회 callback이 호출된다.
|
||||
|
||||
### Phase 3: Figma 기반 UI 컴포넌트
|
||||
|
||||
- [x] **Task 3.1: back-only title bar 구현**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailTitleBar.swift`
|
||||
- 작업 내용:
|
||||
- Figma 기준으로 status bar 아래 60pt 높이 영역에 back chevron만 표시한다.
|
||||
- title text는 표시하지 않는다.
|
||||
- tap action은 부모에서 주입한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "struct CreatorChannelReplyDetailTitleBar|ic_back|chevron|frame\\(height: 60\\)|onTapBack|Text\\(" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailTitleBar.swift`
|
||||
- 기대 결과: back 전용 title bar가 있고 title text가 없어야 한다.
|
||||
|
||||
- [x] **Task 3.2: 원댓글/답글 feed 컴포넌트 구현**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailFeedView.swift`
|
||||
- 작업 내용:
|
||||
- 원댓글은 42pt 프로필, 닉네임, 상대 시간, 본문, 우측 더보기 버튼을 표시한다.
|
||||
- 답글이 없으면 답글 카드와 연결선을 표시하지 않는다.
|
||||
- 답글이 있으면 좌측 연결선과 `Color.gray900`, radius 14pt의 답글 카드를 표시한다.
|
||||
- 답글 카드는 20pt 프로필, 닉네임, 상대 시간, 본문, 우측 더보기 버튼을 표시한다.
|
||||
- 더보기 버튼은 `CreatorChannelReplyDetailActionPopup` 표시를 위한 item 선택 action을 호출한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "struct CreatorChannelReplyDetailFeedView|Color\\.gray900|Color\\.gray800|RoundedRectangle|42|20|selectedActionItem|CreatorChannelReplyDetailDisplayItem|Shape|Path" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailFeedView.swift`
|
||||
- 기대 결과: 원댓글/답글 카드, 답글 연결선, action item 선택 구조가 확인된다.
|
||||
|
||||
- [x] **Task 3.3: 하단 답글 input bar 구현**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailInputBar.swift`
|
||||
- 작업 내용:
|
||||
- 하단 고정 영역 높이는 Figma 기준 60pt로 시작한다.
|
||||
- placeholder는 `I18n.CreatorChannelReplyDetail.replyPlaceholder`를 사용한다.
|
||||
- 비활성 send 버튼은 `Color.gray900` 배경과 `ic_arrow_up_gray` 아이콘을 표시한다.
|
||||
- 활성 send 버튼은 `Color.soda400` 배경과 `ic_arrow_up_white` 아이콘을 표시한다.
|
||||
- `isSendEnabled == false`이면 tap 시 action을 호출하지 않는다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "struct CreatorChannelReplyDetailInputBar|replyPlaceholder|ic_arrow_up_gray|ic_arrow_up_white|Color\\.gray900|Color\\.soda400|isSendEnabled|onTapSend" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailInputBar.swift`
|
||||
- 기대 결과: 활성/비활성 send 버튼 상태가 PRD와 일치한다.
|
||||
|
||||
- [x] **Task 3.4: 수정/삭제 action popup 구현**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailActionPopup.swift`
|
||||
- 작업 내용:
|
||||
- Figma `669:40468` 기준으로 `수정하기`, `삭제하기` 항목을 표시한다.
|
||||
- item 권한에 따라 수정/삭제 노출 여부를 주입받는다.
|
||||
- `수정하기` tap은 ViewModel의 `beginEditing(item:)`으로 연결한다.
|
||||
- `삭제하기` tap은 삭제 confirm dialog 표시로 연결한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "struct CreatorChannelReplyDetailActionPopup|수정하기|삭제하기|canEdit|canDelete|onTapEdit|onTapDelete|Color\\.gray900|Color\\.gray700" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/Components/CreatorChannelReplyDetailActionPopup.swift`
|
||||
- 기대 결과: 수정/삭제 팝업과 권한별 노출 조건이 확인된다.
|
||||
|
||||
- [x] **Task 3.5: 답글 상세 화면 조립**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailView.swift`
|
||||
- 작업 내용:
|
||||
- `CreatorChannelReplyDetailTitleBar`, `CreatorChannelReplyDetailFeedView`, `CreatorChannelReplyDetailInputBar`를 배치한다.
|
||||
- 배경은 `Color.black`을 사용한다.
|
||||
- 하단 input bar는 safe area 하단에 고정한다.
|
||||
- 수정 모드 진입 시 input bar에 기존 답글 내용을 표시한다.
|
||||
- 삭제 confirm dialog와 toast/loading 표시를 연결한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "struct CreatorChannelReplyDetailView|CreatorChannelReplyDetailTitleBar|CreatorChannelReplyDetailFeedView|CreatorChannelReplyDetailInputBar|SodaDialog|sodaToast|Color\\.black|safeAreaInset|editingItem" SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailView.swift`
|
||||
- 기대 결과: 상세 화면 조립과 수정/삭제/오류 UI 연결이 확인된다.
|
||||
|
||||
### Phase 4: 커뮤니티 진입 연결
|
||||
|
||||
- [x] **Task 4.1: 커뮤니티 댓글 목록에서 답글 상세로 진입**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentListView.swift`
|
||||
- 수정: `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentItemView.swift`
|
||||
- 작업 내용:
|
||||
- 기존 V1 댓글 목록 전체를 교체하지 않고, 원댓글 item tap 또는 답글 텍스트 tap을 새 V2 답글 상세 route로 연결한다.
|
||||
- context는 `.community(creatorId:postId:parentComment:)`로 구성한다.
|
||||
- 커뮤니티는 본인 여부와 관계없이 진입 가능하게 한다.
|
||||
- 기존 댓글 작성 sheet 동작은 유지한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "creatorChannelReplyDetail|CreatorChannelReplyDetailContext|case \\.community|parentComment|postId|creatorId" SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentListView.swift SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/CreatorCommunityCommentItemView.swift`
|
||||
- 기대 결과: 커뮤니티 댓글에서 V2 답글 상세 route를 생성하는 코드가 확인된다.
|
||||
|
||||
- [x] **Task 4.2: V2 커뮤니티 탭의 댓글 흐름 회귀 확인**
|
||||
- 대상 파일:
|
||||
- 확인: `SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityTabView.swift`
|
||||
- 작업 내용:
|
||||
- 현재 댓글 버튼이 여는 `CreatorCommunityCommentListView` sheet가 유지되는지 확인한다.
|
||||
- sheet 내부 댓글 item에서 새 답글 상세 route로 진입 가능한지 확인한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "CreatorCommunityCommentListView|isShowCommentListView|NavigationStack|creatorChannelReplyDetail" SodaLive/Sources/V2/CreatorChannel/Community/CreatorChannelCommunityTabView.swift SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment`
|
||||
- 기대 결과: V2 커뮤니티 탭에서 댓글 목록 진입과 답글 상세 진입 경로가 함께 확인된다.
|
||||
|
||||
### Phase 5: 팬Talk 진입 연결
|
||||
|
||||
- [x] **Task 5.1: 팬Talk item tap action 추가**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/CreatorChannel/FanTalk/Components/CreatorChannelFanTalkListItem.swift`
|
||||
- 수정: `SodaLive/Sources/V2/CreatorChannel/FanTalk/CreatorChannelFanTalkTabView.swift`
|
||||
- 작업 내용:
|
||||
- `CreatorChannelFanTalkListItem`에 `onTapDetail` closure를 추가한다.
|
||||
- `CreatorChannelFanTalkTabView`에서 `isOwnCreatorChannel == true`일 때만 detail tap action을 route로 연결한다.
|
||||
- 본인 채널이 아니면 item tap으로 상세 화면에 진입하지 않는다.
|
||||
- 더보기/신고 버튼 tap은 상세 진입과 충돌하지 않게 button action으로 유지한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "onTapDetail|isOwnCreatorChannel|creatorChannelReplyDetail|case \\.fanTalk|contentShape|Button" SodaLive/Sources/V2/CreatorChannel/FanTalk/Components/CreatorChannelFanTalkListItem.swift SodaLive/Sources/V2/CreatorChannel/FanTalk/CreatorChannelFanTalkTabView.swift`
|
||||
- 기대 결과: 팬Talk 본인 채널에서만 상세 진입 route가 생성된다.
|
||||
|
||||
- [x] **Task 5.2: 팬Talk 성공 후 첫 페이지 재조회 callback 연결**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/CreatorChannel/FanTalk/CreatorChannelFanTalkTabView.swift`
|
||||
- 수정: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift`
|
||||
- 작업 내용:
|
||||
- 팬Talk detail context 생성 시 `onFanTalkRefresh`에 `viewModel.fetchFirstPage(creatorId:)`를 전달한다.
|
||||
- 팬Talk 답글 작성/수정/삭제 성공 후 callback을 호출한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "onFanTalkRefresh|fetchFirstPage\\(creatorId: creatorId\\)|writeCheers|modifyCheers" SodaLive/Sources/V2/CreatorChannel/FanTalk/CreatorChannelFanTalkTabView.swift SodaLive/Sources/V2/CreatorChannel/ReplyDetail/CreatorChannelReplyDetailViewModel.swift`
|
||||
- 기대 결과: 팬Talk 답글 mutation 성공 후 첫 페이지 재조회 연결이 확인된다.
|
||||
|
||||
### Phase 6: 문구, asset, 프로젝트 등록
|
||||
|
||||
- [x] **Task 6.1: I18n 문구 추가**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/I18n/I18n.swift`
|
||||
- 작업 내용:
|
||||
- `I18n.CreatorChannelReplyDetail.replyPlaceholder`에 `답글을 입력하세요` ko/en/ja 문구를 추가한다.
|
||||
- 수정/삭제 문구는 기존 공통 문구를 우선 재사용하고, 새 scope 문구가 필요하면 같은 enum에 추가한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "CreatorChannelReplyDetail|replyPlaceholder|답글을 입력하세요" SodaLive/Sources/I18n/I18n.swift`
|
||||
- 기대 결과: 답글 placeholder 다국어 문구가 확인된다.
|
||||
|
||||
- [x] **Task 6.2: asset catalog와 프로젝트 파일 등록**
|
||||
- 대상 파일:
|
||||
- 확인: `SodaLive/Resources/Assets.xcassets/v2/ic_arrow_up_gray.imageset/Contents.json`
|
||||
- 확인: `SodaLive/Resources/Assets.xcassets/v2/ic_arrow_up_white.imageset/Contents.json`
|
||||
- 수정: `SodaLive.xcodeproj/project.pbxproj`
|
||||
- 작업 내용:
|
||||
- `ic_arrow_up_gray`, `ic_arrow_up_white` asset이 Xcode asset catalog에 존재하는지 확인한다.
|
||||
- 신규 Swift 파일이 앱 target에 포함되도록 프로젝트 파일을 등록한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "ic_arrow_up_gray|ic_arrow_up_white" SodaLive/Resources/Assets.xcassets/v2 SodaLive.xcodeproj/project.pbxproj`
|
||||
- 실행 명령: `rg "CreatorChannelReplyDetailView|CreatorChannelReplyDetailViewModel|CreatorChannelReplyDetailInputBar" SodaLive.xcodeproj/project.pbxproj`
|
||||
- 기대 결과: arrow asset과 신규 Swift 파일 target 등록이 확인된다.
|
||||
|
||||
### Phase 7: 빌드와 수동 검증
|
||||
|
||||
- [x] **Task 7.1: 정적 검색 검증**
|
||||
- 대상 파일:
|
||||
- 확인: `SodaLive/Sources/V2/CreatorChannel/ReplyDetail/**`
|
||||
- 확인: `SodaLive/Sources/V2/CreatorChannel/FanTalk/**`
|
||||
- 확인: `SodaLive/Sources/Explorer/Profile/CreatorCommunity/All/Comment/**`
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "CreatorChannelReplyDetail|createCommunityPostComment|writeCheers|modifyCheers|ic_arrow_up_gray|ic_arrow_up_white|isSecret|onFanTalkRefresh" SodaLive/Sources`
|
||||
- 기대 결과: 답글 상세 화면, 기존 API 재사용, send icon, 비밀 답글, 팬Talk refresh callback이 모두 확인된다.
|
||||
|
||||
- [x] **Task 7.2: Debug 빌드 검증**
|
||||
- 대상 파일:
|
||||
- 확인: `SodaLive.xcworkspace`
|
||||
- 검증 기준:
|
||||
- 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`
|
||||
- 기대 결과: `** BUILD SUCCEEDED **`
|
||||
|
||||
- [ ] **Task 7.3: 수동 UI 검증**
|
||||
- 대상 파일:
|
||||
- 확인: 앱 런타임
|
||||
- 검증 기준:
|
||||
- 커뮤니티 댓글 item 터치 시 본인 여부와 관계없이 답글 상세 화면에 진입한다.
|
||||
- 팬Talk item 터치 시 본인 채널에서만 답글 상세 화면에 진입한다.
|
||||
- 답글 없음 상태가 Figma `669:40462`와 같은 정보 구조로 표시된다.
|
||||
- 답글 있음 상태가 Figma `669:40468`와 같은 답글 카드/연결선 구조로 표시된다.
|
||||
- 입력값이 없으면 send 버튼이 `gray900` + `ic_arrow_up_gray` 상태이고 API를 호출하지 않는다.
|
||||
- 입력값이 있으면 send 버튼이 `soda400` + `ic_arrow_up_white` 상태이고 기존 답글 작성 API를 호출한다.
|
||||
- 커뮤니티 비밀 원댓글에 답글 작성 시 `isSecret == true`로 전송된다.
|
||||
- 답글 `수정하기` 터치 시 하단 입력창에 기존 답글 내용이 채워지고 send 시 수정 API가 호출된다.
|
||||
- 답글 `삭제하기` confirm 시 삭제 API가 호출되고 목록이 갱신된다.
|
||||
- 팬Talk 답글 작성/수정/삭제 성공 후 팬Talk 목록 첫 페이지가 재조회된다.
|
||||
|
||||
## 검증 기록
|
||||
|
||||
- 2026-07-07: PRD `docs/20260707_글_상세_답글_쓰기/prd.md`, 문서 정책, 빌드/검증 가이드, 기존 팬Talk plan-task 형식을 확인하고 계획 문서를 작성했다.
|
||||
- 2026-07-07: 답글 상세 구현, 정적 검색 검증, `SodaLive-dev` Debug 빌드 검증을 완료했다. 런타임 수동 UI 검증(Task 7.3)은 미수행 상태로 남겼다.
|
||||
- 2026-07-07: 리뷰 지적 사항을 반영해 팬Talk 임시 답글 row 생성을 제거하고 FanTalk 수정/삭제에 `id > 0` guard를 추가했다. 답글 action popup은 row frame 기반 위치로 변경했고, popup 문구는 `I18n.Explorer.edit`, `I18n.Common.delete`를 사용하도록 수정했다. 정적 검색, ast-grep 검색, `SodaLive-dev` Debug 빌드 검증을 완료했다.
|
||||
- 2026-07-07: 추가 리뷰 지적 사항을 반영해 FanTalk 답글 갱신이 parent `fanTalkId`를 찾을 때까지 `hasNext` 기반으로 페이지를 조회하도록 수정했다. 커뮤니티 답글 상세는 `totalCount` 기반 pagination과 마지막 답글 `onAppear` 추가 조회를 연결했고, 커뮤니티 댓글 item의 전체 row tap은 제거해 본문/답글 텍스트만 답글 상세로 진입하도록 제한했다. 정적 검색, ast-grep 검색, `SodaLive-dev` Debug 빌드 검증을 완료했다.
|
||||
192
docs/20260707_글_상세_답글_쓰기/prd.md
Normal file
192
docs/20260707_글_상세_답글_쓰기/prd.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# PRD: 글 상세 - 답글 쓰기
|
||||
|
||||
## 1. Overview
|
||||
커뮤니티 댓글 또는 팬Talk 댓글을 터치했을 때 진입하는 답글 쓰기 상세 화면을 제공한다. 화면은 선택한 원댓글과 원댓글의 답글 목록, 하단 답글 입력 바를 표시하며, 답글 작성 API는 기존 답글 쓰기 API를 그대로 사용한다.
|
||||
|
||||
Figma 참조:
|
||||
- 답글 없음: `669:40462`, `https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=669-40462&m=dev`
|
||||
- 답글 있음: `669:40468`, `https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=669-40468&m=dev`
|
||||
|
||||
## 2. Problem
|
||||
- 현재 V2 크리에이터 채널 커뮤니티 탭은 댓글 버튼에서 V1 `CreatorCommunityCommentListView` sheet를 열고 있어, Figma 기준의 댓글 상세/답글 쓰기 화면이 없다.
|
||||
- V2 팬Talk 목록은 원글과 크리에이터 답글을 표시하지만, 팬Talk 댓글을 터치해 별도 상세 화면에서 답글을 작성하는 진입점이 없다.
|
||||
- 커뮤니티 댓글 답글 쓰기와 팬Talk 답글 쓰기는 이미 기존 API가 있으므로 새 API를 만들 필요가 없지만, V2 화면/진입 권한/입력 버튼 상태 규칙을 명확히 해야 한다.
|
||||
|
||||
## 3. Goals
|
||||
- 커뮤니티 댓글 또는 팬Talk 댓글을 터치하면 글 상세 - 답글 쓰기 화면으로 진입한다.
|
||||
- 팬Talk 상세는 본인 채널에서만 진입할 수 있다.
|
||||
- 커뮤니티 댓글 상세는 본인 채널/본인 댓글 여부와 관계없이 진입할 수 있다.
|
||||
- 화면은 Figma `669:40462`, `669:40468` 기준으로 상단 back 버튼, 원댓글 영역, 답글 영역, 하단 답글 input bar를 표시한다.
|
||||
- 답글이 없으면 원댓글만 표시하고 답글 카드/연결선은 표시하지 않는다.
|
||||
- 답글이 있으면 원댓글 아래에 좌측 연결선과 답글 카드를 표시한다.
|
||||
- 답글 입력값이 있으면 send 버튼을 활성화한다.
|
||||
- 답글 입력값이 없으면 send 버튼을 비활성화한다.
|
||||
- 답글 작성 성공 후 입력값을 비우고 답글 목록을 갱신한다.
|
||||
- 기존 커뮤니티 답글 API와 기존 팬Talk 답글 API를 그대로 사용한다.
|
||||
- V2 패키지 하위의 기존 재사용 후보를 우선 검토하고, 중복 UI 구현을 최소화한다.
|
||||
|
||||
## 4. Non-Goals
|
||||
- 커뮤니티 댓글 작성/수정/삭제 API를 새로 만들지 않는다.
|
||||
- 팬Talk 답글 작성/수정/삭제 API를 새로 만들지 않는다.
|
||||
- 커뮤니티 게시글 상세 화면 전체를 새로 설계하지 않는다.
|
||||
- 팬Talk 일반 작성/수정 화면을 변경하지 않는다.
|
||||
- 기존 V1 댓글 화면 전체를 V2로 일괄 교체하지 않는다.
|
||||
- 신고, 차단, 프로필 상세 진입 정책을 새로 설계하지 않는다.
|
||||
- Figma localhost asset URL을 앱 코드에 직접 사용하지 않는다.
|
||||
- `Pods/**`, `generated/**`, `build/**`는 수정하지 않는다.
|
||||
|
||||
## 5. Target Users
|
||||
- 커뮤니티 댓글에 답글을 남기려는 사용자
|
||||
- 본인 채널의 팬Talk에 답글을 남기려는 크리에이터
|
||||
|
||||
## 6. User Stories
|
||||
- 사용자는 커뮤니티 댓글을 터치해 해당 댓글의 답글 상세 화면으로 들어가고 답글을 작성할 수 있다.
|
||||
- 크리에이터는 본인 채널의 팬Talk 댓글을 터치해 팬Talk 상세 화면으로 들어가고 팬에게 답글을 작성할 수 있다.
|
||||
- 사용자는 답글 입력값이 없을 때 send 버튼이 비활성화되어 빈 답글이 전송되지 않는 것을 알 수 있다.
|
||||
- 사용자는 답글 입력값이 있을 때 send 버튼이 활성화되어 바로 전송할 수 있다.
|
||||
|
||||
## 7. Core Requirements
|
||||
|
||||
### 7.1 Entry rules
|
||||
- 커뮤니티 댓글 상세:
|
||||
- 커뮤니티 댓글 item 터치 시 진입한다.
|
||||
- 본인 채널 여부, 댓글 작성자 여부와 관계없이 진입할 수 있다.
|
||||
- 기존 커뮤니티 댓글 목록/댓글 버튼 진입 흐름에서 원댓글을 선택할 수 있어야 한다.
|
||||
- 팬Talk 상세:
|
||||
- 팬Talk 댓글 item 터치 시 진입한다.
|
||||
- `isOwnCreatorChannel == true`인 본인 채널에서만 진입할 수 있다.
|
||||
- 본인 채널이 아니면 팬Talk item 터치로 상세 화면에 진입하지 않는다.
|
||||
|
||||
### 7.2 Screen layout
|
||||
- 배경은 `Color.black`을 사용한다.
|
||||
- 상단은 Figma처럼 title text 없이 back chevron만 있는 title bar를 표시한다.
|
||||
- 원댓글 영역은 작성자 프로필, 닉네임, 상대 시간, 본문, 우측 액션을 표시한다.
|
||||
- 답글이 없는 경우 원댓글 아래에는 빈 영역을 유지하고 답글 카드/연결선을 표시하지 않는다.
|
||||
- 답글이 있는 경우 원댓글 아래에 답글 카드를 표시한다.
|
||||
- 답글 카드 배경은 `Color.gray900`, radius는 14pt 기준을 사용한다.
|
||||
- 답글 카드에는 답글 작성자 프로필, 닉네임, 상대 시간, 본문을 표시한다.
|
||||
- 원댓글과 답글 카드 사이 좌측에는 Figma처럼 연결선을 표시한다.
|
||||
- 하단 input bar는 화면 하단에 고정하고 상단 border를 표시한다.
|
||||
- input field placeholder는 `답글을 입력하세요`를 표시한다.
|
||||
|
||||
### 7.3 Send button states
|
||||
- 활성화 기준은 `replyText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false`이다.
|
||||
- 활성화 상태:
|
||||
- button background: `Color.soda400`
|
||||
- icon: `ic_arrow_up_white`
|
||||
- tap 시 답글 작성 API를 호출한다.
|
||||
- 비활성화 상태:
|
||||
- button background: `Color.gray900`
|
||||
- icon: `ic_arrow_up_gray`
|
||||
- tap 시 API를 호출하지 않는다.
|
||||
- 입력값이 공백 또는 줄바꿈만 있으면 비활성화 상태로 처리한다.
|
||||
- 전송 중 중복 tap으로 같은 답글이 여러 번 등록되지 않도록 한다.
|
||||
|
||||
### 7.4 Community reply API reuse
|
||||
- 커뮤니티 답글 작성은 기존 `CreatorCommunityRepository.createCommunityPostComment(comment:postId:parentId:isSecret:)`를 사용한다.
|
||||
- `parentId`에는 선택한 원댓글의 comment id를 전달한다.
|
||||
- `postId`에는 원댓글이 속한 커뮤니티 post id를 전달한다.
|
||||
- 커뮤니티 원댓글이 비밀댓글이면 답글도 자동으로 비밀 답글로 작성한다.
|
||||
- 커뮤니티 원댓글이 일반댓글이면 답글도 일반 답글로 작성한다.
|
||||
- 커뮤니티 댓글 상세에서는 별도 비밀 답글 toggle을 제공하지 않는다.
|
||||
- `isSecret`에는 원댓글의 `isSecret` 값을 전달한다.
|
||||
- 커뮤니티 답글 목록 조회는 기존 `CreatorCommunityRepository.getCommentReplyList(commentId:page:size:)`를 사용한다.
|
||||
- 커뮤니티 답글 수정/삭제가 화면 액션에 포함되는 경우 기존 `CreatorCommunityRepository.modifyComment(request:)`를 사용한다.
|
||||
|
||||
### 7.5 FanTalk reply API reuse
|
||||
- 팬Talk 답글 작성은 기존 `ExplorerRepository.writeCheers(parentCheersId:creatorId:content:)`를 사용한다.
|
||||
- `parentCheersId`에는 선택한 팬Talk 원댓글의 `fanTalkId` 또는 기존 cheers id에 해당하는 값을 전달한다.
|
||||
- `creatorId`에는 현재 크리에이터 채널 id를 전달한다.
|
||||
- 팬Talk 답글 수정/삭제가 화면 액션에 포함되는 경우 기존 `ExplorerRepository.modifyCheers(cheersId:content:isActive:)`를 사용한다.
|
||||
- 팬Talk 목록 응답의 `creatorReplies`가 상세 화면의 초기 답글 데이터로 충분하지 않으면 기존 cheers 목록 API 또는 서버 제공 상세/목록 API 재사용 가능 여부를 구현 전 확인한다.
|
||||
|
||||
### 7.6 Reply list refresh
|
||||
- 화면 진입 시 선택한 원댓글과 기존 답글 목록을 표시한다.
|
||||
- 커뮤니티 댓글 상세는 기존 `getCommentReplyList(commentId:page:size:)`로 답글 목록을 조회한다.
|
||||
- 팬Talk 상세는 진입 시 전달받은 `creatorReplies`를 우선 표시한다.
|
||||
- 팬Talk 답글 작성 성공 후에는 팬Talk 목록 첫 페이지를 재조회해 최신 답글을 반영한다.
|
||||
- 답글 작성 성공 후:
|
||||
- input field를 빈 값으로 초기화한다.
|
||||
- send 버튼을 비활성화 상태로 되돌린다.
|
||||
- 답글 목록을 갱신한다.
|
||||
- 답글 작성 실패 시 기존 V2 화면 관례대로 toast 또는 dialog로 오류를 표시하고 입력값은 유지한다.
|
||||
|
||||
### 7.7 Actions
|
||||
- 원댓글/답글의 더보기 버튼은 기존 권한 규칙을 따른다.
|
||||
- Figma의 원댓글/답글 더보기 메뉴는 이번 범위에서 수정/삭제까지 구현한다.
|
||||
- 본인이 작성한 원댓글 또는 답글이면 `수정하기`, `삭제하기`를 제공한다.
|
||||
- 본인 채널의 팬Talk 답글은 크리에이터 본인이 수정/삭제할 수 있어야 한다.
|
||||
- `수정하기`를 터치하면 하단 답글 입력창에 수정 대상 답글 내용을 채운다.
|
||||
- 답글 수정 모드에서 send 버튼을 터치하면 신규 답글 작성 API가 아니라 기존 수정 API를 호출한다.
|
||||
- 답글 수정 성공 후 수정 모드를 해제하고 input field를 비운 뒤 답글 목록을 갱신한다.
|
||||
- 답글 수정 모드에서 입력값이 원래 답글과 같거나 공백이면 API를 호출하지 않는다.
|
||||
- `삭제하기`를 터치하면 삭제 확인 dialog를 표시하고, 확인 시 기존 삭제 API를 호출한다.
|
||||
- 삭제 확인 dialog는 기존 `SodaDialog` 또는 V2 공용 모달 중 구현 시점에 더 작은 변경으로 맞는 방식을 사용한다.
|
||||
|
||||
### 7.8 Reusable V2 candidates
|
||||
- `SodaLive/Sources/V2/CreatorChannel/FanTalk/Components/CreatorChannelFanTalkListItem.swift`
|
||||
- 팬Talk 원댓글, 답글 카드, 좌측 연결선(`CreatorChannelFanTalkReplyConnector`) 구조가 Figma 답글 있음 화면과 가장 가깝다.
|
||||
- 상세 화면의 원댓글/답글 표시 컴포넌트 후보로 우선 검토한다.
|
||||
- `SodaLive/Sources/V2/CreatorChannel/FanTalk/Components/CreatorChannelFanTalkActionPopup.swift`
|
||||
- `수정하기`, `삭제하기` anchored popup UI가 Figma `669:40468`의 팝업과 유사하다.
|
||||
- `SodaLive/Sources/V2/CreatorChannel/Community/Components/CreatorChannelCommunityListItem.swift`
|
||||
- 커뮤니티 작성자 header, 본문, 댓글 버튼, 더보기 버튼 규칙을 재사용 후보로 검토한다.
|
||||
- 상세 화면용으로는 게시글 카드 전체보다 header/reaction/action 규칙 참고에 가깝다.
|
||||
- `SodaLive/Sources/V2/Component/Modal/SodaV2ActionModal.swift`
|
||||
- 삭제/확인성 액션이 필요할 때 V2 공용 모달 후보로 검토한다.
|
||||
- `SodaLive/Sources/V2/Component/DefaultTitleBar.swift`, `SodaLive/Sources/V2/Component/TitleBar.swift`
|
||||
- 상단 back-only title bar 구현 시 기존 title bar 스타일 재사용 가능성을 확인한다.
|
||||
- `SodaLive/Sources/V2/Component/Text/ExpandableTextView.swift`
|
||||
- 원댓글 본문이 길 때 접기/펼치기 정책이 필요해지면 재사용 후보로 검토한다. Figma 상세 화면은 본문을 그대로 표시하므로 기본 요구사항은 일반 `Text` 표시이다.
|
||||
- `SodaLive/Sources/V2/CreatorChannel/FanTalk/Models/CreatorChannelFanTalkTabResponse.swift`
|
||||
- 팬Talk 원댓글/답글 모델(`CreatorChannelFanTalkItemResponse`, `CreatorChannelFanTalkReplyResponse`)을 상세 화면 전달 모델 후보로 검토한다.
|
||||
|
||||
## 8. UX / UI Expectations
|
||||
- 화면 진입과 back 동작은 기존 SwiftUI navigation 흐름과 일관되어야 한다.
|
||||
- 하단 input bar는 키보드 표시 여부와 관계없이 입력 상태를 유지해야 한다.
|
||||
- 빈 답글은 전송되지 않아야 한다.
|
||||
- send 버튼 활성/비활성 상태는 배경색과 아이콘으로 즉시 구분되어야 한다.
|
||||
- 답글 작성 성공 후 사용자는 새 답글이 목록에 반영된 것을 확인할 수 있어야 한다.
|
||||
|
||||
## 9. Success Criteria
|
||||
- 커뮤니티 댓글 item을 터치하면 본인 여부와 관계없이 글 상세 - 답글 쓰기 화면에 진입한다.
|
||||
- 팬Talk 댓글 item은 본인 채널에서만 글 상세 - 답글 쓰기 화면에 진입한다.
|
||||
- 답글이 없는 상태는 Figma `669:40462`처럼 원댓글과 하단 input bar만 표시한다.
|
||||
- 답글이 있는 상태는 Figma `669:40468`처럼 답글 카드와 좌측 연결선을 표시한다.
|
||||
- 입력값이 없으면 send 버튼 배경이 `gray900`, 아이콘이 `ic_arrow_up_gray`이고 API를 호출하지 않는다.
|
||||
- 입력값이 있으면 send 버튼 배경이 `soda400`, 아이콘이 `ic_arrow_up_white`이고 tap 시 기존 답글 작성 API를 호출한다.
|
||||
- 커뮤니티 답글 작성 시 기존 `CreatorCommunityRepository.createCommunityPostComment`가 `parentId`와 함께 호출된다.
|
||||
- 커뮤니티 원댓글이 비밀댓글이면 답글 작성 시 `isSecret == true`로 전송된다.
|
||||
- 커뮤니티 원댓글이 일반댓글이면 답글 작성 시 `isSecret == false`로 전송된다.
|
||||
- 팬Talk 답글 작성 시 기존 `ExplorerRepository.writeCheers`가 `parentCheersId`와 함께 호출된다.
|
||||
- 답글 작성 성공 후 input field가 비워지고 답글 목록이 갱신된다.
|
||||
- 팬Talk 답글 작성 성공 후 팬Talk 목록 첫 페이지가 재조회된다.
|
||||
- 원댓글/답글 더보기 메뉴에서 수정/삭제 액션을 사용할 수 있다.
|
||||
- 답글 `수정하기`를 터치하면 하단 답글 입력창에 기존 답글 내용이 입력되고, send 시 기존 수정 API가 호출된다.
|
||||
- 답글 삭제 확인 시 기존 삭제 API가 호출되고 성공 후 답글 목록이 갱신된다.
|
||||
- V2 재사용 후보를 검토한 뒤 중복 구현이 필요한 경우에만 새 컴포넌트를 작성한다.
|
||||
|
||||
## 10. Technical Constraints
|
||||
- 기능 변경은 `SodaLive/Sources/V2/**` 하위에서 우선 해결한다.
|
||||
- 신규 화면, ViewModel, Repository 연결 코드는 V2 하위에 작성한다.
|
||||
- 기존 V1 API wrapper를 그대로 호출할 수 있으나, V2 화면 상태와 결합되는 코드는 V2 ViewModel에 둔다.
|
||||
- 신규 공용 컴포넌트가 필요하면 `SodaLive/Sources/V2/Component/**` 아래에 둔다.
|
||||
- 특정 화면에서만 쓰는 컴포넌트는 해당 상세 화면의 `Components` 하위에 둔다.
|
||||
- 신규 문구가 필요하면 `SodaLive/Sources/I18n/I18n.swift`에 ko/en/ja를 추가한다.
|
||||
- 프로젝트 설정 변경은 신규 Swift 파일 target 등록이 필요한 경우에만 수행한다.
|
||||
|
||||
## 11. Assumptions
|
||||
- 팬Talk API의 `fanTalkId`는 기존 cheers API의 `cheersId`와 동일하게 `parentCheersId` 또는 `cheersId`로 사용할 수 있다.
|
||||
- 커뮤니티 댓글 원댓글 데이터는 상세 화면 진입 시 이미 확보되어 있거나 기존 댓글 목록 응답 모델로 전달할 수 있다.
|
||||
- 커뮤니티 답글 목록은 기존 `getCommentReplyList` 응답으로 충분하다.
|
||||
- 팬Talk 상세의 최신 답글 목록 갱신은 팬Talk 목록 첫 페이지 재조회로 처리한다.
|
||||
|
||||
## 12. Open Questions
|
||||
- 해당 없음
|
||||
|
||||
## 13. Verification Notes
|
||||
- 2026-07-07: Figma `get_design_context`와 `get_screenshot`으로 `669:40462`, `669:40468`을 확인했다.
|
||||
- 2026-07-07: 기존 커뮤니티 답글 작성/조회 API로 `CreatorCommunityRepository.createCommunityPostComment`, `CreatorCommunityRepository.getCommentReplyList`, `CreatorCommunityRepository.modifyComment`를 확인했다.
|
||||
- 2026-07-07: 기존 팬Talk 답글 작성/수정 API로 `ExplorerRepository.writeCheers`, `ExplorerRepository.modifyCheers`, `PostWriteCheersRequest(parentId:creatorId:content:)`를 확인했다.
|
||||
- 2026-07-07: V2 재사용 후보로 `CreatorChannelFanTalkListItem`, `CreatorChannelFanTalkActionPopup`, `CreatorChannelCommunityListItem`, `SodaV2ActionModal`, V2 title bar 컴포넌트를 확인했다.
|
||||
- 2026-07-07: 사용자 확인 사항을 반영해 팬Talk 작성 성공 후 첫 페이지 재조회, 커뮤니티 비밀 원댓글의 답글 자동 비밀 처리, 원댓글/답글 수정/삭제 및 답글 입력창 기반 수정 요구사항을 추가했다.
|
||||
Reference in New Issue
Block a user