feat(creator): 대화하기 채팅방 진입을 연결한다

This commit is contained in:
Yu Sung
2026-07-03 18:57:17 +09:00
parent 2b9018f9cb
commit b84098b15e
4 changed files with 60 additions and 5 deletions

View File

@@ -313,7 +313,7 @@ struct CreatorChannelView: View {
if isKoreanCountry && auth == false { if isKoreanCountry && auth == false {
pendingAction = { pendingAction = {
AppState.shared.setAppStep(step: .characterDetail(characterId: characterId)) startChat(characterId: characterId)
} }
isShowAuthConfirmView = true isShowAuthConfirmView = true
return return
@@ -325,7 +325,13 @@ struct CreatorChannelView: View {
return return
} }
AppState.shared.setAppStep(step: .characterDetail(characterId: characterId)) startChat(characterId: characterId)
}
private func startChat(characterId: Int) {
viewModel.createChatRoom(characterId: characterId) { chatRoomId in
AppState.shared.setAppStep(step: .chatRoom(id: chatRoomId))
}
} }
private func moveToContentSettingsWithGuideToast() { private func moveToContentSettingsWithGuideToast() {

View File

@@ -121,6 +121,42 @@ final class CreatorChannelViewModel: ObservableObject {
.store(in: &subscription) .store(in: &subscription)
} }
func createChatRoom(characterId: Int, onSuccess: @escaping (Int) -> Void) {
guard characterId > 0 else { return }
isLoading = true
repository.createChatRoom(characterId: characterId)
.receive(on: DispatchQueue.main)
.sink { [weak self] result in
switch result {
case .finished:
DEBUG_LOG("finish")
case .failure(let error):
ERROR_LOG(error.localizedDescription)
self?.isLoading = false
}
} receiveValue: { [weak self] response in
self?.isLoading = false
do {
let jsonDecoder = JSONDecoder()
let decoded = try jsonDecoder.decode(ApiResponse<CreateChatRoomResponse>.self, from: response.data)
if let data = decoded.data, decoded.success {
onSuccess(data.chatRoomId)
} else {
self?.errorMessage = decoded.message ?? I18n.Common.commonError
self?.isShowPopup = true
}
} catch {
ERROR_LOG(error.localizedDescription)
self?.errorMessage = I18n.Common.commonError
self?.isShowPopup = true
}
}
.store(in: &subscription)
}
private func applyApiFailedPlaceholderState() { private func applyApiFailedPlaceholderState() {
response = nil response = nil
isApiFailedPlaceholderVisible = true isApiFailedPlaceholderVisible = true

View File

@@ -6,8 +6,13 @@ import Moya
final class CreatorChannelHomeRepository { final class CreatorChannelHomeRepository {
private let api = MoyaProvider<CreatorChannelHomeApi>() private let api = MoyaProvider<CreatorChannelHomeApi>()
private let talkApi = MoyaProvider<TalkApi>()
func getHome(creatorId: Int) -> AnyPublisher<Response, MoyaError> { func getHome(creatorId: Int) -> AnyPublisher<Response, MoyaError> {
return api.requestPublisher(.getHome(creatorId: creatorId)) return api.requestPublisher(.getHome(creatorId: creatorId))
} }
func createChatRoom(characterId: Int) -> AnyPublisher<Response, MoyaError> {
return talkApi.requestPublisher(.createChatRoom(request: CreateChatRoomRequest(characterId: characterId)))
}
} }

View File

@@ -559,7 +559,11 @@
- [x] **Task 17.2: 기존 AI 채팅방 진입 guard 연결** - [x] **Task 17.2: 기존 AI 채팅방 진입 guard 연결**
- 대상 파일: - 대상 파일:
- 수정: `SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift` - 수정: `SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift`
- 수정: `SodaLive/Sources/V2/CreatorChannel/CreatorChannelViewModel.swift`
- 수정: `SodaLive/Sources/V2/CreatorChannel/Home/Repository/CreatorChannelHomeRepository.swift`
- 수정: `SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift` - 수정: `SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift`
- 확인: `SodaLive/Sources/Chat/Character/Detail/CharacterDetailView.swift`
- 확인: `SodaLive/Sources/Chat/Character/Detail/CharacterDetailViewModel.swift`
- 확인: `SodaLive/Sources/Chat/ChatTabView.swift` - 확인: `SodaLive/Sources/Chat/ChatTabView.swift`
- 확인: `SodaLive/Sources/App/AppStep.swift` - 확인: `SodaLive/Sources/App/AppStep.swift`
- 작업 내용: - 작업 내용:
@@ -568,10 +572,13 @@
- 국가 코드를 trim/uppercase 처리하고, 비어 있거나 `KR`이면 한국으로 취급한다. - 국가 코드를 trim/uppercase 처리하고, 비어 있거나 `KR`이면 한국으로 취급한다.
- 한국 사용자는 `auth == false`일 때 기존 본인인증 confirm/fullScreenCover 흐름을 재사용하거나 같은 조건으로 연결한다. - 한국 사용자는 `auth == false`일 때 기존 본인인증 confirm/fullScreenCover 흐름을 재사용하거나 같은 조건으로 연결한다.
- 비한국 사용자는 기존 `ChatTabView`의 비한국 분기와 동일하게 `auth` 조건 비교를 적용한다. - 비한국 사용자는 기존 `ChatTabView`의 비한국 분기와 동일하게 `auth` 조건 비교를 적용한다.
- 본인인증과 콘텐츠 보기 설정 guard를 통과하면 `creator.characterId`기존 AI 채팅방/캐릭터 상세 진입 흐름을 연결한다. - 본인인증과 콘텐츠 보기 설정 guard를 통과하면 `creator.characterId``TalkApi.createChatRoom`을 호출하고, 성공 응답의 `chatRoomId``.chatRoom(id:)`에 바로 진입한다.
- 본인인증 완료 후 실행되는 `pendingAction``.characterDetail(characterId:)`가 아니라 같은 채팅방 생성 후 `.chatRoom(id:)` 진입 helper를 사용한다.
- 검증 기준: - 검증 기준:
- 실행 명령: `rg "onTapTalk|countryCode|uppercased\\(\\)|isKoreanCountry|auth == false|isShowAuthConfirmView|characterId|characterDetail|setAppStep\\(step: \\.login\\)" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift` - 실행 명령: `rg "onTapTalk|countryCode|uppercased\\(\\)|isKoreanCountry|auth == false|isShowAuthConfirmView|createChatRoom|chatRoom\\(id:|setAppStep\\(step: \\.login\\)" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift SodaLive/Sources/V2/CreatorChannel/CreatorChannelViewModel.swift SodaLive/Sources/V2/CreatorChannel/Home/Repository/CreatorChannelHomeRepository.swift SodaLive/Sources/V2/CreatorChannel/Home/CreatorChannelHomeView.swift`
- 기대 결과: 기존 AI 채팅 guard와 동일한 국가/본인인증 분기가 확인된다. - 기대 결과: 기존 AI 채팅 guard와 동일한 국가/본인인증 분기가 유지되고, guard 통과 후 캐릭터 상세가 아닌 채팅방으로 직접 이동한다.
- 실행 명령: `rg "characterDetail\\(characterId: characterId\\)" SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift`
- 기대 결과: 검색 결과가 없다.
### Phase 18: 최종 조립과 검증 ### Phase 18: 최종 조립과 검증
@@ -648,3 +655,4 @@
- 2026-07-02: Task 3.2 구현을 완료하고 `CreatorChannelHeaderSection`을 공통 shell에 연결했다. `rg "struct CreatorChannelHeaderSection|CreatorChannelCreatorResponse|profileImageUrl|ignoresSafeArea\\(.*top|nickname|followerCount|DownsampledKFImage|KFImage" SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelHeaderSection.swift SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift``xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 성공으로 검증했다. - 2026-07-02: Task 3.2 구현을 완료하고 `CreatorChannelHeaderSection`을 공통 shell에 연결했다. `rg "struct CreatorChannelHeaderSection|CreatorChannelCreatorResponse|profileImageUrl|ignoresSafeArea\\(.*top|nickname|followerCount|DownsampledKFImage|KFImage" SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelHeaderSection.swift SodaLive/Sources/V2/CreatorChannel/CreatorChannelView.swift``xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 성공으로 검증했다.
- 2026-07-02: Task 3.1 title bar 컴포넌트를 `SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift`로 생성하고 `CreatorChannelView`의 inline title bar를 교체했다. `rg "struct CreatorChannelTitleBar|isFollow|isNotify|backgroundProgress|onTapBack|onTapFollow|onTapUnfollow|onTapNotify|onTapUnnotify|onTapMore|ic_new_bar_back|ic_new_follow|ic_new_following|ic_new_more|ic_bar_bell|ic_bar_bell_fill|팔로우" SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift``xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 성공으로 검증했다. - 2026-07-02: Task 3.1 title bar 컴포넌트를 `SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift`로 생성하고 `CreatorChannelView`의 inline title bar를 교체했다. `rg "struct CreatorChannelTitleBar|isFollow|isNotify|backgroundProgress|onTapBack|onTapFollow|onTapUnfollow|onTapNotify|onTapUnnotify|onTapMore|ic_new_bar_back|ic_new_follow|ic_new_following|ic_new_more|ic_bar_bell|ic_bar_bell_fill|팔로우" SodaLive/Sources/V2/CreatorChannel/Components/CreatorChannelTitleBar.swift``xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` 성공으로 검증했다.
- 2026-07-02: 사용자 확인 사항을 반영해 HeaderView는 `CreatorChannelHomeResponse.creator` 데이터로 채우고, 별도 프로필 이미지 없이 큰 배경 이미지만 표시하며, title bar는 기본 투명 배경으로 header 위에 overlay되도록 Task 3.2/3.4/3.5와 최종 검증 기준을 갱신했다. - 2026-07-02: 사용자 확인 사항을 반영해 HeaderView는 `CreatorChannelHomeResponse.creator` 데이터로 채우고, 별도 프로필 이미지 없이 큰 배경 이미지만 표시하며, title bar는 기본 투명 배경으로 header 위에 overlay되도록 Task 3.2/3.4/3.5와 최종 검증 기준을 갱신했다.
- 2026-07-03: 사용자 요청에 따라 Task 17.2의 대화하기 액션을 캐릭터 상세 이동이 아니라 기존 Character Detail 하단 `대화하기`와 동일한 `TalkApi.createChatRoom` 호출 후 `.chatRoom(id:)` 직접 진입으로 변경했다. `CreatorChannelView`의 로그인/한국 본인인증/content settings guard는 유지했고, 본인인증 완료 후 `pendingAction`도 같은 `startChat(characterId:)` helper를 사용하도록 연결했다. `rg -n "characterDetail\\(characterId: characterId\\)|startChat\\(characterId:|createChatRoom\\(characterId:|chatRoom\\(id:" "SodaLive/Sources/V2/CreatorChannel"`와 ast-grep `AppState.shared.setAppStep(step: .characterDetail(characterId: $ID))` 검색으로 CreatorChannel 대화하기 경로에 캐릭터 상세 이동이 남지 않았음을 확인했다. 테스트는 `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test` 실행 결과 `Scheme SodaLive-dev is not currently configured for the test action.`으로 RED/GREEN 자동화가 불가했다. 빌드는 `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build``BUILD SUCCEEDED`로 완료됐다.