109 lines
3.6 KiB
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 })
|
|
}
|
|
}
|