Files
sodalive-ios/SodaLive/Sources/Live/LiveView.swift
Yu Sung a4663d0853 feat: 메인 라이브
- 팔로잉 채널 신규 UI 사이즈 적용
2025-07-22 03:19:01 +09:00

199 lines
8.8 KiB
Swift

//
// LiveView.swift
// SodaLive
//
// Created by klaus on 2023/08/09.
//
import SwiftUI
import RefreshableScrollView
struct LiveView: View {
@StateObject var viewModel = LiveViewModel()
@StateObject var appState = AppState.shared
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
@AppStorage("role") private var role: String = UserDefaults.string(forKey: UserDefaultsKey.role)
var body: some View {
ZStack {
Color.black.ignoresSafeArea()
ZStack(alignment: .bottomTrailing) {
VStack(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)
}
Image("ic_can_circle")
.onTapGesture {
AppState
.shared
.setAppStep(step: .canCharge(refresh: {}))
}
Image("ic_message")
.onTapGesture {
AppState.shared.setAppStep(step: .message)
}
}
}
.padding(.horizontal, 24)
.padding(.vertical, 20)
ScrollView(.vertical, showsIndicators: false) {
LazyVStack(spacing: 48) {
SectionLiveNowView(
items: viewModel.liveNowItems,
onClickParticipant: {
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
viewModel.enterLiveRoom(roomId: $0)
} else {
AppState.shared.setAppStep(step: .login)
}
},
onTapCreateLive: {
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .NOW, onSuccess: onCreateSuccess))
} else {
AppState.shared.setAppStep(step: .login)
}
},
onClickRefresh: {
viewModel.getLiveMain()
}
)
if viewModel.followedChannelItems.count > 0 {
SectionRecommendChannelView(items: viewModel.followedChannelItems)
}
if viewModel.communityPostItems.count > 0 {
SectionCommunityPostView(items: viewModel.communityPostItems)
}
if viewModel.recommendLiveItems.count > 0 {
SectionRecommendLiveView(items: viewModel.recommendLiveItems)
}
SectionLiveReservationView(
items: viewModel.liveReservationItems,
onClickCancel: { viewModel.getLiveMain() },
onClickStart: { roomId in
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
processStart(roomId: roomId)
} else {
AppState.shared.setAppStep(step: .login)
}
},
onClickReservation: { roomId in
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
viewModel.reservationLiveRoom(roomId: roomId)
} else {
AppState.shared.setAppStep(step: .login)
}
},
onTapCreateLive: {
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .RESERVATION, onSuccess: onCreateSuccess))
} else {
AppState.shared.setAppStep(step: .login)
}
}
)
}
.padding(.vertical, 24)
}
.onAppear {
viewModel.getLiveMain()
}
}
if !appState.isShowPlayer && role == MemberRole.CREATOR.rawValue {
Image("btn_make_live")
.padding(.trailing, 16)
.padding(.bottom, 16)
.onTapGesture {
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
AppState.shared.setAppStep(step: .createLive(timeSettingMode: .NOW, onSuccess: onCreateSuccess))
} else {
AppState.shared.setAppStep(step: .login)
}
}
}
}
if viewModel.isShowPaymentDialog {
LivePaymentDialog(
title: viewModel.paymentDialogTitle,
desc: viewModel.paymentDialogDesc,
desc2: viewModel.paymentDialogDesc2,
confirmButtonTitle: viewModel.paymentDialogConfirmTitle,
confirmButtonAction: viewModel.paymentDialogConfirmAction,
cancelButtonTitle: viewModel.paymentDialogCancelTitle,
cancelButtonAction: viewModel.hidePopup,
startDateTime: viewModel.liveStartDate,
nowDateTime: viewModel.nowDate
)
}
if viewModel.isShowPasswordDialog {
LiveRoomPasswordDialog(
isShowing: $viewModel.isShowPasswordDialog,
can: viewModel.secretOrPasswordDialogCan,
confirmAction: viewModel.passwordDialogConfirmAction
)
}
if viewModel.isLoading {
LoadingView()
}
}
.popup(isPresented: $viewModel.isShowPopup, type: .toast, position: .top, autohideIn: 2) {
GeometryReader { geo in
HStack {
Spacer()
Text(viewModel.errorMessage)
.padding(.vertical, 13.3)
.padding(.horizontal, 6.7)
.frame(width: geo.size.width - 66.7, alignment: .center)
.font(.custom(Font.medium.rawValue, size: 12))
.background(Color(hex: "3bb9f1"))
.foregroundColor(Color.white)
.multilineTextAlignment(.leading)
.fixedSize(horizontal: false, vertical: true)
.cornerRadius(20)
.padding(.top, 66.7)
Spacer()
}
}
}
}
private func onCreateSuccess(response: CreateLiveRoomResponse) {
viewModel.getLiveMain()
if let _ = response.channelName {
viewModel.enterRoom(roomId: response.id!)
}
}
private func processStart(roomId: Int) {
viewModel.startLive(roomId: roomId)
}
}
struct LiveView_Previews: PreviewProvider {
static var previews: some View {
LiveView()
}
}