feat(creator): 대화하기 액션을 연결한다
This commit is contained in:
@@ -3,6 +3,7 @@ import Kingfisher
|
||||
|
||||
struct CreatorChannelHeaderSection: View {
|
||||
let creator: CreatorChannelCreatorResponse
|
||||
let onTapTalk: () -> Void
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .bottom) {
|
||||
@@ -49,7 +50,10 @@ struct CreatorChannelHeaderSection: View {
|
||||
.foregroundColor(.white)
|
||||
.multilineTextAlignment(.center)
|
||||
|
||||
talkButton
|
||||
CreatorChannelTalkActionSection(
|
||||
isAiChatAvailable: creator.isAiChatAvailable,
|
||||
onTapTalk: onTapTalk
|
||||
)
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.horizontal, SodaSpacing.s24)
|
||||
@@ -57,24 +61,4 @@ struct CreatorChannelHeaderSection: View {
|
||||
}
|
||||
.frame(width: screenSize().width, height: screenSize().width)
|
||||
}
|
||||
|
||||
private var talkButton: some View {
|
||||
Button(action: {}) {
|
||||
HStack(spacing: SodaSpacing.s6) {
|
||||
Image("ic_new_talk")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
|
||||
Text(I18n.CreatorChannelHome.talk)
|
||||
.appFont(size: 16, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
.padding(SodaSpacing.s12)
|
||||
.overlay(
|
||||
Capsule()
|
||||
.stroke(Color.white.opacity(0.3), lineWidth: 1)
|
||||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
import SwiftUI
|
||||
import Bootpay
|
||||
import BootpayUI
|
||||
|
||||
struct CreatorChannelView: View {
|
||||
let creatorId: Int
|
||||
|
||||
@StateObject private var viewModel = CreatorChannelViewModel()
|
||||
@StateObject private var channelDonationViewModel = ChannelDonationViewModel()
|
||||
@StateObject private var mypageViewModel = MyPageViewModel()
|
||||
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
|
||||
@AppStorage("auth") private var auth: Bool = UserDefaults.bool(forKey: UserDefaultsKey.auth)
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@State private var tabBarMinY: CGFloat = .greatestFiniteMagnitude
|
||||
@State private var isShowChannelDonationDialog = false
|
||||
@State private var isShowAuthView = false
|
||||
@State private var isShowAuthConfirmView = false
|
||||
@State private var pendingAction: (() -> Void)? = nil
|
||||
@State private var payload = Payload()
|
||||
|
||||
private let titleBarHeight: CGFloat = 56
|
||||
private let tabBarHeight: CGFloat = 52
|
||||
@@ -68,6 +77,10 @@ struct CreatorChannelView: View {
|
||||
LoadingView()
|
||||
}
|
||||
|
||||
if isShowAuthConfirmView {
|
||||
authConfirmDialog
|
||||
}
|
||||
|
||||
if isShowChannelDonationDialog {
|
||||
LiveRoomDonationDialogView(
|
||||
isShowing: $isShowChannelDonationDialog,
|
||||
@@ -92,7 +105,11 @@ struct CreatorChannelView: View {
|
||||
}
|
||||
}
|
||||
.navigationBarBackButtonHidden(true)
|
||||
.fullScreenCover(isPresented: $isShowAuthView) {
|
||||
authView
|
||||
}
|
||||
.onAppear {
|
||||
configurePayload()
|
||||
if viewModel.hasLoaded == false {
|
||||
viewModel.fetchHome(creatorId: creatorId)
|
||||
}
|
||||
@@ -129,7 +146,7 @@ struct CreatorChannelView: View {
|
||||
@ViewBuilder
|
||||
private var headerSection: some View {
|
||||
if let creator = viewModel.response?.creator {
|
||||
CreatorChannelHeaderSection(creator: creator)
|
||||
CreatorChannelHeaderSection(creator: creator, onTapTalk: handleTalkTap)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,6 +185,57 @@ struct CreatorChannelView: View {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private var authConfirmDialog: some View {
|
||||
SodaDialog(
|
||||
title: I18n.Chat.Auth.dialogTitle,
|
||||
desc: I18n.Chat.Auth.dialogDescription,
|
||||
confirmButtonTitle: I18n.Chat.Auth.goToVerification,
|
||||
confirmButtonAction: {
|
||||
isShowAuthConfirmView = false
|
||||
isShowAuthView = true
|
||||
},
|
||||
cancelButtonTitle: I18n.Common.cancel,
|
||||
cancelButtonAction: {
|
||||
isShowAuthConfirmView = false
|
||||
pendingAction = nil
|
||||
},
|
||||
textAlignment: .center
|
||||
)
|
||||
}
|
||||
|
||||
private var authView: some View {
|
||||
BootpayUI(payload: payload, requestType: BootpayRequest.TYPE_AUTHENTICATION)
|
||||
.onConfirm { _ in true }
|
||||
.onCancel { _ in isShowAuthView = false }
|
||||
.onError { _ in
|
||||
AppState.shared.errorMessage = I18n.Chat.Auth.authenticationError
|
||||
AppState.shared.isShowErrorPopup = true
|
||||
isShowAuthView = false
|
||||
}
|
||||
.onDone {
|
||||
DEBUG_LOG("onDone: \($0)")
|
||||
mypageViewModel.authVerify($0) {
|
||||
auth = true
|
||||
isShowAuthView = false
|
||||
if let action = pendingAction {
|
||||
pendingAction = nil
|
||||
action()
|
||||
}
|
||||
}
|
||||
}
|
||||
.onClose { isShowAuthView = false }
|
||||
}
|
||||
|
||||
private func configurePayload() {
|
||||
payload.applicationId = BOOTPAY_APP_ID
|
||||
payload.price = 0
|
||||
payload.pg = "다날"
|
||||
payload.method = "본인인증"
|
||||
payload.orderName = "본인인증"
|
||||
payload.authenticationId = "\(UserDefaults.string(forKey: .nickname))__\(String(NSTimeIntervalSince1970))"
|
||||
}
|
||||
|
||||
private func selectTab(_ tab: CreatorChannelTab) {
|
||||
switch tab {
|
||||
case .audio:
|
||||
@@ -228,6 +296,43 @@ struct CreatorChannelView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private func handleTalkTap() {
|
||||
guard let characterId = viewModel.response?.creator.characterId, characterId > 0 else { return }
|
||||
|
||||
let trimmed = token.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !trimmed.isEmpty else {
|
||||
AppState.shared.setAppStep(step: .login)
|
||||
return
|
||||
}
|
||||
|
||||
let normalizedCountryCode = UserDefaults
|
||||
.string(forKey: .countryCode)
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
.uppercased()
|
||||
let isKoreanCountry = normalizedCountryCode.isEmpty || normalizedCountryCode == "KR"
|
||||
|
||||
if isKoreanCountry && auth == false {
|
||||
pendingAction = {
|
||||
AppState.shared.setAppStep(step: .characterDetail(characterId: characterId))
|
||||
}
|
||||
isShowAuthConfirmView = true
|
||||
return
|
||||
}
|
||||
|
||||
if !UserDefaults.isAdultContentVisible() {
|
||||
pendingAction = nil
|
||||
moveToContentSettingsWithGuideToast()
|
||||
return
|
||||
}
|
||||
|
||||
AppState.shared.setAppStep(step: .characterDetail(characterId: characterId))
|
||||
}
|
||||
|
||||
private func moveToContentSettingsWithGuideToast() {
|
||||
AppState.shared.setPendingContentSettingsGuideMessage(I18n.Settings.adultContentEnableGuide)
|
||||
AppState.shared.setAppStep(step: .contentViewSettings)
|
||||
}
|
||||
|
||||
private func showDonationDialog() {
|
||||
guard let creatorId = viewModel.response?.creator.creatorId else { return }
|
||||
channelDonationViewModel.setCreatorId(creatorId, shouldFetch: false)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import SwiftUI
|
||||
|
||||
struct CreatorChannelTalkActionSection: View {
|
||||
let isAiChatAvailable: Bool
|
||||
let onTapTalk: () -> Void
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Spacer()
|
||||
|
||||
if isAiChatAvailable {
|
||||
Button(action: onTapTalk) {
|
||||
HStack(spacing: SodaSpacing.s6) {
|
||||
Image("ic_new_talk")
|
||||
.resizable()
|
||||
.frame(width: 20, height: 20)
|
||||
|
||||
Text(I18n.CreatorChannelHome.talk)
|
||||
.appFont(size: 16, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
.padding(SodaSpacing.s12)
|
||||
.overlay(
|
||||
Capsule()
|
||||
.stroke(Color.white.opacity(0.3), lineWidth: 1)
|
||||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.frame(height: 44)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.bottom, 14)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user