import SwiftUI struct CreatorChannelLatestAudioSection: View { let latestAudioContent: CreatorChannelAudioContentResponse? let onTapContent: (Int) -> Void init( latestAudioContent: CreatorChannelAudioContentResponse?, onTapContent: @escaping (Int) -> Void = { _ in } ) { self.latestAudioContent = latestAudioContent self.onTapContent = onTapContent } var body: some View { if let latestAudioContent { VStack(alignment: .leading, spacing: SodaSpacing.s8) { SectionTitle(title: I18n.CreatorChannelHome.latestAudio) CreatorChannelLatestAudioCard(audioContent: latestAudioContent) { onTapContent(latestAudioContent.audioContentId) } .padding(.horizontal, SodaSpacing.s14) } .padding(.top, SodaSpacing.s20) } } } private struct CreatorChannelLatestAudioCard: View { let audioContent: CreatorChannelAudioContentResponse let action: () -> Void var body: some View { Button(action: action) { HStack(alignment: .center, spacing: SodaSpacing.s14) { thumbnail VStack(alignment: .leading, spacing: SodaSpacing.s6) { Text("New") .font(.custom("Pattaya", size: 14)) .foregroundColor(Color.soda400) .lineLimit(1) Text(audioContent.title) .appFont(.body1) .foregroundColor(.white) .lineLimit(1) .truncationMode(.tail) if let duration = audioContent.duration, !duration.isEmpty { Text(duration) .appFont(size: 14, weight: .medium) .foregroundColor(Color.gray500) .lineLimit(1) .truncationMode(.tail) } } .frame(maxWidth: .infinity, alignment: .leading) } .padding(SodaSpacing.s14) .frame(maxWidth: .infinity, alignment: .leading) .background(Color.gray900) .clipShape(RoundedRectangle(cornerRadius: SodaSpacing.s14, style: .continuous)) } .buttonStyle(.plain) } private var thumbnail: some View { ZStack(alignment: .topLeading) { DownsampledKFImage( url: audioContent.imageUrl.flatMap(URL.init(string:)), size: CGSize(width: 88, height: 88) ) .background(Color.gray800) VStack(alignment: .leading, spacing: 0) { topTagList Spacer(minLength: 0) bottomTagList } } .frame(width: 88, height: 88) .clipShape(RoundedRectangle(cornerRadius: SodaSpacing.s14, style: .continuous)) } @ViewBuilder private var topTagList: some View { HStack(spacing: 0) { if audioContent.isOriginalSeries == true { CreatorChannelAudioImageTag(imageName: "ic_content_tag_original") } if audioContent.isFirstContent { CreatorChannelAudioFirstTag() } } } @ViewBuilder private var bottomTagList: some View { HStack(spacing: 0) { if audioContent.isPointAvailable { CreatorChannelAudioImageTag(imageName: "ic_content_tag_point") } if audioContent.price == 0 { CreatorChannelAudioFreeTag() } } } } struct CreatorChannelLatestAudioSection_Previews: PreviewProvider { static var previews: some View { CreatorChannelLatestAudioSection( latestAudioContent: CreatorChannelAudioContentResponse( audioContentId: 1, title: "콘텐츠 이름이 한 줄 콘텐츠 이름이 한 줄 콘텐츠 이름이 한 줄", duration: "1:43:25", imageUrl: "https://picsum.photos/300/300", price: 0, isAdult: true, isPointAvailable: true, isFirstContent: true, seriesName: "시리즈명", isOriginalSeries: true, isOwned: false, isRented: false ) ) .background(Color.black) .previewLayout(.sizeThatFits) } }