diff --git a/Sources/Luminate/Luminate.swift b/Sources/Luminate/Luminate.swift index 1e94167..945e385 100644 --- a/Sources/Luminate/Luminate.swift +++ b/Sources/Luminate/Luminate.swift @@ -131,12 +131,11 @@ struct ContentView: View { } .navigationTitle(title) case .collectionPage(let item): - let title = item.name ?? "Library" - CollectionView(item: item, navigation: $stack) + ItemPage(item: item, navigation: $stack) .topToolbar { ToolbarView() } - .navigationTitle(title) + .navigationTitle(item.name ?? "Library") } } initialView: { HomeView(navigation: $stack) diff --git a/Sources/Luminate/Pages/CollectionView.swift b/Sources/Luminate/Pages/CollectionView.swift deleted file mode 100644 index 8063865..0000000 --- a/Sources/Luminate/Pages/CollectionView.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// CollectionView.swift -// -// Copyright 2026 Brendan Szymanski -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -import Adwaita -import LuminateCore -import LuminateUI - -public struct CollectionView: View { - - nonisolated public init( - item: Components.Schemas.BaseItemDto, - navigation: Binding> - ) { - self.item = item - _navigation = navigation - } - - private var item: Components.Schemas.BaseItemDto - @Binding var navigation: NavigationStack - - public var view: Body { - ScrollView { - Clamp() - .maximumSize(1550) - .tighteningThreshold(550) - .child { - ItemGrid( - parentId: item.id, - title: item.name, - navigation: $navigation - ) - .padding(32, .vertical) - } - } - .hscrollbarPolicy(.never) - .propagateNaturalHeight() - } -} diff --git a/Sources/Luminate/Pages/HomeView.swift b/Sources/Luminate/Pages/HomeView.swift index 28a9590..b793728 100644 --- a/Sources/Luminate/Pages/HomeView.swift +++ b/Sources/Luminate/Pages/HomeView.swift @@ -91,8 +91,8 @@ public struct HomeView: View { ) .padding(32, .bottom) } - LibraryGrid( - libraries: libraries, + ItemGrid( + items: libraries, navigation: $navigation ) .padding(32, .bottom) diff --git a/Sources/Luminate/Pages/ItemPage.swift b/Sources/Luminate/Pages/ItemPage.swift index c884db9..47df566 100644 --- a/Sources/Luminate/Pages/ItemPage.swift +++ b/Sources/Luminate/Pages/ItemPage.swift @@ -24,6 +24,7 @@ import Adwaita import LuminateCore +import LuminateDI import LuminateUI public struct ItemPage: View { @@ -33,13 +34,28 @@ public struct ItemPage: View { navigation: Binding> ) { self.title = title - self.items = items + self._items = .init(wrappedValue: items) + self.parentId = nil _navigation = navigation } - private var items: [Components.Schemas.BaseItemDto] - private var title: String + nonisolated public init( + item: Components.Schemas.BaseItemDto, + navigation: Binding> + ) { + self.title = item.name + self.parentId = item.id + _isLoading = .init(wrappedValue: item.id != nil) + _navigation = navigation + } + + private var title: String? + private var parentId: String? @Binding var navigation: NavigationStack + @State private var items: [Components.Schemas.BaseItemDto] = [] + @State private var isLoading = false + @Injected(\.client) var client + @Injected(\.userId) var userId public var view: Body { ScrollView { @@ -47,15 +63,36 @@ public struct ItemPage: View { .maximumSize(1550) .tighteningThreshold(550) .child { - LibraryGrid( - libraries: items, - navigation: $navigation, - title: title - ) - .padding(32, .vertical) + if isLoading, parentId != nil { + Spinner() + } else { + ItemGrid( + items: items, + navigation: $navigation, + title: title + ) + .padding(32, .vertical) + } } } .hscrollbarPolicy(.never) .propagateNaturalHeight() + .onAppear { + loadIfNeeded() + } + } + + private func loadIfNeeded() { + guard let parentId else { return } + Task { + let result = try? await client.getItems( + userId: userId, + parentId: parentId, + sortBy: [.sortName], + sortOrder: [.ascending] + ) + items = result?.items ?? [] + isLoading = false + } } } diff --git a/Sources/LuminateUI/Components/ItemGrid.swift b/Sources/LuminateUI/Components/ItemGrid.swift index ace8961..8c6b62d 100644 --- a/Sources/LuminateUI/Components/ItemGrid.swift +++ b/Sources/LuminateUI/Components/ItemGrid.swift @@ -20,74 +20,38 @@ // import Adwaita +import Foundation import LuminateCore -import LuminateDI public struct ItemGrid: View { - var parentId: String? - var includeItemTypes: [Components.Schemas.BaseItemKind]? - var title: String? - @Binding var navigation: NavigationStack - @Injected(\.client) var client - @Injected(\.userId) var userId - @State private var items: [Components.Schemas.BaseItemDto] = [] - @State private var isLoading = true - private let pageSize: Int32 = 50 + public var items: [Components.Schemas.BaseItemDto] + @Binding public var navigation: NavigationStack + public var title: String? public init( - parentId: String? = nil, - includeItemTypes: [Components.Schemas.BaseItemKind]? = nil, - title: String? = nil, - navigation: Binding> + items: [Components.Schemas.BaseItemDto], + navigation: Binding>, + title: String? = nil ) { - self.parentId = parentId - self.includeItemTypes = includeItemTypes - self.title = title + self.items = items _navigation = navigation + self.title = title } public var view: Body { - VStack { - if let title { - Text(title) - .title2() - .halign(.start) - .padding() - } - if isLoading { - Spinner() - .transition(.crossfade) - } else { - FlowGrid(items, id: \.id) { item in - HomePosterCell(item: item, navigation: $navigation) - } - .columnSpacing(16) - .rowSpacing(16) - .minimumSize(216) - .halign(.fill) - .transition(.crossfade) - } - } - .onAppear { - loadItems() - } - } - - private func loadItems() { - Task { - do { - let result = try await client.getItems( - userId: userId, - parentId: parentId, - sortBy: [.sortName], - sortOrder: [.ascending] - ) - items = result.items ?? [] - isLoading = false - } catch { - isLoading = false + VStack(spacing: 16) { + Text(title ?? "Libraries") + .title3() + .halign(.start) + .padding(10, .horizontal) + FlowGrid(items, id: \.id) { item in + HomePosterCell(item: item, navigation: $navigation) } + .columnSpacing(16) + .rowSpacing(16) + .minimumSize(216) + .halign(.fill) } } } diff --git a/Sources/LuminateUI/Components/LibraryGrid.swift b/Sources/LuminateUI/Components/LibraryGrid.swift deleted file mode 100644 index 196a20d..0000000 --- a/Sources/LuminateUI/Components/LibraryGrid.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// LibraryGrid.swift -// -// Copyright 2026 Brendan Szymanski -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// SPDX-License-Identifier: GPL-3.0-or-later -// - -import Adwaita -import Foundation -import LuminateCore - -public struct LibraryGrid: View { - - public var libraries: [Components.Schemas.BaseItemDto] - @Binding public var navigation: NavigationStack - public var title: String? - - public init( - libraries: [Components.Schemas.BaseItemDto], - navigation: Binding>, - title: String? = nil - ) { - self.libraries = libraries - _navigation = navigation - self.title = title - } - - public var view: Body { - VStack(spacing: 16) { - Text(title ?? "Libraries") - .title3() - .halign(.start) - .padding(10, .horizontal) - FlowGrid(libraries, id: \.id) { item in - HomePosterCell(item: item, navigation: $navigation) - } - .columnSpacing(16) - .rowSpacing(16) - .minimumSize(216) - .halign(.fill) - } - } -}