155 lines
3.9 KiB
Swift
155 lines
3.9 KiB
Swift
//
|
|
// AudioContentCard.swift
|
|
// SodaLive
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
enum AudioContentCardSize {
|
|
case large
|
|
case medium
|
|
case small
|
|
|
|
var width: CGFloat {
|
|
switch self {
|
|
case .large:
|
|
return 185
|
|
case .medium:
|
|
return 163
|
|
case .small:
|
|
return 122
|
|
}
|
|
}
|
|
|
|
var labelWidth: CGFloat {
|
|
width - (labelHorizontalPadding * 2)
|
|
}
|
|
|
|
var labelHorizontalPadding: CGFloat {
|
|
switch self {
|
|
case .large:
|
|
return 0
|
|
case .medium:
|
|
return SodaSpacing.s6
|
|
case .small:
|
|
return SodaSpacing.s4
|
|
}
|
|
}
|
|
|
|
var titleTypography: SodaTypography {
|
|
switch self {
|
|
case .large, .medium:
|
|
return .heading4
|
|
case .small:
|
|
return .body1
|
|
}
|
|
}
|
|
|
|
var subtitleTypography: SodaTypography {
|
|
switch self {
|
|
case .large, .medium:
|
|
return .body5
|
|
case .small:
|
|
return .caption2
|
|
}
|
|
}
|
|
}
|
|
|
|
struct AudioContentCard<Thumbnail: View>: View {
|
|
let size: AudioContentCardSize
|
|
let title: String
|
|
let subtitle: String
|
|
private let thumbnail: Thumbnail
|
|
|
|
init(
|
|
size: AudioContentCardSize,
|
|
title: String,
|
|
subtitle: String,
|
|
@ViewBuilder thumbnail: () -> Thumbnail
|
|
) {
|
|
self.size = size
|
|
self.title = title
|
|
self.subtitle = subtitle
|
|
self.thumbnail = thumbnail()
|
|
}
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: SodaSpacing.s8) {
|
|
thumbnailContent
|
|
|
|
labelContent
|
|
}
|
|
.frame(width: size.width, alignment: .leading)
|
|
}
|
|
|
|
private var thumbnailContent: some View {
|
|
thumbnail
|
|
.frame(width: size.width, height: size.width)
|
|
.clipped()
|
|
.frame(width: size.width, height: size.width)
|
|
.clipShape(RoundedRectangle(cornerRadius: SodaSpacing.s14, style: .continuous))
|
|
}
|
|
|
|
private var labelContent: some View {
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
Text(title)
|
|
.appFont(size.titleTypography)
|
|
.foregroundColor(.white)
|
|
.lineLimit(1)
|
|
.truncationMode(.tail)
|
|
|
|
Text(subtitle)
|
|
.appFont(size.subtitleTypography)
|
|
.foregroundColor(Color.gray500)
|
|
.lineLimit(1)
|
|
.truncationMode(.tail)
|
|
}
|
|
.frame(width: size.labelWidth, alignment: .leading)
|
|
.padding(.horizontal, size.labelHorizontalPadding)
|
|
.frame(width: size.width, alignment: .leading)
|
|
}
|
|
}
|
|
|
|
struct AudioContentCard_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
HStack(alignment: .top, spacing: SodaSpacing.s20) {
|
|
AudioContentCard(
|
|
size: .large,
|
|
title: "오디오 콘텐츠 제목입니다",
|
|
subtitle: "크리에이터명"
|
|
) {
|
|
previewThumbnail(Color.gray800)
|
|
}
|
|
|
|
AudioContentCard(
|
|
size: .medium,
|
|
title: "긴 제목은 한 줄로 말줄임 처리됩니다",
|
|
subtitle: "긴 부제목도 한 줄로 말줄임 처리됩니다"
|
|
) {
|
|
previewThumbnail(Color.gray700)
|
|
}
|
|
|
|
AudioContentCard(
|
|
size: .small,
|
|
title: "스몰 카드",
|
|
subtitle: "오디오"
|
|
) {
|
|
previewThumbnail(Color.gray900)
|
|
}
|
|
}
|
|
.padding(SodaSpacing.s20)
|
|
.background(Color.black)
|
|
.previewLayout(.sizeThatFits)
|
|
}
|
|
|
|
private static func previewThumbnail(_ color: Color) -> some View {
|
|
ZStack {
|
|
color
|
|
|
|
Image(systemName: "waveform")
|
|
.font(.system(size: 32, weight: .bold))
|
|
.foregroundColor(Color.gray500)
|
|
}
|
|
}
|
|
}
|