import SwiftUI struct ContentOverviewView: View { @StateObject private var viewModel: ContentOverviewViewModel let onTapContent: (Int) -> Void private let columns = [ GridItem(.flexible(), spacing: SodaSpacing.s4), GridItem(.flexible(), spacing: SodaSpacing.s4) ] init( type: ContentOverviewType = .newAndHotAudio, onTapContent: @escaping (Int) -> Void ) { self._viewModel = StateObject(wrappedValue: ContentOverviewViewModel(type: type)) self.onTapContent = onTapContent } var body: some View { VStack(spacing: 0) { titleBar content .frame(maxWidth: .infinity, maxHeight: .infinity) } .background(Color.black.ignoresSafeArea()) .onAppear { viewModel.fetchFirstPageIfNeeded() } .sodaToast( isPresented: $viewModel.isShowPopup, message: viewModel.errorMessage, autohideIn: 2 ) } private var titleBar: some View { TitleBar { HStack(spacing: SodaSpacing.s14) { Button { AppState.shared.back() } label: { Image("ic_new_bar_back") .resizable() .scaledToFit() .frame(width: 24, height: 24) } .buttonStyle(.plain) Text(I18n.MainContentRecommendation.newAndHotSectionTitle) .appFont(.heading2) .foregroundColor(.white) .lineLimit(1) } } trailing: { EmptyView() } } @ViewBuilder private var content: some View { if viewModel.isLoading && viewModel.hasLoaded == false { ProgressView() .progressViewStyle(CircularProgressViewStyle(tint: .white)) .frame(maxWidth: .infinity, maxHeight: .infinity) } else if viewModel.shouldShowEmptyState { MainContentAudioEmptyStateView(message: I18n.MainContentAll.emptyStateMessage) } else { ScrollView(showsIndicators: false) { LazyVGrid(columns: columns, alignment: .leading, spacing: SodaSpacing.s20) { ForEach(viewModel.items) { item in Button { onTapContent(item.contentId) } label: { GeometryReader { proxy in AudioContentThumbnailCard( item: AudioContentThumbnailCardItem(contentOverviewItem: item), width: proxy.size.width ) } .aspectRatio(0.78, contentMode: .fit) } .buttonStyle(.plain) .onAppear { viewModel.fetchNextPageIfNeeded(currentItem: item) } } } .padding(.horizontal, SodaSpacing.s14) .padding(.top, SodaSpacing.s8) .padding(.bottom, SodaSpacing.s20) if viewModel.isLoadingNextPage { ProgressView() .progressViewStyle(CircularProgressViewStyle(tint: .white)) .padding(.vertical, SodaSpacing.s20) } } } } } struct ContentOverviewView_Previews: PreviewProvider { static var previews: some View { ContentOverviewView(onTapContent: { _ in }) } }