From 70460f5c8acd35e63842c5fadbc3abcecd9d0ddc Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Fri, 8 Mar 2024 20:40:29 +0900 Subject: [PATCH] =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EB=B8=8C=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=88=98=EC=A0=95=20-=20=EB=A9=94=EB=89=B4?= =?UTF-8?q?=ED=8C=90=20=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Live/Room/Create/LiveRoomCreateView.swift | 2 +- .../Room/Dialog/LiveRoomInfoEditDialog.swift | 217 +++++++++--------- .../Room/Edit/EditLiveRoomInfoRequest.swift | 3 + .../Sources/Live/Room/LiveRoomViewModel.swift | 121 +++++++++- .../Room/Menu/LiveRoomMenuSelectView.swift | 9 +- .../Sources/Live/Room/V2/LiveRoomViewV2.swift | 4 +- 6 files changed, 242 insertions(+), 114 deletions(-) diff --git a/SodaLive/Sources/Live/Room/Create/LiveRoomCreateView.swift b/SodaLive/Sources/Live/Room/Create/LiveRoomCreateView.swift index 079bc12..5931504 100644 --- a/SodaLive/Sources/Live/Room/Create/LiveRoomCreateView.swift +++ b/SodaLive/Sources/Live/Room/Create/LiveRoomCreateView.swift @@ -352,7 +352,7 @@ struct LiveRoomCreateView: View { text: $viewModel.content, placeholder: viewModel.placeholder, textColorHex: "eeeeee", - backgroundColorHex: "222222" + backgroundColorHex: "303030" ) .frame(width: screenSize().width - 26.7, height: 200) .cornerRadius(6.7) diff --git a/SodaLive/Sources/Live/Room/Dialog/LiveRoomInfoEditDialog.swift b/SodaLive/Sources/Live/Room/Dialog/LiveRoomInfoEditDialog.swift index 7ef5ef3..8527106 100644 --- a/SodaLive/Sources/Live/Room/Dialog/LiveRoomInfoEditDialog.swift +++ b/SodaLive/Sources/Live/Room/Dialog/LiveRoomInfoEditDialog.swift @@ -18,7 +18,7 @@ struct LiveRoomInfoEditDialog: View { let placeholder = "라이브 공지를 입력하세요" - let viewModel: LiveRoomViewModel + @StateObject var viewModel: LiveRoomViewModel let isLoading: Bool let coverImageUrl: String? @@ -39,7 +39,7 @@ struct LiveRoomInfoEditDialog: View { self._isShowing = isShowing self._isShowPhotoPicker = isShowPhotoPicker - self.viewModel = viewModel + self._viewModel = StateObject(wrappedValue: viewModel) self.isLoading = isLoading self.title = currentTitle @@ -53,112 +53,123 @@ struct LiveRoomInfoEditDialog: View { var body: some View { ZStack { - GeometryReader { proxy in - ScrollView(.vertical, showsIndicators: false) { - VStack(alignment: .leading, spacing: 0) { - HStack(spacing: 0) { - Text("라이브 수정") - .font(.custom(Font.bold.rawValue, size: 18.3)) - .foregroundColor(Color(hex: "eeeeee")) - - Spacer() - - Image("ic_close_white") - .onTapGesture { - isShowing = false - } - } + ScrollView(.vertical, showsIndicators: false) { + VStack(alignment: .leading, spacing: 0) { + HStack(spacing: 0) { + Text("라이브 수정") + .font(.custom(Font.bold.rawValue, size: 18.3)) + .foregroundColor(Color.grayee) - HStack { - Spacer() - - ZStack { - if let coverImage = coverImage { - Image(uiImage: coverImage) - .resizable() - .scaledToFill() - .frame(width: 80, height: 116.8, alignment: .top) - .clipped() - .cornerRadius(10) - } else if let coverImageUrl = coverImageUrl { - KFImage(URL(string: coverImageUrl)) - .resizable() - .scaledToFill() - .frame(width: 80, height: 116.8, alignment: .top) - .clipped() - .cornerRadius(10) - } else { - Image("ic_logo") - .resizable() - .scaledToFit() - .frame(width: 80, height: 116.8) - .background(Color(hex: "3e3358")) - .cornerRadius(10) - } - - Image("ic_camera") - .padding(10) - .background(Color(hex: "9970ff")) - .cornerRadius(30) - .offset(x: 40, y: 40) - } - .frame(alignment: .bottomTrailing) - .padding(.top, 13.3) + Spacer() + + Image("ic_close_white") .onTapGesture { - isShowPhotoPicker = true + isShowing = false + } + } + + HStack { + Spacer() + + ZStack { + if let coverImage = coverImage { + Image(uiImage: coverImage) + .resizable() + .scaledToFill() + .frame(width: 80, height: 116.8, alignment: .top) + .clipped() + .cornerRadius(10) + } else if let coverImageUrl = coverImageUrl { + KFImage(URL(string: coverImageUrl)) + .resizable() + .scaledToFill() + .frame(width: 80, height: 116.8, alignment: .top) + .clipped() + .cornerRadius(10) + } else { + Image("ic_logo") + .resizable() + .scaledToFit() + .frame(width: 80, height: 116.8) + .background(Color.bg) + .cornerRadius(10) } - Spacer() + Image("ic_camera") + .padding(10) + .background(Color.button) + .cornerRadius(30) + .offset(x: 40, y: 40) } - - TitleInputView() - .padding(.top, 40) - - ContentInputView() - .padding(.top, 33.3) - - HStack(spacing: 13.3) { - Text("취소") - .font(.custom(Font.bold.rawValue, size: 18.3)) - .foregroundColor(Color(hex: "9970ff")) - .padding(.vertical, 16) - .frame(width: (screenSize().width - 40) / 2) - .background(Color(hex: "9970ff").opacity(0.2)) - .cornerRadius(10) - .overlay( - RoundedRectangle(cornerRadius: 10) - .strokeBorder(lineWidth: 1) - .foregroundColor(Color(hex: "9970ff")) - ) - .onTapGesture { - isShowing = false - } - - Text("수정하기") - .font(.custom(Font.bold.rawValue, size: 18.3)) - .foregroundColor(.white) - .padding(.vertical, 16) - .frame(width: (screenSize().width - 40) / 2) - .background(Color(hex: "9970ff")) - .cornerRadius(10) - .onTapGesture { - confirmAction( - title, - notice.trimmingCharacters(in: .whitespacesAndNewlines) != placeholder ? notice : "" - ) - isShowing = false - } + .frame(alignment: .bottomTrailing) + .padding(.top, 13.3) + .onTapGesture { + isShowPhotoPicker = true } - .padding(.top, 45) Spacer() } - .padding(13.3) - .frame(width: proxy.size.width, height: proxy.size.height) - .onTapGesture { hideKeyboard() } + + TitleInputView() + .padding(.top, 40) + + ContentInputView() + .padding(.top, 33.3) + + LiveRoomMenuSelectView( + menu: $viewModel.menu, + isActivate: $viewModel.isActivateMenu, + menuCount: viewModel.menuList.count, + selectedMenu: viewModel.selectedMenu, + selectMenu: { viewModel.selectMenuPreset(selectedMenuPreset: $0) } + ) + .padding(.top, 33.3) + + HStack(spacing: 13.3) { + Text("취소") + .font(.custom(Font.bold.rawValue, size: 18.3)) + .foregroundColor(Color.button) + .padding(.vertical, 16) + .frame(width: (screenSize().width - 40) / 2) + .background(Color.button.opacity(0.2)) + .cornerRadius(10) + .overlay( + RoundedRectangle(cornerRadius: 10) + .strokeBorder(lineWidth: 1) + .foregroundColor(Color.button) + ) + .onTapGesture { + isShowing = false + } + + Text("수정하기") + .font(.custom(Font.bold.rawValue, size: 18.3)) + .foregroundColor(.white) + .padding(.vertical, 16) + .frame(width: (screenSize().width - 40) / 2) + .background(Color.button) + .cornerRadius(10) + .onTapGesture { + confirmAction( + title, + notice.trimmingCharacters(in: .whitespacesAndNewlines) != placeholder ? notice : "" + ) + isShowing = false + } + } + .padding(.top, 45) + + Spacer() + } + .padding(13.3) + .onTapGesture { hideKeyboard() } + .onAppear { + viewModel.getAllMenuPreset { + self.isShowing = false + } } - .background(Color(hex: "222222").edgesIgnoringSafeArea(.all)) } + .background(Color(hex: "222222").edgesIgnoringSafeArea(.all)) if viewModel.isShowPopup { LiveRoomDialogView( @@ -193,15 +204,15 @@ struct LiveRoomInfoEditDialog: View { .autocapitalization(.none) .disableAutocorrection(true) .font(.custom(Font.medium.rawValue, size: 13.3)) - .foregroundColor(Color(hex: "eeeeee")) - .accentColor(Color(hex: "3bb9f1")) + .foregroundColor(Color.grayee) + .accentColor(Color.button) .keyboardType(.default) .padding(.top, 12) .padding(.horizontal, 6.7) Rectangle() .frame(height: 1) - .foregroundColor(Color(hex: "909090").opacity(0.7)) + .foregroundColor(Color.gray90.opacity(0.7)) .padding(.top, 8.3) } } @@ -212,16 +223,16 @@ struct LiveRoomInfoEditDialog: View { HStack(spacing: 0) { Text("공지") .font(.custom(Font.bold.rawValue, size: 16.7)) - .foregroundColor(Color(hex: "eeeeee")) + .foregroundColor(Color.grayee) Spacer() Text("\(notice.count)자") .font(.custom(Font.medium.rawValue, size: 13.3)) - .foregroundColor(Color(hex: "ff5c49")) + + .foregroundColor(Color.mainRed) + Text(" / 1000자") .font(.custom(Font.medium.rawValue, size: 13.3)) - .foregroundColor(Color(hex: "777777")) + .foregroundColor(Color.gray77) } TextViewWrapper( diff --git a/SodaLive/Sources/Live/Room/Edit/EditLiveRoomInfoRequest.swift b/SodaLive/Sources/Live/Room/Edit/EditLiveRoomInfoRequest.swift index b777cb4..949b691 100644 --- a/SodaLive/Sources/Live/Room/Edit/EditLiveRoomInfoRequest.swift +++ b/SodaLive/Sources/Live/Room/Edit/EditLiveRoomInfoRequest.swift @@ -13,4 +13,7 @@ struct EditLiveRoomInfoRequest: Encodable { let numberOfPeople: Int? let beginDateTimeString: String? let timezone: String? + var menuPanId: Int = 0 + var menuPan: String = "" + var isActiveMenuPan: Bool? = nil } diff --git a/SodaLive/Sources/Live/Room/LiveRoomViewModel.swift b/SodaLive/Sources/Live/Room/LiveRoomViewModel.swift index 6bb799b..11db1e7 100644 --- a/SodaLive/Sources/Live/Room/LiveRoomViewModel.swift +++ b/SodaLive/Sources/Live/Room/LiveRoomViewModel.swift @@ -173,6 +173,19 @@ final class LiveRoomViewModel: NSObject, ObservableObject { } } + private var menuId = 0 + @Published var menu = "" + @Published var menuList = [GetMenuPresetResponse]() + + @Published var isActivateMenu = false { + didSet { + if !isActivateMenu { + menu = "" + } + } + } + @Published var selectedMenu: SelectedMenu? = nil + var signatureImageUrls = [String]() var isShowSignatureImage = false @@ -634,10 +647,13 @@ final class LiveRoomViewModel: NSObject, ObservableObject { notice: liveRoomInfo!.notice != notice ? notice : nil, numberOfPeople: nil, beginDateTimeString: nil, - timezone: nil + timezone: nil, + menuPanId: isActivateMenu ? menuId : 0, + menuPan: isActivateMenu ? menu : "", + isActiveMenuPan: isActivateMenu ) - if (request.title == nil && request.notice == nil && coverImage == nil) { + if (request.title == nil && request.notice == nil && coverImage == nil && menu == liveRoomInfo?.menuPan) { self.errorMessage = "변경사항이 없습니다." self.isShowErrorPopup = true return @@ -648,7 +664,7 @@ final class LiveRoomViewModel: NSObject, ObservableObject { let encoder = JSONEncoder() encoder.outputFormatting = .withoutEscapingSlashes - if (request.title != nil || request.notice != nil) { + if (request.title != nil || request.notice != nil || menu != liveRoomInfo?.menuPan) { let jsonData = try? encoder.encode(request) if let jsonData = jsonData { multipartData.append(MultipartFormData(provider: .data(jsonData), name: "request")) @@ -665,8 +681,6 @@ final class LiveRoomViewModel: NSObject, ObservableObject { ) } - - repository.editLiveRoomInfo(roomId: AppState.shared.roomId, parameters: multipartData) .sink { result in switch result { @@ -684,6 +698,11 @@ final class LiveRoomViewModel: NSObject, ObservableObject { if decoded.success { self.coverImage = nil + self.menuList.removeAll() + self.isActivateMenu = false + self.selectedMenu = nil + self.menu = "" + self.isShowMenuPan = false self.getRoomInfo() let editRoomInfoMessage = LiveRoomChatRawMessage( @@ -694,12 +713,102 @@ final class LiveRoomViewModel: NSObject, ObservableObject { ) self.agora.sendRawMessageToGroup(rawMessage: editRoomInfoMessage) + self.errorMessage = "라이브 정보가 수정되었습니다." + self.isShowErrorPopup = true } else { self.errorMessage = decoded.message ?? "라이브 정보를 수정하지 못했습니다.\n다시 시도해 주세요." - self.isShowPopup = true + self.isShowErrorPopup = true } } catch { self.errorMessage = "라이브 정보를 수정하지 못했습니다.\n다시 시도해 주세요." + self.isShowErrorPopup = true + } + } + .store(in: &subscription) + } + + func selectMenuPreset(selectedMenuPreset: SelectedMenu) { + if menuList.isEmpty && (selectedMenuPreset == .MENU_2 || selectedMenuPreset == .MENU_3) { + errorMessage = "메뉴 1을 먼저 설정하세요" + isShowPopup = true + return + } + + if menuList.count == 1 && selectedMenuPreset == .MENU_3 { + errorMessage = "메뉴 1과 메뉴 2를 먼저 설정하세요" + isShowPopup = true + return + } + + if self.selectedMenu != selectedMenuPreset { + self.selectedMenu = selectedMenuPreset + + if menuList.count > selectedMenuPreset.rawValue { + let menu = menuList[selectedMenuPreset.rawValue] + self.menu = menu.menu + self.menuId = menu.id + } else { + self.menu = "" + self.menuId = 0 + } + } + } + + func getAllMenuPreset(onFailure: @escaping () -> Void) { + isLoading = true + + repository.getAllMenuPreset(creatorId: UserDefaults.int(forKey: .userId)) + .sink { result in + switch result { + case .finished: + DEBUG_LOG("finish") + case .failure(let error): + ERROR_LOG(error.localizedDescription) + } + } receiveValue: { [unowned self] response in + self.isLoading = false + let responseData = response.data + + do { + let jsonDecoder = JSONDecoder() + let decoded = try jsonDecoder.decode(ApiResponse<[GetMenuPresetResponse]>.self, from: responseData) + + if let data = decoded.data, decoded.success { + self.menuList.removeAll() + self.menuList.append(contentsOf: data) + self.isActivateMenu = false + self.selectedMenu = nil + + for (index, menuPreset) in self.menuList.enumerated() { + if menuPreset.isActive { + switch index { + case 1: + self.selectMenuPreset(selectedMenuPreset: .MENU_2) + + case 2: + self.selectMenuPreset(selectedMenuPreset: .MENU_3) + + default: + self.selectMenuPreset(selectedMenuPreset: .MENU_1) + } + + self.isActivateMenu = true + } + + } + } else { + onFailure() + if let message = decoded.message { + self.errorMessage = message + } else { + self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + } + + self.isShowPopup = true + } + } catch { + onFailure() + self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.isShowPopup = true } } diff --git a/SodaLive/Sources/Live/Room/Menu/LiveRoomMenuSelectView.swift b/SodaLive/Sources/Live/Room/Menu/LiveRoomMenuSelectView.swift index 8d4be52..bcb76f8 100644 --- a/SodaLive/Sources/Live/Room/Menu/LiveRoomMenuSelectView.swift +++ b/SodaLive/Sources/Live/Room/Menu/LiveRoomMenuSelectView.swift @@ -13,7 +13,7 @@ struct LiveRoomMenuSelectView: View { @Binding var isActivate: Bool let menuCount: Int - let selectedMenu: SelectedMenu + let selectedMenu: SelectedMenu? let selectMenu: (SelectedMenu) -> Void var body: some View { @@ -32,7 +32,10 @@ struct LiveRoomMenuSelectView: View { Image(isActivate ? "btn_toggle_on_big" : "btn_toggle_off_big") .resizable() .frame(width: 33.3, height: 20) - .onTapGesture { isActivate.toggle() } + .onTapGesture { + isActivate.toggle() + selectMenu(.MENU_1) + } } .padding(.top, 8) @@ -71,7 +74,7 @@ struct LiveRoomMenuSelectView: View { text: $menu, placeholder: "메뉴판을 작성해주세요.", textColorHex: "eeeeee", - backgroundColorHex: "222222" + backgroundColorHex: "303030" ) .frame(height: 200) .cornerRadius(6.7) diff --git a/SodaLive/Sources/Live/Room/V2/LiveRoomViewV2.swift b/SodaLive/Sources/Live/Room/V2/LiveRoomViewV2.swift index 210c3d0..f1be537 100644 --- a/SodaLive/Sources/Live/Room/V2/LiveRoomViewV2.swift +++ b/SodaLive/Sources/Live/Room/V2/LiveRoomViewV2.swift @@ -344,7 +344,9 @@ struct LiveRoomViewV2: View { Spacer() } .onDisappear { - viewModel.quitRoom() + if viewModel.liveRoomInfo == nil { + viewModel.quitRoom() + } } } }