Files
sodalive-ios/SodaLive/Sources/V2/Main/Content/Overview/ContentOverviewView.swift

109 lines
3.6 KiB
Swift

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 })
}
}