// // ContentPlaylistDetailView.swift // SodaLive // // Created by klaus on 12/9/24. // import SwiftUI import Kingfisher struct ContentPlaylistDetailView: View { @StateObject var viewModel = ContentPlaylistDetailViewModel() @StateObject var contentPlayerPlayManager = ContentPlayerPlayManager.shared let playlistId: Int @Binding var isShowing: Bool @Binding var reloadData: Bool @State private var isShowPopupMenu = false @State private var isShowDeleteConfirm = false @State private var isShowPlayer = false @State private var isShowModify = false @State private var playlist: [AudioContentPlaylistContent] = [] var body: some View { BaseView(isLoading: $viewModel.isLoading) { if reloadData { Color.clear LoadingView() } else { VStack(spacing: 21.3) { HStack(spacing: 5.3) { Image("ic_back") .resizable() .frame(width: 20, height: 20) .padding(8) .onTapGesture { isShowing = false } Spacer() Image("ic_edit_white") .padding(8) .onTapGesture { isShowModify = true } Image("ic_seemore_vertical_white") .padding(8) .onTapGesture { isShowPopupMenu = true } } .padding(.horizontal, 13.3) .frame(height: 50) .frame(maxWidth: .infinity) .background(Color.black) ScrollView(.vertical, showsIndicators: false) { if let response = viewModel.response { VStack(alignment: .leading, spacing: 0) { HStack(alignment: .top, spacing: 13.3) { VStack(alignment: .center, spacing: 0) { HStack(spacing: 0) { KFImage(URL(string: response.playlistCoverImageList[0])) .cancelOnDisappear(true) .downsampling(size: CGSize(width: 80, height: 80)) .resizable() .scaledToFill() .clipped() .frame(maxWidth: .infinity, maxHeight: .infinity) if response.playlistCoverImageList.count > 2 { KFImage(URL(string: response.playlistCoverImageList[1])) .cancelOnDisappear(true) .downsampling(size: CGSize(width: 80, height: 80)) .resizable() .scaledToFill() .clipped() .frame(maxWidth: 40, maxHeight: 40) } } HStack(spacing: 0) { if response.playlistCoverImageList.count > 2 { KFImage(URL(string: response.playlistCoverImageList[2])) .cancelOnDisappear(true) .downsampling(size: CGSize(width: 80, height: 80)) .resizable() .scaledToFill() .clipped() .frame(maxWidth: 40, maxHeight: 40) } if response.playlistCoverImageList.count > 3 { KFImage(URL(string: response.playlistCoverImageList[3])) .cancelOnDisappear(true) .downsampling(size: CGSize(width: 80, height: 80)) .resizable() .scaledToFill() .clipped() .frame(maxWidth: 40, maxHeight: 40) } } } .frame(width: 80, height: 80) .background(Color.graybb) .cornerRadius(4) VStack(alignment: .leading, spacing: 6.7) { Text(response.title) .font(.custom(Font.bold.rawValue, size: 18.3)) .foregroundColor(Color.grayd2) .lineLimit(2) .truncationMode(.tail) Text(response.desc.prefix(100)) .font(.custom(Font.medium.rawValue, size: 12)) .foregroundColor(Color.gray90) .truncationMode(.tail) } } HStack(spacing: 0) { Text("만든 날짜 \(response.createdDate)") .font(.custom(Font.medium.rawValue, size: 13.3)) .foregroundColor(Color.gray90) Spacer() Text("\(response.contentCount)개") .font(.custom(Font.medium.rawValue, size: 13.3)) .foregroundColor(Color.grayee) } .padding(.top, 13.3) HStack(spacing: 13.3) { HStack(spacing: 5.3) { Image("ic_playlist_play") Text("Play") .font(.custom(Font.bold.rawValue, size: 14.7)) .foregroundColor(Color.white) } .frame(maxWidth: .infinity) .padding(.vertical, 11) .background(Color.button) .cornerRadius(5.3) .contentShape(Rectangle()) .onTapGesture { ContentPlayManager.shared.stopAudio() playlist = response.contentList isShowPlayer = true } HStack(spacing: 5.3) { Image("ic_playlist_shuffle") Text("Shuffle") .font(.custom(Font.bold.rawValue, size: 14.7)) .foregroundColor(Color.white) } .frame(maxWidth: .infinity) .padding(.vertical, 11) .background(Color.button) .cornerRadius(5.3) .contentShape(Rectangle()) .onTapGesture { ContentPlayManager.shared.stopAudio() playlist = response.contentList.shuffled() isShowPlayer = true } } .padding(.top, 18) LazyVStack(alignment: .leading, spacing: 0) { ForEach(0..