feat(content): 추천 오디오 탭을 추가한다
This commit is contained in:
@@ -89,7 +89,7 @@
|
||||
- `audioContentId`, `title`, `duration`, `imageUrl`, `price`
|
||||
- `isAdult`, `isPointAvailable`, `isFirstContent`, `isOriginalSeries`, `creatorNickname`
|
||||
- `CommentedAudioResponse`
|
||||
- `audioContentId`, `title`, `imageUrl`, `latestCommentWriterProfileImageUrl`
|
||||
- `audioContentId`, `title`, `imageUrl`, `latestComment`, `latestCommentWriterProfileImageUrl`
|
||||
|
||||
## 재사용 가능한 V2 위젯 후보
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
- `SodaLive/Sources/V2/Component/TextTabBar.swift`
|
||||
- 내부 `추천` 탭 bar 구성 후보.
|
||||
- `SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift`
|
||||
- 배너 carousel 후보. 현재 정사각형 높이 계산이 들어 있어 Figma의 `362x374` 비율과 맞는지 확인 후 최소 보완한다.
|
||||
- 배너 carousel 후보. 메인 홈 추천 탭과 동일한 1:1 비율, 무한 슬라이딩, 자동 슬라이딩 동작을 재사용한다.
|
||||
- `SodaLive/Sources/V2/Component/SectionTitle.swift`
|
||||
- 섹션 제목과 우측 chevron 표시 후보.
|
||||
- `SodaLive/Sources/V2/Component/AudioContentCard.swift`
|
||||
@@ -159,7 +159,7 @@
|
||||
|
||||
### Phase 1: 기준점 점검과 콘텐츠 탭 shell 설계
|
||||
|
||||
- [ ] **Task 1.1: Figma와 기존 탭 구조 확인**
|
||||
- [x] **Task 1.1: Figma와 기존 탭 구조 확인**
|
||||
- 대상 파일:
|
||||
- 확인: `docs/20260705_메인_콘텐츠_내부_추천_탭/prd.md`
|
||||
- 확인: `docs/20260705_메인_콘텐츠_내부_추천_탭/plan-task.md`
|
||||
@@ -175,7 +175,7 @@
|
||||
- 실행 명령: `rg "GET /api/v2/audio/recommendations|추천 시리즈|키워드의 오디오|Open Questions|미결정 사항 없음|seriesDetail|AppDeepLinkHandler|nickname" docs/20260705_메인_콘텐츠_내부_추천_탭/prd.md && sed -n '140,190p' SodaLive/Sources/V2/Main/MainView.swift && sed -n '1,120p' SodaLive/Sources/V2/Main/Home/MainHomeView.swift`
|
||||
- 기대 결과: PRD의 확정 범위가 확인되고, `.content`는 placeholder이며, `MainHomeView`는 fixed shell과 tab content를 분리한다.
|
||||
|
||||
- [ ] **Task 1.2: 내부 콘텐츠 탭 root 생성**
|
||||
- [x] **Task 1.2: 내부 콘텐츠 탭 root 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/MainContentView.swift`
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/MainContentTab.swift`
|
||||
@@ -191,7 +191,7 @@
|
||||
|
||||
### Phase 2: API, Repository, Response model, ViewModel
|
||||
|
||||
- [ ] **Task 2.1: 추천 오디오 응답 모델 생성**
|
||||
- [x] **Task 2.1: 추천 오디오 응답 모델 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/Recommendation/Models/AudioRecommendationsResponse.swift`
|
||||
- 작업 내용:
|
||||
@@ -203,7 +203,7 @@
|
||||
- 실행 명령: `rg "struct AudioRecommendationsResponse|struct AudioBannerResponse|struct OriginalSeriesResponse|struct AudioCardResponse|struct CommentedAudioResponse|isAdult|isPointAvailable|isFirstContent|isOriginalSeries" SodaLive/Sources/V2/Main/Content/Recommendation/Models/AudioRecommendationsResponse.swift`
|
||||
- 기대 결과: API 응답 필드가 모두 Swift 모델에 반영된다.
|
||||
|
||||
- [ ] **Task 2.2: 추천 오디오 API endpoint 생성**
|
||||
- [x] **Task 2.2: 추천 오디오 API endpoint 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/Recommendation/Repository/MainContentRecommendationApi.swift`
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/Recommendation/Repository/MainContentRecommendationRepository.swift`
|
||||
@@ -218,7 +218,7 @@
|
||||
- 실행 명령: `rg "/api/v2/audio/recommendations|getAudioRecommendations|Authorization|AnyPublisher<Response, MoyaError>" SodaLive/Sources/V2/Main/Content/Recommendation/Repository`
|
||||
- 기대 결과: 신규 endpoint와 repository 메서드가 추천 오디오 전용 경로에만 존재한다.
|
||||
|
||||
- [ ] **Task 2.3: ViewModel 생성과 섹션 표시 상태 정리**
|
||||
- [x] **Task 2.3: ViewModel 생성과 섹션 표시 상태 정리**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/Recommendation/MainContentRecommendationViewModel.swift`
|
||||
- 수정: `SodaLive/Sources/I18n/I18n.swift`
|
||||
@@ -234,7 +234,7 @@
|
||||
|
||||
### Phase 3: 배너 섹션
|
||||
|
||||
- [ ] **Task 3.1: 배너 섹션 생성**
|
||||
- [x] **Task 3.1: 배너 섹션 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioBannerSection.swift`
|
||||
- 확인/보완: `SodaLive/Sources/V2/Component/Banner/BannerCarousel.swift`
|
||||
@@ -252,7 +252,7 @@
|
||||
|
||||
### Phase 4: 새로 올라온 오디오 섹션
|
||||
|
||||
- [ ] **Task 4.1: 가로 카드 섹션 공통 컴포넌트 생성**
|
||||
- [x] **Task 4.1: 가로 카드 섹션 공통 컴포넌트 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift`
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioTagOverlay.swift`
|
||||
@@ -268,7 +268,7 @@
|
||||
|
||||
### Phase 5: New&Hot 섹션
|
||||
|
||||
- [ ] **Task 5.1: New&Hot list carousel 섹션 생성**
|
||||
- [x] **Task 5.1: New&Hot list carousel 섹션 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioListCarouselSection.swift`
|
||||
- 확인: `SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelAudioContentListItem.swift`
|
||||
@@ -284,7 +284,7 @@
|
||||
|
||||
### Phase 6: 오직 보이스온에서만 섹션
|
||||
|
||||
- [ ] **Task 6.1: 보이스온 전용 시리즈 섹션 생성**
|
||||
- [x] **Task 6.1: 보이스온 전용 시리즈 섹션 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentVoiceOnOnlySection.swift`
|
||||
- 확인: `SodaLive/Sources/V2/CreatorChannel/Series/Components/CreatorChannelSeriesListItem.swift`
|
||||
@@ -302,7 +302,7 @@
|
||||
|
||||
### Phase 7: 무료 오디오 섹션
|
||||
|
||||
- [ ] **Task 7.1: 무료 오디오 섹션 연결**
|
||||
- [x] **Task 7.1: 무료 오디오 섹션 연결**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/Main/Content/Recommendation/MainContentRecommendationView.swift`
|
||||
- 확인: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift`
|
||||
@@ -316,7 +316,7 @@
|
||||
|
||||
### Phase 8: 포인트 오디오 섹션
|
||||
|
||||
- [ ] **Task 8.1: 포인트 오디오 섹션 연결**
|
||||
- [x] **Task 8.1: 포인트 오디오 섹션 연결**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/Main/Content/Recommendation/MainContentRecommendationView.swift`
|
||||
- 확인: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift`
|
||||
@@ -330,25 +330,26 @@
|
||||
|
||||
### Phase 9: 최근 댓글이 많은 오디오 섹션
|
||||
|
||||
- [ ] **Task 9.1: 댓글 카드 carousel 섹션 생성**
|
||||
- [x] **Task 9.1: 댓글 카드 carousel 섹션 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentMostCommentedAudioSection.swift`
|
||||
- 작업 내용:
|
||||
- Figma `24:6820`의 `최근 댓글이 많은 오디오`를 `mostCommentedAudios`로 표시한다.
|
||||
- 오디오 row와 댓글 preview bubble을 하나의 카드로 묶고, 카드 단위로 가로 스크롤한다.
|
||||
- `latestComment`를 댓글 본문으로 표시한다.
|
||||
- `latestCommentWriterProfileImageUrl`을 댓글 작성자 profile image로 표시한다.
|
||||
- 댓글 preview bubble에는 nickname을 표시하지 않는다.
|
||||
- `CommentedAudioResponse`에는 creator nickname이 없으므로 댓글 영역에 nickname용 UI나 placeholder를 추가하지 않는다.
|
||||
- 카드 탭 시 `onTapContent(audioContentId)`를 호출한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "MainContentMostCommentedAudioSection|mostCommentedAudios|CommentedAudioResponse|latestCommentWriterProfileImageUrl|onTapContent" SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentMostCommentedAudioSection.swift`
|
||||
- 기대 결과: 최근 댓글 섹션은 댓글 작성자 profile image와 오디오 탭 callback을 사용한다.
|
||||
- 실행 명령: `rg "MainContentMostCommentedAudioSection|mostCommentedAudios|CommentedAudioResponse|latestComment|latestCommentWriterProfileImageUrl|onTapContent" SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentMostCommentedAudioSection.swift SodaLive/Sources/V2/Main/Content/Recommendation/Models/AudioRecommendationsResponse.swift`
|
||||
- 기대 결과: 최근 댓글 섹션은 실제 댓글 본문, 댓글 작성자 profile image, 오디오 탭 callback을 사용한다.
|
||||
- 실행 명령: `rg "nickname|creatorNickname" SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentMostCommentedAudioSection.swift`
|
||||
- 기대 결과: 검색 결과가 없어야 한다. 댓글 bubble에는 nickname을 표시하지 않는다.
|
||||
|
||||
### Phase 10: 추천 오디오 섹션
|
||||
|
||||
- [ ] **Task 10.1: 추천 오디오 grid 섹션 생성**
|
||||
- [x] **Task 10.1: 추천 오디오 grid 섹션 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swift`
|
||||
- 수정: `SodaLive/Sources/V2/Main/Content/Recommendation/MainContentRecommendationView.swift`
|
||||
@@ -364,7 +365,7 @@
|
||||
|
||||
### Phase 11: 제외 섹션 미구현 확인
|
||||
|
||||
- [ ] **Task 11.1: 추천 시리즈와 키워드의 오디오 제외 확인**
|
||||
- [x] **Task 11.1: 추천 시리즈와 키워드의 오디오 제외 확인**
|
||||
- 대상 파일:
|
||||
- 확인: `SodaLive/Sources/V2/Main/Content/Recommendation/**`
|
||||
- 작업 내용:
|
||||
@@ -377,7 +378,7 @@
|
||||
|
||||
### Phase 12: 라우팅, 프로젝트 포함, 전체 검증
|
||||
|
||||
- [ ] **Task 12.1: 상세 진입 callback 연결**
|
||||
- [x] **Task 12.1: 상세 진입 callback 연결**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/Main/MainView.swift`
|
||||
- 확인: `SodaLive/Sources/App/AppStep.swift`
|
||||
@@ -393,7 +394,7 @@
|
||||
- 실행 명령: `rg "contentDetail|eventItem|eventDetail|creatorDetail|seriesDetail|AppDeepLinkHandler|UIApplication.shared.open|MainContentView" SodaLive/Sources/V2/Main/MainView.swift SodaLive/Sources/App/AppStep.swift SodaLive/Sources/ContentView.swift`
|
||||
- 기대 결과: 상세 진입과 event/creator/series route가 기존 route와 guard 흐름을 재사용하고, link는 deep link 우선 후 외부 브라우저로 처리한다.
|
||||
|
||||
- [ ] **Task 12.2: 프로젝트 포함 및 빌드 검증**
|
||||
- [x] **Task 12.2: 프로젝트 포함 및 빌드 검증**
|
||||
- 대상 파일:
|
||||
- 확인/보완: `SodaLive.xcodeproj/project.pbxproj`
|
||||
- 확인: `SodaLive/Sources/V2/Main/Content/**`
|
||||
@@ -407,6 +408,155 @@
|
||||
- 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`
|
||||
- 기대 결과: `BUILD SUCCEEDED`
|
||||
|
||||
### Phase 13: 오디오 row 공용 컴포넌트 정리
|
||||
|
||||
- [x] **Task 13.1: 공용 오디오 list row 컴포넌트 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Component/AudioContent/AudioContentListRow.swift`
|
||||
- 확인: `SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelHomeAudioContentListItem.swift`
|
||||
- 확인: `SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelAudioContentListItem.swift`
|
||||
- 작업 내용:
|
||||
- 크리에이터 채널 홈 탭 오디오 item과 크리에이터 채널 오디오 탭 item의 공통 row 구조를 기반으로 `AudioContentListRow`를 만든다.
|
||||
- 표시 데이터는 API 모델에 직접 의존하지 않는 `AudioContentListRowItem`으로 둔다.
|
||||
- 표시 변형은 `AudioContentListRowStyle.compact(width:)`, `AudioContentListRowStyle.purchaseState`로 분리한다.
|
||||
- `compact`는 title 1줄, subtitle 1줄, trailing 상태 없음으로 구성한다.
|
||||
- `purchaseState`는 title 2줄, duration subtitle, owned/rented/free/price trailing 상태를 표시한다.
|
||||
- 기존 tag asset 조합(`ic_content_tag_original`, `ic_content_tag_first_star`, `ic_content_tag_point`, `ic_new_shield_small`, `무료`)을 공용 row 안에서 재사용한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "struct AudioContentListRow|struct AudioContentListRowItem|enum AudioContentListRowStyle|case compact|case purchaseState|ic_content_tag_original|ic_content_tag_point|ic_content_tag_first_star|ic_new_shield_small" SodaLive/Sources/V2/Component/AudioContent/AudioContentListRow.swift`
|
||||
- 기대 결과: 공용 row, 표시 모델, style enum, tag asset 사용이 확인된다.
|
||||
|
||||
- [x] **Task 13.2: 메인 콘텐츠 추천 New&Hot에 공용 row 적용**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioListCarouselSection.swift`
|
||||
- 작업 내용:
|
||||
- 기존 private `row(_:)` 직접 구현을 제거한다.
|
||||
- `AudioCardResponse`를 `AudioContentListRowItem`으로 매핑한다.
|
||||
- subtitle은 Figma 기준 `creatorNickname`을 사용한다.
|
||||
- style은 `.compact(width: UIScreen.main.bounds.width - (SodaSpacing.s20 * 2))` 또는 동일한 column 폭 기준으로 사용한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "AudioContentListRow|AudioContentListRowItem|\.compact|creatorNickname|private func row|MainContentAudioTagOverlay" SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioListCarouselSection.swift`
|
||||
- 기대 결과: 공용 row 사용이 확인되고, 기존 private row와 `MainContentAudioTagOverlay` 의존이 제거된다.
|
||||
|
||||
- [x] **Task 13.3: 크리에이터 채널 홈 오디오 섹션에 공용 row 적용**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelAudioSection.swift`
|
||||
- 작업 내용:
|
||||
- `CreatorChannelHomeAudioContentListItem` 사용을 제거한다.
|
||||
- `CreatorChannelAudioContentResponse`를 `AudioContentListRowItem`으로 매핑한다.
|
||||
- subtitle은 기존과 동일하게 `duration`과 `seriesName`을 ` • `로 조합한다.
|
||||
- style은 기존 row 폭과 동일하게 `.compact(width: 346)`을 사용한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "AudioContentListRow|AudioContentListRowItem|\.compact\(width: 346\)|CreatorChannelHomeAudioContentListItem" SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelAudioSection.swift`
|
||||
- 기대 결과: 공용 row 사용이 확인되고 기존 home item 참조는 없어야 한다.
|
||||
|
||||
- [x] **Task 13.4: 크리에이터 채널 오디오/라이브 replay 탭에 공용 row 적용**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/CreatorChannel/Audio/CreatorChannelAudioTabView.swift`
|
||||
- 수정: `SodaLive/Sources/V2/CreatorChannel/Live/CreatorChannelLiveTabView.swift`
|
||||
- 작업 내용:
|
||||
- `CreatorChannelAudioContentListItem` 사용을 제거한다.
|
||||
- `CreatorChannelAudioContentResponse`를 `AudioContentListRowItem`으로 매핑한다.
|
||||
- style은 `.purchaseState`를 사용해 기존 가격/소유/대여/무료 재생 상태를 유지한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "AudioContentListRow|AudioContentListRowItem|\.purchaseState|CreatorChannelAudioContentListItem" SodaLive/Sources/V2/CreatorChannel/Audio/CreatorChannelAudioTabView.swift SodaLive/Sources/V2/CreatorChannel/Live/CreatorChannelLiveTabView.swift`
|
||||
- 기대 결과: 공용 row 사용이 확인되고 기존 audio item 참조는 없어야 한다.
|
||||
|
||||
- [x] **Task 13.5: 미사용 기존 item 컴포넌트 삭제와 프로젝트 정리**
|
||||
- 대상 파일:
|
||||
- 삭제: `SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelHomeAudioContentListItem.swift`
|
||||
- 삭제: `SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelAudioContentListItem.swift`
|
||||
- 확인/보완: `SodaLive.xcodeproj/project.pbxproj`
|
||||
- 작업 내용:
|
||||
- 공용 row 적용 후 참조가 사라진 기존 item 컴포넌트 파일을 삭제한다.
|
||||
- Xcode project의 file reference/build phase에서 삭제 파일을 제거하고 신규 공용 파일을 추가한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `! rg "CreatorChannelHomeAudioContentListItem|CreatorChannelAudioContentListItem" SodaLive/Sources/V2`
|
||||
- 기대 결과: 삭제한 기존 item 컴포넌트 참조가 남아 있지 않아야 한다.
|
||||
- 실행 명령: `plutil -lint SodaLive.xcodeproj/project.pbxproj`
|
||||
- 기대 결과: `OK`
|
||||
|
||||
- [x] **Task 13.6: 공용 오디오 row 리팩터링 빌드 검증**
|
||||
- 대상 파일:
|
||||
- 확인: `SodaLive/Sources/V2/Component/AudioContent/AudioContentListRow.swift`
|
||||
- 확인: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioListCarouselSection.swift`
|
||||
- 확인: `SodaLive/Sources/V2/CreatorChannel/Home/Components/CreatorChannelAudioSection.swift`
|
||||
- 확인: `SodaLive/Sources/V2/CreatorChannel/Audio/CreatorChannelAudioTabView.swift`
|
||||
- 확인: `SodaLive/Sources/V2/CreatorChannel/Live/CreatorChannelLiveTabView.swift`
|
||||
- 작업 내용:
|
||||
- New&Hot, 크리에이터 채널 홈 오디오, 크리에이터 채널 오디오 탭, 라이브 replay 탭이 공용 row를 사용하도록 최종 확인한다.
|
||||
- `SodaLive-dev` 빌드를 실행한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`
|
||||
- 기대 결과: `BUILD SUCCEEDED`
|
||||
|
||||
### Phase 14: 오디오 card 공용 컴포넌트 정리
|
||||
|
||||
- [x] **Task 14.1: 공용 오디오 card 컴포넌트 생성**
|
||||
- 대상 파일:
|
||||
- 생성: `SodaLive/Sources/V2/Component/AudioContent/AudioContentThumbnailCard.swift`
|
||||
- 확인: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift`
|
||||
- 확인: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swift`
|
||||
- 확인: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioTagOverlay.swift`
|
||||
- 작업 내용:
|
||||
- 새로 올라온 오디오, 무료 오디오, 포인트 오디오, 추천 오디오 섹션에서 공통으로 쓰는 카드형 오디오 item 컴포넌트를 만든다.
|
||||
- 표시 데이터는 API 모델에 직접 의존하지 않는 `AudioContentThumbnailCardItem`으로 둔다.
|
||||
- title/subtitle typography는 기존 `AudioContentCardSize` 규칙을 유지한다.
|
||||
- 이미지 좌측 상단에는 오리지널, 처음 업로드 오디오 태그를 표시한다.
|
||||
- 이미지 우측 상단에는 `isAdult` shield 태그를 표시한다.
|
||||
- 이미지 좌측 하단에는 포인트, 무료 태그를 표시한다.
|
||||
- 태그는 Figma node `567:18089`, `567:18090`, `567:18124`, `567:18272` 기준으로 `ic_content_tag_original`, `ic_content_tag_first_star`, `ic_content_tag_point`, `ic_new_shield_small`, `무료` 조합을 사용한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "struct AudioContentThumbnailCard|struct AudioContentThumbnailCardItem|ic_content_tag_original|ic_content_tag_first_star|ic_content_tag_point|ic_new_shield_small|무료" SodaLive/Sources/V2/Component/AudioContent/AudioContentThumbnailCard.swift`
|
||||
- 기대 결과: 공용 카드, 표시 모델, Figma 기준 태그 조합이 확인된다.
|
||||
|
||||
- [x] **Task 14.2: 새로 올라온/무료/포인트 오디오 섹션에 공용 card 적용**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift`
|
||||
- 작업 내용:
|
||||
- `AudioContentCard`와 `MainContentAudioTagOverlay` 조합을 제거한다.
|
||||
- `AudioCardResponse`를 `AudioContentThumbnailCardItem`으로 매핑한다.
|
||||
- 기존과 동일하게 medium 카드 크기, title, creatorNickname subtitle을 유지한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "AudioContentThumbnailCard|AudioContentThumbnailCardItem|AudioContentCard\(|MainContentAudioTagOverlay" SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift`
|
||||
- 기대 결과: 공용 카드 사용이 확인되고 기존 직접 조합은 없어야 한다.
|
||||
|
||||
- [x] **Task 14.3: 추천 오디오 grid 섹션에 공용 card 적용**
|
||||
- 대상 파일:
|
||||
- 수정: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swift`
|
||||
- 작업 내용:
|
||||
- 기존 thumbnail/tag/title/subtitle 직접 구현을 제거한다.
|
||||
- `GeometryReader`에서 계산한 width를 공용 card에 전달한다.
|
||||
- 기존과 동일하게 grid item의 `aspectRatio(0.78, contentMode: .fit)` 흐름을 유지한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `rg "AudioContentThumbnailCard|AudioContentThumbnailCardItem|MainContentAudioTagOverlay|DownsampledKFImage|Text\(item.title\)" SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swift`
|
||||
- 기대 결과: 공용 카드 사용이 확인되고 grid 내부 직접 구현은 없어야 한다.
|
||||
|
||||
- [x] **Task 14.4: 기존 main content tag overlay 삭제와 프로젝트 정리**
|
||||
- 대상 파일:
|
||||
- 삭제: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioTagOverlay.swift`
|
||||
- 확인/보완: `SodaLive.xcodeproj/project.pbxproj`
|
||||
- 작업 내용:
|
||||
- 공용 card 적용 후 사용하지 않는 기존 main content 전용 tag overlay를 삭제한다.
|
||||
- Xcode project의 file reference/build phase에서 삭제 파일을 제거하고 신규 공용 파일을 추가한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `! rg "MainContentAudioTagOverlay" SodaLive/Sources/V2 SodaLive.xcodeproj/project.pbxproj`
|
||||
- 기대 결과: 기존 tag overlay 참조가 남아 있지 않아야 한다.
|
||||
- 실행 명령: `plutil -lint SodaLive.xcodeproj/project.pbxproj`
|
||||
- 기대 결과: `OK`
|
||||
|
||||
- [x] **Task 14.5: 공용 오디오 card 리팩터링 빌드 검증**
|
||||
- 대상 파일:
|
||||
- 확인: `SodaLive/Sources/V2/Component/AudioContent/AudioContentThumbnailCard.swift`
|
||||
- 확인: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift`
|
||||
- 확인: `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swift`
|
||||
- 작업 내용:
|
||||
- 새로 올라온 오디오, 무료 오디오, 포인트 오디오, 추천 오디오 섹션이 공용 card를 사용하도록 최종 확인한다.
|
||||
- `SodaLive-dev` 빌드를 실행한다.
|
||||
- 검증 기준:
|
||||
- 실행 명령: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`
|
||||
- 기대 결과: `BUILD SUCCEEDED`
|
||||
|
||||
## 검증 기록
|
||||
|
||||
- 2026-07-05 문서 작성:
|
||||
@@ -451,5 +601,37 @@
|
||||
- `docs/20260705_메인_콘텐츠_내부_추천_탭/plan-task.md`
|
||||
- 결과:
|
||||
- 신규 사용자 노출 문구를 I18n ko/en/ja로 추가한다는 기준을 Task 2.3에 명시했다.
|
||||
- 배너 `eventItem`의 기존 event detail 흐름 재사용 기준을 Phase 12 최종 라우팅 검증에 추가했다.
|
||||
- 이번 작업은 문서 보완만 수행했으므로 빌드/테스트는 실행하지 않았다.
|
||||
- 배너 `eventItem`의 기존 event detail 흐름 재사용 기준을 Phase 12 최종 라우팅 검증에 추가했다.
|
||||
- 이번 작업은 문서 보완만 수행했으므로 빌드/테스트는 실행하지 않았다.
|
||||
- 2026-07-06 문서 기준 구현:
|
||||
- 실행/확인:
|
||||
- `SodaLive/Sources/V2/Main/Content/**`
|
||||
- `SodaLive/Sources/V2/Main/MainView.swift`
|
||||
- `SodaLive/Sources/I18n/I18n.swift`
|
||||
- `SodaLive.xcodeproj/project.pbxproj`
|
||||
- `rg "enum MainContentTab|struct MainContentView|MainContentRecommendationView|case \\.content" SodaLive/Sources/V2/Main`
|
||||
- `rg "/api/v2/audio/recommendations|getAudioRecommendations|Authorization|AnyPublisher<Response, MoyaError>" SodaLive/Sources/V2/Main/Content/Recommendation/Repository`
|
||||
- `rg "MainContentAudioBannerSection|AudioBannerResponse|imageUrl|eventItem|creatorId|seriesId|link|seriesDetail|AppDeepLinkHandler|UIApplication.shared.open" SodaLive/Sources/V2/Main/Content/Recommendation SodaLive/Sources/V2/Main/MainView.swift`
|
||||
- `rg "MainContentVoiceOnOnlySection|originalSeries|OriginalSeriesResponse|ic_series_original|img_new_only|onTapSeries|seriesDetail" SodaLive/Sources/V2/Main/Content/Recommendation SodaLive/Sources/V2/Main/MainView.swift SodaLive/Resources/Assets.xcassets/v2`
|
||||
- `! rg "추천 시리즈|Keyword|키워드의 오디오|RecommendedSeries" SodaLive/Sources/V2/Main/Content/Recommendation`
|
||||
- `plutil -lint SodaLive.xcodeproj/project.pbxproj`
|
||||
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`
|
||||
- 결과:
|
||||
- `.content` 탭을 신규 `MainContentView`로 교체하고 고정 title bar, 내부 `추천` tab bar, 추천 body 스크롤 구조를 구현했다.
|
||||
- `GET /api/v2/audio/recommendations` endpoint, repository, response model, ViewModel 상태/디코딩/I18n 문구를 추가했다.
|
||||
- 배너, 새로 올라온 오디오, New&Hot, 오직 보이스온에서만, 무료 오디오, 포인트 오디오, 최근 댓글이 많은 오디오, 추천 오디오 섹션을 구현했다.
|
||||
- `추천 시리즈`, `키워드의 오디오`는 구현하지 않았고, 최근 댓글 섹션에는 nickname UI를 추가하지 않았다.
|
||||
- `plutil`은 `OK`, `xcodebuild`는 `BUILD SUCCEEDED`로 통과했다.
|
||||
- 2026-07-06 오디오 card 공용 컴포넌트 정리:
|
||||
- 실행/확인:
|
||||
- `SodaLive/Sources/V2/Component/AudioContent/AudioContentThumbnailCard.swift`
|
||||
- `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentAudioHorizontalCardSection.swift`
|
||||
- `SodaLive/Sources/V2/Main/Content/Recommendation/Components/MainContentRecommendedAudioGridSection.swift`
|
||||
- `SodaLive.xcodeproj/project.pbxproj`
|
||||
- `rg "MainContentAudioTagOverlay|AudioContentThumbnailCard" "SodaLive/Sources/V2" "SodaLive.xcodeproj/project.pbxproj"`
|
||||
- `plutil -lint "SodaLive.xcodeproj/project.pbxproj"`
|
||||
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build`
|
||||
- 결과:
|
||||
- 새로 올라온 오디오, 무료 오디오, 포인트 오디오, 추천 오디오 섹션이 `AudioContentThumbnailCard`를 사용하도록 정리했다.
|
||||
- 기존 `MainContentAudioTagOverlay.swift`를 삭제하고 신규 공용 card 파일을 Xcode project에 추가했다.
|
||||
- `plutil`은 `OK`, `xcodebuild`는 `BUILD SUCCEEDED`로 통과했다.
|
||||
|
||||
@@ -134,7 +134,7 @@ Swift 모델은 기존 V2 관례에 맞춰 `Decodable` 구조체로 선언한다
|
||||
- 일반 오디오 카드 섹션은 가로 스크롤 카드 목록으로 표시한다.
|
||||
- `New&Hot`은 3개 row를 한 묶음으로 구성하고 묶음 단위로 가로 스크롤한다.
|
||||
- `최근 댓글이 많은 오디오`는 오디오 row와 댓글 preview bubble을 하나의 카드로 묶어 가로 스크롤한다.
|
||||
- `최근 댓글이 많은 오디오`의 댓글 preview bubble에는 nickname을 표시하지 않는다. Figma `24:6820` 기준으로 `latestCommentWriterProfileImageUrl`과 댓글 텍스트 영역만 사용한다.
|
||||
- `최근 댓글이 많은 오디오`의 댓글 preview bubble에는 nickname을 표시하지 않는다. Figma `24:6820` 기준으로 `latestCommentWriterProfileImageUrl`과 `latestComment` 댓글 텍스트 영역만 사용한다.
|
||||
- `추천 오디오`는 2열 grid로 표시한다.
|
||||
- 텍스트가 길면 한 줄 또는 Figma 기준 line limit로 말줄임 처리한다.
|
||||
- 카드/row의 루트 레이아웃은 가능한 부모 width, grid column, aspect ratio 기반으로 구성한다.
|
||||
|
||||
Reference in New Issue
Block a user