// // VoiceMessageView.swift // SodaLive // // Created by klaus on 2023/08/10. // import SwiftUI struct VoiceMessageView: View { @StateObject var viewModel = VoiceMessageViewModel() @StateObject var soundManager = SoundManager() var body: some View { ZStack { Color.black.ignoresSafeArea() ZStack(alignment: .bottomTrailing) { VStack(spacing: 13.3) { MessageFilterTabView(currentFilterTab: $viewModel.currentFilter) .padding(.top, 20) ScrollView(.vertical, showsIndicators: false) { if viewModel.items.count > 0 { VStack(spacing: 26.7) { ForEach(0..<viewModel.items.count, id: \.self) { index in let item = viewModel.items[index] VoiceMessageItemView( index: index, item: item, currentFilter: viewModel.currentFilter, soundManager: soundManager, openPlayerItemIndex: $viewModel.openPlayerItemIndex, onClickSave: { viewModel.selectedMessageId = item.messageId soundManager.stopAudio() if item.isKept { viewModel.errorMessage = "이미 보관된 메시지 입니다" viewModel.isShowPopup = true return } else { viewModel.keepVoiceMessage() } }, onClickReply: { viewModel.selectedMessageId = item.messageId soundManager.stopAudio() AppState.shared.setAppStep( step: .writeVoiceMessage( userId: item.senderId, nickname: item.senderNickname, onRefresh: { viewModel.refresh() } ) ) }, onClickDelete: { viewModel.selectedMessageId = item.messageId soundManager.stopAudio() viewModel.deleteMessage() } ) .onAppear { if index == viewModel.items.count - 1 { viewModel.loadMessage() } } } } } else { VStack(spacing: 6.7) { Image("ic_no_item") .resizable() .frame(width: 60, height: 60) Text("메시지가 없습니다.\n친구들과 소통해보세요!") .multilineTextAlignment(.center) .font(.custom(Font.medium.rawValue, size: 10.7)) .foregroundColor(Color(hex: "bbbbbb")) } .frame(width: screenSize().width - 26.7, height: screenSize().height / 2) .background(Color(hex: "13181b")) .cornerRadius(4.7) } } } Image("ic_make_voice") .resizable() .padding(13.3) .frame(width: 53.3, height: 53.3) .background(Color(hex: "3bb9f1")) .cornerRadius(26.7) .padding(.bottom, 33.3) .onTapGesture { AppState.shared.setAppStep( step: .writeVoiceMessage( userId: nil, nickname: nil, onRefresh: { viewModel.refresh() } ) ) } } if viewModel.isShowSavePopup { ZStack { Color.black.opacity(0.7) .ignoresSafeArea() VStack(spacing: 0) { Text("메시지 보관") .font(.custom(Font.bold.rawValue, size: 18.3)) .foregroundColor(Color(hex: "bbbbbb")) .padding(.top, 40) Text("메시지를 보관하는데\n\(viewModel.saveMessagePrice)캔이 필요합니다.\n메시지를 보관하시겠습니까?") .font(.custom(Font.medium.rawValue, size: 15)) .foregroundColor(Color(hex: "bbbbbb")) .padding(.top, 13.3) .multilineTextAlignment(.center) Text("※ 메시지 보관시, 본인이 삭제하기 전까지 영구보관됩니다.") .font(.custom(Font.medium.rawValue, size: 12)) .foregroundColor(Color(hex: "bbbbbb")) .padding(.top, 13.3) .padding(.horizontal, 13.3) .multilineTextAlignment(.center) HStack(spacing: 13.3) { Text("취소") .font(.custom(Font.bold.rawValue, size: 18.3)) .foregroundColor(Color(hex: "3bb9f1")) .padding(.vertical, 16) .frame(width: (screenSize().width - 66.7) / 3) .background(Color(hex: "13181b")) .cornerRadius(10) .overlay( RoundedRectangle(cornerRadius: 10) .stroke( Color(hex: "3bb9f1"), lineWidth: 1 ) ) .onTapGesture { viewModel.isShowSavePopup = false } Text("확인") .font(.custom(Font.bold.rawValue, size: 18.3)) .foregroundColor(.white) .padding(.vertical, 16) .frame(width: (screenSize().width - 66.7) * 2 / 3) .background(Color(hex: "3bb9f1")) .cornerRadius(10) .onTapGesture { viewModel.isShowSavePopup = false viewModel.keepTextMessage() } } .padding(.vertical, 20) .padding(.horizontal, 16.7) } .frame(width: screenSize().width - 26.7) .background(Color(hex: "222222")) .cornerRadius(10) } } if viewModel.isLoading || soundManager.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() } } } .onAppear { viewModel.refresh() } } } struct VoiceMessageView_Previews: PreviewProvider { static var previews: some View { VoiceMessageView() } }