docs(creator): 채널 홈 탭 채팅 계획을 보완한다

This commit is contained in:
2026-06-12 23:47:29 +09:00
parent 3514104e7c
commit 92fdd6ab54
2 changed files with 41 additions and 19 deletions

View File

@@ -23,7 +23,7 @@
- `라이브`, `오디오`, `시리즈`, `커뮤니티`, `팬Talk`, `후원` 탭의 상세 컨텐츠와 pagination은 구현하지 않는다.
- 홈 API는 `GET /api/v2/creator-channels/{creatorId}/home`을 사용한다.
- 팔로우/알림 변경은 기존 `UserRepository.creatorFollow()``CreatorFollowNotifyFragment` 사용 패턴을 재사용한다.
- `대화하기``ChatRoomActivity`, `DM 보내기``DmChatRoomActivity.newIntentByCreatorId()`로 이동한다.
- `대화하기``TalkApi.createChatRoom` 호출 후 반환된 `chatRoomId``ChatRoomActivity`, `DM 보내기``DmChatRoomActivity.newIntentByCreatorId()`로 이동한다.
- title-bar black 전환 기준은 title-bar와 tab-bar의 실제 거리 및 프로필 이미지가 절반 이상 사라졌는지를 함께 사용한다.
- 구현 완료 후 최소 다음 명령을 실행한다.
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*"`
@@ -77,7 +77,7 @@
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/data/CreatorChannelHomeModels.kt`
- PRD의 서버 DTO를 Android DTO로 정의한다.
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/data/CreatorChannelHomeRepository.kt`
- 홈 API 기존 크리에이터 팔로우 API 호출을 ViewModel에 제공한다.
- 홈 API, 기존 크리에이터 팔로우 API, 기존 `TalkApi.createChatRoom` 호출을 ViewModel에 제공한다.
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/model/CreatorChannelHomeUiModels.kt`
- 화면 상태, tab 항목, header/action/home section UI model을 정의한다.
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/model/CreatorChannelHomeMappers.kt`
@@ -110,21 +110,26 @@
### Phase 1: 기존 구조 확인과 작업 경계 고정
- [ ] **Task 1.1: 기존 v2 홈/채팅/팔로우 구조 확인**
- [x] **Task 1.1: 기존 v2 홈/채팅/팔로우 구조 확인**
- 확인:
- `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/data/HomeRecommendationApi.kt`
- `app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeRecommendationViewModel.kt`
- `app/src/main/java/kr/co/vividnext/sodalive/user/UserRepository.kt`
- `app/src/main/java/kr/co/vividnext/sodalive/explorer/profile/CreatorFollowNotifyFragment.kt`
- `app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/ChatRoomActivity.kt`
- `app/src/main/java/kr/co/vividnext/sodalive/chat/talk/TalkApi.kt`
- `app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/CreateChatRoomRequest.kt`
- `app/src/main/java/kr/co/vividnext/sodalive/chat/talk/room/CreateChatRoomResponse.kt`
- `app/src/main/java/kr/co/vividnext/sodalive/chat/character/detail/detail/CharacterDetailViewModel.kt`
- `app/src/main/java/kr/co/vividnext/sodalive/v2/main/chat/dm/DmChatRoomActivity.kt`
- `app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt`
- 검증:
- REST는 Retrofit + RxJava3 + `ApiResponse<T>` 패턴을 따른다.
- AI 채팅 이동은 `TalkApi.createChatRoom(CreateChatRoomRequest(characterId))` 호출 후 `CreateChatRoomResponse.chatRoomId`를 받아 `ChatRoomActivity.newIntent(context, roomId)`로 이동하는 패턴을 따른다.
- DM 이동은 `DmChatRoomActivity.newIntentByCreatorId(context, creatorId)`를 사용할 수 있음을 확인한다.
- 팔로우/알림 변경은 `UserRepository.creatorFollow(creatorId, follow, notify)`를 재사용할 수 있음을 확인한다.
- 팔로우/알림 변경은 `UserRepository.creatorFollow(creatorId, follow, notify, token)`를 재사용할 수 있음을 확인한다.
- [ ] **Task 1.2: 구현 제외 범위 재확인**
- [x] **Task 1.2: 구현 제외 범위 재확인**
- 확인:
- `docs/20260611_크리에이터_채널_홈_탭/prd.md`
- 제외:
@@ -184,6 +189,7 @@
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/data/CreatorChannelHomeModels.kt`
- 작업:
- PRD의 `CreatorChannelHomeResponse`와 하위 DTO를 모두 `@Keep`, `@SerializedName` 기반 data class로 추가한다.
- `CreatorChannelCreatorResponse`에는 `creatorId: Long``characterId: Long?`를 모두 추가한다.
- `CreatorChannelScheduleResponse.type`은 공용 `CreatorActivityType`을 사용한다.
- Retrofit endpoint는 `@GET("/api/v2/creator-channels/{creatorId}/home")`로 정의한다.
- 반환 타입은 `Single<ApiResponse<CreatorChannelHomeResponse>>`를 사용한다.
@@ -197,7 +203,8 @@
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/data/CreatorChannelHomeRepository.kt`
- 작업:
- `getHome(creatorId: Long, token: String)`에서 홈 API를 호출한다.
- 기존 `UserRepository`를 생성자 인자로 받아 `followCreator(creatorId, follow, notify)`를 얇게 위임한다.
- 기존 `UserRepository`를 생성자 인자로 받아 `followCreator(creatorId, follow, notify, token)`를 얇게 위임한다.
- 기존 `TalkApi`를 생성자 인자로 받아 `createChatRoom(characterId, token)`에서 `CreateChatRoomRequest(characterId)``TalkApi.createChatRoom`을 호출한다.
- token 문자열은 기존 ViewModel 패턴과 맞춰 ViewModel에서 `"Bearer ${SharedPreferenceManager.token}"`로 만든다.
- 검증 명령:
- `./gradlew :app:compileDebugKotlin`
@@ -210,7 +217,8 @@
- 작업:
- `CreatorChannelHomeApi`, `CreatorChannelHomeRepository`, `CreatorChannelHomeViewModel` import를 추가한다.
- `networkModule``single { ApiBuilder().build(get(), CreatorChannelHomeApi::class.java) }`를 추가한다.
- `repositoryModule` `factory { CreatorChannelHomeRepository(api = get(), userRepository = get()) }`를 추가한다.
- 기존 `networkModule` `TalkApi` 등록을 재사용한다.
- `repositoryModule``factory { CreatorChannelHomeRepository(api = get(), userRepository = get(), talkApi = get()) }`를 추가한다.
- `viewModelModule``viewModel { CreatorChannelHomeViewModel(get()) }`를 추가한다.
- 검증 명령:
- `./gradlew :app:compileDebugKotlin`
@@ -225,7 +233,7 @@
- 생성:
- `app/src/test/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeMapperTest.kt`
- 작업:
- `creator.isFollow`, `creator.isNotify`, `creator.isAiChatAvailable`, `creator.isDmAvailable`가 UI model에 그대로 반영되는지 검증한다.
- `creator.characterId`, `creator.isFollow`, `creator.isNotify`, `creator.isAiChatAvailable`, `creator.isDmAvailable`가 UI model에 그대로 반영되는지 검증한다.
- tab 목록이 `홈`, `라이브`, `오디오`, `시리즈`, `커뮤니티`, `팬Talk`, `후원` 순서인지 검증한다.
- `currentLive`, `latestAudioContent`가 null이면 해당 홈 section이 생성되지 않는지 검증한다.
- 빈 list는 crash 없이 빈 section 또는 hidden section 정책으로 매핑되는지 검증한다.
@@ -242,7 +250,7 @@
- 작업:
- `CreatorChannelHomeUiState.Loading`, `Content`, `Empty`, `Error`를 정의한다.
- `CreatorChannelTab.Home`, `Live`, `Audio`, `Series`, `Community`, `FanTalk`, `Donation`을 정의한다.
- `CreatorChannelHeaderUiModel``creatorId`, `nickname`, `profileImageUrl`, `followerCount`, `isFollow`, `isNotify`, `isAiChatAvailable`, `isDmAvailable`을 둔다.
- `CreatorChannelHeaderUiModel``creatorId`, `characterId`, `nickname`, `profileImageUrl`, `followerCount`, `isFollow`, `isNotify`, `isAiChatAvailable`, `isDmAvailable`을 둔다.
- 홈 section은 Figma 순서에 맞춰 `sealed interface CreatorChannelHomeSection`으로 정의한다.
- `CreatorChannelHomeResponse.toUiContent()` 매퍼를 구현한다.
- 검증 명령:
@@ -273,7 +281,9 @@
- API 성공 시 `CreatorChannelHomeUiState.Content`를 발행한다.
- API 실패 또는 exception 시 `Error`와 unknown error toast를 발행한다.
- `follow(follow, notify)`는 기존 팔로우 API를 호출하고 성공 시 로컬 header의 `isFollow`, `isNotify`를 갱신한다.
- `createChatRoom(characterId)``characterId > 0`일 때만 `TalkApi.createChatRoom` 위임 API를 호출하고, 성공 시 `ChatRoomActivity` 이동에 사용할 `chatRoomId` 이벤트를 발행한다.
- 팔로우/알림 변경 중에는 중복 요청을 막는다.
- 채팅방 생성 중에는 중복 요청을 막는다.
- 검증 명령:
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.CreatorChannelHomeViewModelTest"`
- 기대 결과:
@@ -360,16 +370,18 @@
- 수정:
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeActivity.kt`
- 작업:
- `isAiChatAvailable=false`이면 `대화하기` 버튼을 숨긴다.
- `isAiChatAvailable=false`거나 `characterId == null``대화하기` 버튼을 숨긴다.
- `isDmAvailable=false`이면 `DM 보내기` 버튼을 숨긴다.
- 두 버튼 중 하나만 보일 때는 버튼 container 안에서 가운데 정렬한다.
- 두 버튼이 모두 숨김이어도 버튼 영역 container 높이는 유지한다.
- `대화하기``ChatRoomActivity.newIntent(context, roomId)` 계약상 `roomId`가 필요하므로, 홈 API에 room id가 없으면 기존 AI 채팅 진입에 필요한 source를 구현 계획 단계에서 추가 확인하고, 확인 전에는 click을 비활성 처리하지 말고 별도 route helper에 `creatorId` 기반 진입 불가를 명시한다.
- `대화하기`ViewModel의 `createChatRoom(characterId)`를 호출한다.
- 채팅방 생성 성공 이벤트의 `chatRoomId`를 받아 `ChatRoomActivity.newIntent(context, roomId)`로 이동한다.
- 채팅방 생성 실패 시 기존 unknown error toast 패턴을 따른다.
- `DM 보내기``DmChatRoomActivity.newIntentByCreatorId(context, creatorId)`로 이동한다.
- 검증 명령:
- `./gradlew :app:compileDebugKotlin`
- 기대 결과:
- 버튼 표시 조건과 DM 이동이 컴파일된다.
- 버튼 표시 조건과 AI 채팅/DM 이동이 컴파일된다.
---
@@ -501,3 +513,10 @@
- 2026-06-12: 기존 `HomeRecommendationApi`, `HomeRecommendationModels`, `HomeRecommendationRepository`, `HomeRecommendationViewModel`, `RecommendedActivityType`, `HomeRecommendationMappers`, `HomeRecommendationUiModels`, `AppDI`, `ChatRoomActivity`, `DmChatRoomActivity`를 확인해 신규 크리에이터 채널 홈 구현 계획의 파일 경계와 재사용 지점을 정리했다.
- 2026-06-12: 이번 단계는 구현 계획/TASK 문서 작성만 수행했으며 구현/빌드/테스트는 실행하지 않았다.
- 2026-06-12: Figma Design 참조가 필요한 Phase를 점검해 Phase 5, Phase 6, Phase 8은 필수 참조, Phase 1, Phase 4, Phase 7은 부분 참조, Phase 2, Phase 3은 참조 불필요로 계획 문서에 명시했다.
- 2026-06-12: Phase 1 진행으로 `HomeRecommendationApi`, `HomeRecommendationRepository`, `HomeRecommendationViewModel`을 확인해 기존 v2 홈 네트워크가 Retrofit + RxJava3 `Single<ApiResponse<T>>``Bearer ${SharedPreferenceManager.token}` 패턴을 사용함을 재확인했다.
- 2026-06-12: `UserRepository.creatorFollow(creatorId, follow, notify, token)``CreatorFollowNotifyFragment`의 알림 전체/없음/언팔로우 callback 구조를 확인해 크리에이터 채널 홈의 팔로우/알림 변경에 기존 API와 bottom sheet를 재사용할 수 있음을 확인했다.
- 2026-06-12: `ChatRoomActivity``newIntent(context, roomId)` 계약으로 `roomId`가 필요하고, `DmChatRoomActivity.newIntentByCreatorId(context, creatorId)`가 존재함을 확인해 계획서의 AI 채팅/DM 이동 경계를 재확인했다.
- 2026-06-12: `TalkApi.createChatRoom`, `CreateChatRoomRequest(characterId)`, `CreateChatRoomResponse.chatRoomId`, `CharacterDetailViewModel.createChatRoom(characterId)`를 확인해 `대화하기``characterId` 기반 채팅방 생성 후 `chatRoomId``ChatRoomActivity`에 진입해야 함을 확인했다.
- 2026-06-12: `AppDI``networkModule`, `repositoryModule`, `viewModelModule` 등록 패턴을 확인해 Phase 3 이후 신규 API/Repository/ViewModel 등록 위치와 형태를 확인했다.
- 2026-06-12: `prd.md`의 Non-Goals와 Technical Constraints를 확인해 `라이브`, `오디오`, `시리즈`, `커뮤니티`, `팬Talk`, `후원` 탭 상세, 홈 pagination, 신규 팔로우/알림 API, 채팅 내부 동작 변경, 별도 analytics/logging을 Phase 1 기준 제외 범위로 유지했다. Phase 1은 문서 확인/체크 갱신만 수행했으며 구현/빌드/테스트는 실행하지 않았다.
- 2026-06-12: 사용자 추가 요구사항에 따라 `CreatorChannelCreatorResponse.characterId: Long?`를 PRD/계획에 반영하고, `CharacterDetailViewModel.createChatRoom`과 동일하게 `TalkApi.createChatRoom(CreateChatRoomRequest(characterId))` 호출 후 반환된 `chatRoomId``ChatRoomActivity`에 이동하도록 Phase 3/4/5 작업을 갱신했다. 이번 단계는 문서 수정만 수행했으며 구현/빌드/테스트는 실행하지 않았다.