diff --git a/SodaLive/Resources/Assets.xcassets/AppIcon.appiconset/1024x1024.jpg b/SodaLive/Resources/Assets.xcassets/AppIcon.appiconset/1024x1024.jpg new file mode 100644 index 0000000..f933384 Binary files /dev/null and b/SodaLive/Resources/Assets.xcassets/AppIcon.appiconset/1024x1024.jpg differ diff --git a/SodaLive/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/SodaLive/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json index 18454dd..3cafc98 100644 --- a/SodaLive/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/SodaLive/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "launcher.png", + "filename" : "1024x1024.jpg", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" diff --git a/SodaLive/Resources/Assets.xcassets/AppIcon.appiconset/launcher.png b/SodaLive/Resources/Assets.xcassets/AppIcon.appiconset/launcher.png deleted file mode 100644 index 39e67f9..0000000 Binary files a/SodaLive/Resources/Assets.xcassets/AppIcon.appiconset/launcher.png and /dev/null differ diff --git a/SodaLive/Sources/Chat/Character/CharacterViewModel.swift b/SodaLive/Sources/Chat/Character/CharacterViewModel.swift index e816aab..4b99b09 100644 --- a/SodaLive/Sources/Chat/Character/CharacterViewModel.swift +++ b/SodaLive/Sources/Chat/Character/CharacterViewModel.swift @@ -39,7 +39,6 @@ final class CharacterViewModel: ObservableObject { } } receiveValue: { response in let responseData = response.data - self.isLoading = false do { let jsonDecoder = JSONDecoder() @@ -60,7 +59,9 @@ final class CharacterViewModel: ObservableObject { self.isShowPopup = true } + self.isLoading = false } catch { + self.isLoading = false self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.isShowPopup = true } diff --git a/SodaLive/Sources/Chat/ChatTabView.swift b/SodaLive/Sources/Chat/ChatTabView.swift index 3cda059..b1746bc 100644 --- a/SodaLive/Sources/Chat/ChatTabView.swift +++ b/SodaLive/Sources/Chat/ChatTabView.swift @@ -28,6 +28,7 @@ struct ChatTabView: View { @State private var selectedTab: InnerTab = .character @State private var isShowAuthView: Bool = false + @State private var isShowAuthConfirmView: Bool = false @State private var pendingCharacterId: Int? = nil @State private var payload = Payload() @@ -41,97 +42,118 @@ struct ChatTabView: View { if auth == false { // 본인인증 전체화면 표시 후 완료 시 바로 이동 pendingCharacterId = characterId - isShowAuthView = true + isShowAuthConfirmView = true return } AppState.shared.setAppStep(step: .characterDetail(characterId: characterId)) } var body: some View { - VStack(alignment: .leading, spacing: 0) { - // 앱 바 - HStack(spacing: 24) { - Image("img_text_logo") - - Spacer() - - if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { - Image("ic_search_white") - .onTapGesture { - AppState - .shared - .setAppStep(step: .search) - } + ZStack { + VStack(alignment: .leading, spacing: 0) { + // 앱 바 + HStack(spacing: 24) { + Image("img_text_logo") - Image("ic_can") - .onTapGesture { - AppState - .shared - .setAppStep(step: .canCharge(refresh: {})) - } - } - } - .padding(.horizontal, 24) - .padding(.vertical, 20) - - // 내부 탭 (캐릭터 / 톡) - HStack(spacing: 0) { - ChatInnerTab( - title: InnerTab.character.title, - isSelected: selectedTab == .character, - onTap: { if selectedTab != .character { selectedTab = .character } } - ) - - ChatInnerTab( - title: InnerTab.talk.title, - isSelected: selectedTab == .talk, - onTap: { if selectedTab != .talk { selectedTab = .talk } } - ) - } - .padding(.bottom, 12) - - Group { - switch selectedTab { - case .character: - CharacterView(onSelectCharacter: handleCharacterSelection) - case .talk: - TalkView() - } - } - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) - } - .onAppear { - payload.applicationId = BOOTPAY_APP_ID - payload.price = 0 - payload.pg = "다날" - payload.method = "본인인증" - payload.orderName = "본인인증" - payload.authenticationId = "\(UserDefaults.string(forKey: .nickname))__\(String(NSTimeIntervalSince1970))" - } - .fullScreenCover(isPresented: $isShowAuthView) { - BootpayUI(payload: payload, requestType: BootpayRequest.TYPE_AUTHENTICATION) - .onConfirm { _ in - true - } - .onCancel { _ in - isShowAuthView = false - } - .onError { _ in - AppState.shared.errorMessage = "본인인증 중 오류가 발생했습니다." - AppState.shared.isShowErrorPopup = true - isShowAuthView = false - } - .onDone { _ in - auth = true - isShowAuthView = false - if let chId = pendingCharacterId { - pendingCharacterId = nil - AppState.shared.setAppStep(step: .characterDetail(characterId: chId)) + Spacer() + + if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { + Image("ic_search_white") + .onTapGesture { + AppState + .shared + .setAppStep(step: .search) + } + + Image("ic_can") + .onTapGesture { + AppState + .shared + .setAppStep(step: .canCharge(refresh: {})) + } } } - .onClose { - isShowAuthView = false + .padding(.horizontal, 24) + .padding(.vertical, 20) + + // 내부 탭 (캐릭터 / 톡) + HStack(spacing: 0) { + ChatInnerTab( + title: InnerTab.character.title, + isSelected: selectedTab == .character, + onTap: { if selectedTab != .character { selectedTab = .character } } + ) + + ChatInnerTab( + title: InnerTab.talk.title, + isSelected: selectedTab == .talk, + onTap: { if selectedTab != .talk { selectedTab = .talk } } + ) } + .padding(.bottom, 12) + + Group { + switch selectedTab { + case .character: + CharacterView(onSelectCharacter: handleCharacterSelection) + case .talk: + TalkView() + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + } + .onAppear { + payload.applicationId = BOOTPAY_APP_ID + payload.price = 0 + payload.pg = "다날" + payload.method = "본인인증" + payload.orderName = "본인인증" + payload.authenticationId = "\(UserDefaults.string(forKey: .nickname))__\(String(NSTimeIntervalSince1970))" + } + .fullScreenCover(isPresented: $isShowAuthView) { + BootpayUI(payload: payload, requestType: BootpayRequest.TYPE_AUTHENTICATION) + .onConfirm { _ in + true + } + .onCancel { _ in + isShowAuthView = false + } + .onError { _ in + AppState.shared.errorMessage = "본인인증 중 오류가 발생했습니다." + AppState.shared.isShowErrorPopup = true + isShowAuthView = false + } + .onDone { _ in + auth = true + isShowAuthView = false + if let chId = pendingCharacterId { + pendingCharacterId = nil + AppState.shared.setAppStep(step: .characterDetail(characterId: chId)) + } + } + .onClose { + isShowAuthView = false + } + } + + if isShowAuthConfirmView { + SodaDialog( + title: "본인인증", + desc: "보이스온의 오픈월드 캐릭터톡은\n청소년 보호를 위해 본인인증한\n성인만 이용이 가능합니다.\n" + + "캐릭터톡 서비스를 이용하시려면\n본인인증을 하고 이용해주세요.", + confirmButtonTitle: "본인인증 하러가기", + confirmButtonAction: { + isShowAuthConfirmView = false + isShowAuthView = true + }, + cancelButtonTitle: "취소", + cancelButtonAction: { + isShowAuthConfirmView = false + pendingCharacterId = nil + }, + textAlignment: .center + ) + } } } } diff --git a/SodaLive/Sources/Dialog/SodaDialog.swift b/SodaLive/Sources/Dialog/SodaDialog.swift index 7022eee..af20640 100644 --- a/SodaLive/Sources/Dialog/SodaDialog.swift +++ b/SodaLive/Sources/Dialog/SodaDialog.swift @@ -15,6 +15,7 @@ struct SodaDialog: View { let confirmButtonAction: () -> Void let cancelButtonTitle: String let cancelButtonAction: () -> Void + let textAlignment: TextAlignment init( title: String, @@ -22,7 +23,8 @@ struct SodaDialog: View { confirmButtonTitle: String, confirmButtonAction: @escaping () -> Void, cancelButtonTitle: String = "", - cancelButtonAction: @escaping () -> Void = {} + cancelButtonAction: @escaping () -> Void = {}, + textAlignment: TextAlignment = .leading ) { self.title = title self.desc = desc @@ -30,6 +32,7 @@ struct SodaDialog: View { self.confirmButtonAction = confirmButtonAction self.cancelButtonTitle = cancelButtonTitle self.cancelButtonAction = cancelButtonAction + self.textAlignment = textAlignment } var body: some View { @@ -48,7 +51,7 @@ struct SodaDialog: View { Text(desc) .font(.custom(Font.medium.rawValue, size: 15)) .foregroundColor(Color.graybb) - .multilineTextAlignment(.leading) + .multilineTextAlignment(textAlignment) .padding(.top, 12) .padding(.horizontal, 13.3) .fixedSize(horizontal: false, vertical: true)