Luminate/Sources/Luminate/Pages/HomeView.swift

124 lines
4.6 KiB
Swift

//
// HomeView.swift
// Luminate
//
// Created by Brendan Szymanski on 6/5/26.
//
import Adwaita
import LuminateCore
import LuminateDI
import LuminateUI
public struct HomeView: View {
nonisolated public init(navigation: Binding<NavigationStack<Page>>) {
_navigation = navigation
}
@Injected(\.client) var client
@Injected(\.userId) var userId
@Binding var navigation: NavigationStack<Page>
@State private var resumeItems: [Components.Schemas.BaseItemDto] = []
@State private var nextUpItems: [Components.Schemas.BaseItemDto] = []
@State private var latestItems: [Components.Schemas.BaseItemDto] = []
@State private var libraries: [Components.Schemas.BaseItemDto] = []
@State private var isLoading = true
@State private var isLoadingData = false
public var view: Body {
ScrollView {
Clamp()
.maximumSize(1550)
.tighteningThreshold(550)
.child {
VStack {
if isLoading {
Spinner()
.halign(.center)
.valign(.center)
.frame(minWidth: 64)
.frame(maxWidth: 64)
} else {
if !resumeItems.isEmpty {
let title = "Continue Watching"
MediaRow(
title: title,
items: resumeItems,
navigation: $navigation,
onSeeAll: {
navigation.push(.folder(title: title, items: resumeItems))
}
)
.padding(32, .bottom)
}
if !nextUpItems.isEmpty {
let title = "Next Up"
MediaRow(
title: title,
items: nextUpItems,
navigation: $navigation,
onSeeAll: {
navigation.push(.folder(title: title, items: nextUpItems))
}
)
.padding(32, .bottom)
}
if !latestItems.isEmpty {
let title = "Recently Added"
MediaRow(
title: title,
items: latestItems,
navigation: $navigation,
onSeeAll: {
navigation.push(.folder(title: title, items: latestItems))
}
)
.padding(32, .bottom)
}
LibraryGrid(
libraries: libraries,
navigation: $navigation
)
.padding(32, .bottom)
}
}
.padding(8, .horizontal)
.padding(32, .bottom)
}
}
.hscrollbarPolicy(.never)
.propagateNaturalHeight()
.onAppear {
loadHomeData()
}
}
private func loadHomeData() {
Task {
async let resume = client.getItems(
userId: userId,
filters: [.isResumable],
sortBy: [.datePlayed],
sortOrder: [.descending],
limit: 20,
recursive: true
)
async let nextUp = client.getNextUp(userId: userId, limit: 20)
async let latest = client.getLatestMedia(userId: userId, limit: 20)
async let views = client.getUserViews(userId: userId)
do {
let (resume, nextUp, latest, views) = try await (resume, nextUp, latest, views)
resumeItems = resume.items ?? []
nextUpItems = nextUp.items ?? []
latestItems = latest
libraries = views.items ?? []
isLoading = false
} catch {
isLoading = false
}
isLoadingData = false
}
}
}