import SwiftUI struct MainContentAudioRankingRow: View { let item: AudioRankingItemResponse let showRankChange: Bool let onTapContent: (Int) -> Void var body: some View { Button { onTapContent(item.contentId) } label: { GeometryReader { proxy in let rowHeight = proxy.size.height let imageSide = rowHeight * 0.8 HStack(alignment: .center, spacing: SodaSpacing.s14) { rankColumn DownsampledKFImage( url: URL(string: item.coverImageUrl ?? ""), size: CGSize(width: imageSide, height: imageSide) ) .background(Color.gray800) .aspectRatio(1, contentMode: .fit) .clipShape(RoundedRectangle(cornerRadius: SodaSpacing.s14, style: .continuous)) VStack(alignment: .leading, spacing: SodaSpacing.s4) { Text(item.title) .appFont(.heading4) .foregroundColor(.white) .lineLimit(1) .truncationMode(.tail) Text(item.creatorNickname) .appFont(.body4) .foregroundColor(Color.gray400) .lineLimit(1) .truncationMode(.tail) } .frame(maxWidth: .infinity, alignment: .leading) } .padding(.horizontal, SodaSpacing.s14) .padding(.vertical, rowHeight * 0.1) } .aspectRatio(3.74, contentMode: .fit) .background(Color.black) } .buttonStyle(.plain) } private var rankColumn: some View { VStack(alignment: .center, spacing: 0) { Text("\(item.rank)") .appFont(size: 40, family: .pattaya) .foregroundStyle( LinearGradient( colors: [.white, Color.gray200], startPoint: .top, endPoint: .bottom ) ) .shadow(color: Color.black.opacity(0.48), radius: 2) .lineLimit(1) .frame(maxWidth: .infinity, alignment: .center) MainContentRankChangeBadge( showRankChange: showRankChange, rankChange: item.rankChange, isNew: item.isNew ) .frame(maxWidth: .infinity, alignment: .center) } .frame(width: 49, alignment: .center) } }