docs(creator): 채널 홈 탭 계획을 갱신한다
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
**Goal:** `GET /api/v2/creator-channels/{creatorId}/home` 응답을 기반으로 크리에이터 채널 신규 페이지의 상단 구성과 `홈` 탭 컨텐츠를 표시한다.
|
**Goal:** `GET /api/v2/creator-channels/{creatorId}/home` 응답을 기반으로 크리에이터 채널 신규 페이지의 상단 구성과 `홈` 탭 컨텐츠를 표시한다.
|
||||||
|
|
||||||
**Architecture:** 신규 화면은 `kr.co.vividnext.sodalive.v2.creatorchannel` 하위에 Activity, ViewModel, data/model/ui 패키지를 두고 기존 Retrofit + RxJava3 + `ApiResponse<T>` + Koin 패턴을 따른다. `RecommendedActivityType`은 홈 추천 전용 이름을 제거해 공용 `CreatorActivityType`으로 이동하고, 홈 추천과 크리에이터 채널 홈이 같은 타입을 참조하게 한다. UI는 Android XML Views/ViewBinding 기반으로 구성하고, 홈 탭 외 다른 탭 상세 화면은 이번 범위에서 연결하지 않는다.
|
**Architecture:** 신규 화면은 `kr.co.vividnext.sodalive.v2.creator.channel` 하위에 Activity, ViewModel, data/model/ui 패키지를 두고 기존 Retrofit + RxJava3 + `ApiResponse<T>` + Koin 패턴을 따른다. `RecommendedActivityType`은 홈 추천 전용 이름을 제거해 공용 `CreatorActivityType`으로 이동하고, 홈 추천과 크리에이터 채널 홈이 같은 타입을 참조하게 한다. UI는 Android XML Views/ViewBinding 기반으로 구성하고, 홈 탭 외 다른 탭 상세 화면은 이번 범위에서 연결하지 않는다.
|
||||||
|
|
||||||
**Tech Stack:** Kotlin, Android XML Views, ViewBinding, RecyclerView/NestedScroll, Retrofit, Gson, RxJava3, Koin, JUnit4/Robolectric local unit test.
|
**Tech Stack:** Kotlin, Android XML Views, ViewBinding, RecyclerView/NestedScroll, Retrofit, Gson, RxJava3, Koin, JUnit4/Robolectric local unit test.
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
- title-bar black 전환 기준은 title-bar와 tab-bar의 실제 거리 및 프로필 이미지가 절반 이상 사라졌는지를 함께 사용한다.
|
- title-bar black 전환 기준은 title-bar와 tab-bar의 실제 거리 및 프로필 이미지가 절반 이상 사라졌는지를 함께 사용한다.
|
||||||
- 구현 완료 후 최소 다음 명령을 실행한다.
|
- 구현 완료 후 최소 다음 명령을 실행한다.
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*"`
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.*"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"`
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"`
|
||||||
- `./gradlew :app:mergeDebugResources`
|
- `./gradlew :app:mergeDebugResources`
|
||||||
- `./gradlew :app:compileDebugKotlin`
|
- `./gradlew :app:compileDebugKotlin`
|
||||||
@@ -68,27 +68,27 @@
|
|||||||
- 최근 활동 크리에이터 UI 모델의 타입을 공용 `CreatorActivityType`으로 변경한다.
|
- 최근 활동 크리에이터 UI 모델의 타입을 공용 `CreatorActivityType`으로 변경한다.
|
||||||
- 수정: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/RecommendedActivityTypeTest.kt`
|
- 수정: `app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/RecommendedActivityTypeTest.kt`
|
||||||
- 테스트명을 유지하거나 `CreatorActivityTypeTest`로 이동해 공용 타입 검증으로 변경한다.
|
- 테스트명을 유지하거나 `CreatorActivityTypeTest`로 이동해 공용 타입 검증으로 변경한다.
|
||||||
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeActivity.kt`
|
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt`
|
||||||
- 크리에이터 채널 홈 화면, intent 진입, edge-to-edge/inset, title/tab scroll, click 연결을 담당한다.
|
- 크리에이터 채널 홈 화면, intent 진입, edge-to-edge/inset, title/tab scroll, click 연결을 담당한다.
|
||||||
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeViewModel.kt`
|
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModel.kt`
|
||||||
- 홈 API 호출, 팔로우/알림 변경, loading/error/content 상태를 관리한다.
|
- 홈 API 호출, 팔로우/알림 변경, loading/error/content 상태를 관리한다.
|
||||||
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/data/CreatorChannelHomeApi.kt`
|
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeApi.kt`
|
||||||
- `GET /api/v2/creator-channels/{creatorId}/home` endpoint를 정의한다.
|
- `GET /api/v2/creator-channels/{creatorId}/home` endpoint를 정의한다.
|
||||||
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/data/CreatorChannelHomeModels.kt`
|
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeModels.kt`
|
||||||
- PRD의 서버 DTO를 Android DTO로 정의한다.
|
- PRD의 서버 DTO를 Android DTO로 정의한다.
|
||||||
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/data/CreatorChannelHomeRepository.kt`
|
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeRepository.kt`
|
||||||
- 홈 API, 기존 크리에이터 팔로우 API, 기존 `TalkApi.createChatRoom` 호출을 ViewModel에 제공한다.
|
- 홈 API, 기존 크리에이터 팔로우 API, 기존 `TalkApi.createChatRoom` 호출을 ViewModel에 제공한다.
|
||||||
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/model/CreatorChannelHomeUiModels.kt`
|
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeUiModels.kt`
|
||||||
- 화면 상태, tab 항목, header/action/home section UI model을 정의한다.
|
- 화면 상태, tab 항목, header/action/home section UI model을 정의한다.
|
||||||
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/model/CreatorChannelHomeMappers.kt`
|
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeMappers.kt`
|
||||||
- API 응답을 UI model로 변환한다.
|
- API 응답을 UI model로 변환한다.
|
||||||
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/model/CreatorChannelTitleBarState.kt`
|
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelTitleBarState.kt`
|
||||||
- 팔로우/알림 조합별 title-bar 아이콘 상태와 버튼 표시 상태를 순수 모델로 정의한다.
|
- 팔로우/알림 조합별 title-bar 아이콘 상태와 버튼 표시 상태를 순수 모델로 정의한다.
|
||||||
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/model/CreatorChannelScrollState.kt`
|
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelScrollState.kt`
|
||||||
- title-bar black 전환과 tab-bar sticky 기준을 순수 함수로 계산한다.
|
- title-bar black 전환과 tab-bar sticky 기준을 순수 함수로 계산한다.
|
||||||
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/ui/CreatorChannelHomeSectionAdapter.kt`
|
- 생성: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt`
|
||||||
- 홈 탭 section 목록을 RecyclerView로 표시한다.
|
- 홈 탭 section 목록을 RecyclerView로 표시한다.
|
||||||
- 생성 후보: `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/ui/CreatorChannelTabAdapter.kt`
|
- 생성 후보: `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelTabAdapter.kt`
|
||||||
- 기존 `TextTabBarView`로 7개 탭 표시가 어렵거나 Figma tab-bar와 맞지 않을 때만 추가한다.
|
- 기존 `TextTabBarView`로 7개 탭 표시가 어렵거나 Figma tab-bar와 맞지 않을 때만 추가한다.
|
||||||
- 생성: `app/src/main/res/layout/activity_creator_channel_home.xml`
|
- 생성: `app/src/main/res/layout/activity_creator_channel_home.xml`
|
||||||
- 크리에이터 이미지 영역, title-bar, tab-bar, 홈 컨텐츠 RecyclerView를 포함한 화면 레이아웃이다.
|
- 크리에이터 이미지 영역, title-bar, tab-bar, 홈 컨텐츠 RecyclerView를 포함한 화면 레이아웃이다.
|
||||||
@@ -100,11 +100,11 @@
|
|||||||
- 신규 API, Repository, ViewModel을 Koin에 등록한다.
|
- 신규 API, Repository, ViewModel을 Koin에 등록한다.
|
||||||
- 테스트 생성/수정:
|
- 테스트 생성/수정:
|
||||||
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/common/CreatorActivityTypeTest.kt`
|
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/common/CreatorActivityTypeTest.kt`
|
||||||
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeMapperTest.kt`
|
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeMapperTest.kt`
|
||||||
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelTitleBarStateTest.kt`
|
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelTitleBarStateTest.kt`
|
||||||
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelScrollStateTest.kt`
|
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelScrollStateTest.kt`
|
||||||
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeViewModelTest.kt`
|
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModelTest.kt`
|
||||||
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeActivitySourceTest.kt`
|
- 생성: `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivitySourceTest.kt`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
|
|
||||||
### Phase 2: `CreatorActivityType` 공용화
|
### Phase 2: `CreatorActivityType` 공용화
|
||||||
|
|
||||||
- [ ] **Task 2.1: 공용 활동 타입 RED 테스트 작성**
|
- [x] **Task 2.1: 공용 활동 타입 RED 테스트 작성**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/test/java/kr/co/vividnext/sodalive/v2/common/CreatorActivityTypeTest.kt`
|
- `app/src/test/java/kr/co/vividnext/sodalive/v2/common/CreatorActivityTypeTest.kt`
|
||||||
- 수정:
|
- 수정:
|
||||||
@@ -154,12 +154,13 @@
|
|||||||
- `LIVE`, `LIVE_REPLAY`, `AUDIO`, `COMMUNITY`가 대소문자 무시로 파싱되는지 검증한다.
|
- `LIVE`, `LIVE_REPLAY`, `AUDIO`, `COMMUNITY`가 대소문자 무시로 파싱되는지 검증한다.
|
||||||
- 각 타입의 label resource가 기존 `RecommendedActivityType`과 동일한지 검증한다.
|
- 각 타입의 label resource가 기존 `RecommendedActivityType`과 동일한지 검증한다.
|
||||||
- 알 수 없는 code는 `null`을 반환하는지 검증한다.
|
- 알 수 없는 code는 `null`을 반환하는지 검증한다.
|
||||||
|
- 대소문자 무시 파싱은 홈 추천 등 클라이언트 helper 호환성 검증이며, 크리에이터 채널 홈 API의 서버 enum 계약은 대문자 code만 내려오는 것으로 본다.
|
||||||
- 검증 명령:
|
- 검증 명령:
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.CreatorActivityTypeTest"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.CreatorActivityTypeTest"`
|
||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- 공용 타입 미구현으로 RED 실패한다.
|
- 공용 타입 미구현으로 RED 실패한다.
|
||||||
|
|
||||||
- [ ] **Task 2.2: `CreatorActivityType` 생성 및 홈 추천 참조 변경**
|
- [x] **Task 2.2: `CreatorActivityType` 생성 및 홈 추천 참조 변경**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/common/CreatorActivityType.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/common/CreatorActivityType.kt`
|
||||||
- 수정:
|
- 수정:
|
||||||
@@ -183,14 +184,16 @@
|
|||||||
|
|
||||||
### Phase 3: 크리에이터 채널 홈 API/DTO/Repository 추가
|
### Phase 3: 크리에이터 채널 홈 API/DTO/Repository 추가
|
||||||
|
|
||||||
- [ ] **Task 3.1: API DTO와 endpoint 정의**
|
- [x] **Task 3.1: API DTO와 endpoint 정의**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/data/CreatorChannelHomeApi.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeApi.kt`
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/data/CreatorChannelHomeModels.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeModels.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- PRD의 `CreatorChannelHomeResponse`와 하위 DTO를 모두 `@Keep`, `@SerializedName` 기반 data class로 추가한다.
|
- PRD의 `CreatorChannelHomeResponse`와 하위 DTO를 모두 `@Keep`, `@SerializedName` 기반 data class로 추가한다.
|
||||||
- `CreatorChannelCreatorResponse`에는 `creatorId: Long`과 `characterId: Long?`를 모두 추가한다.
|
- `CreatorChannelCreatorResponse`에는 `creatorId: Long`과 `characterId: Long?`를 모두 추가한다.
|
||||||
- `CreatorChannelScheduleResponse.type`은 공용 `CreatorActivityType`을 사용한다.
|
- `CreatorChannelScheduleResponse.type`은 공용 `CreatorActivityType`을 사용한다.
|
||||||
|
- 백엔드 `CreatorActivityType` 원본 enum은 `LIVE`, `AUDIO`, `COMMUNITY`, `LIVE_REPLAY` 대문자 code를 내려주므로 DTO에서 공용 enum을 직접 사용하는 것을 정상 계약으로 본다.
|
||||||
|
- 이후 코드리뷰에서는 별도 서버 계약 변경 근거가 없는 한 `type` 대소문자 불일치 대응 또는 Gson enum TypeAdapter 부재를 문제로 보지 않는다.
|
||||||
- Retrofit endpoint는 `@GET("/api/v2/creator-channels/{creatorId}/home")`로 정의한다.
|
- Retrofit endpoint는 `@GET("/api/v2/creator-channels/{creatorId}/home")`로 정의한다.
|
||||||
- 반환 타입은 `Single<ApiResponse<CreatorChannelHomeResponse>>`를 사용한다.
|
- 반환 타입은 `Single<ApiResponse<CreatorChannelHomeResponse>>`를 사용한다.
|
||||||
- 검증 명령:
|
- 검증 명령:
|
||||||
@@ -198,9 +201,9 @@
|
|||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- 신규 DTO와 API가 컴파일된다.
|
- 신규 DTO와 API가 컴파일된다.
|
||||||
|
|
||||||
- [ ] **Task 3.2: Repository 추가**
|
- [x] **Task 3.2: Repository 추가**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/data/CreatorChannelHomeRepository.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/data/CreatorChannelHomeRepository.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- `getHome(creatorId: Long, token: String)`에서 홈 API를 호출한다.
|
- `getHome(creatorId: Long, token: String)`에서 홈 API를 호출한다.
|
||||||
- 기존 `UserRepository`를 생성자 인자로 받아 `followCreator(creatorId, follow, notify, token)`를 얇게 위임한다.
|
- 기존 `UserRepository`를 생성자 인자로 받아 `followCreator(creatorId, follow, notify, token)`를 얇게 위임한다.
|
||||||
@@ -211,7 +214,7 @@
|
|||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- Repository가 기존 DI 패턴과 충돌 없이 컴파일된다.
|
- Repository가 기존 DI 패턴과 충돌 없이 컴파일된다.
|
||||||
|
|
||||||
- [ ] **Task 3.3: Koin DI 등록**
|
- [x] **Task 3.3: Koin DI 등록**
|
||||||
- 수정:
|
- 수정:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
@@ -220,6 +223,7 @@
|
|||||||
- 기존 `networkModule`의 `TalkApi` 등록을 재사용한다.
|
- 기존 `networkModule`의 `TalkApi` 등록을 재사용한다.
|
||||||
- `repositoryModule`에 `factory { CreatorChannelHomeRepository(api = get(), userRepository = get(), talkApi = get()) }`를 추가한다.
|
- `repositoryModule`에 `factory { CreatorChannelHomeRepository(api = get(), userRepository = get(), talkApi = get()) }`를 추가한다.
|
||||||
- `viewModelModule`에 `viewModel { CreatorChannelHomeViewModel(get()) }`를 추가한다.
|
- `viewModelModule`에 `viewModel { CreatorChannelHomeViewModel(get()) }`를 추가한다.
|
||||||
|
- 참고: Phase 3 현재 구현에서는 `CreatorChannelHomeViewModel` 클래스가 Phase 4 산출물이므로 컴파일을 깨지 않기 위해 ViewModel DI 등록은 Phase 4로 보류하고, API/Repository 등록만 완료했다.
|
||||||
- 검증 명령:
|
- 검증 명령:
|
||||||
- `./gradlew :app:compileDebugKotlin`
|
- `./gradlew :app:compileDebugKotlin`
|
||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
@@ -231,7 +235,7 @@
|
|||||||
|
|
||||||
- [ ] **Task 4.1: 홈 응답 매퍼 RED 테스트 작성**
|
- [ ] **Task 4.1: 홈 응답 매퍼 RED 테스트 작성**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/test/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeMapperTest.kt`
|
- `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeMapperTest.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- `creator.characterId`, `creator.isFollow`, `creator.isNotify`, `creator.isAiChatAvailable`, `creator.isDmAvailable`가 UI model에 그대로 반영되는지 검증한다.
|
- `creator.characterId`, `creator.isFollow`, `creator.isNotify`, `creator.isAiChatAvailable`, `creator.isDmAvailable`가 UI model에 그대로 반영되는지 검증한다.
|
||||||
- tab 목록이 `홈`, `라이브`, `오디오`, `시리즈`, `커뮤니티`, `팬Talk`, `후원` 순서인지 검증한다.
|
- tab 목록이 `홈`, `라이브`, `오디오`, `시리즈`, `커뮤니티`, `팬Talk`, `후원` 순서인지 검증한다.
|
||||||
@@ -239,14 +243,14 @@
|
|||||||
- 빈 list는 crash 없이 빈 section 또는 hidden section 정책으로 매핑되는지 검증한다.
|
- 빈 list는 crash 없이 빈 section 또는 hidden section 정책으로 매핑되는지 검증한다.
|
||||||
- SNS URL이 빈 문자열이면 해당 SNS item이 숨김 또는 disabled 상태로 매핑되는지 검증한다.
|
- SNS URL이 빈 문자열이면 해당 SNS item이 숨김 또는 disabled 상태로 매핑되는지 검증한다.
|
||||||
- 검증 명령:
|
- 검증 명령:
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.CreatorChannelHomeMapperTest"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest"`
|
||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- UI model/mapper 미구현으로 RED 실패한다.
|
- UI model/mapper 미구현으로 RED 실패한다.
|
||||||
|
|
||||||
- [ ] **Task 4.2: UI model과 mapper 구현**
|
- [ ] **Task 4.2: UI model과 mapper 구현**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/model/CreatorChannelHomeUiModels.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeUiModels.kt`
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/model/CreatorChannelHomeMappers.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelHomeMappers.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- `CreatorChannelHomeUiState.Loading`, `Content`, `Empty`, `Error`를 정의한다.
|
- `CreatorChannelHomeUiState.Loading`, `Content`, `Empty`, `Error`를 정의한다.
|
||||||
- `CreatorChannelTab.Home`, `Live`, `Audio`, `Series`, `Community`, `FanTalk`, `Donation`을 정의한다.
|
- `CreatorChannelTab.Home`, `Live`, `Audio`, `Series`, `Community`, `FanTalk`, `Donation`을 정의한다.
|
||||||
@@ -254,28 +258,28 @@
|
|||||||
- 홈 section은 Figma 순서에 맞춰 `sealed interface CreatorChannelHomeSection`으로 정의한다.
|
- 홈 section은 Figma 순서에 맞춰 `sealed interface CreatorChannelHomeSection`으로 정의한다.
|
||||||
- `CreatorChannelHomeResponse.toUiContent()` 매퍼를 구현한다.
|
- `CreatorChannelHomeResponse.toUiContent()` 매퍼를 구현한다.
|
||||||
- 검증 명령:
|
- 검증 명령:
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.CreatorChannelHomeMapperTest"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeMapperTest"`
|
||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- 매퍼 테스트가 PASS한다.
|
- 매퍼 테스트가 PASS한다.
|
||||||
|
|
||||||
- [ ] **Task 4.3: title-bar 상태 순수 모델 테스트와 구현**
|
- [ ] **Task 4.3: title-bar 상태 순수 모델 테스트와 구현**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/test/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelTitleBarStateTest.kt`
|
- `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelTitleBarStateTest.kt`
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/model/CreatorChannelTitleBarState.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelTitleBarState.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- `isFollow=false`이면 follow icon은 `ic_new_follow`, bell icon은 없음으로 계산한다.
|
- `isFollow=false`이면 follow icon은 `ic_new_follow`, bell icon은 없음으로 계산한다.
|
||||||
- `isFollow=true && isNotify=true`이면 follow icon은 `ic_new_following`, bell icon은 `ic_bar_bell_colored`로 계산한다.
|
- `isFollow=true && isNotify=true`이면 follow icon은 `ic_new_following`, bell icon은 `ic_bar_bell_colored`로 계산한다.
|
||||||
- `isFollow=true && isNotify=false`이면 follow icon은 `ic_new_following`, bell icon은 `ic_bar_bell`로 계산한다.
|
- `isFollow=true && isNotify=false`이면 follow icon은 `ic_new_following`, bell icon은 `ic_bar_bell`로 계산한다.
|
||||||
- 상태 변경 중에는 중복 클릭 방지를 위한 `isActionEnabled=false` 상태를 표현한다.
|
- 상태 변경 중에는 중복 클릭 방지를 위한 `isActionEnabled=false` 상태를 표현한다.
|
||||||
- 검증 명령:
|
- 검증 명령:
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.CreatorChannelTitleBarStateTest"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelTitleBarStateTest"`
|
||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- title-bar 상태 테스트가 PASS한다.
|
- title-bar 상태 테스트가 PASS한다.
|
||||||
|
|
||||||
- [ ] **Task 4.4: ViewModel RED 테스트와 구현**
|
- [ ] **Task 4.4: ViewModel RED 테스트와 구현**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/test/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeViewModelTest.kt`
|
- `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModelTest.kt`
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeViewModel.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModel.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- `loadHome(creatorId)`는 `creatorId > 0`일 때만 홈 API를 호출한다.
|
- `loadHome(creatorId)`는 `creatorId > 0`일 때만 홈 API를 호출한다.
|
||||||
- API 성공 시 `CreatorChannelHomeUiState.Content`를 발행한다.
|
- API 성공 시 `CreatorChannelHomeUiState.Content`를 발행한다.
|
||||||
@@ -285,7 +289,7 @@
|
|||||||
- 팔로우/알림 변경 중에는 중복 요청을 막는다.
|
- 팔로우/알림 변경 중에는 중복 요청을 막는다.
|
||||||
- 채팅방 생성 중에는 중복 요청을 막는다.
|
- 채팅방 생성 중에는 중복 요청을 막는다.
|
||||||
- 검증 명령:
|
- 검증 명령:
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.CreatorChannelHomeViewModelTest"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest"`
|
||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- ViewModel 테스트가 PASS한다.
|
- ViewModel 테스트가 PASS한다.
|
||||||
|
|
||||||
@@ -311,7 +315,7 @@
|
|||||||
|
|
||||||
- [ ] **Task 5.2: 홈 섹션 Adapter와 item layout 추가**
|
- [ ] **Task 5.2: 홈 섹션 Adapter와 item layout 추가**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/ui/CreatorChannelHomeSectionAdapter.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt`
|
||||||
- `app/src/main/res/layout/item_creator_channel_home_live.xml`
|
- `app/src/main/res/layout/item_creator_channel_home_live.xml`
|
||||||
- `app/src/main/res/layout/item_creator_channel_home_latest_audio.xml`
|
- `app/src/main/res/layout/item_creator_channel_home_latest_audio.xml`
|
||||||
- `app/src/main/res/layout/item_creator_channel_home_donation.xml`
|
- `app/src/main/res/layout/item_creator_channel_home_donation.xml`
|
||||||
@@ -336,8 +340,8 @@
|
|||||||
|
|
||||||
- [ ] **Task 5.3: Activity 생성 및 ViewModel observe 연결**
|
- [ ] **Task 5.3: Activity 생성 및 ViewModel observe 연결**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeActivity.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt`
|
||||||
- `app/src/test/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeActivitySourceTest.kt`
|
- `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivitySourceTest.kt`
|
||||||
- 수정:
|
- 수정:
|
||||||
- `app/src/main/AndroidManifest.xml`
|
- `app/src/main/AndroidManifest.xml`
|
||||||
- 작업:
|
- 작업:
|
||||||
@@ -347,14 +351,14 @@
|
|||||||
- `onCreate` 또는 `onStart`에서 `viewModel.loadHome(creatorId)`를 호출한다.
|
- `onCreate` 또는 `onStart`에서 `viewModel.loadHome(creatorId)`를 호출한다.
|
||||||
- Manifest에 Activity를 등록한다.
|
- Manifest에 Activity를 등록한다.
|
||||||
- 검증 명령:
|
- 검증 명령:
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.CreatorChannelHomeActivitySourceTest"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeActivitySourceTest"`
|
||||||
- `./gradlew :app:compileDebugKotlin`
|
- `./gradlew :app:compileDebugKotlin`
|
||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- intent extra, invalid creatorId 처리, Manifest 등록 검증이 PASS한다.
|
- intent extra, invalid creatorId 처리, Manifest 등록 검증이 PASS한다.
|
||||||
|
|
||||||
- [ ] **Task 5.4: title-bar와 이미지 영역 bind 구현**
|
- [ ] **Task 5.4: title-bar와 이미지 영역 bind 구현**
|
||||||
- 수정:
|
- 수정:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeActivity.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- `creator.profileImageUrl`, `nickname`, `followerCount`를 이미지 영역에 표시한다.
|
- `creator.profileImageUrl`, `nickname`, `followerCount`를 이미지 영역에 표시한다.
|
||||||
- `CreatorChannelTitleBarState`에 따라 `ic_new_follow`, `ic_new_following`, `ic_bar_bell_colored`, `ic_bar_bell`을 표시한다.
|
- `CreatorChannelTitleBarState`에 따라 `ic_new_follow`, `ic_new_following`, `ic_bar_bell_colored`, `ic_bar_bell`을 표시한다.
|
||||||
@@ -368,7 +372,7 @@
|
|||||||
|
|
||||||
- [ ] **Task 5.5: 대화하기/DM 버튼 표시와 이동 연결**
|
- [ ] **Task 5.5: 대화하기/DM 버튼 표시와 이동 연결**
|
||||||
- 수정:
|
- 수정:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeActivity.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- `isAiChatAvailable=false`이거나 `characterId == null`이면 `대화하기` 버튼을 숨긴다.
|
- `isAiChatAvailable=false`이거나 `characterId == null`이면 `대화하기` 버튼을 숨긴다.
|
||||||
- `isDmAvailable=false`이면 `DM 보내기` 버튼을 숨긴다.
|
- `isDmAvailable=false`이면 `DM 보내기` 버튼을 숨긴다.
|
||||||
@@ -389,32 +393,32 @@
|
|||||||
|
|
||||||
- [ ] **Task 6.1: scroll 상태 계산 RED 테스트 작성**
|
- [ ] **Task 6.1: scroll 상태 계산 RED 테스트 작성**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/test/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelScrollStateTest.kt`
|
- `app/src/test/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelScrollStateTest.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- title-bar와 tab-bar의 실제 거리가 기준 이하이고 프로필 이미지가 절반 이상 사라졌을 때 black 전환이 `true`인지 검증한다.
|
- title-bar와 tab-bar의 실제 거리가 기준 이하이고 프로필 이미지가 절반 이상 사라졌을 때 black 전환이 `true`인지 검증한다.
|
||||||
- 둘 중 하나라도 만족하지 않으면 black 전환이 `false`인지 검증한다.
|
- 둘 중 하나라도 만족하지 않으면 black 전환이 `false`인지 검증한다.
|
||||||
- tab-bar sticky top은 status bar 높이와 title-bar 높이를 합산해 계산되는지 검증한다.
|
- tab-bar sticky top은 status bar 높이와 title-bar 높이를 합산해 계산되는지 검증한다.
|
||||||
- 검증 명령:
|
- 검증 명령:
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.CreatorChannelScrollStateTest"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelScrollStateTest"`
|
||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- scroll 상태 모델 미구현으로 RED 실패한다.
|
- scroll 상태 모델 미구현으로 RED 실패한다.
|
||||||
|
|
||||||
- [ ] **Task 6.2: scroll 상태 계산 모델 구현**
|
- [ ] **Task 6.2: scroll 상태 계산 모델 구현**
|
||||||
- 생성:
|
- 생성:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/model/CreatorChannelScrollState.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/model/CreatorChannelScrollState.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- `shouldUseBlackTitleBar(titleBarBottom: Int, tabBarTop: Int, profileImageVisibleHeight: Int, profileImageTotalHeight: Int): Boolean`을 추가한다.
|
- `shouldUseBlackTitleBar(titleBarBottom: Int, tabBarTop: Int, profileImageVisibleHeight: Int, profileImageTotalHeight: Int): Boolean`을 추가한다.
|
||||||
- 실제 거리 조건은 `tabBarTop <= titleBarBottom` 또는 기존 layout에서 측정 가능한 최소 gap 기준으로 구현한다.
|
- 실제 거리 조건은 `tabBarTop <= titleBarBottom` 또는 기존 layout에서 측정 가능한 최소 gap 기준으로 구현한다.
|
||||||
- 프로필 이미지 절반 이상 사라짐은 `profileImageVisibleHeight <= profileImageTotalHeight / 2`로 계산한다.
|
- 프로필 이미지 절반 이상 사라짐은 `profileImageVisibleHeight <= profileImageTotalHeight / 2`로 계산한다.
|
||||||
- sticky top 계산 helper는 `statusBarHeight + titleBarHeight`를 반환한다.
|
- sticky top 계산 helper는 `statusBarHeight + titleBarHeight`를 반환한다.
|
||||||
- 검증 명령:
|
- 검증 명령:
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.CreatorChannelScrollStateTest"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelScrollStateTest"`
|
||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- scroll 상태 테스트가 PASS한다.
|
- scroll 상태 테스트가 PASS한다.
|
||||||
|
|
||||||
- [ ] **Task 6.3: Activity scroll listener 연결**
|
- [ ] **Task 6.3: Activity scroll listener 연결**
|
||||||
- 수정:
|
- 수정:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeActivity.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- system bar inset을 읽어 이미지 영역이 status bar 뒤까지 확장되도록 적용한다.
|
- system bar inset을 읽어 이미지 영역이 status bar 뒤까지 확장되도록 적용한다.
|
||||||
- title-bar content에는 status bar inset만큼 top padding 또는 margin을 적용해 터치 영역을 보존한다.
|
- title-bar content에는 status bar inset만큼 top padding 또는 margin을 적용해 터치 영역을 보존한다.
|
||||||
@@ -433,25 +437,25 @@
|
|||||||
|
|
||||||
- [ ] **Task 7.1: 팔로우/알림 click 흐름 연결**
|
- [ ] **Task 7.1: 팔로우/알림 click 흐름 연결**
|
||||||
- 수정:
|
- 수정:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeActivity.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt`
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeViewModel.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeViewModel.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- 미팔로우 상태에서 follow icon 클릭 시 `viewModel.follow(follow = true, notify = true)`를 호출한다.
|
- 미팔로우 상태에서 follow icon 클릭 시 `viewModel.follow(follow = true, notify = true)`를 호출한다.
|
||||||
- 팔로우 중 상태에서 follow/following icon 클릭 시 `CreatorFollowNotifyFragment`를 띄운다.
|
- 팔로우 중 상태에서 follow/following icon 클릭 시 `CreatorFollowNotifyFragment`를 띄운다.
|
||||||
- `알림 모두 받기`, `알림 받지 않기`, `언팔로우` 선택은 각각 기존 `follow=true/notify=true`, `follow=true/notify=false`, `follow=false/notify=false` 조합으로 호출한다.
|
- `알림 모두 받기`, `알림 받지 않기`, `언팔로우` 선택은 각각 기존 `follow=true/notify=true`, `follow=true/notify=false`, `follow=false/notify=false` 조합으로 호출한다.
|
||||||
- 요청 중에는 title-bar follow/bell click을 막는다.
|
- 요청 중에는 title-bar follow/bell click을 막는다.
|
||||||
- 검증 명령:
|
- 검증 명령:
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.CreatorChannelHomeViewModelTest"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.CreatorChannelHomeViewModelTest"`
|
||||||
- `./gradlew :app:compileDebugKotlin`
|
- `./gradlew :app:compileDebugKotlin`
|
||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- 팔로우/알림 상태 변경 테스트와 컴파일이 PASS한다.
|
- 팔로우/알림 상태 변경 테스트와 컴파일이 PASS한다.
|
||||||
|
|
||||||
- [ ] **Task 7.2: tab-bar 7개 항목 표시와 홈 외 탭 클릭 정책 적용**
|
- [ ] **Task 7.2: tab-bar 7개 항목 표시와 홈 외 탭 클릭 정책 적용**
|
||||||
- 수정:
|
- 수정:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/CreatorChannelHomeActivity.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeActivity.kt`
|
||||||
- `app/src/main/res/layout/activity_creator_channel_home.xml`
|
- `app/src/main/res/layout/activity_creator_channel_home.xml`
|
||||||
- 생성 후보:
|
- 생성 후보:
|
||||||
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creatorchannel/ui/CreatorChannelTabAdapter.kt`
|
- `app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelTabAdapter.kt`
|
||||||
- 작업:
|
- 작업:
|
||||||
- tab-bar에 `홈`, `라이브`, `오디오`, `시리즈`, `커뮤니티`, `팬Talk`, `후원`을 표시한다.
|
- tab-bar에 `홈`, `라이브`, `오디오`, `시리즈`, `커뮤니티`, `팬Talk`, `후원`을 표시한다.
|
||||||
- 기본 선택은 `홈`이다.
|
- 기본 선택은 `홈`이다.
|
||||||
@@ -472,7 +476,7 @@
|
|||||||
- [ ] **Task 8.1: 단위 테스트 실행**
|
- [ ] **Task 8.1: 단위 테스트 실행**
|
||||||
- 실행:
|
- 실행:
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*"`
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.*"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creator.channel.*"`
|
||||||
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"`
|
- `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"`
|
||||||
- 기대 결과:
|
- 기대 결과:
|
||||||
- 신규 공용 타입, 크리에이터 채널 홈, 기존 홈 추천 관련 테스트가 모두 `BUILD SUCCESSFUL`로 통과한다.
|
- 신규 공용 타입, 크리에이터 채널 홈, 기존 홈 추천 관련 테스트가 모두 `BUILD SUCCESSFUL`로 통과한다.
|
||||||
@@ -520,3 +524,17 @@
|
|||||||
- 2026-06-12: `AppDI`의 `networkModule`, `repositoryModule`, `viewModelModule` 등록 패턴을 확인해 Phase 3 이후 신규 API/Repository/ViewModel 등록 위치와 형태를 확인했다.
|
- 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: `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 작업을 갱신했다. 이번 단계는 문서 수정만 수행했으며 구현/빌드/테스트는 실행하지 않았다.
|
- 2026-06-12: 사용자 추가 요구사항에 따라 `CreatorChannelCreatorResponse.characterId: Long?`를 PRD/계획에 반영하고, `CharacterDetailViewModel.createChatRoom`과 동일하게 `TalkApi.createChatRoom(CreateChatRoomRequest(characterId))` 호출 후 반환된 `chatRoomId`로 `ChatRoomActivity`에 이동하도록 Phase 3/4/5 작업을 갱신했다. 이번 단계는 문서 수정만 수행했으며 구현/빌드/테스트는 실행하지 않았다.
|
||||||
|
|
||||||
|
- 2026-06-13: Phase 2 RED 테스트로 `CreatorActivityTypeTest`를 먼저 추가하고 `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.CreatorActivityTypeTest"`를 실행해 `CreatorActivityType` 미구현으로 실패함을 확인했다.
|
||||||
|
- 2026-06-13: `RecommendedActivityType`을 `v2/common/CreatorActivityType`으로 공용화하고 홈 추천 mapper/model/test 참조를 갱신했다. `RecommendedActivityType.kt`는 제거했으며 `rg -n "RecommendedActivityType|toRecommendedActivityTypeLabelRes" app/src/main app/src/test` 결과 남은 참조가 없음을 확인했다.
|
||||||
|
- 2026-06-13: Phase 3 RED 테스트로 `CreatorChannelHomeModelsTest`를 추가해 Gson이 `CreatorChannelScheduleResponse.type`을 `CreatorActivityType`으로 파싱하고 nullable 필드를 보존하는지 검증하도록 했다. 초기 실행은 `CreatorChannelHomeResponse`와 `CreatorActivityType` 미구현으로 실패했다.
|
||||||
|
- 2026-06-13: `CreatorChannelHomeApi`, `CreatorChannelHomeModels`, `CreatorChannelHomeRepository`를 추가하고 `AppDI`에 `CreatorChannelHomeApi`와 `CreatorChannelHomeRepository`를 등록했다. `CreatorChannelHomeViewModel` 등록은 Phase 4 클래스가 아직 없으므로 컴파일 유지를 위해 보류했다.
|
||||||
|
- 2026-06-13: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*"`, `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.creatorchannel.*"`, `./gradlew :app:compileDebugKotlin`, `./gradlew :app:mergeDebugResources`, `./gradlew :app:ktlintCheck`를 실행해 모두 `BUILD SUCCESSFUL`을 확인했다.
|
||||||
|
- 2026-06-13: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.main.home.*"`는 88개 중 8개가 `HomeMainFragmentLayoutTest.kt:1410`의 `FileNotFoundException`으로 실패했다. 별도 focused 실행인 `HomeCreatorActivityTypeLabelResTest`와 recent activity route 관련 2개 테스트는 `BUILD SUCCESSFUL`로 통과해 이번 타입 공용화 변경과 직접 관련된 회귀는 없음을 확인했다.
|
||||||
|
- 2026-06-13: reviewer gate를 실행해 Phase 2/3 구현 범위, PRD DTO 일치, stale 참조 제거, DI 등록 범위, 검증 증거에 대해 무조건 승인을 받았다.
|
||||||
|
- 2026-06-13: `HomeMainFragmentLayoutTest.kt`의 source-path helper가 실제 파일 위치와 다른 `v2/main/HomeMainFragment.kt`를 읽고 있어 `FileNotFoundException`이 발생함을 확인하고, 실제 위치인 `v2/main/home/HomeMainFragment.kt`로 수정했다.
|
||||||
|
- 2026-06-13: 백엔드 `CreatorActivityType` 원본 enum이 `LIVE`, `AUDIO`, `COMMUNITY`, `LIVE_REPLAY` 대문자 상수와 동일한 `code`를 사용함을 확인해 Android Gson enum 파싱용 별도 TypeAdapter는 추가하지 않기로 판단했다.
|
||||||
|
- 2026-06-13: 사용자 추가 요청에 따라 신규 크리에이터 채널 홈 패키지를 `kr.co.vividnext.sodalive.v2.creatorchannel`에서 `kr.co.vividnext.sodalive.v2.creator.channel`로 변경하고, 계획 본문의 신규 파일 경로와 테스트 필터를 새 패키지명 기준으로 갱신했다.
|
||||||
|
- 2026-06-13: `./gradlew :app:testDebugUnitTest --tests "kr.co.vividnext.sodalive.v2.common.*" --tests "kr.co.vividnext.sodalive.v2.creator.channel.*" --tests "kr.co.vividnext.sodalive.v2.main.home.*" :app:compileDebugKotlin`를 실행해 `BUILD SUCCESSFUL`을 확인했다.
|
||||||
|
- 2026-06-13: 패키지 이동 후 `./gradlew :app:ktlintCheck`를 실행해 `BUILD SUCCESSFUL`을 확인했다.
|
||||||
|
- 2026-06-13: 사용자 확인에 따라 백엔드 `CreatorActivityType` 원본 enum이 `LIVE`, `AUDIO`, `COMMUNITY`, `LIVE_REPLAY` 대문자 code를 내려주는 계약임을 Phase 2/3 작업 항목에 명시했다. 이후 코드리뷰에서는 별도 서버 계약 변경 근거가 없는 한 크리에이터 채널 홈 DTO의 `CreatorActivityType` 직접 사용과 Gson enum TypeAdapter 부재를 대소문자 대응 문제로 제기하지 않는다. 이번 단계는 문서 수정만 수행했으며 빌드/테스트는 실행하지 않았다.
|
||||||
|
|||||||
@@ -215,8 +215,19 @@ data class CreatorChannelSnsResponse(
|
|||||||
val youtubeUrl: String,
|
val youtubeUrl: String,
|
||||||
val kakaoOpenChatUrl: String
|
val kakaoOpenChatUrl: String
|
||||||
)
|
)
|
||||||
|
|
||||||
|
enum class CreatorActivityType(val code: String) {
|
||||||
|
LIVE("LIVE"),
|
||||||
|
AUDIO("AUDIO"),
|
||||||
|
COMMUNITY("COMMUNITY"),
|
||||||
|
LIVE_REPLAY("LIVE_REPLAY")
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- 백엔드 `CreatorActivityType` 원본 enum은 `LIVE`, `AUDIO`, `COMMUNITY`, `LIVE_REPLAY` 대문자 상수와 동일한 `code`를 내려준다.
|
||||||
|
- Android DTO의 `CreatorChannelScheduleResponse.type`은 위 서버 계약을 전제로 공용 `CreatorActivityType` enum을 직접 사용한다.
|
||||||
|
- 홈 추천 등 클라이언트 내부 helper에서 대소문자 무시 파싱을 지원하더라도, 크리에이터 채널 홈 API DTO 리뷰에서는 서버가 소문자/혼합 대소문자 값을 내려주는 경우를 별도 전제로 문제 제기하지 않는다.
|
||||||
|
|
||||||
#### Requirements
|
#### Requirements
|
||||||
- `creatorId`는 페이지 진입 인자로 전달받고, `creatorId > 0`일 때만 홈 API를 호출한다.
|
- `creatorId`는 페이지 진입 인자로 전달받고, `creatorId > 0`일 때만 홈 API를 호출한다.
|
||||||
- `creator.nickname`, `creator.profileImageUrl`, `creator.followerCount`를 크리에이터 이미지 영역의 기본 정보로 사용한다.
|
- `creator.nickname`, `creator.profileImageUrl`, `creator.followerCount`를 크리에이터 이미지 영역의 기본 정보로 사용한다.
|
||||||
@@ -357,6 +368,7 @@ tab-bar는 스크롤 중 title-bar 하단에 고정되는 sticky 영역으로
|
|||||||
- system bar 영역 확장은 Android edge-to-edge/inset 처리와 기존 앱의 status bar 정책을 확인한 뒤 적용한다.
|
- system bar 영역 확장은 Android edge-to-edge/inset 처리와 기존 앱의 status bar 정책을 확인한 뒤 적용한다.
|
||||||
- tab-bar sticky 동작은 기존 화면의 app bar/collapsing/header scroll 구현 패턴이 있으면 우선 재사용한다.
|
- tab-bar sticky 동작은 기존 화면의 app bar/collapsing/header scroll 구현 패턴이 있으면 우선 재사용한다.
|
||||||
- 홈 API는 `GET /api/v2/creator-channels/{creatorId}/home` 계약을 따른다.
|
- 홈 API는 `GET /api/v2/creator-channels/{creatorId}/home` 계약을 따른다.
|
||||||
|
- 홈 API의 schedule `type`은 백엔드 `CreatorActivityType` 원본 enum과 동일하게 `LIVE`, `AUDIO`, `COMMUNITY`, `LIVE_REPLAY` 중 하나로 내려오므로 Android DTO에서 공용 enum을 직접 사용한다.
|
||||||
- 팔로우/알림 변경은 기존 크리에이터 팔로우 API 사용 패턴을 재사용한다.
|
- 팔로우/알림 변경은 기존 크리에이터 팔로우 API 사용 패턴을 재사용한다.
|
||||||
- `대화하기` 이동은 `CharacterDetailViewModel.createChatRoom`과 동일하게 `TalkApi.createChatRoom` 호출 후 `ChatRoomActivity`로 이동하는 패턴을 따른다.
|
- `대화하기` 이동은 `CharacterDetailViewModel.createChatRoom`과 동일하게 `TalkApi.createChatRoom` 호출 후 `ChatRoomActivity`로 이동하는 패턴을 따른다.
|
||||||
- `DM 보내기` 이동은 신규 `DmChatRoomActivity` 사용 패턴을 따른다.
|
- `DM 보내기` 이동은 신규 `DmChatRoomActivity` 사용 패턴을 따른다.
|
||||||
@@ -418,3 +430,10 @@ tab-bar는 스크롤 중 title-bar 하단에 고정되는 sticky 영역으로
|
|||||||
- 2026-06-12: 이번 단계는 PRD 문서 보완만 수행했으며 구현/빌드/테스트는 실행하지 않았다.
|
- 2026-06-12: 이번 단계는 PRD 문서 보완만 수행했으며 구현/빌드/테스트는 실행하지 않았다.
|
||||||
- 2026-06-12: 문서 범위가 크리에이터 채널 신규 페이지 전체가 아니라 홈 탭 1차 범위임을 명확히 하기 위해 문서 폴더명을 `docs/20260611_크리에이터_채널_신규_페이지/`에서 `docs/20260611_크리에이터_채널_홈_탭/`으로 변경했다.
|
- 2026-06-12: 문서 범위가 크리에이터 채널 신규 페이지 전체가 아니라 홈 탭 1차 범위임을 명확히 하기 위해 문서 폴더명을 `docs/20260611_크리에이터_채널_신규_페이지/`에서 `docs/20260611_크리에이터_채널_홈_탭/`으로 변경했다.
|
||||||
- 2026-06-12: 사용자 추가 요구사항에 따라 `CreatorChannelCreatorResponse.characterId: Long?`를 추가하고, `대화하기` 이동을 `TalkApi.createChatRoom` 호출 후 반환된 `chatRoomId`로 `ChatRoomActivity`에 진입하는 흐름으로 변경했다.
|
- 2026-06-12: 사용자 추가 요구사항에 따라 `CreatorChannelCreatorResponse.characterId: Long?`를 추가하고, `대화하기` 이동을 `TalkApi.createChatRoom` 호출 후 반환된 `chatRoomId`로 `ChatRoomActivity`에 진입하는 흐름으로 변경했다.
|
||||||
|
|
||||||
|
- 2026-06-13: Phase 2/3 구현으로 `RecommendedActivityType`을 공용 `CreatorActivityType`으로 이동하고 홈 추천 참조를 갱신했으며, 크리에이터 채널 홈 API/DTO/Repository와 Koin API/Repository 등록을 추가했다.
|
||||||
|
- 2026-06-13: `CreatorChannelCreatorResponse.characterId: Long?`, `CreatorChannelScheduleResponse.type: CreatorActivityType`, `GET /api/v2/creator-channels/{creatorId}/home` 계약이 구현 DTO/API에 반영됨을 테스트와 컴파일로 확인했다.
|
||||||
|
- 2026-06-13: 검증으로 `v2.common.*`, `v2.creatorchannel.*`, `compileDebugKotlin`, `mergeDebugResources`, `ktlintCheck`는 성공했다. `v2.main.home.*` 전체 실행은 기존 source-path 테스트의 `FileNotFoundException`으로 일부 실패했으며, 타입 공용화 관련 focused 홈 테스트는 성공했다.
|
||||||
|
- 2026-06-13: 백엔드 `CreatorActivityType` 원본 enum이 `LIVE`, `AUDIO`, `COMMUNITY`, `LIVE_REPLAY` 대문자 상수와 동일한 `code`를 사용함을 확인해 Android Gson enum 파싱용 별도 TypeAdapter는 추가하지 않기로 판단했다.
|
||||||
|
- 2026-06-13: 사용자 추가 요청에 따라 신규 크리에이터 채널 홈 패키지를 `kr.co.vividnext.sodalive.v2.creatorchannel`에서 `kr.co.vividnext.sodalive.v2.creator.channel`로 변경했다.
|
||||||
|
- 2026-06-13: 사용자 확인에 따라 백엔드 `CreatorActivityType` 원본 enum과 동일한 대문자 code 계약을 API 계약/기술 제약에 명시했다. 이후 코드리뷰에서는 별도 서버 계약 변경 근거가 없는 한 크리에이터 채널 홈 DTO의 `CreatorActivityType` 직접 사용과 Gson enum TypeAdapter 부재를 대소문자 대응 문제로 제기하지 않는다. 이번 단계는 문서 수정만 수행했으며 빌드/테스트는 실행하지 않았다.
|
||||||
|
|||||||
Reference in New Issue
Block a user